aboutsummaryrefslogtreecommitdiff
path: root/net/openbgpd/files
diff options
context:
space:
mode:
authorKurt Jaeger <pi@FreeBSD.org>2019-05-31 15:04:30 +0000
committerKurt Jaeger <pi@FreeBSD.org>2019-05-31 15:04:30 +0000
commite3e5543a6dc3364105a52ea6b86c3f060bd230e2 (patch)
tree41240bb6a84aa0d4143fc4a8d939e719a4f83e79 /net/openbgpd/files
parent75b69fed682eeb918b8cb5661e89976ee7328f25 (diff)
downloadports-e3e5543a6dc3364105a52ea6b86c3f060bd230e2.tar.gz
ports-e3e5543a6dc3364105a52ea6b86c3f060bd230e2.zip
Notes
Diffstat (limited to 'net/openbgpd/files')
-rw-r--r--net/openbgpd/files/patch-Makefile12
-rw-r--r--net/openbgpd/files/patch-Makefile.am20
-rw-r--r--net/openbgpd/files/patch-Makefile.inc12
-rw-r--r--net/openbgpd/files/patch-bgpctl_Makefile31
-rw-r--r--net/openbgpd/files/patch-bgpctl_bgpctl.8287
-rw-r--r--net/openbgpd/files/patch-bgpctl_bgpctl.c1529
-rw-r--r--net/openbgpd/files/patch-bgpctl_irr_asset.c14
-rw-r--r--net/openbgpd/files/patch-bgpctl_irr_output.c14
-rw-r--r--net/openbgpd/files/patch-bgpctl_irr_parser.c48
-rw-r--r--net/openbgpd/files/patch-bgpctl_irr_prefix.c157
-rw-r--r--net/openbgpd/files/patch-bgpctl_irrfilter.c24
-rw-r--r--net/openbgpd/files/patch-bgpctl_irrfilter.h59
-rw-r--r--net/openbgpd/files/patch-bgpctl_mrtparser.c977
-rw-r--r--net/openbgpd/files/patch-bgpctl_mrtparser.h122
-rw-r--r--net/openbgpd/files/patch-bgpctl_parser.c400
-rw-r--r--net/openbgpd/files/patch-bgpctl_parser.h55
-rw-r--r--net/openbgpd/files/patch-bgpctl_whois.c18
-rw-r--r--net/openbgpd/files/patch-bgpd_Makefile30
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.8348
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.c693
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.conf.5746
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.h872
-rw-r--r--net/openbgpd/files/patch-bgpd_buffer.c104
-rw-r--r--net/openbgpd/files/patch-bgpd_carp.c54
-rw-r--r--net/openbgpd/files/patch-bgpd_config.c109
-rw-r--r--net/openbgpd/files/patch-bgpd_control.c171
-rw-r--r--net/openbgpd/files/patch-bgpd_imsg.c275
-rw-r--r--net/openbgpd/files/patch-bgpd_imsg.h115
-rw-r--r--net/openbgpd/files/patch-bgpd_kroute.c3140
-rw-r--r--net/openbgpd/files/patch-bgpd_log.c117
-rw-r--r--net/openbgpd/files/patch-bgpd_log.h39
-rw-r--r--net/openbgpd/files/patch-bgpd_mrt.c864
-rw-r--r--net/openbgpd/files/patch-bgpd_mrt.h287
-rw-r--r--net/openbgpd/files/patch-bgpd_name2id.c14
-rw-r--r--net/openbgpd/files/patch-bgpd_parse.y1626
-rw-r--r--net/openbgpd/files/patch-bgpd_pfkey.c471
-rw-r--r--net/openbgpd/files/patch-bgpd_pftable.c17
-rw-r--r--net/openbgpd/files/patch-bgpd_printconf.c439
-rw-r--r--net/openbgpd/files/patch-bgpd_rde.c2614
-rw-r--r--net/openbgpd/files/patch-bgpd_rde.h361
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_attr.c562
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_decide.c133
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_filter.c297
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_prefix.c301
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_rib.c513
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_update.c644
-rw-r--r--net/openbgpd/files/patch-bgpd_session.c2075
-rw-r--r--net/openbgpd/files/patch-bgpd_session.h188
-rw-r--r--net/openbgpd/files/patch-bgpd_timer.c32
-rw-r--r--net/openbgpd/files/patch-bgpd_util.c440
-rw-r--r--net/openbgpd/files/patch-openbsd-compat_fmt_scaled.c275
-rw-r--r--net/openbgpd/files/patch-openbsd-compat_hash.h134
-rw-r--r--net/openbgpd/files/patch-openbsd-compat_if_media.h619
-rw-r--r--net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c312
-rw-r--r--net/openbgpd/files/patch-openbsd-compat_imsg.c312
-rw-r--r--net/openbgpd/files/patch-openbsd-compat_imsg.h119
-rw-r--r--net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h98
-rw-r--r--net/openbgpd/files/patch-openbsd-compat_util.h126
58 files changed, 20 insertions, 24445 deletions
diff --git a/net/openbgpd/files/patch-Makefile b/net/openbgpd/files/patch-Makefile
deleted file mode 100644
index 77ae22e026e6..000000000000
--- a/net/openbgpd/files/patch-Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-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>
diff --git a/net/openbgpd/files/patch-Makefile.am b/net/openbgpd/files/patch-Makefile.am
new file mode 100644
index 000000000000..da85a8ad6103
--- /dev/null
+++ b/net/openbgpd/files/patch-Makefile.am
@@ -0,0 +1,20 @@
+--- 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; \
diff --git a/net/openbgpd/files/patch-Makefile.inc b/net/openbgpd/files/patch-Makefile.inc
deleted file mode 100644
index 7a2bef96c0d8..000000000000
--- a/net/openbgpd/files/patch-Makefile.inc
+++ /dev/null
@@ -1,12 +0,0 @@
-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
diff --git a/net/openbgpd/files/patch-bgpctl_Makefile b/net/openbgpd/files/patch-bgpctl_Makefile
deleted file mode 100644
index 572c0fcb8362..000000000000
--- a/net/openbgpd/files/patch-bgpctl_Makefile
+++ /dev/null
@@ -1,31 +0,0 @@
-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}
diff --git a/net/openbgpd/files/patch-bgpctl_bgpctl.8 b/net/openbgpd/files/patch-bgpctl_bgpctl.8
deleted file mode 100644
index 2e08c575981e..000000000000
--- a/net/openbgpd/files/patch-bgpctl_bgpctl.8
+++ /dev/null
@@ -1,287 +0,0 @@
-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
diff --git a/net/openbgpd/files/patch-bgpctl_bgpctl.c b/net/openbgpd/files/patch-bgpctl_bgpctl.c
deleted file mode 100644
index 1553efc83281..000000000000
--- a/net/openbgpd/files/patch-bgpctl_bgpctl.c
+++ /dev/null
@@ -1,1529 +0,0 @@
-Index: bgpctl/bgpctl.c
-===================================================================
-RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/bgpctl.c,v
-retrieving revision 1.1.1.7
-retrieving revision 1.10
-diff -u -p -r1.1.1.7 -r1.10
---- bgpctl/bgpctl.c 14 Feb 2010 20:20:14 -0000 1.1.1.7
-+++ bgpctl/bgpctl.c 8 Dec 2012 20:17:55 -0000 1.10
-@@ -1,4 +1,4 @@
--/* $OpenBSD: bgpctl.c,v 1.142 2009/06/06 06:33:15 eric Exp $ */
-+/* $OpenBSD: bgpctl.c,v 1.167 2012/11/15 19:55:08 sthen Exp $ */
-
- /*
- * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
-@@ -16,11 +16,19 @@
- * 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 <sys/un.h>
- #include <net/if.h>
-+#if defined(__FreeBSD__) /* net/if_media.h */
-+#include "if_media.h"
-+#else
- #include <net/if_media.h>
-+#endif /* defined(__FreeBSD__) */
- #include <net/if_types.h>
-
- #include <err.h>
-@@ -29,7 +37,11 @@
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
-+#if defined(__FreeBSD__) /* util.h */
-+#include "util.h"
-+#else
- #include <util.h>
-+#endif /* defined(__FreeBSD__) */
-
- #include "bgpd.h"
- #include "session.h"
-@@ -37,6 +49,11 @@
- #include "log.h"
- #include "parser.h"
- #include "irrfilter.h"
-+#include "mrtparser.h"
-+
-+#if defined(__FreeBSD__) /* FreeBSD has no LINK_STATE_IS_UP macro. */
-+#define LINK_STATE_IS_UP(_s) ((_s) >= LINK_STATE_UP)
-+#endif /* defined(__FreeBSD__) */
-
- enum neighbor_views {
- NV_DEFAULT,
-@@ -50,12 +67,14 @@ int show_summary_msg(struct imsg *, in
- int show_summary_terse_msg(struct imsg *, int);
- int show_neighbor_terse(struct imsg *);
- int show_neighbor_msg(struct imsg *, enum neighbor_views);
--void print_neighbor_capa_mp_safi(u_int8_t);
-+void print_neighbor_capa_mp(struct peer *);
-+void print_neighbor_capa_restart(struct peer *);
- void print_neighbor_msgstats(struct peer *);
- void print_timer(const char *, time_t);
- static char *fmt_timeframe(time_t t);
- static char *fmt_timeframe_core(time_t t);
- void show_fib_head(void);
-+void show_fib_tables_head(void);
- void show_network_head(void);
- void show_fib_flags(u_int16_t);
- int show_fib_msg(struct imsg *);
-@@ -65,7 +84,7 @@ void show_interface_head(void);
- int ift2ifm(int);
- const char * get_media_descr(int);
- const char * get_linkstate(int, int);
--void print_baudrate(u_int64_t);
-+const char * get_baudrate(u_int64_t, char *);
- int show_interface_msg(struct imsg *);
- void show_rib_summary_head(void);
- void print_prefix(struct bgpd_addr *, u_int8_t, u_int8_t);
-@@ -73,16 +92,25 @@ const char * print_origin(u_int8_t, int
- void print_flags(u_int8_t, int);
- int show_rib_summary_msg(struct imsg *);
- int show_rib_detail_msg(struct imsg *, int);
-+void show_rib_brief(struct ctl_show_rib *, u_char *);
-+void show_rib_detail(struct ctl_show_rib *, u_char *, int);
-+void show_attr(void *, u_int16_t);
- void show_community(u_char *, u_int16_t);
--const char *get_ext_subtype(u_int8_t);
- void show_ext_community(u_char *, u_int16_t);
- char *fmt_mem(int64_t);
- int show_rib_memory_msg(struct imsg *);
- void send_filterset(struct imsgbuf *, struct filter_set_head *);
- static const char *get_errstr(u_int8_t, u_int8_t);
- int show_result(struct imsg *);
-+void show_mrt_dump(struct mrt_rib *, struct mrt_peer *, void *);
-+void network_mrt_dump(struct mrt_rib *, struct mrt_peer *, void *);
-+void show_mrt_state(struct mrt_bgp_state *, void *);
-+void show_mrt_msg(struct mrt_bgp_msg *, void *);
-+void mrt_to_bgpd_addr(union mrt_addr *, struct bgpd_addr *);
-
- struct imsgbuf *ibuf;
-+struct mrt_parser show_mrt = { show_mrt_dump, show_mrt_state, show_mrt_msg };
-+struct mrt_parser net_mrt = { network_mrt_dump, NULL, NULL };
-
- __dead void
- usage(void)
-@@ -98,7 +126,7 @@ int
- main(int argc, char *argv[])
- {
- struct sockaddr_un sun;
-- int fd, n, done, ch, nodescr = 0;
-+ int fd, n, done, ch, nodescr = 0, verbose = 0;
- struct imsg imsg;
- struct network_config net;
- struct parse_result *res;
-@@ -128,8 +156,11 @@ main(int argc, char *argv[])
- if ((res = parse(argc, argv)) == NULL)
- exit(1);
-
-- if (res->action == IRRFILTER)
-+ if (res->action == IRRFILTER) {
-+ if (!(res->flags & (F_IPV4|F_IPV6)))
-+ res->flags |= (F_IPV4|F_IPV6);
- irr_main(res->as.as, res->flags, res->irr_outdir);
-+ }
-
- memcpy(&neighbor.addr, &res->peeraddr, sizeof(neighbor.addr));
- strlcpy(neighbor.descr, res->peerdesc, sizeof(neighbor.descr));
-@@ -154,7 +185,7 @@ main(int argc, char *argv[])
- case NONE:
- case IRRFILTER:
- usage();
-- /* not reached */
-+ /* NOTREACHED */
- case SHOW:
- case SHOW_SUMMARY:
- imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1, NULL, 0);
-@@ -164,24 +195,32 @@ main(int argc, char *argv[])
- imsg_compose(ibuf, IMSG_CTL_SHOW_TERSE, 0, 0, -1, NULL, 0);
- break;
- case SHOW_FIB:
-- if (!res->addr.af) {
-- struct buf *msg;
--
-- if ((msg = imsg_create(ibuf, IMSG_CTL_KROUTE, 0, 0,
-- sizeof(res->flags) + sizeof(res->af))) == NULL)
-+ if (!res->addr.aid) {
-+ struct ibuf *msg;
-+ sa_family_t af;
-+
-+ af = aid2af(res->aid);
-+ if ((msg = imsg_create(ibuf, IMSG_CTL_KROUTE,
-+ res->rtableid, 0, sizeof(res->flags) +
-+ sizeof(af))) == NULL)
- errx(1, "imsg_create failure");
- if (imsg_add(msg, &res->flags, sizeof(res->flags)) ==
- -1 ||
-- imsg_add(msg, &res->af, sizeof(res->af)) == -1)
-+ imsg_add(msg, &af, sizeof(af)) == -1)
- errx(1, "imsg_add failure");
- imsg_close(ibuf, msg);
- } else
-- imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1,
-- &res->addr, sizeof(res->addr));
-+ imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, res->rtableid,
-+ 0, -1, &res->addr, sizeof(res->addr));
- show_fib_head();
- break;
-+ case SHOW_FIB_TABLES:
-+ imsg_compose(ibuf, IMSG_CTL_SHOW_FIB_TABLES, 0, 0, -1, NULL, 0);
-+ show_fib_tables_head();
-+ break;
- case SHOW_NEXTHOP:
-- imsg_compose(ibuf, IMSG_CTL_SHOW_NEXTHOP, 0, 0, -1, NULL, 0);
-+ imsg_compose(ibuf, IMSG_CTL_SHOW_NEXTHOP, res->rtableid, 0, -1,
-+ NULL, 0);
- show_nexthop_head();
- break;
- case SHOW_INTERFACE:
-@@ -192,7 +231,7 @@ main(int argc, char *argv[])
- case SHOW_NEIGHBOR_TIMERS:
- case SHOW_NEIGHBOR_TERSE:
- neighbor.show_timers = (res->action == SHOW_NEIGHBOR_TIMERS);
-- if (res->peeraddr.af || res->peerdesc[0])
-+ if (res->peeraddr.aid || res->peerdesc[0])
- imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1,
- &neighbor, sizeof(neighbor));
- else
-@@ -206,7 +245,7 @@ main(int argc, char *argv[])
- memcpy(&ribreq.as, &res->as, sizeof(res->as));
- type = IMSG_CTL_SHOW_RIB_AS;
- }
-- if (res->addr.af) {
-+ if (res->addr.aid) {
- memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr));
- ribreq.prefixlen = res->prefixlen;
- type = IMSG_CTL_SHOW_RIB_PREFIX;
-@@ -217,15 +256,35 @@ main(int argc, char *argv[])
- sizeof(res->community));
- type = IMSG_CTL_SHOW_RIB_COMMUNITY;
- }
-- memcpy(&ribreq.neighbor, &neighbor,
-- sizeof(ribreq.neighbor));
-+ memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor));
- strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib));
-- ribreq.af = res->af;
-+ ribreq.aid = res->aid;
- ribreq.flags = res->flags;
- imsg_compose(ibuf, type, 0, 0, -1, &ribreq, sizeof(ribreq));
- if (!(res->flags & F_CTL_DETAIL))
- show_rib_summary_head();
- break;
-+ case SHOW_MRT:
-+ close(fd);
-+ bzero(&ribreq, sizeof(ribreq));
-+ if (res->as.type != AS_NONE)
-+ memcpy(&ribreq.as, &res->as, sizeof(res->as));
-+ if (res->addr.aid) {
-+ memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr));
-+ ribreq.prefixlen = res->prefixlen;
-+ }
-+ if (res->community.as != COMMUNITY_UNSET &&
-+ res->community.type != COMMUNITY_UNSET)
-+ memcpy(&ribreq.community, &res->community,
-+ sizeof(res->community));
-+ memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor));
-+ ribreq.aid = res->aid;
-+ ribreq.flags = res->flags;
-+ show_mrt.arg = &ribreq;
-+ if (!(res->flags & F_CTL_DETAIL))
-+ show_rib_summary_head();
-+ mrt_parse(res->mrtfd, &show_mrt, 1);
-+ exit(0);
- case SHOW_RIB_MEM:
- imsg_compose(ibuf, IMSG_CTL_SHOW_RIB_MEM, 0, 0, -1, NULL, 0);
- break;
-@@ -237,12 +296,14 @@ main(int argc, char *argv[])
- errx(1, "action==FIB");
- break;
- case FIB_COUPLE:
-- imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0);
-+ imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, res->rtableid, 0, -1,
-+ NULL, 0);
- printf("couple request sent.\n");
- done = 1;
- break;
- case FIB_DECOUPLE:
-- imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0);
-+ imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, res->rtableid, 0, -1,
-+ NULL, 0);
- printf("decouple request sent.\n");
- done = 1;
- break;
-@@ -290,12 +351,40 @@ main(int argc, char *argv[])
- break;
- case NETWORK_SHOW:
- bzero(&ribreq, sizeof(ribreq));
-- ribreq.af = res->af;
-+ ribreq.aid = res->aid;
- strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib));
- imsg_compose(ibuf, IMSG_CTL_SHOW_NETWORK, 0, 0, -1,
- &ribreq, sizeof(ribreq));
- show_network_head();
- break;
-+ case NETWORK_MRT:
-+ bzero(&ribreq, sizeof(ribreq));
-+ if (res->as.type != AS_NONE)
-+ memcpy(&ribreq.as, &res->as, sizeof(res->as));
-+ if (res->addr.aid) {
-+ memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr));
-+ ribreq.prefixlen = res->prefixlen;
-+ }
-+ if (res->community.as != COMMUNITY_UNSET &&
-+ res->community.type != COMMUNITY_UNSET)
-+ memcpy(&ribreq.community, &res->community,
-+ sizeof(res->community));
-+ memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor));
-+ ribreq.aid = res->aid;
-+ ribreq.flags = res->flags;
-+ net_mrt.arg = &ribreq;
-+ mrt_parse(res->mrtfd, &net_mrt, 1);
-+ done = 1;
-+ break;
-+ case LOG_VERBOSE:
-+ verbose = 1;
-+ /* FALLTHROUGH */
-+ case LOG_BRIEF:
-+ imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
-+ &verbose, sizeof(verbose));
-+ printf("logging request sent.\n");
-+ done = 1;
-+ break;
- }
-
- while (ibuf->w.queued)
-@@ -304,13 +393,13 @@ main(int argc, char *argv[])
-
- while (!done) {
- if ((n = imsg_read(ibuf)) == -1)
-- errx(1, "imsg_read error");
-+ err(1, "imsg_read error");
- if (n == 0)
- errx(1, "pipe closed");
-
- while (!done) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
-- errx(1, "imsg_get error");
-+ err(1, "imsg_get error");
- if (n == 0)
- break;
-
-@@ -329,6 +418,8 @@ main(int argc, char *argv[])
- done = show_summary_terse_msg(&imsg, nodescr);
- break;
- case SHOW_FIB:
-+ case SHOW_FIB_TABLES:
-+ case NETWORK_SHOW:
- done = show_fib_msg(&imsg);
- break;
- case SHOW_NEXTHOP:
-@@ -356,9 +447,6 @@ main(int argc, char *argv[])
- case SHOW_RIB_MEM:
- done = show_rib_memory_msg(&imsg);
- break;
-- case NETWORK_SHOW:
-- done = show_fib_msg(&imsg);
-- break;
- case NEIGHBOR:
- case NEIGHBOR_UP:
- case NEIGHBOR_DOWN:
-@@ -373,6 +461,10 @@ main(int argc, char *argv[])
- case NETWORK_REMOVE:
- case NETWORK_FLUSH:
- case IRRFILTER:
-+ case LOG_VERBOSE:
-+ case LOG_BRIEF:
-+ case SHOW_MRT:
-+ case NETWORK_MRT:
- break;
- }
- imsg_free(&imsg);
-@@ -398,8 +490,8 @@ fmt_peer(const char *descr, const struct
- }
-
- ip = log_addr(remote_addr);
-- if (masklen != -1 && ((remote_addr->af == AF_INET && masklen != 32) ||
-- (remote_addr->af == AF_INET6 && masklen != 128))) {
-+ if (masklen != -1 && ((remote_addr->aid == AID_INET && masklen != 32) ||
-+ (remote_addr->aid == AID_INET6 && masklen != 128))) {
- if (asprintf(&p, "%s/%u", ip, masklen) == -1)
- err(1, NULL);
- } else {
-@@ -430,7 +522,7 @@ show_summary_msg(struct imsg *imsg, int
- p->conf.remote_masklen, nodescr);
- if (strlen(s) >= 20)
- s[20] = 0;
-- printf("%-20s %8s %10llu %10llu %5u %-8s ",
-+ printf("%-20s %8s %10" PRIu64 " %10" PRIu64 " %5u %-8s ",
- s, log_as(p->conf.remote_as),
- p->stats.msg_rcvd_open + p->stats.msg_rcvd_notification +
- p->stats.msg_rcvd_update + p->stats.msg_rcvd_keepalive +
-@@ -492,8 +584,8 @@ show_neighbor_terse(struct imsg *imsg)
- switch (imsg->hdr.type) {
- case IMSG_CTL_SHOW_NEIGHBOR:
- p = imsg->data;
-- printf("%llu %llu %llu %llu %llu %llu %llu "
-- "%llu %llu %llu %u %u %llu %llu %llu %llu\n",
-+ printf("%" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " "
-+ "%" PRIu64 " %" PRIu64 " %" PRIu64 " %u %u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
- p->stats.msg_sent_open, p->stats.msg_rcvd_open,
- p->stats.msg_sent_notification,
- p->stats.msg_rcvd_notification,
-@@ -521,13 +613,15 @@ show_neighbor_msg(struct imsg *imsg, enu
- struct ctl_timer *t;
- struct in_addr ina;
- char buf[NI_MAXHOST], pbuf[NI_MAXSERV], *s;
-+ int hascapamp = 0;
-+ u_int8_t i;
-
- switch (imsg->hdr.type) {
- case IMSG_CTL_SHOW_NEIGHBOR:
- p = imsg->data;
-- if ((p->conf.remote_addr.af == AF_INET &&
-+ if ((p->conf.remote_addr.aid == AID_INET &&
- p->conf.remote_masklen != 32) ||
-- (p->conf.remote_addr.af == AF_INET6 &&
-+ (p->conf.remote_addr.aid == AID_INET6 &&
- p->conf.remote_masklen != 128)) {
- if (asprintf(&s, "%s/%u",
- log_addr(&p->conf.remote_addr),
-@@ -549,9 +643,20 @@ show_neighbor_msg(struct imsg *imsg, enu
- printf(", Template");
- if (p->conf.cloned)
- printf(", Cloned");
-+ if (p->conf.passive)
-+ printf(", Passive");
-+ if (p->conf.ebgp && p->conf.distance > 1)
-+ printf(", Multihop (%u)", (int)p->conf.distance);
- printf("\n");
- if (p->conf.descr[0])
- printf(" Description: %s\n", p->conf.descr);
-+ if (p->conf.max_prefix) {
-+ printf(" Max-prefix: %u", p->conf.max_prefix);
-+ if (p->conf.max_prefix_restart)
-+ printf(" (restart %u)",
-+ p->conf.max_prefix_restart);
-+ printf("\n");
-+ }
- printf(" BGP version 4, remote router-id %s\n",
- inet_ntoa(ina));
- printf(" BGP state = %s", statenames[p->state]);
-@@ -563,22 +668,24 @@ show_neighbor_msg(struct imsg *imsg, enu
- printf(" Last read %s, holdtime %us, keepalive interval %us\n",
- fmt_timeframe(p->stats.last_read),
- p->holdtime, p->holdtime/3);
-- if (p->capa.peer.mp_v4 || p->capa.peer.mp_v6 ||
-- p->capa.peer.refresh || p->capa.peer.restart ||
-- p->capa.peer.as4byte) {
-+ for (i = 0; i < AID_MAX; i++)
-+ if (p->capa.peer.mp[i])
-+ hascapamp = 1;
-+ if (hascapamp || p->capa.peer.refresh ||
-+ p->capa.peer.grestart.restart || p->capa.peer.as4byte) {
- printf(" Neighbor capabilities:\n");
-- if (p->capa.peer.mp_v4) {
-- printf(" Multiprotocol extensions: IPv4");
-- print_neighbor_capa_mp_safi(p->capa.peer.mp_v4);
-- }
-- if (p->capa.peer.mp_v6) {
-- printf(" Multiprotocol extensions: IPv6");
-- print_neighbor_capa_mp_safi(p->capa.peer.mp_v6);
-+ if (hascapamp) {
-+ printf(" Multiprotocol extensions: ");
-+ print_neighbor_capa_mp(p);
-+ printf("\n");
- }
- if (p->capa.peer.refresh)
- printf(" Route Refresh\n");
-- if (p->capa.peer.restart)
-- printf(" Graceful Restart\n");
-+ if (p->capa.peer.grestart.restart) {
-+ printf(" Graceful Restart");
-+ print_neighbor_capa_restart(p);
-+ printf("\n");
-+ }
- if (p->capa.peer.as4byte)
- printf(" 4-byte AS numbers\n");
- }
-@@ -633,20 +740,38 @@ show_neighbor_msg(struct imsg *imsg, enu
- }
-
- void
--print_neighbor_capa_mp_safi(u_int8_t safi)
-+print_neighbor_capa_mp(struct peer *p)
- {
-- switch (safi) {
-- case SAFI_UNICAST:
-- printf(" Unicast");
-- break;
-- case SAFI_MULTICAST:
-- printf(" Multicast");
-- break;
-- default:
-- printf(" unknown (%u)", safi);
-- break;
-- }
-- printf("\n");
-+ int comma;
-+ u_int8_t i;
-+
-+ for (i = 0, comma = 0; i < AID_MAX; i++)
-+ if (p->capa.peer.mp[i]) {
-+ printf("%s%s", comma ? ", " : "", aid2str(i));
-+ comma = 1;
-+ }
-+}
-+
-+void
-+print_neighbor_capa_restart(struct peer *p)
-+{
-+ int comma;
-+ u_int8_t i;
-+
-+ if (p->capa.peer.grestart.timeout)
-+ printf(": Timeout: %d, ", p->capa.peer.grestart.timeout);
-+ for (i = 0, comma = 0; i < AID_MAX; i++)
-+ if (p->capa.peer.grestart.flags[i] & CAPA_GR_PRESENT) {
-+ if (!comma &&
-+ p->capa.peer.grestart.flags[i] & CAPA_GR_RESTART)
-+ printf("restarted, ");
-+ if (comma)
-+ printf(", ");
-+ printf("%s", aid2str(i));
-+ if (p->capa.peer.grestart.flags[i] & CAPA_GR_FORWARD)
-+ printf(" (preserved)");
-+ comma = 1;
-+ }
- }
-
- void
-@@ -654,17 +779,17 @@ print_neighbor_msgstats(struct peer *p)
- {
- printf(" Message statistics:\n");
- printf(" %-15s %-10s %-10s\n", "", "Sent", "Received");
-- printf(" %-15s %10llu %10llu\n", "Opens",
-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Opens",
- p->stats.msg_sent_open, p->stats.msg_rcvd_open);
-- printf(" %-15s %10llu %10llu\n", "Notifications",
-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Notifications",
- p->stats.msg_sent_notification, p->stats.msg_rcvd_notification);
-- printf(" %-15s %10llu %10llu\n", "Updates",
-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Updates",
- p->stats.msg_sent_update, p->stats.msg_rcvd_update);
-- printf(" %-15s %10llu %10llu\n", "Keepalives",
-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Keepalives",
- p->stats.msg_sent_keepalive, p->stats.msg_rcvd_keepalive);
-- printf(" %-15s %10llu %10llu\n", "Route Refresh",
-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Route Refresh",
- p->stats.msg_sent_rrefresh, p->stats.msg_rcvd_rrefresh);
-- printf(" %-15s %10llu %10llu\n\n", "Total",
-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n\n", "Total",
- p->stats.msg_sent_open + p->stats.msg_sent_notification +
- p->stats.msg_sent_update + p->stats.msg_sent_keepalive +
- p->stats.msg_sent_rrefresh,
-@@ -673,14 +798,16 @@ print_neighbor_msgstats(struct peer *p)
- p->stats.msg_rcvd_rrefresh);
- printf(" Update statistics:\n");
- printf(" %-15s %-10s %-10s\n", "", "Sent", "Received");
-- printf(" %-15s %10llu %10llu\n", "Updates",
-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Updates",
- p->stats.prefix_sent_update, p->stats.prefix_rcvd_update);
-- printf(" %-15s %10llu %10llu\n", "Withdraws",
-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Withdraws",
- p->stats.prefix_sent_withdraw, p->stats.prefix_rcvd_withdraw);
-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "End-of-Rib",
-+ p->stats.prefix_sent_eor, p->stats.prefix_rcvd_eor);
- }
-
- void
--print_timer(const char *name, timer_t d)
-+print_timer(const char *name, time_t d)
- {
- printf(" %-20s ", name);
-
-@@ -745,6 +872,12 @@ show_fib_head(void)
- }
-
- void
-+show_fib_tables_head(void)
-+{
-+ printf("%-5s %-20s %-8s\n", "Table", "Description", "State");
-+}
-+
-+void
- show_network_head(void)
- {
- printf("flags: S = Static\n");
-@@ -788,56 +921,44 @@ show_fib_flags(u_int16_t flags)
- int
- show_fib_msg(struct imsg *imsg)
- {
-- struct kroute *k;
-- struct kroute6 *k6;
-+ struct kroute_full *kf;
-+ struct ktable *kt;
- char *p;
-
- switch (imsg->hdr.type) {
- case IMSG_CTL_KROUTE:
- case IMSG_CTL_SHOW_NETWORK:
-- if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
-+ if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(*kf))
- errx(1, "wrong imsg len");
-- k = imsg->data;
-+ kf = imsg->data;
-
-- show_fib_flags(k->flags);
-+ show_fib_flags(kf->flags);
-
-- if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), k->prefixlen) ==
-- -1)
-+ if (asprintf(&p, "%s/%u", log_addr(&kf->prefix),
-+ kf->prefixlen) == -1)
- err(1, NULL);
-- printf("%4i %-20s ", k->priority, p);
-+ printf("%4i %-20s ", kf->priority, p);
- free(p);
-
-- if (k->nexthop.s_addr)
-- printf("%s", inet_ntoa(k->nexthop));
-- else if (k->flags & F_CONNECTED)
-- printf("link#%u", k->ifindex);
-+ if (kf->flags & F_CONNECTED)
-+ printf("link#%u", kf->ifindex);
-+ else
-+ printf("%s", log_addr(&kf->nexthop));
- printf("\n");
-
- break;
-- case IMSG_CTL_KROUTE6:
-- case IMSG_CTL_SHOW_NETWORK6:
-- if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute6))
-+ case IMSG_CTL_SHOW_FIB_TABLES:
-+ if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(*kt))
- errx(1, "wrong imsg len");
-- k6 = imsg->data;
--
-- show_fib_flags(k6->flags);
-+ kt = imsg->data;
-
-- if (asprintf(&p, "%s/%u", log_in6addr(&k6->prefix),
-- k6->prefixlen) == -1)
-- err(1, NULL);
-- printf("%4i %-20s ", k6->priority, p);
-- free(p);
--
-- if (!IN6_IS_ADDR_UNSPECIFIED(&k6->nexthop))
-- printf("%s", log_in6addr(&k6->nexthop));
-- else if (k6->flags & F_CONNECTED)
-- printf("link#%u", k6->ifindex);
-- printf("\n");
-+ printf("%5i %-20s %-8s%s\n", kt->rtableid, kt->descr,
-+ kt->fib_sync ? "coupled" : "decoupled",
-+ kt->fib_sync != kt->fib_conf ? "*" : "");
-
- break;
- case IMSG_CTL_END:
- return (1);
-- break;
- default:
- break;
- }
-@@ -848,35 +969,70 @@ show_fib_msg(struct imsg *imsg)
- void
- show_nexthop_head(void)
- {
-- printf("%-20s %-10s\n", "Nexthop", "State");
-+ printf("Flags: * = nexthop valid\n");
-+ printf("\n %-15s %-19s%-4s %-15s %-20s\n", "Nexthop", "Route",
-+ "Prio", "Gateway", "Iface");
- }
-
- int
- show_nexthop_msg(struct imsg *imsg)
- {
- struct ctl_show_nexthop *p;
-- int ifms_type;
-+ struct kroute *k;
-+ struct kroute6 *k6;
-+ char *s;
-
- switch (imsg->hdr.type) {
- case IMSG_CTL_SHOW_NEXTHOP:
- p = imsg->data;
-- printf("%-20s %-10s", log_addr(&p->addr),
-- p->valid ? "valid" : "invalid");
-+ printf("%s %-15s ", p->valid ? "*" : " ", log_addr(&p->addr));
-+ if (!p->krvalid) {
-+ printf("\n");
-+ return (0);
-+ }
-+ switch (p->addr.aid) {
-+ case AID_INET:
-+ k = &p->kr.kr4;
-+ if (asprintf(&s, "%s/%u", inet_ntoa(k->prefix),
-+ k->prefixlen) == -1)
-+ err(1, NULL);
-+ printf("%-20s", s);
-+ free(s);
-+ printf("%3i %-15s ", k->priority,
-+ k->flags & F_CONNECTED ? "connected" :
-+ inet_ntoa(k->nexthop));
-+ break;
-+ case AID_INET6:
-+ k6 = &p->kr.kr6;
-+ if (asprintf(&s, "%s/%u", log_in6addr(&k6->prefix),
-+ k6->prefixlen) == -1)
-+ err(1, NULL);
-+ printf("%-20s", s);
-+ free(s);
-+ printf("%3i %-15s ", k6->priority,
-+ k6->flags & F_CONNECTED ? "connected" :
-+ log_in6addr(&k6->nexthop));
-+ break;
-+ default:
-+ printf("unknown address family\n");
-+ return (0);
-+ }
- if (p->kif.ifname[0]) {
-- printf("%-8s", p->kif.ifname);
-- if (p->kif.flags & IFF_UP) {
-- printf("UP");
-- ifms_type = ift2ifm(p->kif.media_type);
-- if (ifms_type != 0)
-- printf(", %s, %s",
-- get_media_descr(ifms_type),
-- get_linkstate(ifms_type,
-- p->kif.link_state));
-- if (p->kif.baudrate) {
-- printf(", ");
-- print_baudrate(p->kif.baudrate);
-- }
-- }
-+ char *s1;
-+ if (p->kif.baudrate) {
-+ if (asprintf(&s1, ", %s",
-+ get_baudrate(p->kif.baudrate,
-+ "bps")) == -1)
-+ err(1, NULL);
-+ } else if (asprintf(&s1, ", %s", get_linkstate(
-+ p->kif.media_type, p->kif.link_state)) == -1)
-+ err(1, NULL);
-+ if (asprintf(&s, "%s (%s%s)", p->kif.ifname,
-+ p->kif.flags & IFF_UP ? "UP" : "DOWN", s1) == -1)
-+ err(1, NULL);
-+ printf("%-15s", s);
-+ free(s1);
-+ free(s);
- }
- printf("\n");
- break;
-@@ -898,9 +1054,8 @@ show_interface_head(void)
- "Link state");
- }
-
--const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST;
--const struct ifmedia_status_description
-- ifm_status_descriptions[] = IFM_STATUS_DESCRIPTIONS;
-+const struct if_status_description
-+ if_status_descriptions[] = LINK_STATE_DESCRIPTIONS;
- const struct ifmedia_description
- ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
-
-@@ -936,36 +1091,36 @@ get_media_descr(int media_type)
- const char *
- get_linkstate(int media_type, int link_state)
- {
-- const struct ifmedia_status_description *p;
-- int i;
--
-- if (link_state == LINK_STATE_UNKNOWN)
-- return ("unknown");
--
-- for (i = 0; ifm_status_valid_list[i] != 0; i++)
-- for (p = ifm_status_descriptions; p->ifms_valid != 0; p++) {
-- if (p->ifms_type != media_type ||
-- p->ifms_valid != ifm_status_valid_list[i])
-- continue;
-- if (LINK_STATE_IS_UP(link_state))
-- return (p->ifms_string[1]);
-- return (p->ifms_string[0]);
-- }
-+ const struct if_status_description *p;
-+ static char buf[8];
-
-- return ("unknown link state");
-+ for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
-+ if (LINK_STATE_DESC_MATCH(p, media_type, link_state))
-+ return (p->ifs_string);
-+ }
-+ snprintf(buf, sizeof(buf), "[#%d]", link_state);
-+ return (buf);
- }
-
--void
--print_baudrate(u_int64_t baudrate)
-+const char *
-+get_baudrate(u_int64_t baudrate, char *unit)
- {
-+ static char bbuf[16];
-+
- if (baudrate > IF_Gbps(1))
-- printf("%llu GBit/s", baudrate / IF_Gbps(1));
-+ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " G%s",
-+ baudrate / IF_Gbps(1), unit);
- else if (baudrate > IF_Mbps(1))
-- printf("%llu MBit/s", baudrate / IF_Mbps(1));
-+ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " M%s",
-+ baudrate / IF_Mbps(1), unit);
- else if (baudrate > IF_Kbps(1))
-- printf("%llu KBit/s", baudrate / IF_Kbps(1));
-+ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " K%s",
-+ baudrate / IF_Kbps(1), unit);
- else
-- printf("%llu Bit/s", baudrate);
-+ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " %s",
-+ baudrate, unit);
-+
-+ return (bbuf);
- }
-
- int
-@@ -982,17 +1137,12 @@ show_interface_msg(struct imsg *imsg)
- printf("%-15s", k->flags & IFF_UP ? "UP" : "");
-
- if ((ifms_type = ift2ifm(k->media_type)) != 0)
-- printf("%s, %s", get_media_descr(ifms_type),
-- get_linkstate(ifms_type, k->link_state));
-- else if (k->link_state == LINK_STATE_UNKNOWN)
-- printf("unknown");
-- else
-- printf("link state %u", k->link_state);
-+ printf("%s, ", get_media_descr(ifms_type));
-
-- if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) {
-- printf(", ");
-- print_baudrate(k->baudrate);
-- }
-+ printf("%s", get_linkstate(k->media_type, k->link_state));
-+
-+ if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0)
-+ printf(", %s", get_baudrate(k->baudrate, "Bit/s"));
- printf("\n");
- break;
- case IMSG_CTL_END:
-@@ -1008,10 +1158,10 @@ show_interface_msg(struct imsg *imsg)
- void
- show_rib_summary_head(void)
- {
-- printf(
-- "flags: * = Valid, > = Selected, I = via IBGP, A = Announced\n");
-+ printf("flags: * = Valid, > = Selected, I = via IBGP, A = Announced, "
-+ "S = Stale\n");
- printf("origin: i = IGP, e = EGP, ? = Incomplete\n\n");
-- printf("%-5s %-20s%-15s %5s %5s %s\n", "flags", "destination",
-+ printf("%-5s %-20s %-15s %5s %5s %s\n", "flags", "destination",
- "gateway", "lpref", "med", "aspath origin");
- }
-
-@@ -1049,26 +1199,30 @@ print_flags(u_int8_t flags, int sum)
- char *p = flagstr;
-
- if (sum) {
-- if (flags & F_RIB_ANNOUNCE)
-+ if (flags & F_PREF_ANNOUNCE)
- *p++ = 'A';
-- if (flags & F_RIB_INTERNAL)
-+ if (flags & F_PREF_INTERNAL)
- *p++ = 'I';
-- if (flags & F_RIB_ELIGIBLE)
-+ if (flags & F_PREF_STALE)
-+ *p++ = 'S';
-+ if (flags & F_PREF_ELIGIBLE)
- *p++ = '*';
-- if (flags & F_RIB_ACTIVE)
-+ if (flags & F_PREF_ACTIVE)
- *p++ = '>';
- *p = '\0';
- printf("%-5s ", flagstr);
- } else {
-- if (flags & F_RIB_INTERNAL)
-+ if (flags & F_PREF_INTERNAL)
- printf("internal");
- else
- printf("external");
-- if (flags & F_RIB_ELIGIBLE)
-+ if (flags & F_PREF_STALE)
-+ printf(", stale");
-+ if (flags & F_PREF_ELIGIBLE)
- printf(", valid");
-- if (flags & F_RIB_ACTIVE)
-+ if (flags & F_PREF_ACTIVE)
- printf(", best");
-- if (flags & F_RIB_ANNOUNCE)
-+ if (flags & F_PREF_ANNOUNCE)
- printf(", announced");
- }
- }
-@@ -1077,27 +1231,14 @@ int
- show_rib_summary_msg(struct imsg *imsg)
- {
- struct ctl_show_rib rib;
-- char *aspath;
- u_char *asdata;
-
- switch (imsg->hdr.type) {
- case IMSG_CTL_SHOW_RIB:
- memcpy(&rib, imsg->data, sizeof(rib));
--
-- print_prefix(&rib.prefix, rib.prefixlen, rib.flags);
-- printf("%-15s ", log_addr(&rib.exit_nexthop));
--
-- printf(" %5u %5u ", rib.local_pref, rib.med);
--
- asdata = imsg->data;
- asdata += sizeof(struct ctl_show_rib);
-- if (aspath_asprint(&aspath, asdata, rib.aspath_len) == -1)
-- err(1, NULL);
-- if (strlen(aspath) > 0)
-- printf("%s ", aspath);
-- free(aspath);
--
-- printf("%s\n", print_origin(rib.origin, 1));
-+ show_rib_brief(&rib, asdata);
- break;
- case IMSG_CTL_END:
- return (1);
-@@ -1112,108 +1253,21 @@ int
- show_rib_detail_msg(struct imsg *imsg, int nodescr)
- {
- struct ctl_show_rib rib;
-- struct in_addr id;
-- char *aspath, *s;
-- u_char *data;
-- u_int32_t as;
-- u_int16_t ilen, alen, ioff;
-- u_int8_t flags, type;
-- time_t now;
-+ u_char *asdata;
-+ u_int16_t ilen;
-
- switch (imsg->hdr.type) {
- case IMSG_CTL_SHOW_RIB:
- memcpy(&rib, imsg->data, sizeof(rib));
--
-- printf("\nBGP routing table entry for %s/%u\n",
-- log_addr(&rib.prefix), rib.prefixlen);
--
-- data = imsg->data;
-- data += sizeof(struct ctl_show_rib);
-- if (aspath_asprint(&aspath, data, rib.aspath_len) == -1)
-- err(1, NULL);
-- if (strlen(aspath) > 0)
-- printf(" %s\n", aspath);
-- free(aspath);
--
-- s = fmt_peer(rib.descr, &rib.remote_addr, -1, nodescr);
-- printf(" Nexthop %s ", log_addr(&rib.exit_nexthop));
-- printf("(via %s) from %s (", log_addr(&rib.true_nexthop), s);
-- free(s);
-- id.s_addr = htonl(rib.remote_id);
-- printf("%s)\n", inet_ntoa(id));
--
-- printf(" Origin %s, metric %u, localpref %u, ",
-- print_origin(rib.origin, 0), rib.med, rib.local_pref);
-- print_flags(rib.flags, 0);
--
-- now = time(NULL);
-- if (now > rib.lastchange)
-- now -= rib.lastchange;
-- else
-- now = 0;
--
-- printf("\n Last update: %s ago\n",
-- fmt_timeframe_core(now));
-+ asdata = imsg->data;
-+ asdata += sizeof(struct ctl_show_rib);
-+ show_rib_detail(&rib, asdata, nodescr);
- break;
- case IMSG_CTL_SHOW_RIB_ATTR:
- ilen = imsg->hdr.len - IMSG_HEADER_SIZE;
- if (ilen < 3)
- errx(1, "bad IMSG_CTL_SHOW_RIB_ATTR received");
-- data = imsg->data;
-- flags = data[0];
-- type = data[1];
--
-- /* get the attribute length */
-- if (flags & ATTR_EXTLEN) {
-- if (ilen < 4)
-- errx(1, "bad IMSG_CTL_SHOW_RIB_ATTR received");
-- memcpy(&alen, data+2, sizeof(u_int16_t));
-- alen = ntohs(alen);
-- data += 4;
-- ilen -= 4;
-- } else {
-- alen = data[2];
-- data += 3;
-- ilen -= 3;
-- }
-- /* bad imsg len how can that happen!? */
-- if (alen != ilen)
-- errx(1, "bad IMSG_CTL_SHOW_RIB_ATTR received");
--
-- switch (type) {
-- case ATTR_COMMUNITIES:
-- printf(" Communities: ");
-- show_community(data, alen);
-- printf("\n");
-- break;
-- case ATTR_AGGREGATOR:
-- memcpy(&as, data, sizeof(as));
-- memcpy(&id, data + sizeof(as), sizeof(id));
-- printf(" Aggregator: %s [%s]\n",
-- log_as(htonl(as)), inet_ntoa(id));
-- break;
-- case ATTR_ORIGINATOR_ID:
-- memcpy(&id, data, sizeof(id));
-- printf(" Originator Id: %s\n", inet_ntoa(id));
-- break;
-- case ATTR_CLUSTER_LIST:
-- printf(" Cluster ID List:");
-- for (ioff = 0; ioff + sizeof(id) <= ilen;
-- ioff += sizeof(id)) {
-- memcpy(&id, data + ioff, sizeof(id));
-- printf(" %s", inet_ntoa(id));
-- }
-- printf("\n");
-- break;
-- case ATTR_EXT_COMMUNITIES:
-- printf(" Ext. communities: ");
-- show_ext_community(data, alen);
-- printf("\n");
-- break;
-- default:
-- /* ignore unknown attributes */
-- break;
-- }
-+ show_attr(imsg->data, ilen);
- break;
- case IMSG_CTL_END:
- printf("\n");
-@@ -1225,67 +1279,128 @@ show_rib_detail_msg(struct imsg *imsg, i
- return (0);
- }
-
--char *
--fmt_mem(int64_t num)
-+void
-+show_rib_brief(struct ctl_show_rib *r, u_char *asdata)
- {
-- static char buf[16];
-+ char *aspath;
-
-- if (fmt_scaled(num, buf) == -1)
-- snprintf(buf, sizeof(buf), "%lldB", (long long)num);
-+ print_prefix(&r->prefix, r->prefixlen, r->flags);
-+ printf(" %-15s ", log_addr(&r->exit_nexthop));
-+ printf(" %5u %5u ", r->local_pref, r->med);
-
-- return (buf);
-+ if (aspath_asprint(&aspath, asdata, r->aspath_len) == -1)
-+ err(1, NULL);
-+ if (strlen(aspath) > 0)
-+ printf("%s ", aspath);
-+ free(aspath);
-+
-+ printf("%s\n", print_origin(r->origin, 1));
- }
-
--int
--show_rib_memory_msg(struct imsg *imsg)
-+void
-+show_rib_detail(struct ctl_show_rib *r, u_char *asdata, int nodescr)
- {
-- struct rde_memstats stats;
-+ struct in_addr id;
-+ char *aspath, *s;
-+ time_t now;
-
-- switch (imsg->hdr.type) {
-- case IMSG_CTL_SHOW_RIB_MEM:
-- memcpy(&stats, imsg->data, sizeof(stats));
-- printf("RDE memory statistics\n");
-- printf("%10lld IPv4 network entries using %s of memory\n",
-- (long long)stats.pt4_cnt, fmt_mem(stats.pt4_cnt *
-- sizeof(struct pt_entry4)));
-- if (stats.pt6_cnt != 0)
-- printf("%10lld IPv6 network entries using "
-- "%s of memory\n", (long long)stats.pt6_cnt,
-- fmt_mem(stats.pt6_cnt * sizeof(struct pt_entry6)));
-- printf("%10lld rib entries using %s of memory\n",
-- (long long)stats.rib_cnt, fmt_mem(stats.rib_cnt *
-- sizeof(struct rib_entry)));
-- printf("%10lld prefix entries using %s of memory\n",
-- (long long)stats.prefix_cnt, fmt_mem(stats.prefix_cnt *
-- sizeof(struct prefix)));
-- printf("%10lld BGP path attribute entries using %s of memory\n",
-- (long long)stats.path_cnt, fmt_mem(stats.path_cnt *
-- sizeof(struct rde_aspath)));
-- printf("%10lld BGP AS-PATH attribute entries using "
-- "%s of memory,\n\t and holding %lld references\n",
-- (long long)stats.aspath_cnt, fmt_mem(stats.aspath_size),
-- (long long)stats.aspath_refs);
-- printf("%10lld BGP attributes entries using %s of memory\n",
-- (long long)stats.attr_cnt, fmt_mem(stats.attr_cnt *
-- sizeof(struct attr)));
-- printf("\t and holding %lld references\n",
-- (long long)stats.attr_refs);
-- printf("%10lld BGP attributes using %s of memory\n",
-- (long long)stats.attr_dcnt, fmt_mem(stats.attr_data));
-- printf("RIB using %s of memory\n", fmt_mem(
-- stats.pt4_cnt * sizeof(struct pt_entry4) +
-- stats.pt6_cnt * sizeof(struct pt_entry6) +
-- stats.prefix_cnt * sizeof(struct prefix) +
-- stats.rib_cnt * sizeof(struct rib_entry) +
-- stats.path_cnt * sizeof(struct rde_aspath) +
-- stats.aspath_size + stats.attr_cnt * sizeof(struct attr) +
-- stats.attr_data));
-+ printf("\nBGP routing table entry for %s/%u\n",
-+ log_addr(&r->prefix), r->prefixlen);
-+
-+ if (aspath_asprint(&aspath, asdata, r->aspath_len) == -1)
-+ err(1, NULL);
-+ if (strlen(aspath) > 0)
-+ printf(" %s\n", aspath);
-+ free(aspath);
-+
-+ s = fmt_peer(r->descr, &r->remote_addr, -1, nodescr);
-+ printf(" Nexthop %s ", log_addr(&r->exit_nexthop));
-+ printf("(via %s) from %s (", log_addr(&r->true_nexthop), s);
-+ free(s);
-+ id.s_addr = htonl(r->remote_id);
-+ printf("%s)\n", inet_ntoa(id));
-+
-+ printf(" Origin %s, metric %u, localpref %u, weight %u, ",
-+ print_origin(r->origin, 0), r->med, r->local_pref, r->weight);
-+ print_flags(r->flags, 0);
-+
-+ now = time(NULL);
-+ if (now > r->lastchange)
-+ now -= r->lastchange;
-+ else
-+ now = 0;
-+
-+ printf("\n Last update: %s ago\n", fmt_timeframe_core(now));
-+}
-+
-+void
-+show_attr(void *b, u_int16_t len)
-+{
-+ char *data = b;
-+ struct in_addr id;
-+ u_int32_t as;
-+ u_int16_t alen, ioff;
-+ u_int8_t flags, type;
-+
-+ data = b;
-+ if (len < 3)
-+ errx(1, "show_attr: too short bgp attr");
-+
-+ flags = data[0];
-+ type = data[1];
-+
-+ /* get the attribute length */
-+ if (flags & ATTR_EXTLEN) {
-+ if (len < 4)
-+ errx(1, "show_attr: too short bgp attr");
-+ memcpy(&alen, data+2, sizeof(u_int16_t));
-+ alen = ntohs(alen);
-+ data += 4;
-+ len -= 4;
-+ } else {
-+ alen = data[2];
-+ data += 3;
-+ len -= 3;
-+ }
-+
-+ /* bad imsg len how can that happen!? */
-+ if (alen > len)
-+ errx(1, "show_attr: bad length");
-+
-+ switch (type) {
-+ case ATTR_COMMUNITIES:
-+ printf(" Communities: ");
-+ show_community(data, alen);
-+ printf("\n");
-+ break;
-+ case ATTR_AGGREGATOR:
-+ memcpy(&as, data, sizeof(as));
-+ memcpy(&id, data + sizeof(as), sizeof(id));
-+ printf(" Aggregator: %s [%s]\n",
-+ log_as(ntohl(as)), inet_ntoa(id));
-+ break;
-+ case ATTR_ORIGINATOR_ID:
-+ memcpy(&id, data, sizeof(id));
-+ printf(" Originator Id: %s\n", inet_ntoa(id));
-+ break;
-+ case ATTR_CLUSTER_LIST:
-+ printf(" Cluster ID List:");
-+ for (ioff = 0; ioff + sizeof(id) <= alen;
-+ ioff += sizeof(id)) {
-+ memcpy(&id, data + ioff, sizeof(id));
-+ printf(" %s", inet_ntoa(id));
-+ }
-+ printf("\n");
-+ break;
-+ case ATTR_EXT_COMMUNITIES:
-+ printf(" Ext. communities: ");
-+ show_ext_community(data, alen);
-+ printf("\n");
- break;
- default:
-+ /* ignore unknown attributes */
- break;
- }
--
-- return (1);
- }
-
- void
-@@ -1328,30 +1443,6 @@ show_community(u_char *data, u_int16_t l
- }
- }
-
--const char *
--get_ext_subtype(u_int8_t type)
--{
-- static char etype[6];
--
-- switch (type) {
-- 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), "[%i]", (int)type);
-- return etype;
-- }
--}
--
- void
- show_ext_community(u_char *data, u_int16_t len)
- {
-@@ -1372,34 +1463,101 @@ show_ext_community(u_char *data, u_int16
- case EXT_COMMUNITY_TWO_AS:
- memcpy(&as2, data + i + 2, sizeof(as2));
- memcpy(&u32, data + i + 4, sizeof(u32));
-- printf("%s %hu:%u", get_ext_subtype(subtype), as2, u32);
-+ printf("%s %s:%u", log_ext_subtype(subtype),
-+ log_as(ntohs(as2)), ntohl(u32));
- break;
- case EXT_COMMUNITY_IPV4:
- memcpy(&ip, data + i + 2, sizeof(ip));
- memcpy(&u16, data + i + 6, sizeof(u16));
-- printf("%s %s:%hu", get_ext_subtype(subtype),
-- inet_ntoa(ip), u16);
-+ printf("%s %s:%hu", log_ext_subtype(subtype),
-+ inet_ntoa(ip), ntohs(u16));
- break;
- case EXT_COMMUNITY_FOUR_AS:
- memcpy(&as4, data + i + 2, sizeof(as4));
- memcpy(&u16, data + i + 6, sizeof(u16));
-- printf("%s %s:%hu", get_ext_subtype(subtype),
-- log_as(as4), u16);
-+ printf("%s %s:%hu", log_ext_subtype(subtype),
-+ log_as(ntohl(as4)), ntohs(u16));
- break;
- case EXT_COMMUNITY_OPAQUE:
- memcpy(&ext, data + i, sizeof(ext));
- ext = betoh64(ext) & 0xffffffffffffLL;
-- printf("%s 0x%llx", get_ext_subtype(subtype), ext);
-+ printf("%s 0x%" PRIx64, log_ext_subtype(subtype), ext);
- break;
- default:
- memcpy(&ext, data + i, sizeof(ext));
-- printf("0x%llx", betoh64(ext));
-+ printf("0x%" PRIx64, betoh64(ext));
- }
- if (i + 8 < len)
- printf(", ");
- }
- }
-
-+char *
-+fmt_mem(int64_t num)
-+{
-+ static char buf[16];
-+
-+ if (fmt_scaled(num, buf) == -1)
-+ snprintf(buf, sizeof(buf), "%lldB", (long long)num);
-+
-+ return (buf);
-+}
-+
-+size_t pt_sizes[AID_MAX] = AID_PTSIZE;
-+
-+int
-+show_rib_memory_msg(struct imsg *imsg)
-+{
-+ struct rde_memstats stats;
-+ size_t pts = 0;
-+ int i;
-+
-+ switch (imsg->hdr.type) {
-+ case IMSG_CTL_SHOW_RIB_MEM:
-+ memcpy(&stats, imsg->data, sizeof(stats));
-+ printf("RDE memory statistics\n");
-+ for (i = 0; i < AID_MAX; i++) {
-+ if (stats.pt_cnt[i] == 0)
-+ continue;
-+ pts += stats.pt_cnt[i] * pt_sizes[i];
-+ printf("%10lld %s network entries using %s of memory\n",
-+ (long long)stats.pt_cnt[i], aid_vals[i].name,
-+ fmt_mem(stats.pt_cnt[i] * pt_sizes[i]));
-+ }
-+ printf("%10lld rib entries using %s of memory\n",
-+ (long long)stats.rib_cnt, fmt_mem(stats.rib_cnt *
-+ sizeof(struct rib_entry)));
-+ printf("%10lld prefix entries using %s of memory\n",
-+ (long long)stats.prefix_cnt, fmt_mem(stats.prefix_cnt *
-+ sizeof(struct prefix)));
-+ printf("%10lld BGP path attribute entries using %s of memory\n",
-+ (long long)stats.path_cnt, fmt_mem(stats.path_cnt *
-+ sizeof(struct rde_aspath)));
-+ printf("%10lld BGP AS-PATH attribute entries using "
-+ "%s of memory,\n\t and holding %lld references\n",
-+ (long long)stats.aspath_cnt, fmt_mem(stats.aspath_size),
-+ (long long)stats.aspath_refs);
-+ printf("%10lld BGP attributes entries using %s of memory\n",
-+ (long long)stats.attr_cnt, fmt_mem(stats.attr_cnt *
-+ sizeof(struct attr)));
-+ printf("\t and holding %lld references\n",
-+ (long long)stats.attr_refs);
-+ printf("%10lld BGP attributes using %s of memory\n",
-+ (long long)stats.attr_dcnt, fmt_mem(stats.attr_data));
-+ printf("RIB using %s of memory\n", fmt_mem(pts +
-+ stats.prefix_cnt * sizeof(struct prefix) +
-+ stats.rib_cnt * sizeof(struct rib_entry) +
-+ stats.path_cnt * sizeof(struct rde_aspath) +
-+ stats.aspath_size + stats.attr_cnt * sizeof(struct attr) +
-+ stats.attr_data));
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ return (1);
-+}
-+
- void
- send_filterset(struct imsgbuf *i, struct filter_set_head *set)
- {
-@@ -1469,6 +1627,183 @@ show_result(struct imsg *imsg)
- return (1);
- }
-
-+void
-+show_mrt_dump(struct mrt_rib *mr, struct mrt_peer *mp, void *arg)
-+{
-+ struct ctl_show_rib ctl;
-+ struct ctl_show_rib_request *req = arg;
-+ struct mrt_rib_entry *mre;
-+ u_int16_t i, j;
-+
-+ for (i = 0; i < mr->nentries; i++) {
-+ mre = &mr->entries[i];
-+ bzero(&ctl, sizeof(ctl));
-+ mrt_to_bgpd_addr(&mr->prefix, &ctl.prefix);
-+ ctl.prefixlen = mr->prefixlen;
-+ ctl.lastchange = mre->originated;
-+ mrt_to_bgpd_addr(&mre->nexthop, &ctl.true_nexthop);
-+ mrt_to_bgpd_addr(&mre->nexthop, &ctl.exit_nexthop);
-+ ctl.origin = mre->origin;
-+ ctl.local_pref = mre->local_pref;
-+ ctl.med = mre->med;
-+ /* weight is not part of the mrt dump so it can't be set */
-+ ctl.aspath_len = mre->aspath_len;
-+
-+ if (mre->peer_idx < mp->npeers) {
-+ mrt_to_bgpd_addr(&mp->peers[mre->peer_idx].addr,
-+ &ctl.remote_addr);
-+ ctl.remote_id = mp->peers[mre->peer_idx].bgp_id;
-+ }
-+
-+ /* filter by neighbor */
-+ if (req->neighbor.addr.aid != AID_UNSPEC &&
-+ memcmp(&req->neighbor.addr, &ctl.remote_addr,
-+ sizeof(ctl.remote_addr)) != 0)
-+ continue;
-+ /* filter by AF */
-+ if (req->aid && req->aid != ctl.prefix.aid)
-+ return;
-+ /* filter by prefix */
-+ if (req->prefix.aid != AID_UNSPEC) {
-+ if (!prefix_compare(&req->prefix, &ctl.prefix,
-+ req->prefixlen)) {
-+ if (req->flags & F_LONGER) {
-+ if (req->prefixlen > ctl.prefixlen)
-+ return;
-+ } else if (req->prefixlen != ctl.prefixlen)
-+ return;
-+ } else
-+ return;
-+ }
-+ /* filter by AS */
-+ if (req->as.type != AS_NONE &&
-+ !aspath_match(mre->aspath, mre->aspath_len,
-+ req->as.type, req->as.as))
-+ continue;
-+
-+ if (req->flags & F_CTL_DETAIL) {
-+ show_rib_detail(&ctl, mre->aspath, 1);
-+ for (j = 0; j < mre->nattrs; j++)
-+ show_attr(mre->attrs[j].attr,
-+ mre->attrs[j].attr_len);
-+ } else
-+ show_rib_brief(&ctl, mre->aspath);
-+ }
-+}
-+
-+void
-+network_mrt_dump(struct mrt_rib *mr, struct mrt_peer *mp, void *arg)
-+{
-+ struct ctl_show_rib ctl;
-+ struct network_config net;
-+ struct ctl_show_rib_request *req = arg;
-+ struct mrt_rib_entry *mre;
-+ struct ibuf *msg;
-+ u_int16_t i, j;
-+
-+ for (i = 0; i < mr->nentries; i++) {
-+ mre = &mr->entries[i];
-+ bzero(&ctl, sizeof(ctl));
-+ mrt_to_bgpd_addr(&mr->prefix, &ctl.prefix);
-+ ctl.prefixlen = mr->prefixlen;
-+ ctl.lastchange = mre->originated;
-+ mrt_to_bgpd_addr(&mre->nexthop, &ctl.true_nexthop);
-+ mrt_to_bgpd_addr(&mre->nexthop, &ctl.exit_nexthop);
-+ ctl.origin = mre->origin;
-+ ctl.local_pref = mre->local_pref;
-+ ctl.med = mre->med;
-+ ctl.aspath_len = mre->aspath_len;
-+
-+ if (mre->peer_idx < mp->npeers) {
-+ mrt_to_bgpd_addr(&mp->peers[mre->peer_idx].addr,
-+ &ctl.remote_addr);
-+ ctl.remote_id = mp->peers[mre->peer_idx].bgp_id;
-+ }
-+
-+ /* filter by neighbor */
-+ if (req->neighbor.addr.aid != AID_UNSPEC &&
-+ memcmp(&req->neighbor.addr, &ctl.remote_addr,
-+ sizeof(ctl.remote_addr)) != 0)
-+ continue;
-+ /* filter by AF */
-+ if (req->aid && req->aid != ctl.prefix.aid)
-+ return;
-+ /* filter by prefix */
-+ if (req->prefix.aid != AID_UNSPEC) {
-+ if (!prefix_compare(&req->prefix, &ctl.prefix,
-+ req->prefixlen)) {
-+ if (req->flags & F_LONGER) {
-+ if (req->prefixlen > ctl.prefixlen)
-+ return;
-+ } else if (req->prefixlen != ctl.prefixlen)
-+ return;
-+ } else
-+ return;
-+ }
-+ /* filter by AS */
-+ if (req->as.type != AS_NONE &&
-+ !aspath_match(mre->aspath, mre->aspath_len,
-+ req->as.type, req->as.as))
-+ continue;
-+
-+ bzero(&net, sizeof(net));
-+ memcpy(&net.prefix, &ctl.prefix, sizeof(net.prefix));
-+ net.prefixlen = ctl.prefixlen;
-+ net.type = NETWORK_MRTCLONE;
-+ /* XXX rtableid */
-+
-+ imsg_compose(ibuf, IMSG_NETWORK_ADD, 0, 0, -1,
-+ &net, sizeof(net));
-+ if ((msg = imsg_create(ibuf, IMSG_NETWORK_ASPATH,
-+ 0, 0, sizeof(ctl) + mre->aspath_len)) == NULL)
-+ errx(1, "imsg_create failure");
-+ if (imsg_add(msg, &ctl, sizeof(ctl)) == -1 ||
-+ imsg_add(msg, mre->aspath, mre->aspath_len) == -1)
-+ errx(1, "imsg_add failure");
-+ imsg_close(ibuf, msg);
-+ for (j = 0; j < mre->nattrs; j++)
-+ imsg_compose(ibuf, IMSG_NETWORK_ATTR, 0, 0, -1,
-+ mre->attrs[j].attr, mre->attrs[j].attr_len);
-+ imsg_compose(ibuf, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0);
-+
-+ while (ibuf->w.queued) {
-+ if (msgbuf_write(&ibuf->w) < 0)
-+ err(1, "write error");
-+ }
-+ }
-+}
-+
-+void
-+show_mrt_state(struct mrt_bgp_state *ms, void *arg)
-+{
-+ printf("show_mrt_state\n");
-+}
-+
-+void
-+show_mrt_msg(struct mrt_bgp_msg *mm, void *arg)
-+{
-+ printf("show_mrt_msg\n");
-+}
-+
-+void
-+mrt_to_bgpd_addr(union mrt_addr *ma, struct bgpd_addr *ba)
-+{
-+ switch (ma->sa.sa_family) {
-+ case AF_INET:
-+ case AF_INET6:
-+ sa2addr(&ma->sa, ba);
-+ break;
-+ case AF_VPNv4:
-+ bzero(ba, sizeof(*ba));
-+ ba->aid = AID_VPN_IPv4;
-+ ba->vpn4.rd = ma->svpn4.sv_rd;
-+ ba->vpn4.addr.s_addr = ma->svpn4.sv_addr.s_addr;
-+ memcpy(ba->vpn4.labelstack, ma->svpn4.sv_label,
-+ sizeof(ba->vpn4.labelstack));
-+ break;
-+ }
-+}
-+
- /* following functions are necessary for imsg framework */
- void
- log_warnx(const char *emsg, ...)
-@@ -1495,3 +1830,9 @@ fatal(const char *emsg)
- {
- err(1, emsg);
- }
-+
-+void
-+fatalx(const char *emsg)
-+{
-+ errx(1, emsg);
-+}
diff --git a/net/openbgpd/files/patch-bgpctl_irr_asset.c b/net/openbgpd/files/patch-bgpctl_irr_asset.c
deleted file mode 100644
index cf0e4a449c66..000000000000
--- a/net/openbgpd/files/patch-bgpctl_irr_asset.c
+++ /dev/null
@@ -1,14 +0,0 @@
-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>
diff --git a/net/openbgpd/files/patch-bgpctl_irr_output.c b/net/openbgpd/files/patch-bgpctl_irr_output.c
deleted file mode 100644
index b611216c1928..000000000000
--- a/net/openbgpd/files/patch-bgpctl_irr_output.c
+++ /dev/null
@@ -1,14 +0,0 @@
-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>
diff --git a/net/openbgpd/files/patch-bgpctl_irr_parser.c b/net/openbgpd/files/patch-bgpctl_irr_parser.c
deleted file mode 100644
index 2e445ea37809..000000000000
--- a/net/openbgpd/files/patch-bgpctl_irr_parser.c
+++ /dev/null
@@ -1,48 +0,0 @@
-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));
diff --git a/net/openbgpd/files/patch-bgpctl_irr_prefix.c b/net/openbgpd/files/patch-bgpctl_irr_prefix.c
deleted file mode 100644
index 4c97de2a4c7d..000000000000
--- a/net/openbgpd/files/patch-bgpctl_irr_prefix.c
+++ /dev/null
@@ -1,157 +0,0 @@
-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);
-
diff --git a/net/openbgpd/files/patch-bgpctl_irrfilter.c b/net/openbgpd/files/patch-bgpctl_irrfilter.c
deleted file mode 100644
index 79c31fc722aa..000000000000
--- a/net/openbgpd/files/patch-bgpctl_irrfilter.c
+++ /dev/null
@@ -1,24 +0,0 @@
-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>
diff --git a/net/openbgpd/files/patch-bgpctl_irrfilter.h b/net/openbgpd/files/patch-bgpctl_irrfilter.h
deleted file mode 100644
index 485b97320e58..000000000000
--- a/net/openbgpd/files/patch-bgpctl_irrfilter.h
+++ /dev/null
@@ -1,59 +0,0 @@
-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;
diff --git a/net/openbgpd/files/patch-bgpctl_mrtparser.c b/net/openbgpd/files/patch-bgpctl_mrtparser.c
deleted file mode 100644
index 0d463c0064ef..000000000000
--- a/net/openbgpd/files/patch-bgpctl_mrtparser.c
+++ /dev/null
@@ -1,977 +0,0 @@
-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);
-+ }
-+}
diff --git a/net/openbgpd/files/patch-bgpctl_mrtparser.h b/net/openbgpd/files/patch-bgpctl_mrtparser.h
deleted file mode 100644
index 2f11567e54f1..000000000000
--- a/net/openbgpd/files/patch-bgpctl_mrtparser.h
+++ /dev/null
@@ -1,122 +0,0 @@
-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);
diff --git a/net/openbgpd/files/patch-bgpctl_parser.c b/net/openbgpd/files/patch-bgpctl_parser.c
deleted file mode 100644
index 0ce85818b1eb..000000000000
--- a/net/openbgpd/files/patch-bgpctl_parser.c
+++ /dev/null
@@ -1,400 +0,0 @@
-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;
diff --git a/net/openbgpd/files/patch-bgpctl_parser.h b/net/openbgpd/files/patch-bgpctl_parser.h
deleted file mode 100644
index 1d570c747a7c..000000000000
--- a/net/openbgpd/files/patch-bgpctl_parser.h
+++ /dev/null
@@ -1,55 +0,0 @@
-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);
diff --git a/net/openbgpd/files/patch-bgpctl_whois.c b/net/openbgpd/files/patch-bgpctl_whois.c
deleted file mode 100644
index 0e4b86c84b6e..000000000000
--- a/net/openbgpd/files/patch-bgpctl_whois.c
+++ /dev/null
@@ -1,18 +0,0 @@
-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";
diff --git a/net/openbgpd/files/patch-bgpd_Makefile b/net/openbgpd/files/patch-bgpd_Makefile
deleted file mode 100644
index fc2701497ef1..000000000000
--- a/net/openbgpd/files/patch-bgpd_Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
---- 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
-
diff --git a/net/openbgpd/files/patch-bgpd_bgpd.8 b/net/openbgpd/files/patch-bgpd_bgpd.8
deleted file mode 100644
index f59cd5269f2c..000000000000
--- a/net/openbgpd/files/patch-bgpd_bgpd.8
+++ /dev/null
@@ -1,348 +0,0 @@
-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
diff --git a/net/openbgpd/files/patch-bgpd_bgpd.c b/net/openbgpd/files/patch-bgpd_bgpd.c
deleted file mode 100644
index 322a8088a075..000000000000
--- a/net/openbgpd/files/patch-bgpd_bgpd.c
+++ /dev/null
@@ -1,693 +0,0 @@
-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);
-+}
diff --git a/net/openbgpd/files/patch-bgpd_bgpd.conf.5 b/net/openbgpd/files/patch-bgpd_bgpd.conf.5
deleted file mode 100644
index 32f4439fc0ab..000000000000
--- a/net/openbgpd/files/patch-bgpd_bgpd.conf.5
+++ /dev/null
@@ -1,746 +0,0 @@
-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
diff --git a/net/openbgpd/files/patch-bgpd_bgpd.h b/net/openbgpd/files/patch-bgpd_bgpd.h
deleted file mode 100644
index 2ce5fe58102f..000000000000
--- a/net/openbgpd/files/patch-bgpd_bgpd.h
+++ /dev/null
@@ -1,872 +0,0 @@
-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__ */
diff --git a/net/openbgpd/files/patch-bgpd_buffer.c b/net/openbgpd/files/patch-bgpd_buffer.c
deleted file mode 100644
index 692fe85c1687..000000000000
--- a/net/openbgpd/files/patch-bgpd_buffer.c
+++ /dev/null
@@ -1,104 +0,0 @@
-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);
- }
diff --git a/net/openbgpd/files/patch-bgpd_carp.c b/net/openbgpd/files/patch-bgpd_carp.c
deleted file mode 100644
index 7ed50075cd5c..000000000000
--- a/net/openbgpd/files/patch-bgpd_carp.c
+++ /dev/null
@@ -1,54 +0,0 @@
-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__) */
- }
diff --git a/net/openbgpd/files/patch-bgpd_config.c b/net/openbgpd/files/patch-bgpd_config.c
deleted file mode 100644
index fbd02e102483..000000000000
--- a/net/openbgpd/files/patch-bgpd_config.c
+++ /dev/null
@@ -1,109 +0,0 @@
-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);
-+}
diff --git a/net/openbgpd/files/patch-bgpd_control.c b/net/openbgpd/files/patch-bgpd_control.c
deleted file mode 100644
index 5d6bade713cc..000000000000
--- a/net/openbgpd/files/patch-bgpd_control.c
+++ /dev/null
@@ -1,171 +0,0 @@
-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;
- }
diff --git a/net/openbgpd/files/patch-bgpd_imsg.c b/net/openbgpd/files/patch-bgpd_imsg.c
deleted file mode 100644
index 0ae6c8a603e7..000000000000
--- a/net/openbgpd/files/patch-bgpd_imsg.c
+++ /dev/null
@@ -1,275 +0,0 @@
-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);
--}
diff --git a/net/openbgpd/files/patch-bgpd_imsg.h b/net/openbgpd/files/patch-bgpd_imsg.h
deleted file mode 100644
index 09fe037f51eb..000000000000
--- a/net/openbgpd/files/patch-bgpd_imsg.h
+++ /dev/null
@@ -1,115 +0,0 @@
-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 *);
diff --git a/net/openbgpd/files/patch-bgpd_kroute.c b/net/openbgpd/files/patch-bgpd_kroute.c
deleted file mode 100644
index 0b7f3943ac4a..000000000000
--- a/net/openbgpd/files/patch-bgpd_kroute.c
+++ /dev/null
@@ -1,3140 +0,0 @@
-Index: bgpd/kroute.c
-===================================================================
-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/kroute.c,v
-retrieving revision 1.1.1.7
-retrieving revision 1.15
-diff -u -p -r1.1.1.7 -r1.15
---- bgpd/kroute.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/kroute.c 16 May 2014 00:36:26 -0000 1.15
-@@ -1,4 +1,4 @@
--/* $OpenBSD: kroute.c,v 1.169 2009/06/25 15:54:22 claudio Exp $ */
-+/* $OpenBSD: kroute.c,v 1.190 2012/07/13 16:57:35 claudio Exp $ */
-
- /*
- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
-@@ -27,6 +27,9 @@
- #include <net/if.h>
- #include <net/if_dl.h>
- #include <net/route.h>
-+#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */
-+#include <netmpls/mpls.h>
-+#endif
- #include <err.h>
- #include <errno.h>
- #include <fcntl.h>
-@@ -37,11 +40,12 @@
-
- #include "bgpd.h"
-
-+struct ktable **krt;
-+u_int krt_size;
-+
- struct {
- u_int32_t rtseq;
- pid_t pid;
-- u_int rtableid;
-- int fib_sync;
- int fd;
- } kr_state;
-
-@@ -83,32 +87,52 @@ struct kif_node {
- struct kif_kr6_head kroute6_l;
- };
-
--int kr_redistribute(int, struct kroute *);
--int kr_redistribute6(int, struct kroute6 *);
-+int ktable_new(u_int, u_int, char *, char *, int);
-+void ktable_free(u_int);
-+void ktable_destroy(struct ktable *);
-+struct ktable *ktable_get(u_int);
-+
-+int kr4_change(struct ktable *, struct kroute_full *);
-+int kr6_change(struct ktable *, struct kroute_full *);
-+int krVPN4_change(struct ktable *, struct kroute_full *);
-+int kr4_delete(struct ktable *, struct kroute_full *);
-+int kr6_delete(struct ktable *, struct kroute_full *);
-+int krVPN4_delete(struct ktable *, struct kroute_full *);
-+void kr_net_delete(struct network *);
-+struct network *kr_net_match(struct ktable *, struct kroute *);
-+struct network *kr_net_match6(struct ktable *, struct kroute6 *);
-+struct network *kr_net_find(struct ktable *, struct network *);
-+int kr_redistribute(int, struct ktable *, struct kroute *);
-+int kr_redistribute6(int, struct ktable *, struct kroute6 *);
-+struct kroute_full *kr_tofull(struct kroute *);
-+struct kroute_full *kr6_tofull(struct kroute6 *);
- int kroute_compare(struct kroute_node *, struct kroute_node *);
- int kroute6_compare(struct kroute6_node *, struct kroute6_node *);
- int knexthop_compare(struct knexthop_node *, struct knexthop_node *);
- int kif_compare(struct kif_node *, struct kif_node *);
-
--struct kroute_node *kroute_find(in_addr_t, u_int8_t, u_int8_t);
-+struct kroute_node *kroute_find(struct ktable *, in_addr_t, u_int8_t,
-+ u_int8_t);
- struct kroute_node *kroute_matchgw(struct kroute_node *,
- struct sockaddr_in *);
--int kroute_insert(struct kroute_node *);
--int kroute_remove(struct kroute_node *);
--void kroute_clear(void);
-+int kroute_insert(struct ktable *, struct kroute_node *);
-+int kroute_remove(struct ktable *, struct kroute_node *);
-+void kroute_clear(struct ktable *);
-
--struct kroute6_node *kroute6_find(const struct in6_addr *, u_int8_t,
-- u_int8_t);
-+struct kroute6_node *kroute6_find(struct ktable *, const struct in6_addr *,
-+ u_int8_t, u_int8_t);
- struct kroute6_node *kroute6_matchgw(struct kroute6_node *,
- struct sockaddr_in6 *);
--int kroute6_insert(struct kroute6_node *);
--int kroute6_remove(struct kroute6_node *);
--void kroute6_clear(void);
--
--struct knexthop_node *knexthop_find(struct bgpd_addr *);
--int knexthop_insert(struct knexthop_node *);
--int knexthop_remove(struct knexthop_node *);
--void knexthop_clear(void);
-+int kroute6_insert(struct ktable *, struct kroute6_node *);
-+int kroute6_remove(struct ktable *, struct kroute6_node *);
-+void kroute6_clear(struct ktable *);
-+
-+struct knexthop_node *knexthop_find(struct ktable *, struct bgpd_addr *);
-+int knexthop_insert(struct ktable *,
-+ struct knexthop_node *);
-+int knexthop_remove(struct ktable *,
-+ struct knexthop_node *);
-+void knexthop_clear(struct ktable *);
-
- struct kif_node *kif_find(int);
- int kif_insert(struct kif_node *);
-@@ -124,13 +148,16 @@ int kif_kr6_remove(struct kroute6_nod
- int kif_validate(struct kif *);
- int kroute_validate(struct kroute *);
- int kroute6_validate(struct kroute6 *);
--void knexthop_validate(struct knexthop_node *);
--void knexthop_track(void *);
--struct kroute_node *kroute_match(in_addr_t, int);
--struct kroute6_node *kroute6_match(struct in6_addr *, int);
--void kroute_detach_nexthop(struct knexthop_node *);
-+void knexthop_validate(struct ktable *,
-+ struct knexthop_node *);
-+void knexthop_track(struct ktable *, void *);
-+void knexthop_send_update(struct knexthop_node *);
-+struct kroute_node *kroute_match(struct ktable *, in_addr_t, int);
-+struct kroute6_node *kroute6_match(struct ktable *, struct in6_addr *, int);
-+void kroute_detach_nexthop(struct ktable *,
-+ struct knexthop_node *);
-
--int protect_lo(void);
-+int protect_lo(struct ktable *);
- u_int8_t prefixlen_classful(in_addr_t);
- u_int8_t mask2prefixlen(in_addr_t);
- u_int8_t mask2prefixlen6(struct sockaddr_in6 *);
-@@ -138,23 +165,20 @@ void get_rtaddrs(int, struct sockaddr *
- void if_change(u_short, int, struct if_data *);
- void if_announce(void *);
-
--int send_rtmsg(int, int, struct kroute *);
--int send_rt6msg(int, int, struct kroute6 *);
-+int send_rtmsg(int, int, struct ktable *, struct kroute *);
-+int send_rt6msg(int, int, struct ktable *, struct kroute6 *);
- int dispatch_rtmsg(void);
--int fetchtable(u_int, int);
-+int fetchtable(struct ktable *);
- int fetchifs(int);
- int dispatch_rtmsg_addr(struct rt_msghdr *,
-- struct sockaddr *[RTAX_MAX], int);
-+ struct sockaddr *[RTAX_MAX], struct ktable *);
-
--RB_HEAD(kroute_tree, kroute_node) krt;
- RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare)
- RB_GENERATE(kroute_tree, kroute_node, entry, kroute_compare)
-
--RB_HEAD(kroute6_tree, kroute6_node) krt6;
- RB_PROTOTYPE(kroute6_tree, kroute6_node, entry, kroute6_compare)
- RB_GENERATE(kroute6_tree, kroute6_node, entry, kroute6_compare)
-
--RB_HEAD(knexthop_tree, knexthop_node) knt;
- RB_PROTOTYPE(knexthop_tree, knexthop_node, entry, knexthop_compare)
- RB_GENERATE(knexthop_tree, knexthop_node, entry, knexthop_compare)
-
-@@ -162,19 +186,21 @@ RB_HEAD(kif_tree, kif_node) kit;
- RB_PROTOTYPE(kif_tree, kif_node, entry, kif_compare)
- RB_GENERATE(kif_tree, kif_node, entry, kif_compare)
-
-+#define KT2KNT(x) (&(ktable_get((x)->nhtableid)->knt))
-+
- /*
- * exported functions
- */
-
- int
--kr_init(int fs, u_int rtableid)
-+kr_init(void)
- {
- int opt = 0, rcvbuf, default_rcvbuf;
-+#if !defined(__FreeBSD__) /* FreeBSD does not have ROUTE_TABLEFILTER. */
-+ unsigned int tid = RTABLE_ANY;
-+#endif
- socklen_t optlen;
-
-- kr_state.rtableid = rtableid;
-- kr_state.fib_sync = fs;
--
- if ((kr_state.fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) {
- log_warn("kr_init: socket");
- return (-1);
-@@ -198,194 +224,533 @@ kr_init(int fs, u_int rtableid)
- rcvbuf /= 2)
- ; /* nothing */
-
-+#if !defined(__FreeBSD__) /* FreeBSD does not have ROUTE_TABLEFILTER. */
-+ if (setsockopt(kr_state.fd, AF_ROUTE, ROUTE_TABLEFILTER, &tid,
-+ sizeof(tid)) == -1) {
-+ log_warn("kr_init: setsockopt AF_ROUTE ROUTE_TABLEFILTER");
-+ return (-1);
-+ }
-+#endif
-+
- kr_state.pid = getpid();
- kr_state.rtseq = 1;
-
-- RB_INIT(&krt);
-- RB_INIT(&krt6);
-- RB_INIT(&knt);
- RB_INIT(&kit);
-
- if (fetchifs(0) == -1)
- return (-1);
-
-- if (fetchtable(kr_state.rtableid, 0) == -1)
-- return (-1);
-- if (kr_state.rtableid != 0)
-- if (fetchtable(0, 1) == -1)
-+ return (kr_state.fd);
-+}
-+
-+int
-+ktable_new(u_int rtableid, u_int rdomid, char *name, char *ifname, int fs)
-+{
-+ struct ktable **xkrt;
-+ struct ktable *kt;
-+ size_t newsize, oldsize;
-+
-+ /* resize index table if needed */
-+ if (rtableid >= krt_size) {
-+ oldsize = sizeof(struct ktable *) * krt_size;
-+ newsize = sizeof(struct ktable *) * (rtableid + 1);
-+ if ((xkrt = realloc(krt, newsize)) == NULL) {
-+ log_warn("ktable_new");
- return (-1);
-+ }
-+ krt = xkrt;
-+ krt_size = rtableid + 1;
-+ bzero((char *)krt + oldsize, newsize - oldsize);
-+ }
-+
-+ if (krt[rtableid])
-+ fatalx("ktable_new: table already exists.");
-
-- if (protect_lo() == -1)
-+ /* allocate new element */
-+ kt = krt[rtableid] = calloc(1, sizeof(struct ktable));
-+ if (kt == NULL) {
-+ log_warn("ktable_new");
- return (-1);
-+ }
-
-- return (kr_state.fd);
-+ /* initialize structure ... */
-+ strlcpy(kt->descr, name, sizeof(kt->descr));
-+ RB_INIT(&kt->krt);
-+ RB_INIT(&kt->krt6);
-+ RB_INIT(&kt->knt);
-+ TAILQ_INIT(&kt->krn);
-+ kt->fib_conf = kt->fib_sync = fs;
-+ kt->rtableid = rtableid;
-+ kt->nhtableid = rdomid;
-+ /* bump refcount of rdomain table for the nexthop lookups */
-+ ktable_get(kt->nhtableid)->nhrefcnt++;
-+ if (ifname) {
-+ strlcpy(kt->ifmpe, ifname, IFNAMSIZ);
-+ kt->ifindex = if_nametoindex(ifname);
-+ }
-+
-+ /* ... and load it */
-+ if (fetchtable(kt) == -1)
-+ return (-1);
-+ if (protect_lo(kt) == -1)
-+ return (-1);
-+
-+ /* everything is up and running */
-+ kt->state = RECONF_REINIT;
-+ log_debug("new ktable %s for rtableid %d", name, rtableid);
-+ return (0);
-+}
-+
-+void
-+ktable_free(u_int rtableid)
-+{
-+ struct ktable *kt, *nkt;
-+
-+ if ((kt = ktable_get(rtableid)) == NULL)
-+ return;
-+
-+ /* decouple from kernel, no new routes will be entered from here */
-+ kr_fib_decouple(kt->rtableid);
-+
-+ /* first unhook from the nexthop table */
-+ nkt = ktable_get(kt->nhtableid);
-+ nkt->nhrefcnt--;
-+
-+ /*
-+ * Evil little details:
-+ * If kt->nhrefcnt > 0 then kt == nkt and nothing needs to be done.
-+ * If kt != nkt then kt->nhrefcnt must be 0 and kt must be killed.
-+ * If nkt is no longer referenced it must be killed (possible double
-+ * free so check that kt != nkt).
-+ */
-+ if (kt != nkt && nkt->nhrefcnt <= 0)
-+ ktable_destroy(nkt);
-+ if (kt->nhrefcnt <= 0)
-+ ktable_destroy(kt);
-+}
-+
-+void
-+ktable_destroy(struct ktable *kt)
-+{
-+ /* decouple just to be sure, does not hurt */
-+ kr_fib_decouple(kt->rtableid);
-+
-+ log_debug("freeing ktable %s rtableid %u", kt->descr, kt->rtableid);
-+ knexthop_clear(kt);
-+ kroute_clear(kt);
-+ kroute6_clear(kt);
-+
-+ krt[kt->rtableid] = NULL;
-+ free(kt);
-+}
-+
-+struct ktable *
-+ktable_get(u_int rtableid)
-+{
-+ if (rtableid >= krt_size)
-+ return (NULL);
-+ return (krt[rtableid]);
-+}
-+
-+int
-+ktable_update(u_int rtableid, char *name, char *ifname, int flags)
-+{
-+ struct ktable *kt, *rkt;
-+ u_int rdomid;
-+
-+ if (!ktable_exists(rtableid, &rdomid))
-+ fatalx("King Bula lost a table"); /* may not happen */
-+
-+ if (rdomid != rtableid || flags & F_RIB_NOFIB) {
-+ rkt = ktable_get(rdomid);
-+ if (rkt == NULL) {
-+ char buf[32];
-+ snprintf(buf, sizeof(buf), "rdomain_%d", rdomid);
-+ if (ktable_new(rdomid, rdomid, buf, NULL, 0))
-+ return (-1);
-+ } else {
-+ /* there is no need for full fib synchronisation if
-+ * the table is only used for nexthop lookups.
-+ */
-+ if (rkt->state == RECONF_DELETE) {
-+ rkt->fib_conf = 0;
-+ rkt->state = RECONF_KEEP;
-+ }
-+ }
-+ }
-+
-+ if (flags & (F_RIB_NOEVALUATE | F_RIB_NOFIB))
-+ /* only rdomain table must exist */
-+ return (0);
-+
-+ kt = ktable_get(rtableid);
-+ if (kt == NULL) {
-+ if (ktable_new(rtableid, rdomid, name, ifname,
-+ !(flags & F_RIB_NOFIBSYNC)))
-+ return (-1);
-+ } else {
-+ /* fib sync has higher preference then no sync */
-+ if (kt->state == RECONF_DELETE) {
-+ kt->fib_conf = !(flags & F_RIB_NOFIBSYNC);
-+ kt->state = RECONF_KEEP;
-+ } else if (!kt->fib_conf)
-+ kt->fib_conf = !(flags & F_RIB_NOFIBSYNC);
-+
-+ strlcpy(kt->descr, name, sizeof(kt->descr));
-+ }
-+ return (0);
-+}
-+
-+void
-+ktable_preload(void)
-+{
-+ struct ktable *kt;
-+ u_int i;
-+
-+ for (i = 0; i < krt_size; i++) {
-+ if ((kt = ktable_get(i)) == NULL)
-+ continue;
-+ kt->state = RECONF_DELETE;
-+ }
-+}
-+
-+void
-+ktable_postload(void)
-+{
-+ struct ktable *kt;
-+ u_int i;
-+
-+ for (i = krt_size; i > 0; i--) {
-+ if ((kt = ktable_get(i - 1)) == NULL)
-+ continue;
-+ if (kt->state == RECONF_DELETE)
-+ ktable_free(i - 1);
-+ else if (kt->state == RECONF_REINIT)
-+ kt->fib_sync = kt->fib_conf;
-+ }
-+}
-+
-+int
-+ktable_exists(u_int rtableid, u_int *rdomid)
-+{
-+#if !defined(__FreeBSD__) /* FreeBSD does not have NET_RT_TABLE. */
-+ size_t len;
-+ struct rt_tableinfo info;
-+ int mib[6];
-+
-+ mib[0] = CTL_NET;
-+ mib[1] = AF_ROUTE;
-+ mib[2] = 0;
-+ mib[3] = 0;
-+ mib[4] = NET_RT_TABLE;
-+ mib[5] = rtableid;
-+
-+ len = sizeof(info);
-+ if (sysctl(mib, 6, &info, &len, NULL, 0) == -1) {
-+ if (errno == ENOENT)
-+ /* table nonexistent */
-+ return (0);
-+ log_warn("sysctl");
-+ /* must return 0 so that the table is considered non-existent */
-+ return (0);
-+ }
-+ if (rdomid)
-+ *rdomid = info.rti_domainid;
-+#else
-+ *rdomid = 0;
-+#endif
-+ return (1);
- }
-
- int
--kr_change(struct kroute_label *kl)
-+kr_change(u_int rtableid, struct kroute_full *kl)
-+{
-+ struct ktable *kt;
-+
-+ if ((kt = ktable_get(rtableid)) == NULL)
-+ /* too noisy during reloads, just ignore */
-+ return (0);
-+ switch (kl->prefix.aid) {
-+ case AID_INET:
-+ return (kr4_change(kt, kl));
-+ case AID_INET6:
-+ return (kr6_change(kt, kl));
-+ case AID_VPN_IPv4:
-+ return (krVPN4_change(kt, kl));
-+ }
-+ log_warnx("kr_change: not handled AID");
-+ return (-1);
-+}
-+
-+int
-+kr4_change(struct ktable *kt, struct kroute_full *kl)
- {
- struct kroute_node *kr;
- int action = RTM_ADD;
-+ u_int16_t labelid;
-
-- if ((kr = kroute_find(kl->kr.prefix.s_addr, kl->kr.prefixlen, RTP_BGP))
-- != NULL)
-+ if ((kr = kroute_find(kt, kl->prefix.v4.s_addr, kl->prefixlen,
-+ RTP_BGP)) != NULL)
- action = RTM_CHANGE;
-
- /* nexthop within 127/8 -> ignore silently */
-- if ((kl->kr.nexthop.s_addr & htonl(IN_CLASSA_NET)) ==
-+ if ((kl->nexthop.v4.s_addr & htonl(IN_CLASSA_NET)) ==
- htonl(INADDR_LOOPBACK & IN_CLASSA_NET))
- return (0);
-
-- if (kr)
-- rtlabel_unref(kr->r.labelid);
-- kl->kr.labelid = rtlabel_name2id(kl->label);
-+ labelid = rtlabel_name2id(kl->label);
-
- /* for blackhole and reject routes nexthop needs to be 127.0.0.1 */
-- if (kl->kr.flags & (F_BLACKHOLE|F_REJECT))
-- kl->kr.nexthop.s_addr = htonl(INADDR_LOOPBACK);
--
-- if (send_rtmsg(kr_state.fd, action, &kl->kr) == -1)
-- return (-1);
-+ if (kl->flags & (F_BLACKHOLE|F_REJECT))
-+ kl->nexthop.v4.s_addr = htonl(INADDR_LOOPBACK);
-
- if (action == RTM_ADD) {
- if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) {
- log_warn("kr_change");
- return (-1);
- }
-- kr->r.prefix.s_addr = kl->kr.prefix.s_addr;
-- kr->r.prefixlen = kl->kr.prefixlen;
-- kr->r.nexthop.s_addr = kl->kr.nexthop.s_addr;
-- kr->r.flags = kl->kr.flags | F_BGPD_INSERTED;
-+ kr->r.prefix.s_addr = kl->prefix.v4.s_addr;
-+ kr->r.prefixlen = kl->prefixlen;
-+ kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr;
-+ kr->r.flags = kl->flags | F_BGPD_INSERTED;
- kr->r.priority = RTP_BGP;
-- kr->r.labelid = kl->kr.labelid;
-+ kr->r.labelid = labelid;
-
-- if (kroute_insert(kr) == -1)
-+ if (kroute_insert(kt, kr) == -1)
- free(kr);
- } else {
-- kr->r.nexthop.s_addr = kl->kr.nexthop.s_addr;
-- kr->r.labelid = kl->kr.labelid;
-- if (kl->kr.flags & F_BLACKHOLE)
-+ kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr;
-+ rtlabel_unref(kr->r.labelid);
-+ kr->r.labelid = labelid;
-+ if (kl->flags & F_BLACKHOLE)
- kr->r.flags |= F_BLACKHOLE;
- else
- kr->r.flags &= ~F_BLACKHOLE;
-- if (kl->kr.flags & F_REJECT)
-+ if (kl->flags & F_REJECT)
- kr->r.flags |= F_REJECT;
- else
- kr->r.flags &= ~F_REJECT;
- }
-
-+ if (send_rtmsg(kr_state.fd, action, kt, &kr->r) == -1)
-+ return (-1);
-+
- return (0);
- }
-
- int
--kr_delete(struct kroute_label *kl)
-+kr6_change(struct ktable *kt, struct kroute_full *kl)
- {
-- struct kroute_node *kr;
-+ struct kroute6_node *kr6;
-+ struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT;
-+ int action = RTM_ADD;
-+ u_int16_t labelid;
-
-- if ((kr = kroute_find(kl->kr.prefix.s_addr, kl->kr.prefixlen, RTP_BGP))
-- == NULL)
-- return (0);
-+ if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen, RTP_BGP)) !=
-+ NULL)
-+ action = RTM_CHANGE;
-
-- if (!(kr->r.flags & F_BGPD_INSERTED))
-+ /* nexthop to loopback -> ignore silently */
-+ if (IN6_IS_ADDR_LOOPBACK(&kl->nexthop.v6))
- return (0);
-
-- /* nexthop within 127/8 -> ignore silently */
-- if ((kl->kr.nexthop.s_addr & htonl(IN_CLASSA_NET)) ==
-- htonl(INADDR_LOOPBACK & IN_CLASSA_NET))
-- return (0);
-+ labelid = rtlabel_name2id(kl->label);
-
-- if (send_rtmsg(kr_state.fd, RTM_DELETE, &kl->kr) == -1)
-- return (-1);
-+ /* for blackhole and reject routes nexthop needs to be ::1 */
-+ if (kl->flags & (F_BLACKHOLE|F_REJECT))
-+ bcopy(&lo6, &kl->nexthop.v6, sizeof(kl->nexthop.v6));
-
-- rtlabel_unref(kl->kr.labelid);
-+ if (action == RTM_ADD) {
-+ if ((kr6 = calloc(1, sizeof(struct kroute6_node))) == NULL) {
-+ log_warn("kr_change");
-+ return (-1);
-+ }
-+ memcpy(&kr6->r.prefix, &kl->prefix.v6, sizeof(struct in6_addr));
-+ kr6->r.prefixlen = kl->prefixlen;
-+ memcpy(&kr6->r.nexthop, &kl->nexthop.v6,
-+ sizeof(struct in6_addr));
-+ kr6->r.flags = kl->flags | F_BGPD_INSERTED;
-+ kr6->r.priority = RTP_BGP;
-+ kr6->r.labelid = labelid;
-
-- if (kroute_remove(kr) == -1)
-+ if (kroute6_insert(kt, kr6) == -1)
-+ free(kr6);
-+ } else {
-+ memcpy(&kr6->r.nexthop, &kl->nexthop.v6,
-+ sizeof(struct in6_addr));
-+ rtlabel_unref(kr6->r.labelid);
-+ kr6->r.labelid = labelid;
-+ if (kl->flags & F_BLACKHOLE)
-+ kr6->r.flags |= F_BLACKHOLE;
-+ else
-+ kr6->r.flags &= ~F_BLACKHOLE;
-+ if (kl->flags & F_REJECT)
-+ kr6->r.flags |= F_REJECT;
-+ else
-+ kr6->r.flags &= ~F_REJECT;
-+ }
-+
-+ if (send_rt6msg(kr_state.fd, action, kt, &kr6->r) == -1)
- return (-1);
-
- return (0);
- }
-
- int
--kr6_change(struct kroute6_label *kl)
-+krVPN4_change(struct ktable *kt, struct kroute_full *kl)
- {
-- struct kroute6_node *kr6;
-+ struct kroute_node *kr;
- int action = RTM_ADD;
-- struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT;
-+ u_int32_t mplslabel = 0;
-+ u_int16_t labelid;
-
-- if ((kr6 = kroute6_find(&kl->kr.prefix, kl->kr.prefixlen, RTP_BGP))
-- != NULL)
-+ if ((kr = kroute_find(kt, kl->prefix.vpn4.addr.s_addr, kl->prefixlen,
-+ RTP_BGP)) != NULL)
- action = RTM_CHANGE;
-
-- /* nexthop to loopback -> ignore silently */
-- if (IN6_IS_ADDR_LOOPBACK(&kl->kr.nexthop))
-+ /* nexthop within 127/8 -> ignore silently */
-+ if ((kl->nexthop.v4.s_addr & htonl(IN_CLASSA_NET)) ==
-+ htonl(INADDR_LOOPBACK & IN_CLASSA_NET))
- return (0);
-
-- if (kr6)
-- rtlabel_unref(kr6->r.labelid);
-- kl->kr.labelid = rtlabel_name2id(kl->label);
-+ /* only single MPLS label are supported for now */
-+ if (kl->prefix.vpn4.labellen != 3) {
-+ log_warnx("krVPN4_change: %s/%u has not a single label",
-+ log_addr(&kl->prefix), kl->prefixlen);
-+ return (0);
-+ }
-+ mplslabel = (kl->prefix.vpn4.labelstack[0] << 24) |
-+ (kl->prefix.vpn4.labelstack[1] << 16) |
-+ (kl->prefix.vpn4.labelstack[2] << 8);
-+ mplslabel = htonl(mplslabel);
-
-- /* for blackhole and reject routes nexthop needs to be ::1 */
-- if (kl->kr.flags & (F_BLACKHOLE|F_REJECT))
-- bcopy(&lo6, &kl->kr.nexthop, sizeof(kl->kr.nexthop));
-+ labelid = rtlabel_name2id(kl->label);
-
-- if (send_rt6msg(kr_state.fd, action, &kl->kr) == -1)
-- return (-1);
-+ /* for blackhole and reject routes nexthop needs to be 127.0.0.1 */
-+ if (kl->flags & (F_BLACKHOLE|F_REJECT))
-+ kl->nexthop.v4.s_addr = htonl(INADDR_LOOPBACK);
-
- if (action == RTM_ADD) {
-- if ((kr6 = calloc(1, sizeof(struct kroute6_node))) == NULL) {
-+ if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) {
- log_warn("kr_change");
- return (-1);
- }
-- memcpy(&kr6->r.prefix, &kl->kr.prefix,
-- sizeof(struct in6_addr));
-- kr6->r.prefixlen = kl->kr.prefixlen;
-- memcpy(&kr6->r.nexthop, &kl->kr.nexthop,
-- sizeof(struct in6_addr));
-- kr6->r.flags = kl->kr.flags | F_BGPD_INSERTED;
-- kr6->r.priority = RTP_BGP;
-- kr6->r.labelid = kl->kr.labelid;
-+ kr->r.prefix.s_addr = kl->prefix.vpn4.addr.s_addr;
-+ kr->r.prefixlen = kl->prefixlen;
-+ kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr;
-+ kr->r.flags = kl->flags | F_BGPD_INSERTED | F_MPLS;
-+ kr->r.priority = RTP_BGP;
-+ kr->r.labelid = labelid;
-+ kr->r.mplslabel = mplslabel;
-
-- if (kroute6_insert(kr6) == -1)
-- free(kr6);
-+ if (kroute_insert(kt, kr) == -1)
-+ free(kr);
- } else {
-- memcpy(&kr6->r.nexthop, &kl->kr.nexthop,
-- sizeof(struct in6_addr));
-- kr6->r.labelid = kl->kr.labelid;
-- if (kl->kr.flags & F_BLACKHOLE)
-- kr6->r.flags |= F_BLACKHOLE;
-+ kr->r.mplslabel = mplslabel;
-+ kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr;
-+ rtlabel_unref(kr->r.labelid);
-+ kr->r.labelid = labelid;
-+ if (kl->flags & F_BLACKHOLE)
-+ kr->r.flags |= F_BLACKHOLE;
- else
-- kr6->r.flags &= ~F_BLACKHOLE;
-- if (kl->kr.flags & F_REJECT)
-- kr6->r.flags |= F_REJECT;
-+ kr->r.flags &= ~F_BLACKHOLE;
-+ if (kl->flags & F_REJECT)
-+ kr->r.flags |= F_REJECT;
- else
-- kr6->r.flags &= ~F_REJECT;
-+ kr->r.flags &= ~F_REJECT;
- }
-
-+ if (send_rtmsg(kr_state.fd, action, kt, &kr->r) == -1)
-+ return (-1);
-+
- return (0);
- }
-
- int
--kr6_delete(struct kroute6_label *kl)
-+kr_delete(u_int rtableid, struct kroute_full *kl)
-+{
-+ struct ktable *kt;
-+
-+ if ((kt = ktable_get(rtableid)) == NULL)
-+ /* too noisy during reloads, just ignore */
-+ return (0);
-+
-+ switch (kl->prefix.aid) {
-+ case AID_INET:
-+ return (kr4_delete(kt, kl));
-+ case AID_INET6:
-+ return (kr6_delete(kt, kl));
-+ case AID_VPN_IPv4:
-+ return (krVPN4_delete(kt, kl));
-+ }
-+ log_warnx("kr_change: not handled AID");
-+ return (-1);
-+}
-+
-+int
-+kr4_delete(struct ktable *kt, struct kroute_full *kl)
-+{
-+ struct kroute_node *kr;
-+
-+ if ((kr = kroute_find(kt, kl->prefix.v4.s_addr, kl->prefixlen,
-+ RTP_BGP)) == NULL)
-+ return (0);
-+
-+ if (!(kr->r.flags & F_BGPD_INSERTED))
-+ return (0);
-+
-+ if (send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r) == -1)
-+ return (-1);
-+
-+ rtlabel_unref(kr->r.labelid);
-+
-+ if (kroute_remove(kt, kr) == -1)
-+ return (-1);
-+
-+ return (0);
-+}
-+
-+int
-+kr6_delete(struct ktable *kt, struct kroute_full *kl)
- {
- struct kroute6_node *kr6;
-
-- if ((kr6 = kroute6_find(&kl->kr.prefix, kl->kr.prefixlen, RTP_BGP))
-- == NULL)
-+ if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen, RTP_BGP)) ==
-+ NULL)
- return (0);
-
- if (!(kr6->r.flags & F_BGPD_INSERTED))
- return (0);
-
-- /* nexthop to loopback -> ignore silently */
-- if (IN6_IS_ADDR_LOOPBACK(&kl->kr.nexthop))
-+ if (send_rt6msg(kr_state.fd, RTM_DELETE, kt, &kr6->r) == -1)
-+ return (-1);
-+
-+ rtlabel_unref(kr6->r.labelid);
-+
-+ if (kroute6_remove(kt, kr6) == -1)
-+ return (-1);
-+
-+ return (0);
-+}
-+
-+int
-+krVPN4_delete(struct ktable *kt, struct kroute_full *kl)
-+{
-+ struct kroute_node *kr;
-+
-+ if ((kr = kroute_find(kt, kl->prefix.vpn4.addr.s_addr, kl->prefixlen,
-+ RTP_BGP)) == NULL)
- return (0);
-
-- if (send_rt6msg(kr_state.fd, RTM_DELETE, &kl->kr) == -1)
-+ if (!(kr->r.flags & F_BGPD_INSERTED))
-+ return (0);
-+
-+ if (send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r) == -1)
- return (-1);
-
-- rtlabel_unref(kl->kr.labelid);
-+ rtlabel_unref(kr->r.labelid);
-
-- if (kroute6_remove(kr6) == -1)
-+ if (kroute_remove(kt, kr) == -1)
- return (-1);
-
- return (0);
-@@ -394,53 +759,63 @@ kr6_delete(struct kroute6_label *kl)
- void
- kr_shutdown(void)
- {
-- kr_fib_decouple();
-- knexthop_clear();
-- kroute_clear();
-- kroute6_clear();
-+ u_int i;
-+
-+ for (i = krt_size; i > 0; i--)
-+ ktable_free(i - 1);
- kif_clear();
- }
-
- void
--kr_fib_couple(void)
-+kr_fib_couple(u_int rtableid)
- {
-+ struct ktable *kt;
- struct kroute_node *kr;
- struct kroute6_node *kr6;
-
-- if (kr_state.fib_sync == 1) /* already coupled */
-+ if ((kt = ktable_get(rtableid)) == NULL) /* table does not exist */
- return;
-
-- kr_state.fib_sync = 1;
-+ if (kt->fib_sync) /* already coupled */
-+ return;
-
-- RB_FOREACH(kr, kroute_tree, &krt)
-+ kt->fib_sync = 1;
-+
-+ RB_FOREACH(kr, kroute_tree, &kt->krt)
- if ((kr->r.flags & F_BGPD_INSERTED))
-- send_rtmsg(kr_state.fd, RTM_ADD, &kr->r);
-- RB_FOREACH(kr6, kroute6_tree, &krt6)
-+ send_rtmsg(kr_state.fd, RTM_ADD, kt, &kr->r);
-+ RB_FOREACH(kr6, kroute6_tree, &kt->krt6)
- if ((kr6->r.flags & F_BGPD_INSERTED))
-- send_rt6msg(kr_state.fd, RTM_ADD, &kr6->r);
-+ send_rt6msg(kr_state.fd, RTM_ADD, kt, &kr6->r);
-
-- log_info("kernel routing table coupled");
-+ log_info("kernel routing table %u (%s) coupled", kt->rtableid,
-+ kt->descr);
- }
-
- void
--kr_fib_decouple(void)
-+kr_fib_decouple(u_int rtableid)
- {
-+ struct ktable *kt;
- struct kroute_node *kr;
- struct kroute6_node *kr6;
-
-- if (kr_state.fib_sync == 0) /* already decoupled */
-+ if ((kt = ktable_get(rtableid)) == NULL) /* table does not exist */
-+ return;
-+
-+ if (!kt->fib_sync) /* already decoupled */
- return;
-
-- RB_FOREACH(kr, kroute_tree, &krt)
-+ RB_FOREACH(kr, kroute_tree, &kt->krt)
- if ((kr->r.flags & F_BGPD_INSERTED))
-- send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r);
-- RB_FOREACH(kr6, kroute6_tree, &krt6)
-+ send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r);
-+ RB_FOREACH(kr6, kroute6_tree, &kt->krt6)
- if ((kr6->r.flags & F_BGPD_INSERTED))
-- send_rt6msg(kr_state.fd, RTM_DELETE, &kr6->r);
-+ send_rt6msg(kr_state.fd, RTM_DELETE, kt, &kr6->r);
-
-- kr_state.fib_sync = 0;
-+ kt->fib_sync = 0;
-
-- log_info("kernel routing table decoupled");
-+ log_info("kernel routing table %u (%s) decoupled", kt->rtableid,
-+ kt->descr);
- }
-
- int
-@@ -450,41 +825,18 @@ kr_dispatch_msg(void)
- }
-
- int
--kr_nexthop_add(struct bgpd_addr *addr)
-+kr_nexthop_add(u_int rtableid, struct bgpd_addr *addr)
- {
-+ struct ktable *kt;
- struct knexthop_node *h;
-
-- if ((h = knexthop_find(addr)) != NULL) {
-+ if ((kt = ktable_get(rtableid)) == NULL) {
-+ log_warnx("kr_nexthop_add: non-existent rtableid %d", rtableid);
-+ return (0);
-+ }
-+ if ((h = knexthop_find(kt, addr)) != NULL) {
- /* should not happen... this is actually an error path */
-- struct kroute_nexthop nh;
-- struct kroute_node *k;
-- struct kroute6_node *k6;
--
-- bzero(&nh, sizeof(nh));
-- memcpy(&nh.nexthop, addr, sizeof(nh.nexthop));
-- nh.valid = 1;
-- if (h->kroute != NULL && addr->af == AF_INET) {
-- k = h->kroute;
-- nh.connected = k->r.flags & F_CONNECTED;
-- if (k->r.nexthop.s_addr != 0) {
-- nh.gateway.af = AF_INET;
-- nh.gateway.v4.s_addr =
-- k->r.nexthop.s_addr;
-- }
-- memcpy(&nh.kr.kr4, &k->r, sizeof(nh.kr.kr4));
-- } else if (h->kroute != NULL && addr->af == AF_INET6) {
-- k6 = h->kroute;
-- nh.connected = k6->r.flags & F_CONNECTED;
-- if (memcmp(&k6->r.nexthop, &in6addr_any,
-- sizeof(struct in6_addr)) != 0) {
-- nh.gateway.af = AF_INET6;
-- memcpy(&nh.gateway.v6, &k6->r.nexthop,
-- sizeof(struct in6_addr));
-- }
-- memcpy(&nh.kr.kr6, &k6->r, sizeof(nh.kr.kr6));
-- }
--
-- send_nexthop_update(&nh);
-+ knexthop_send_update(h);
- } else {
- if ((h = calloc(1, sizeof(struct knexthop_node))) == NULL) {
- log_warn("kr_nexthop_add");
-@@ -492,7 +844,7 @@ kr_nexthop_add(struct bgpd_addr *addr)
- }
- memcpy(&h->nexthop, addr, sizeof(h->nexthop));
-
-- if (knexthop_insert(h) == -1)
-+ if (knexthop_insert(kt, h) == -1)
- return (-1);
- }
-
-@@ -500,19 +852,26 @@ kr_nexthop_add(struct bgpd_addr *addr)
- }
-
- void
--kr_nexthop_delete(struct bgpd_addr *addr)
-+kr_nexthop_delete(u_int rtableid, struct bgpd_addr *addr)
- {
-+ struct ktable *kt;
- struct knexthop_node *kn;
-
-- if ((kn = knexthop_find(addr)) == NULL)
-+ if ((kt = ktable_get(rtableid)) == NULL) {
-+ log_warnx("kr_nexthop_delete: non-existent rtableid %d",
-+ rtableid);
-+ return;
-+ }
-+ if ((kn = knexthop_find(kt, addr)) == NULL)
- return;
-
-- knexthop_remove(kn);
-+ knexthop_remove(kt, kn);
- }
-
- void
- kr_show_route(struct imsg *imsg)
- {
-+ struct ktable *kt;
- struct kroute_node *kr, *kn;
- struct kroute6_node *kr6, *kn6;
- struct bgpd_addr *addr;
-@@ -521,6 +880,7 @@ kr_show_route(struct imsg *imsg)
- struct ctl_show_nexthop snh;
- struct knexthop_node *h;
- struct kif_node *kif;
-+ u_int i;
- u_short ifindex = 0;
-
- switch (imsg->hdr.type) {
-@@ -528,70 +888,96 @@ kr_show_route(struct imsg *imsg)
- if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(flags) +
- sizeof(af)) {
- log_warnx("kr_show_route: wrong imsg len");
-- return;
-+ break;
-+ }
-+ kt = ktable_get(imsg->hdr.peerid);
-+ if (kt == NULL) {
-+ log_warnx("kr_show_route: table %u does not exist",
-+ imsg->hdr.peerid);
-+ break;
- }
- memcpy(&flags, imsg->data, sizeof(flags));
- memcpy(&af, (char *)imsg->data + sizeof(flags), sizeof(af));
- if (!af || af == AF_INET)
-- RB_FOREACH(kr, kroute_tree, &krt)
-- if (!flags || kr->r.flags & flags) {
-- kn = kr;
-- do {
-- send_imsg_session(
-- IMSG_CTL_KROUTE,
-- imsg->hdr.pid, &kn->r,
-- sizeof(kn->r));
-- } while ((kn = kn->next) != NULL);
-- }
-+ RB_FOREACH(kr, kroute_tree, &kt->krt) {
-+ if (flags && (kr->r.flags & flags) == 0)
-+ continue;
-+ kn = kr;
-+ do {
-+ send_imsg_session(IMSG_CTL_KROUTE,
-+ imsg->hdr.pid, kr_tofull(&kn->r),
-+ sizeof(struct kroute_full));
-+ } while ((kn = kn->next) != NULL);
-+ }
- if (!af || af == AF_INET6)
-- RB_FOREACH(kr6, kroute6_tree, &krt6)
-- if (!flags || kr6->r.flags & flags) {
-- kn6 = kr6;
-- do {
-- send_imsg_session(
-- IMSG_CTL_KROUTE6,
-- imsg->hdr.pid, &kn6->r,
-- sizeof(kn6->r));
-- } while ((kn6 = kn6->next) != NULL);
-- }
-+ RB_FOREACH(kr6, kroute6_tree, &kt->krt6) {
-+ if (flags && (kr6->r.flags & flags) == 0)
-+ continue;
-+ kn6 = kr6;
-+ do {
-+ send_imsg_session(IMSG_CTL_KROUTE,
-+ imsg->hdr.pid, kr6_tofull(&kn6->r),
-+ sizeof(struct kroute_full));
-+ } while ((kn6 = kn6->next) != NULL);
-+ }
- break;
- case IMSG_CTL_KROUTE_ADDR:
- if (imsg->hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct bgpd_addr)) {
- log_warnx("kr_show_route: wrong imsg len");
-- return;
-+ break;
-+ }
-+ kt = ktable_get(imsg->hdr.peerid);
-+ if (kt == NULL) {
-+ log_warnx("kr_show_route: table %u does not exist",
-+ imsg->hdr.peerid);
-+ break;
- }
- addr = imsg->data;
- kr = NULL;
-- switch (addr->af) {
-- case AF_INET:
-- kr = kroute_match(addr->v4.s_addr, 1);
-+ switch (addr->aid) {
-+ case AID_INET:
-+ kr = kroute_match(kt, addr->v4.s_addr, 1);
- if (kr != NULL)
- send_imsg_session(IMSG_CTL_KROUTE,
-- imsg->hdr.pid, &kr->r, sizeof(kr->r));
-+ imsg->hdr.pid, kr_tofull(&kr->r),
-+ sizeof(struct kroute_full));
- break;
-- case AF_INET6:
-- kr6 = kroute6_match(&addr->v6, 1);
-+ case AID_INET6:
-+ kr6 = kroute6_match(kt, &addr->v6, 1);
- if (kr6 != NULL)
-- send_imsg_session(IMSG_CTL_KROUTE6,
-- imsg->hdr.pid, &kr6->r, sizeof(kr6->r));
-+ send_imsg_session(IMSG_CTL_KROUTE,
-+ imsg->hdr.pid, kr6_tofull(&kr6->r),
-+ sizeof(struct kroute_full));
- break;
- }
- break;
- case IMSG_CTL_SHOW_NEXTHOP:
-- RB_FOREACH(h, knexthop_tree, &knt) {
-+ kt = ktable_get(imsg->hdr.peerid);
-+ if (kt == NULL) {
-+ log_warnx("kr_show_route: table %u does not exist",
-+ imsg->hdr.peerid);
-+ break;
-+ }
-+ RB_FOREACH(h, knexthop_tree, KT2KNT(kt)) {
- bzero(&snh, sizeof(snh));
- memcpy(&snh.addr, &h->nexthop, sizeof(snh.addr));
- if (h->kroute != NULL) {
-- switch (h->nexthop.af) {
-- case AF_INET:
-+ switch (h->nexthop.aid) {
-+ case AID_INET:
- kr = h->kroute;
- snh.valid = kroute_validate(&kr->r);
-+ snh.krvalid = 1;
-+ memcpy(&snh.kr.kr4, &kr->r,
-+ sizeof(snh.kr.kr4));
- ifindex = kr->r.ifindex;
- break;
-- case AF_INET6:
-+ case AID_INET6:
- kr6 = h->kroute;
- snh.valid = kroute6_validate(&kr6->r);
-+ snh.krvalid = 1;
-+ memcpy(&snh.kr.kr6, &kr6->r,
-+ sizeof(snh.kr.kr6));
- ifindex = kr6->r.ifindex;
- break;
- }
-@@ -608,41 +994,190 @@ kr_show_route(struct imsg *imsg)
- send_imsg_session(IMSG_CTL_SHOW_INTERFACE,
- imsg->hdr.pid, &kif->k, sizeof(kif->k));
- break;
-+ case IMSG_CTL_SHOW_FIB_TABLES:
-+ for (i = 0; i < krt_size; i++) {
-+ struct ktable ktab;
-+
-+ if ((kt = ktable_get(i)) == NULL)
-+ continue;
-+
-+ ktab = *kt;
-+ /* do not leak internal information */
-+ RB_INIT(&ktab.krt);
-+ RB_INIT(&ktab.krt6);
-+ RB_INIT(&ktab.knt);
-+ TAILQ_INIT(&ktab.krn);
-+
-+ send_imsg_session(IMSG_CTL_SHOW_FIB_TABLES,
-+ imsg->hdr.pid, &ktab, sizeof(ktab));
-+ }
-+ break;
- default: /* nada */
- break;
- }
--
-- send_imsg_session(IMSG_CTL_END, imsg->hdr.pid, NULL, 0);
-+
-+ send_imsg_session(IMSG_CTL_END, imsg->hdr.pid, NULL, 0);
-+}
-+
-+void
-+kr_ifinfo(char *ifname)
-+{
-+ struct kif_node *kif;
-+
-+ RB_FOREACH(kif, kif_tree, &kit)
-+ if (!strcmp(ifname, kif->k.ifname)) {
-+ send_imsg_session(IMSG_IFINFO, 0,
-+ &kif->k, sizeof(kif->k));
-+ return;
-+ }
-+}
-+
-+void
-+kr_net_delete(struct network *n)
-+{
-+ filterset_free(&n->net.attrset);
-+ free(n);
-+}
-+
-+struct network *
-+kr_net_match(struct ktable *kt, struct kroute *kr)
-+{
-+ struct network *xn;
-+
-+ TAILQ_FOREACH(xn, &kt->krn, entry) {
-+ if (xn->net.prefix.aid != AID_INET)
-+ continue;
-+ switch (xn->net.type) {
-+ case NETWORK_DEFAULT:
-+ if (xn->net.prefixlen == kr->prefixlen &&
-+ xn->net.prefix.v4.s_addr == kr->prefix.s_addr)
-+ /* static match already redistributed */
-+ return (NULL);
-+ break;
-+ case NETWORK_STATIC:
-+ if (kr->flags & F_STATIC)
-+ return (xn);
-+ break;
-+ case NETWORK_CONNECTED:
-+ if (kr->flags & F_CONNECTED)
-+ return (xn);
-+ break;
-+ case NETWORK_MRTCLONE:
-+ /* can not happen */
-+ break;
-+ }
-+ }
-+ return (NULL);
- }
-
--void
--kr_ifinfo(char *ifname)
-+struct network *
-+kr_net_match6(struct ktable *kt, struct kroute6 *kr6)
- {
-- struct kif_node *kif;
-+ struct network *xn;
-
-- RB_FOREACH(kif, kif_tree, &kit)
-- if (!strcmp(ifname, kif->k.ifname)) {
-- send_imsg_session(IMSG_IFINFO, 0,
-- &kif->k, sizeof(kif->k));
-- return;
-+ TAILQ_FOREACH(xn, &kt->krn, entry) {
-+ if (xn->net.prefix.aid != AID_INET6)
-+ continue;
-+ switch (xn->net.type) {
-+ case NETWORK_DEFAULT:
-+ if (xn->net.prefixlen == kr6->prefixlen &&
-+ memcmp(&xn->net.prefix.v6, &kr6->prefix,
-+ sizeof(struct in6_addr)) == 0)
-+ /* static match already redistributed */
-+ return (NULL);
-+ break;
-+ case NETWORK_STATIC:
-+ if (kr6->flags & F_STATIC)
-+ return (xn);
-+ break;
-+ case NETWORK_CONNECTED:
-+ if (kr6->flags & F_CONNECTED)
-+ return (xn);
-+ break;
-+ case NETWORK_MRTCLONE:
-+ /* can not happen */
-+ break;
- }
-+ }
-+ return (NULL);
- }
-
--struct redist_node {
-- LIST_ENTRY(redist_node) entry;
-- struct kroute *kr;
-- struct kroute6 *kr6;
--};
-+struct network *
-+kr_net_find(struct ktable *kt, struct network *n)
-+{
-+ struct network *xn;
-+
-+ TAILQ_FOREACH(xn, &kt->krn, entry) {
-+ if (n->net.type != xn->net.type ||
-+ n->net.prefixlen != xn->net.prefixlen ||
-+ n->net.rtableid != xn->net.rtableid)
-+ continue;
-+ if (memcmp(&n->net.prefix, &xn->net.prefix,
-+ sizeof(n->net.prefix)) == 0)
-+ return (xn);
-+ }
-+ return (NULL);
-+}
-+
-+int
-+kr_net_reload(u_int rtableid, struct network_head *nh)
-+{
-+ struct network *n, *xn;
-+ struct ktable *kt;
-+
-+ if ((kt = ktable_get(rtableid)) == NULL) {
-+ log_warnx("kr_net_reload: non-existent rtableid %d", rtableid);
-+ return (-1);
-+ }
-+
-+ TAILQ_FOREACH(n, &kt->krn, entry)
-+ n->net.old = 1;
-+
-+ while ((n = TAILQ_FIRST(nh)) != NULL) {
-+ TAILQ_REMOVE(nh, n, entry);
-+ n->net.old = 0;
-+ n->net.rtableid = rtableid;
-+ xn = kr_net_find(kt, n);
-+ if (xn) {
-+ xn->net.old = 0;
-+ filterset_free(&xn->net.attrset);
-+ filterset_move(&n->net.attrset, &xn->net.attrset);
-+ kr_net_delete(n);
-+ } else
-+ TAILQ_INSERT_TAIL(&kt->krn, n, entry);
-+ }
-
-+ for (n = TAILQ_FIRST(&kt->krn); n != NULL; n = xn) {
-+ xn = TAILQ_NEXT(n, entry);
-+ if (n->net.old) {
-+ if (n->net.type == NETWORK_DEFAULT)
-+ if (send_network(IMSG_NETWORK_REMOVE, &n->net,
-+ NULL))
-+ return (-1);
-+ TAILQ_REMOVE(&kt->krn, n, entry);
-+ kr_net_delete(n);
-+ }
-+ }
-
--LIST_HEAD(, redist_node) redistlist;
-+ return (0);
-+}
-
- int
--kr_redistribute(int type, struct kroute *kr)
-+kr_redistribute(int type, struct ktable *kt, struct kroute *kr)
- {
-- struct redist_node *rn;
-+ struct network *match;
-+ struct network_config net;
- u_int32_t a;
-
-+ /* shortcut for removals */
-+ if (type == IMSG_NETWORK_REMOVE) {
-+ if (!(kr->flags & F_REDISTRIBUTED))
-+ return (0); /* no match, don't redistribute */
-+ kr->flags &= ~F_REDISTRIBUTED;
-+ match = NULL;
-+ goto sendit;
-+ }
-+
- if (!(kr->flags & F_KERNEL))
- return (0);
-
-@@ -670,41 +1205,40 @@ kr_redistribute(int type, struct kroute
- if (kr->prefix.s_addr == INADDR_ANY && kr->prefixlen == 0)
- return (0);
-
-- /* Add or delete kr from list ... */
-- LIST_FOREACH(rn, &redistlist, entry)
-- if (rn->kr == kr)
-- break;
--
-- switch (type) {
-- case IMSG_NETWORK_ADD:
-- if (rn == NULL) {
-- if ((rn = calloc(1, sizeof(struct redist_node))) ==
-- NULL) {
-- log_warn("kr_redistribute");
-- return (-1);
-- }
-- rn->kr = kr;
-- LIST_INSERT_HEAD(&redistlist, rn, entry);
-- }
-- break;
-- case IMSG_NETWORK_REMOVE:
-- if (rn != NULL) {
-- LIST_REMOVE(rn, entry);
-- free(rn);
-- }
-- break;
-- default:
-- errno = EINVAL;
-- return (-1);
-- }
--
-- return (bgpd_redistribute(type, kr, NULL));
-+ match = kr_net_match(kt, kr);
-+ if (match == NULL) {
-+ if (!(kr->flags & F_REDISTRIBUTED))
-+ return (0); /* no match, don't redistribute */
-+ /* route no longer matches but is redistributed, so remove */
-+ kr->flags &= ~F_REDISTRIBUTED;
-+ type = IMSG_NETWORK_REMOVE;
-+ } else
-+ kr->flags |= F_REDISTRIBUTED;
-+
-+sendit:
-+ bzero(&net, sizeof(net));
-+ net.prefix.aid = AID_INET;
-+ net.prefix.v4.s_addr = kr->prefix.s_addr;
-+ net.prefixlen = kr->prefixlen;
-+ net.rtableid = kt->rtableid;
-+
-+ return (send_network(type, &net, match ? &match->net.attrset : NULL));
- }
-
- int
--kr_redistribute6(int type, struct kroute6 *kr6)
--{
-- struct redist_node *rn;
-+kr_redistribute6(int type, struct ktable *kt, struct kroute6 *kr6)
-+{
-+ struct network *match;
-+ struct network_config net;
-+
-+ /* shortcut for removals */
-+ if (type == IMSG_NETWORK_REMOVE) {
-+ if (!(kr6->flags & F_REDISTRIBUTED))
-+ return (0); /* no match, don't redistribute */
-+ kr6->flags &= ~F_REDISTRIBUTED;
-+ match = NULL;
-+ goto sendit;
-+ }
-
- if (!(kr6->flags & F_KERNEL))
- return (0);
-@@ -736,60 +1270,107 @@ kr_redistribute6(int type, struct kroute
- * never allow ::/0 the default route can only be redistributed
- * with announce default.
- */
-- if (memcmp(&kr6->prefix, &in6addr_any, sizeof(struct in6_addr)) == 0 &&
-- kr6->prefixlen == 0)
-+ if (kr6->prefixlen == 0 &&
-+ memcmp(&kr6->prefix, &in6addr_any, sizeof(struct in6_addr)) == 0)
- return (0);
-
-- /* Add or delete kr from list ...
-- * using a linear list to store the redistributed networks will hurt
-- * as soon as redistribute ospf comes but until then keep it simple.
-- */
-- LIST_FOREACH(rn, &redistlist, entry)
-- if (rn->kr6 == kr6)
-- break;
--
-- switch (type) {
-- case IMSG_NETWORK_ADD:
-- if (rn == NULL) {
-- if ((rn = calloc(1, sizeof(struct redist_node))) ==
-- NULL) {
-- log_warn("kr_redistribute");
-- return (-1);
-- }
-- rn->kr6 = kr6;
-- LIST_INSERT_HEAD(&redistlist, rn, entry);
-- }
-- break;
-- case IMSG_NETWORK_REMOVE:
-- if (rn != NULL) {
-- LIST_REMOVE(rn, entry);
-- free(rn);
-- }
-- break;
-- default:
-- errno = EINVAL;
-- return (-1);
-- }
-+ match = kr_net_match6(kt, kr6);
-+ if (match == NULL) {
-+ if (!(kr6->flags & F_REDISTRIBUTED))
-+ return (0); /* no match, don't redistribute */
-+ /* route no longer matches but is redistributed, so remove */
-+ kr6->flags &= ~F_REDISTRIBUTED;
-+ type = IMSG_NETWORK_REMOVE;
-+ } else
-+ kr6->flags |= F_REDISTRIBUTED;
-+sendit:
-+ bzero(&net, sizeof(net));
-+ net.prefix.aid = AID_INET6;
-+ memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr));
-+ net.prefixlen = kr6->prefixlen;
-+ net.rtableid = kt->rtableid;
-
-- return (bgpd_redistribute(type, NULL, kr6));
-+ return (send_network(type, &net, match ? &match->net.attrset : NULL));
- }
-
- int
- kr_reload(void)
- {
-- struct redist_node *rn;
-+ struct ktable *kt;
-+ struct kroute_node *kr;
-+ struct kroute6_node *kr6;
- struct knexthop_node *nh;
-+ struct network *n;
-+ u_int rid;
-+ int hasdyn = 0;
-
-- LIST_FOREACH(rn, &redistlist, entry)
-- if (bgpd_redistribute(IMSG_NETWORK_ADD, rn->kr, rn->kr6) == -1)
-- return (-1);
-+ for (rid = 0; rid < krt_size; rid++) {
-+ if ((kt = ktable_get(rid)) == NULL)
-+ continue;
-
-- RB_FOREACH(nh, knexthop_tree, &knt)
-- knexthop_validate(nh);
-+ RB_FOREACH(nh, knexthop_tree, KT2KNT(kt))
-+ knexthop_validate(kt, nh);
-+
-+ TAILQ_FOREACH(n, &kt->krn, entry)
-+ if (n->net.type == NETWORK_DEFAULT) {
-+ if (send_network(IMSG_NETWORK_ADD, &n->net,
-+ &n->net.attrset))
-+ return (-1);
-+ } else
-+ hasdyn = 1;
-+
-+ if (hasdyn) {
-+ /* only evaluate the full tree if we need */
-+ RB_FOREACH(kr, kroute_tree, &kt->krt)
-+ kr_redistribute(IMSG_NETWORK_ADD, kt, &kr->r);
-+ RB_FOREACH(kr6, kroute6_tree, &kt->krt6)
-+ kr_redistribute6(IMSG_NETWORK_ADD, kt, &kr6->r);
-+ }
-+ }
-
- return (0);
- }
-
-+struct kroute_full *
-+kr_tofull(struct kroute *kr)
-+{
-+ static struct kroute_full kf;
-+
-+ bzero(&kf, sizeof(kf));
-+
-+ kf.prefix.aid = AID_INET;
-+ kf.prefix.v4.s_addr = kr->prefix.s_addr;
-+ kf.nexthop.aid = AID_INET;
-+ kf.nexthop.v4.s_addr = kr->nexthop.s_addr;
-+ strlcpy(kf.label, rtlabel_id2name(kr->labelid), sizeof(kf.label));
-+ kf.flags = kr->flags;
-+ kf.ifindex = kr->ifindex;
-+ kf.prefixlen = kr->prefixlen;
-+ kf.priority = kr->priority;
-+
-+ return (&kf);
-+}
-+
-+struct kroute_full *
-+kr6_tofull(struct kroute6 *kr6)
-+{
-+ static struct kroute_full kf;
-+
-+ bzero(&kf, sizeof(kf));
-+
-+ kf.prefix.aid = AID_INET6;
-+ memcpy(&kf.prefix.v6, &kr6->prefix, sizeof(struct in6_addr));
-+ kf.nexthop.aid = AID_INET6;
-+ memcpy(&kf.nexthop.v6, &kr6->nexthop, sizeof(struct in6_addr));
-+ strlcpy(kf.label, rtlabel_id2name(kr6->labelid), sizeof(kf.label));
-+ kf.flags = kr6->flags;
-+ kf.ifindex = kr6->ifindex;
-+ kf.prefixlen = kr6->prefixlen;
-+ kf.priority = kr6->priority;
-+
-+ return (&kf);
-+}
-+
- /*
- * RB-tree compare functions
- */
-@@ -846,26 +1427,28 @@ kroute6_compare(struct kroute6_node *a,
- int
- knexthop_compare(struct knexthop_node *a, struct knexthop_node *b)
- {
-- u_int32_t r;
-+ int i;
-
-- if (a->nexthop.af != b->nexthop.af)
-- return (b->nexthop.af - a->nexthop.af);
-+ if (a->nexthop.aid != b->nexthop.aid)
-+ return (b->nexthop.aid - a->nexthop.aid);
-
-- switch (a->nexthop.af) {
-- case AF_INET:
-- if ((r = b->nexthop.addr32[0] - a->nexthop.addr32[0]) != 0)
-- return (r);
-+ switch (a->nexthop.aid) {
-+ case AID_INET:
-+ if (ntohl(a->nexthop.v4.s_addr) < ntohl(b->nexthop.v4.s_addr))
-+ return (-1);
-+ if (ntohl(a->nexthop.v4.s_addr) > ntohl(b->nexthop.v4.s_addr))
-+ return (1);
- break;
-- case AF_INET6:
-- if ((r = b->nexthop.addr32[3] - a->nexthop.addr32[3]) != 0)
-- return (r);
-- if ((r = b->nexthop.addr32[2] - a->nexthop.addr32[2]) != 0)
-- return (r);
-- if ((r = b->nexthop.addr32[1] - a->nexthop.addr32[1]) != 0)
-- return (r);
-- if ((r = b->nexthop.addr32[0] - a->nexthop.addr32[0]) != 0)
-- return (r);
-+ case AID_INET6:
-+ for (i = 0; i < 16; i++) {
-+ if (a->nexthop.v6.s6_addr[i] < b->nexthop.v6.s6_addr[i])
-+ return (-1);
-+ if (a->nexthop.v6.s6_addr[i] > b->nexthop.v6.s6_addr[i])
-+ return (1);
-+ }
- break;
-+ default:
-+ fatalx("knexthop_compare: unknown AF");
- }
-
- return (0);
-@@ -883,7 +1466,8 @@ kif_compare(struct kif_node *a, struct k
- */
-
- struct kroute_node *
--kroute_find(in_addr_t prefix, u_int8_t prefixlen, u_int8_t prio)
-+kroute_find(struct ktable *kt, in_addr_t prefix, u_int8_t prefixlen,
-+ u_int8_t prio)
- {
- struct kroute_node s;
- struct kroute_node *kn, *tmp;
-@@ -892,15 +1476,15 @@ kroute_find(in_addr_t prefix, u_int8_t p
- s.r.prefixlen = prefixlen;
- s.r.priority = prio;
-
-- kn = RB_FIND(kroute_tree, &krt, &s);
-+ kn = RB_FIND(kroute_tree, &kt->krt, &s);
- if (kn && prio == RTP_ANY) {
-- tmp = RB_PREV(kroute_tree, &krt, kn);
-+ tmp = RB_PREV(kroute_tree, &kt->krt, kn);
- while (tmp) {
- if (kroute_compare(&s, tmp) == 0)
- kn = tmp;
- else
- break;
-- tmp = RB_PREV(kroute_tree, &krt, kn);
-+ tmp = RB_PREV(kroute_tree, &kt->krt, kn);
- }
- }
- return (kn);
-@@ -927,13 +1511,13 @@ kroute_matchgw(struct kroute_node *kr, s
- }
-
- int
--kroute_insert(struct kroute_node *kr)
-+kroute_insert(struct ktable *kt, struct kroute_node *kr)
- {
- struct kroute_node *krm;
- struct knexthop_node *h;
- in_addr_t mask, ina;
-
-- if ((krm = RB_INSERT(kroute_tree, &krt, kr)) != NULL) {
-+ if ((krm = RB_INSERT(kroute_tree, &kt->krt, kr)) != NULL) {
- /* multipath route, add at end of list */
- while (krm->next != NULL)
- krm = krm->next;
-@@ -941,13 +1525,14 @@ kroute_insert(struct kroute_node *kr)
- kr->next = NULL; /* to be sure */
- }
-
-+ /* XXX this is wrong for nexthop validated via BGP */
- if (kr->r.flags & F_KERNEL) {
- mask = prefixlen2mask(kr->r.prefixlen);
- ina = ntohl(kr->r.prefix.s_addr);
-- RB_FOREACH(h, knexthop_tree, &knt)
-- if (h->nexthop.af == AF_INET &&
-+ RB_FOREACH(h, knexthop_tree, KT2KNT(kt))
-+ if (h->nexthop.aid == AID_INET &&
- (ntohl(h->nexthop.v4.s_addr) & mask) == ina)
-- knexthop_validate(h);
-+ knexthop_validate(kt, h);
-
- if (kr->r.flags & F_CONNECTED)
- if (kif_kr_insert(kr) == -1)
-@@ -955,19 +1540,19 @@ kroute_insert(struct kroute_node *kr)
-
- if (krm == NULL)
- /* redistribute multipath routes only once */
-- kr_redistribute(IMSG_NETWORK_ADD, &kr->r);
-+ kr_redistribute(IMSG_NETWORK_ADD, kt, &kr->r);
- }
- return (0);
- }
-
-
- int
--kroute_remove(struct kroute_node *kr)
-+kroute_remove(struct ktable *kt, struct kroute_node *kr)
- {
- struct kroute_node *krm;
- struct knexthop_node *s;
-
-- if ((krm = RB_FIND(kroute_tree, &krt, kr)) == NULL) {
-+ if ((krm = RB_FIND(kroute_tree, &kt->krt, kr)) == NULL) {
- log_warnx("kroute_remove failed to find %s/%u",
- inet_ntoa(kr->r.prefix), kr->r.prefixlen);
- return (-1);
-@@ -975,13 +1560,14 @@ kroute_remove(struct kroute_node *kr)
-
- if (krm == kr) {
- /* head element */
-- if (RB_REMOVE(kroute_tree, &krt, kr) == NULL) {
-+ if (RB_REMOVE(kroute_tree, &kt->krt, kr) == NULL) {
- log_warnx("kroute_remove failed for %s/%u",
- inet_ntoa(kr->r.prefix), kr->r.prefixlen);
- return (-1);
- }
- if (kr->next != NULL) {
-- if (RB_INSERT(kroute_tree, &krt, kr->next) != NULL) {
-+ if (RB_INSERT(kroute_tree, &kt->krt, kr->next) !=
-+ NULL) {
- log_warnx("kroute_remove failed to add %s/%u",
- inet_ntoa(kr->r.prefix), kr->r.prefixlen);
- return (-1);
-@@ -1001,14 +1587,14 @@ kroute_remove(struct kroute_node *kr)
- }
-
- /* check whether a nexthop depends on this kroute */
-- if ((kr->r.flags & F_KERNEL) && (kr->r.flags & F_NEXTHOP))
-- RB_FOREACH(s, knexthop_tree, &knt)
-+ if (kr->r.flags & F_NEXTHOP)
-+ RB_FOREACH(s, knexthop_tree, KT2KNT(kt))
- if (s->kroute == kr)
-- knexthop_validate(s);
-+ knexthop_validate(kt, s);
-
- if (kr->r.flags & F_KERNEL && kr == krm && kr->next == NULL)
- /* again remove only once */
-- kr_redistribute(IMSG_NETWORK_REMOVE, &kr->r);
-+ kr_redistribute(IMSG_NETWORK_REMOVE, kt, &kr->r);
-
- if (kr->r.flags & F_CONNECTED)
- if (kif_kr_remove(kr) == -1) {
-@@ -1021,16 +1607,17 @@ kroute_remove(struct kroute_node *kr)
- }
-
- void
--kroute_clear(void)
-+kroute_clear(struct ktable *kt)
- {
- struct kroute_node *kr;
-
-- while ((kr = RB_MIN(kroute_tree, &krt)) != NULL)
-- kroute_remove(kr);
-+ while ((kr = RB_MIN(kroute_tree, &kt->krt)) != NULL)
-+ kroute_remove(kt, kr);
- }
-
- struct kroute6_node *
--kroute6_find(const struct in6_addr *prefix, u_int8_t prefixlen, u_int8_t prio)
-+kroute6_find(struct ktable *kt, const struct in6_addr *prefix,
-+ u_int8_t prefixlen, u_int8_t prio)
- {
- struct kroute6_node s;
- struct kroute6_node *kn6, *tmp;
-@@ -1039,15 +1626,15 @@ kroute6_find(const struct in6_addr *pref
- s.r.prefixlen = prefixlen;
- s.r.priority = prio;
-
-- kn6 = RB_FIND(kroute6_tree, &krt6, &s);
-+ kn6 = RB_FIND(kroute6_tree, &kt->krt6, &s);
- if (kn6 && prio == RTP_ANY) {
-- tmp = RB_PREV(kroute6_tree, &krt6, kn6);
-+ tmp = RB_PREV(kroute6_tree, &kt->krt6, kn6);
- while (tmp) {
- if (kroute6_compare(&s, tmp) == 0)
- kn6 = tmp;
-- else
-+ else
- break;
-- tmp = RB_PREV(kroute6_tree, &krt6, kn6);
-+ tmp = RB_PREV(kroute6_tree, &kt->krt6, kn6);
- }
- }
- return (kn6);
-@@ -1056,17 +1643,29 @@ kroute6_find(const struct in6_addr *pref
- struct kroute6_node *
- kroute6_matchgw(struct kroute6_node *kr, struct sockaddr_in6 *sa_in6)
- {
-- struct in6_addr nexthop;
-+ struct sockaddr_in6 nexthop;
-
- if (sa_in6 == NULL) {
- log_warnx("kroute6_matchgw: no nexthop defined");
- return (NULL);
- }
-- memcpy(&nexthop, &sa_in6->sin6_addr, sizeof(nexthop));
-+ memcpy(&nexthop, sa_in6, sizeof(nexthop));
-+#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER)
-+ if (IN6_IS_ADDR_LINKLOCAL(&nexthop.sin6_addr)) {
-+ /* Embed scope id and set sin6_scope_id. */
-+ if (nexthop.sin6_scope_id == 0)
-+ nexthop.sin6_scope_id =
-+ IN6_LINKLOCAL_IFINDEX(nexthop.sin6_addr);
-+ else
-+ SET_IN6_LINKLOCAL_IFINDEX(nexthop.sin6_addr,
-+ nexthop.sin6_scope_id);
-+ }
-+#endif
-
- while (kr) {
-- if (memcmp(&kr->r.nexthop, &nexthop, sizeof(nexthop)) == NULL)
-- return (kr);
-+ if (memcmp(&kr->r.nexthop, &nexthop.sin6_addr,
-+ sizeof(nexthop.sin6_addr)) == 0)
-+ return (kr);
- kr = kr->next;
- }
-
-@@ -1074,13 +1673,13 @@ kroute6_matchgw(struct kroute6_node *kr,
- }
-
- int
--kroute6_insert(struct kroute6_node *kr)
-+kroute6_insert(struct ktable *kt, struct kroute6_node *kr)
- {
- struct kroute6_node *krm;
- struct knexthop_node *h;
- struct in6_addr ina, inb;
-
-- if ((krm = RB_INSERT(kroute6_tree, &krt6, kr)) != NULL) {
-+ if ((krm = RB_INSERT(kroute6_tree, &kt->krt6, kr)) != NULL) {
- /* multipath route, add at end of list */
- while (krm->next != NULL)
- krm = krm->next;
-@@ -1088,14 +1687,15 @@ kroute6_insert(struct kroute6_node *kr)
- kr->next = NULL; /* to be sure */
- }
-
-+ /* XXX this is wrong for nexthop validated via BGP */
- if (kr->r.flags & F_KERNEL) {
- inet6applymask(&ina, &kr->r.prefix, kr->r.prefixlen);
-- RB_FOREACH(h, knexthop_tree, &knt)
-- if (h->nexthop.af == AF_INET6) {
-+ RB_FOREACH(h, knexthop_tree, KT2KNT(kt))
-+ if (h->nexthop.aid == AID_INET6) {
- inet6applymask(&inb, &h->nexthop.v6,
- kr->r.prefixlen);
- if (memcmp(&ina, &inb, sizeof(ina)) == 0)
-- knexthop_validate(h);
-+ knexthop_validate(kt, h);
- }
-
- if (kr->r.flags & F_CONNECTED)
-@@ -1104,19 +1704,19 @@ kroute6_insert(struct kroute6_node *kr)
-
- if (krm == NULL)
- /* redistribute multipath routes only once */
-- kr_redistribute6(IMSG_NETWORK_ADD, &kr->r);
-+ kr_redistribute6(IMSG_NETWORK_ADD, kt, &kr->r);
- }
-
- return (0);
- }
-
- int
--kroute6_remove(struct kroute6_node *kr)
-+kroute6_remove(struct ktable *kt, struct kroute6_node *kr)
- {
- struct kroute6_node *krm;
- struct knexthop_node *s;
-
-- if ((krm = RB_FIND(kroute6_tree, &krt6, kr)) == NULL) {
-+ if ((krm = RB_FIND(kroute6_tree, &kt->krt6, kr)) == NULL) {
- log_warnx("kroute6_remove failed for %s/%u",
- log_in6addr(&kr->r.prefix), kr->r.prefixlen);
- return (-1);
-@@ -1124,13 +1724,14 @@ kroute6_remove(struct kroute6_node *kr)
-
- if (krm == kr) {
- /* head element */
-- if (RB_REMOVE(kroute6_tree, &krt6, kr) == NULL) {
-+ if (RB_REMOVE(kroute6_tree, &kt->krt6, kr) == NULL) {
- log_warnx("kroute6_remove failed for %s/%u",
- log_in6addr(&kr->r.prefix), kr->r.prefixlen);
- return (-1);
- }
- if (kr->next != NULL) {
-- if (RB_INSERT(kroute6_tree, &krt6, kr->next) != NULL) {
-+ if (RB_INSERT(kroute6_tree, &kt->krt6, kr->next) !=
-+ NULL) {
- log_warnx("kroute6_remove failed to add %s/%u",
- log_in6addr(&kr->r.prefix),
- kr->r.prefixlen);
-@@ -1151,14 +1752,14 @@ kroute6_remove(struct kroute6_node *kr)
- }
-
- /* check whether a nexthop depends on this kroute */
-- if ((kr->r.flags & F_KERNEL) && (kr->r.flags & F_NEXTHOP))
-- RB_FOREACH(s, knexthop_tree, &knt)
-+ if (kr->r.flags & F_NEXTHOP)
-+ RB_FOREACH(s, knexthop_tree, KT2KNT(kt))
- if (s->kroute == kr)
-- knexthop_validate(s);
-+ knexthop_validate(kt, s);
-
- if (kr->r.flags & F_KERNEL && kr == krm && kr->next == NULL)
- /* again remove only once */
-- kr_redistribute6(IMSG_NETWORK_REMOVE, &kr->r);
-+ kr_redistribute6(IMSG_NETWORK_REMOVE, kt, &kr->r);
-
- if (kr->r.flags & F_CONNECTED)
- if (kif_kr6_remove(kr) == -1) {
-@@ -1171,45 +1772,46 @@ kroute6_remove(struct kroute6_node *kr)
- }
-
- void
--kroute6_clear(void)
-+kroute6_clear(struct ktable *kt)
- {
- struct kroute6_node *kr;
-
-- while ((kr = RB_MIN(kroute6_tree, &krt6)) != NULL)
-- kroute6_remove(kr);
-+ while ((kr = RB_MIN(kroute6_tree, &kt->krt6)) != NULL)
-+ kroute6_remove(kt, kr);
- }
-
- struct knexthop_node *
--knexthop_find(struct bgpd_addr *addr)
-+knexthop_find(struct ktable *kt, struct bgpd_addr *addr)
- {
- struct knexthop_node s;
-
-+ bzero(&s, sizeof(s));
- memcpy(&s.nexthop, addr, sizeof(s.nexthop));
-
-- return (RB_FIND(knexthop_tree, &knt, &s));
-+ return (RB_FIND(knexthop_tree, KT2KNT(kt), &s));
- }
-
- int
--knexthop_insert(struct knexthop_node *kn)
-+knexthop_insert(struct ktable *kt, struct knexthop_node *kn)
- {
-- if (RB_INSERT(knexthop_tree, &knt, kn) != NULL) {
-+ if (RB_INSERT(knexthop_tree, KT2KNT(kt), kn) != NULL) {
- log_warnx("knexthop_tree insert failed for %s",
- log_addr(&kn->nexthop));
- free(kn);
- return (-1);
- }
-
-- knexthop_validate(kn);
-+ knexthop_validate(kt, kn);
-
- return (0);
- }
-
- int
--knexthop_remove(struct knexthop_node *kn)
-+knexthop_remove(struct ktable *kt, struct knexthop_node *kn)
- {
-- kroute_detach_nexthop(kn);
-+ kroute_detach_nexthop(kt, kn);
-
-- if (RB_REMOVE(knexthop_tree, &knt, kn) == NULL) {
-+ if (RB_REMOVE(knexthop_tree, KT2KNT(kt), kn) == NULL) {
- log_warnx("knexthop_remove failed for %s",
- log_addr(&kn->nexthop));
- return (-1);
-@@ -1220,12 +1822,12 @@ knexthop_remove(struct knexthop_node *kn
- }
-
- void
--knexthop_clear(void)
-+knexthop_clear(struct ktable *kt)
- {
- struct knexthop_node *kn;
-
-- while ((kn = RB_MIN(knexthop_tree, &knt)) != NULL)
-- knexthop_remove(kn);
-+ while ((kn = RB_MIN(knexthop_tree, KT2KNT(kt))) != NULL)
-+ knexthop_remove(kt, kn);
- }
-
- struct kif_node *
-@@ -1257,6 +1859,7 @@ kif_insert(struct kif_node *kif)
- int
- kif_remove(struct kif_node *kif)
- {
-+ struct ktable *kt;
- struct kif_kr *kkr;
- struct kif_kr6 *kkr6;
-
-@@ -1265,20 +1868,23 @@ kif_remove(struct kif_node *kif)
- return (-1);
- }
-
-+ if ((kt = ktable_get(/* XXX */ 0)) == NULL)
-+ goto done;
-+
- while ((kkr = LIST_FIRST(&kif->kroute_l)) != NULL) {
- LIST_REMOVE(kkr, entry);
- kkr->kr->r.flags &= ~F_NEXTHOP;
-- kroute_remove(kkr->kr);
-+ kroute_remove(kt, kkr->kr);
- free(kkr);
- }
-
- while ((kkr6 = LIST_FIRST(&kif->kroute6_l)) != NULL) {
- LIST_REMOVE(kkr6, entry);
- kkr6->kr->r.flags &= ~F_NEXTHOP;
-- kroute6_remove(kkr6->kr);
-+ kroute6_remove(kt, kkr6->kr);
- free(kkr6);
- }
--
-+done:
- free(kif);
- return (0);
- }
-@@ -1473,113 +2079,109 @@ kroute6_validate(struct kroute6 *kr)
- }
-
- void
--knexthop_validate(struct knexthop_node *kn)
-+knexthop_validate(struct ktable *kt, struct knexthop_node *kn)
- {
-+ void *oldk;
- struct kroute_node *kr;
- struct kroute6_node *kr6;
-- struct kroute_nexthop n;
-- int was_valid = 0;
-
-- if (kn->nexthop.af == AF_INET && (kr = kn->kroute) != NULL)
-- was_valid = kroute_validate(&kr->r);
-- if (kn->nexthop.af == AF_INET6 && (kr6 = kn->kroute) != NULL)
-- was_valid = kroute6_validate(&kr6->r);
-+ oldk = kn->kroute;
-+ kroute_detach_nexthop(kt, kn);
-
-- bzero(&n, sizeof(n));
-- memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop));
-- kroute_detach_nexthop(kn);
--
-- switch (kn->nexthop.af) {
-- case AF_INET:
-- if ((kr = kroute_match(kn->nexthop.v4.s_addr, 0)) == NULL) {
-- if (was_valid)
-- send_nexthop_update(&n);
-- } else { /* match */
-- if (kroute_validate(&kr->r)) { /* valid */
-- n.valid = 1;
-- n.connected = kr->r.flags & F_CONNECTED;
-- if ((n.gateway.v4.s_addr =
-- kr->r.nexthop.s_addr) != 0)
-- n.gateway.af = AF_INET;
-- memcpy(&n.kr.kr4, &kr->r, sizeof(n.kr.kr4));
-- send_nexthop_update(&n);
-- } else /* down */
-- if (was_valid)
-- send_nexthop_update(&n);
-+ switch (kn->nexthop.aid) {
-+ case AID_INET:
-+ kr = kroute_match(kt, kn->nexthop.v4.s_addr, 0);
-
-+ if (kr) {
- kn->kroute = kr;
- kr->r.flags |= F_NEXTHOP;
- }
-+
-+ /*
-+ * Send update if nexthop route changed under us if
-+ * the route remains the same then the NH state has not
-+ * changed. State changes are tracked by knexthop_track().
-+ */
-+ if (kr != oldk)
-+ knexthop_send_update(kn);
- break;
-- case AF_INET6:
-- if ((kr6 = kroute6_match(&kn->nexthop.v6, 0)) == NULL) {
-- if (was_valid)
-- send_nexthop_update(&n);
-- } else { /* match */
-- if (kroute6_validate(&kr6->r)) { /* valid */
-- n.valid = 1;
-- n.connected = kr6->r.flags & F_CONNECTED;
-- if (memcmp(&kr6->r.nexthop, &in6addr_any,
-- sizeof(struct in6_addr)) != 0) {
-- n.gateway.af = AF_INET6;
-- memcpy(&n.gateway.v6, &kr6->r.nexthop,
-- sizeof(struct in6_addr));
-- }
-- memcpy(&n.kr.kr6, &kr6->r, sizeof(n.kr.kr6));
-- send_nexthop_update(&n);
-- } else /* down */
-- if (was_valid)
-- send_nexthop_update(&n);
-+ case AID_INET6:
-+ kr6 = kroute6_match(kt, &kn->nexthop.v6, 0);
-
-+ if (kr6) {
- kn->kroute = kr6;
- kr6->r.flags |= F_NEXTHOP;
- }
-+
-+ if (kr6 != oldk)
-+ knexthop_send_update(kn);
- break;
- }
- }
-
- void
--knexthop_track(void *krn)
-+knexthop_track(struct ktable *kt, void *krp)
- {
- struct knexthop_node *kn;
-+
-+ RB_FOREACH(kn, knexthop_tree, KT2KNT(kt))
-+ if (kn->kroute == krp)
-+ knexthop_send_update(kn);
-+}
-+
-+void
-+knexthop_send_update(struct knexthop_node *kn)
-+{
-+ struct kroute_nexthop n;
- struct kroute_node *kr;
- struct kroute6_node *kr6;
-- struct kroute_nexthop n;
-
-- RB_FOREACH(kn, knexthop_tree, &knt)
-- if (kn->kroute == krn) {
-- bzero(&n, sizeof(n));
-- memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop));
-+ bzero(&n, sizeof(n));
-+ memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop));
-
-- switch (kn->nexthop.af) {
-- case AF_INET:
-- kr = krn;
-- n.valid = 1;
-- n.connected = kr->r.flags & F_CONNECTED;
-- if ((n.gateway.v4.s_addr =
-- kr->r.nexthop.s_addr) != 0)
-- n.gateway.af = AF_INET;
-- memcpy(&n.kr.kr4, &kr->r, sizeof(n.kr.kr4));
-- break;
-- case AF_INET6:
-- kr6 = krn;
-- n.valid = 1;
-- n.connected = kr6->r.flags & F_CONNECTED;
-- if (memcmp(&kr6->r.nexthop, &in6addr_any,
-- sizeof(struct in6_addr)) != 0) {
-- n.gateway.af = AF_INET6;
-- memcpy(&n.gateway.v6, &kr6->r.nexthop,
-- sizeof(struct in6_addr));
-- }
-- memcpy(&n.kr.kr6, &kr6->r, sizeof(n.kr.kr6));
-- break;
-- }
-- send_nexthop_update(&n);
-+ if (kn->kroute == NULL) {
-+ n.valid = 0; /* NH is not valid */
-+ send_nexthop_update(&n);
-+ return;
-+ }
-+
-+ switch (kn->nexthop.aid) {
-+ case AID_INET:
-+ kr = kn->kroute;
-+ n.valid = kroute_validate(&kr->r);
-+ n.connected = kr->r.flags & F_CONNECTED;
-+ if ((n.gateway.v4.s_addr =
-+ kr->r.nexthop.s_addr) != 0)
-+ n.gateway.aid = AID_INET;
-+ if (n.connected) {
-+ n.net.aid = AID_INET;
-+ n.net.v4.s_addr = kr->r.prefix.s_addr;
-+ n.netlen = kr->r.prefixlen;
- }
-+ break;
-+ case AID_INET6:
-+ kr6 = kn->kroute;
-+ n.valid = kroute6_validate(&kr6->r);
-+ n.connected = kr6->r.flags & F_CONNECTED;
-+ if (memcmp(&kr6->r.nexthop, &in6addr_any,
-+ sizeof(struct in6_addr)) != 0) {
-+ n.gateway.aid = AID_INET6;
-+ memcpy(&n.gateway.v6, &kr6->r.nexthop,
-+ sizeof(struct in6_addr));
-+ }
-+ if (n.connected) {
-+ n.net.aid = AID_INET6;
-+ memcpy(&n.net.v6, &kr6->r.nexthop,
-+ sizeof(struct in6_addr));
-+ n.netlen = kr6->r.prefixlen;
-+ }
-+ break;
-+ }
-+ send_nexthop_update(&n);
- }
-
- struct kroute_node *
--kroute_match(in_addr_t key, int matchall)
-+kroute_match(struct ktable *kt, in_addr_t key, int matchall)
- {
- int i;
- struct kroute_node *kr;
-@@ -1589,13 +2191,13 @@ kroute_match(in_addr_t key, int matchall
-
- /* we will never match the default route */
- for (i = 32; i > 0; i--)
-- if ((kr = kroute_find(htonl(ina & prefixlen2mask(i)), i,
-+ if ((kr = kroute_find(kt, htonl(ina & prefixlen2mask(i)), i,
- RTP_ANY)) != NULL)
- if (matchall || bgpd_filternexthop(&kr->r, NULL) == 0)
- return (kr);
-
- /* if we don't have a match yet, try to find a default route */
-- if ((kr = kroute_find(0, 0, RTP_ANY)) != NULL)
-+ if ((kr = kroute_find(kt, 0, 0, RTP_ANY)) != NULL)
- if (matchall || bgpd_filternexthop(&kr->r, NULL) == 0)
- return (kr);
-
-@@ -1603,7 +2205,7 @@ kroute_match(in_addr_t key, int matchall
- }
-
- struct kroute6_node *
--kroute6_match(struct in6_addr *key, int matchall)
-+kroute6_match(struct ktable *kt, struct in6_addr *key, int matchall)
- {
- int i;
- struct kroute6_node *kr6;
-@@ -1612,13 +2214,13 @@ kroute6_match(struct in6_addr *key, int
- /* we will never match the default route */
- for (i = 128; i > 0; i--) {
- inet6applymask(&ina, key, i);
-- if ((kr6 = kroute6_find(&ina, i, RTP_ANY)) != NULL)
-+ if ((kr6 = kroute6_find(kt, &ina, i, RTP_ANY)) != NULL)
- if (matchall || bgpd_filternexthop(NULL, &kr6->r) == 0)
- return (kr6);
- }
-
- /* if we don't have a match yet, try to find a default route */
-- if ((kr6 = kroute6_find(&in6addr_any, 0, RTP_ANY)) != NULL)
-+ if ((kr6 = kroute6_find(kt, &in6addr_any, 0, RTP_ANY)) != NULL)
- if (matchall || bgpd_filternexthop(NULL, &kr6->r) == 0)
- return (kr6);
-
-@@ -1626,31 +2228,30 @@ kroute6_match(struct in6_addr *key, int
- }
-
- void
--kroute_detach_nexthop(struct knexthop_node *kn)
-+kroute_detach_nexthop(struct ktable *kt, struct knexthop_node *kn)
- {
- struct knexthop_node *s;
- struct kroute_node *k;
- struct kroute6_node *k6;
-
-+ if (kn->kroute == NULL)
-+ return;
-+
- /*
- * check whether there's another nexthop depending on this kroute
- * if not remove the flag
- */
--
-- if (kn->kroute == NULL)
-- return;
--
-- for (s = RB_MIN(knexthop_tree, &knt); s != NULL &&
-- s->kroute != kn->kroute; s = RB_NEXT(knexthop_tree, &knt, s))
-- ; /* nothing */
-+ RB_FOREACH(s, knexthop_tree, KT2KNT(kt))
-+ if (s->kroute == kn->kroute && s != kn)
-+ break;
-
- if (s == NULL) {
-- switch (kn->nexthop.af) {
-- case AF_INET:
-+ switch (kn->nexthop.aid) {
-+ case AID_INET:
- k = kn->kroute;
- k->r.flags &= ~F_NEXTHOP;
- break;
-- case AF_INET6:
-+ case AID_INET6:
- k6 = kn->kroute;
- k6->r.flags &= ~F_NEXTHOP;
- break;
-@@ -1665,7 +2266,7 @@ kroute_detach_nexthop(struct knexthop_no
- */
-
- int
--protect_lo(void)
-+protect_lo(struct ktable *kt)
- {
- struct kroute_node *kr;
- struct kroute6_node *kr6;
-@@ -1675,11 +2276,11 @@ protect_lo(void)
- log_warn("protect_lo");
- return (-1);
- }
-- kr->r.prefix.s_addr = htonl(INADDR_LOOPBACK);
-+ kr->r.prefix.s_addr = htonl(INADDR_LOOPBACK & IN_CLASSA_NET);
- kr->r.prefixlen = 8;
- kr->r.flags = F_KERNEL|F_CONNECTED;
-
-- if (RB_INSERT(kroute_tree, &krt, kr) != NULL)
-+ if (RB_INSERT(kroute_tree, &kt->krt, kr) != NULL)
- free(kr); /* kernel route already there, no problem */
-
- /* special protection for loopback */
-@@ -1689,9 +2290,9 @@ protect_lo(void)
- }
- memcpy(&kr6->r.prefix, &in6addr_loopback, sizeof(kr6->r.prefix));
- kr6->r.prefixlen = 128;
-- kr->r.flags = F_KERNEL|F_CONNECTED;
-+ kr6->r.flags = F_KERNEL|F_CONNECTED;
-
-- if (RB_INSERT(kroute6_tree, &krt6, kr6) != NULL)
-+ if (RB_INSERT(kroute6_tree, &kt->krt6, kr6) != NULL)
- free(kr6); /* kernel route already there, no problem */
-
- return (0);
-@@ -1726,17 +2327,17 @@ mask2prefixlen(in_addr_t ina)
- u_int8_t
- mask2prefixlen6(struct sockaddr_in6 *sa_in6)
- {
-- u_int8_t l = 0, i, len;
-+ u_int8_t l = 0, *ap, *ep;
-
- /*
- * sin6_len is the size of the sockaddr so substract the offset of
- * the possibly truncated sin6_addr struct.
- */
-- len = sa_in6->sin6_len -
-- (u_int8_t)(&((struct sockaddr_in6 *)NULL)->sin6_addr);
-- for (i = 0; i < len; i++) {
-+ ap = (u_int8_t *)&sa_in6->sin6_addr;
-+ ep = (u_int8_t *)sa_in6 + sa_in6->sin6_len;
-+ for (; ap < ep; ap++) {
- /* this "beauty" is adopted from sbin/route/show.c ... */
-- switch (sa_in6->sin6_addr.s6_addr[i]) {
-+ switch (*ap) {
- case 0xff:
- l += 8;
- break;
-@@ -1764,7 +2365,7 @@ mask2prefixlen6(struct sockaddr_in6 *sa_
- case 0x00:
- return (l);
- default:
-- fatalx("non continguous inet6 netmask");
-+ fatalx("non contiguous inet6 netmask");
- }
- }
-
-@@ -1788,7 +2389,7 @@ prefixlen2mask6(u_int8_t prefixlen)
- }
-
- #define ROUNDUP(a) \
-- (((a) & ((sizeof(long)) - 1)) ? (1 + ((a) | ((sizeof(long)) - 1))) : (a))
-+ (((a) & (sizeof(long) - 1)) ? (1 + ((a) | (sizeof(long) - 1))) : (a))
-
- void
- get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
-@@ -1808,11 +2409,10 @@ get_rtaddrs(int addrs, struct sockaddr *
- void
- if_change(u_short ifindex, int flags, struct if_data *ifd)
- {
-+ struct ktable *kt;
- struct kif_node *kif;
- struct kif_kr *kkr;
- struct kif_kr6 *kkr6;
-- struct kroute_nexthop nh;
-- struct knexthop_node *n;
- u_int8_t reachable;
-
- if ((kif = kif_find(ifindex)) == NULL) {
-@@ -1833,28 +2433,18 @@ if_change(u_short ifindex, int flags, st
-
- kif->k.nh_reachable = reachable;
-
-+ kt = ktable_get(/* XXX */ 0);
-+
- LIST_FOREACH(kkr, &kif->kroute_l, entry) {
- if (reachable)
- kkr->kr->r.flags &= ~F_DOWN;
- else
- kkr->kr->r.flags |= F_DOWN;
-
-- RB_FOREACH(n, knexthop_tree, &knt)
-- if (n->kroute == kkr->kr) {
-- bzero(&nh, sizeof(nh));
-- memcpy(&nh.nexthop, &n->nexthop,
-- sizeof(nh.nexthop));
-- if (kroute_validate(&kkr->kr->r)) {
-- nh.valid = 1;
-- nh.connected = 1;
-- if ((nh.gateway.v4.s_addr =
-- kkr->kr->r.nexthop.s_addr) != 0)
-- nh.gateway.af = AF_INET;
-- }
-- memcpy(&nh.kr.kr4, &kkr->kr->r,
-- sizeof(nh.kr.kr4));
-- send_nexthop_update(&nh);
-- }
-+ if (kt == NULL)
-+ continue;
-+
-+ knexthop_track(kt, kkr->kr);
- }
- LIST_FOREACH(kkr6, &kif->kroute6_l, entry) {
- if (reachable)
-@@ -1862,27 +2452,10 @@ if_change(u_short ifindex, int flags, st
- else
- kkr6->kr->r.flags |= F_DOWN;
-
-- RB_FOREACH(n, knexthop_tree, &knt)
-- if (n->kroute == kkr6->kr) {
-- bzero(&nh, sizeof(nh));
-- memcpy(&nh.nexthop, &n->nexthop,
-- sizeof(nh.nexthop));
-- if (kroute6_validate(&kkr6->kr->r)) {
-- nh.valid = 1;
-- nh.connected = 1;
-- if (memcmp(&kkr6->kr->r.nexthop,
-- &in6addr_any, sizeof(struct
-- in6_addr))) {
-- nh.gateway.af = AF_INET6;
-- memcpy(&nh.gateway.v6,
-- &kkr6->kr->r.nexthop,
-- sizeof(struct in6_addr));
-- }
-- }
-- memcpy(&nh.kr.kr6, &kkr6->kr->r,
-- sizeof(nh.kr.kr6));
-- send_nexthop_update(&nh);
-- }
-+ if (kt == NULL)
-+ continue;
-+
-+ knexthop_track(kt, kkr6->kr);
- }
- }
-
-@@ -1917,25 +2490,38 @@ if_announce(void *msg)
- */
-
- int
--send_rtmsg(int fd, int action, struct kroute *kroute)
-+send_rtmsg(int fd, int action, struct ktable *kt, struct kroute *kroute)
- {
-- struct iovec iov[5];
-+ struct iovec iov[7];
- struct rt_msghdr hdr;
- struct sockaddr_in prefix;
- struct sockaddr_in nexthop;
- struct sockaddr_in mask;
-+ struct {
-+ struct sockaddr_dl dl;
-+ char pad[sizeof(long)];
-+ } ifp;
-+#if !defined(__FreeBSD__) /* FreeBSD has no route labeling. */
-+ struct sockaddr_mpls mpls;
- struct sockaddr_rtlabel label;
-+#endif /* !defined(__FreeBSD__) */
- int iovcnt = 0;
-
-- if (kr_state.fib_sync == 0)
-+ if (!kt->fib_sync)
- return (0);
-
- /* initialize header */
- bzero(&hdr, sizeof(hdr));
- hdr.rtm_version = RTM_VERSION;
- hdr.rtm_type = action;
-- hdr.rtm_tableid = kr_state.rtableid;
-+#if !defined(__FreeBSD__) /* XXX: FreeBSD has no multiple routing tables */
-+ hdr.rtm_tableid = kt->rtableid;
-+#endif /* !defined(__FreeBSD__) */
-+#if !defined(__FreeBSD__) /* XXX: FreeBSD has no rtm_priority */
- hdr.rtm_priority = RTP_BGP;
-+#else
-+ hdr.rtm_flags = RTF_PROTO1;
-+#endif /* !defined(__FreeBSD__) */
- if (kroute->flags & F_BLACKHOLE)
- hdr.rtm_flags |= RTF_BLACKHOLE;
- if (kroute->flags & F_REJECT)
-@@ -1984,6 +2570,37 @@ send_rtmsg(int fd, int action, struct kr
- iov[iovcnt].iov_base = &mask;
- iov[iovcnt++].iov_len = sizeof(mask);
-
-+ if (kt->ifindex) {
-+ bzero(&ifp, sizeof(ifp));
-+ ifp.dl.sdl_len = sizeof(struct sockaddr_dl);
-+ ifp.dl.sdl_family = AF_LINK;
-+ ifp.dl.sdl_index = kt->ifindex;
-+ /* adjust header */
-+ hdr.rtm_addrs |= RTA_IFP;
-+ hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_dl));
-+ /* adjust iovec */
-+ iov[iovcnt].iov_base = &ifp;
-+ iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_dl));
-+ }
-+
-+#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */
-+ if (kroute->flags & F_MPLS) {
-+ bzero(&mpls, sizeof(mpls));
-+ mpls.smpls_len = sizeof(mpls);
-+ mpls.smpls_family = AF_MPLS;
-+ mpls.smpls_label = kroute->mplslabel;
-+ /* adjust header */
-+ hdr.rtm_flags |= RTF_MPLS;
-+ hdr.rtm_mpls = MPLS_OP_PUSH;
-+ hdr.rtm_addrs |= RTA_SRC;
-+ hdr.rtm_msglen += sizeof(mpls);
-+ /* adjust iovec */
-+ iov[iovcnt].iov_base = &mpls;
-+ iov[iovcnt++].iov_len = sizeof(mpls);
-+ }
-+#endif
-+
-+#if !defined(__FreeBSD__) /* FreeBSD has no route labeling. */
- if (kroute->labelid) {
- bzero(&label, sizeof(label));
- label.sr_len = sizeof(label);
-@@ -1996,11 +2613,11 @@ send_rtmsg(int fd, int action, struct kr
- iov[iovcnt].iov_base = &label;
- iov[iovcnt++].iov_len = sizeof(label);
- }
-+#endif /* !defined(__FreeBSD__) */
-
- retry:
- if (writev(fd, iov, iovcnt) == -1) {
-- switch (errno) {
-- case ESRCH:
-+ if (errno == ESRCH) {
- if (hdr.rtm_type == RTM_CHANGE) {
- hdr.rtm_type = RTM_ADD;
- goto retry;
-@@ -2009,27 +2626,18 @@ retry:
- inet_ntoa(kroute->prefix),
- kroute->prefixlen);
- return (0);
-- } else {
-- log_warnx("send_rtmsg: action %u, "
-- "prefix %s/%u: %s", hdr.rtm_type,
-- inet_ntoa(kroute->prefix),
-- kroute->prefixlen, strerror(errno));
-- return (0);
- }
-- break;
-- default:
-- log_warnx("send_rtmsg: action %u, prefix %s/%u: %s",
-- hdr.rtm_type, inet_ntoa(kroute->prefix),
-- kroute->prefixlen, strerror(errno));
-- return (0);
- }
-+ log_warn("send_rtmsg: action %u, prefix %s/%u", hdr.rtm_type,
-+ inet_ntoa(kroute->prefix), kroute->prefixlen);
-+ return (0);
- }
-
- return (0);
- }
-
- int
--send_rt6msg(int fd, int action, struct kroute6 *kroute)
-+send_rt6msg(int fd, int action, struct ktable *kt, struct kroute6 *kroute)
- {
- struct iovec iov[5];
- struct rt_msghdr hdr;
-@@ -2037,17 +2645,23 @@ send_rt6msg(int fd, int action, struct k
- struct sockaddr_in6 addr;
- char pad[sizeof(long)];
- } prefix, nexthop, mask;
-+#if !defined(__FreeBSD__) /* FreeBSD has no route labeling. */
- struct sockaddr_rtlabel label;
-+#endif /* !defined(__FreeBSD__) */
- int iovcnt = 0;
-
-- if (kr_state.fib_sync == 0)
-+ if (!kt->fib_sync)
- return (0);
-
- /* initialize header */
- bzero(&hdr, sizeof(hdr));
- hdr.rtm_version = RTM_VERSION;
- hdr.rtm_type = action;
-+#if !defined(__FreeBSD__) /* XXX: FreeBSD has no multiple routing tables */
- hdr.rtm_tableid = kr_state.rtableid;
-+#else
-+ hdr.rtm_flags = RTF_PROTO1;
-+#endif /* !defined(__FreeBSD__) */
- if (kroute->flags & F_BLACKHOLE)
- hdr.rtm_flags |= RTF_BLACKHOLE;
- if (kroute->flags & F_REJECT)
-@@ -2100,6 +2714,7 @@ send_rt6msg(int fd, int action, struct k
- iov[iovcnt].iov_base = &mask;
- iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6));
-
-+#if !defined(__FreeBSD__) /* FreeBSD has no route labeling. */
- if (kroute->labelid) {
- bzero(&label, sizeof(label));
- label.sr_len = sizeof(label);
-@@ -2112,11 +2727,11 @@ send_rt6msg(int fd, int action, struct k
- iov[iovcnt].iov_base = &label;
- iov[iovcnt++].iov_len = sizeof(label);
- }
-+#endif /* !defined(__FreeBSD__) */
-
- retry:
- if (writev(fd, iov, iovcnt) == -1) {
-- switch (errno) {
-- case ESRCH:
-+ if (errno == ESRCH) {
- if (hdr.rtm_type == RTM_CHANGE) {
- hdr.rtm_type = RTM_ADD;
- goto retry;
-@@ -2125,31 +2740,26 @@ retry:
- log_in6addr(&kroute->prefix),
- kroute->prefixlen);
- return (0);
-- } else {
-- log_warnx("send_rt6msg: action %u, "
-- "prefix %s/%u: %s", hdr.rtm_type,
-- log_in6addr(&kroute->prefix),
-- kroute->prefixlen, strerror(errno));
-- return (0);
- }
-- break;
-- default:
-- log_warnx("send_rt6msg: action %u, prefix %s/%u: %s",
-- hdr.rtm_type, log_in6addr(&kroute->prefix),
-- kroute->prefixlen, strerror(errno));
-- return (0);
- }
-+ log_warn("send_rt6msg: action %u, prefix %s/%u", hdr.rtm_type,
-+ log_in6addr(&kroute->prefix), kroute->prefixlen);
-+ return (0);
- }
-
- return (0);
- }
-
- int
--fetchtable(u_int rtableid, int connected_only)
-+fetchtable(struct ktable *kt)
- {
- size_t len;
-+#if !defined(__FreeBSD__) /* FreeBSD has no table id. */
- int mib[7];
-- char *buf, *next, *lim;
-+#else
-+ int mib[6];
-+#endif
-+ char *buf = NULL, *next, *lim;
- struct rt_msghdr *rtm;
- struct sockaddr *sa, *gw, *rti_info[RTAX_MAX];
- struct sockaddr_in *sa_in;
-@@ -2163,22 +2773,35 @@ fetchtable(u_int rtableid, int connected
- mib[3] = 0;
- mib[4] = NET_RT_DUMP;
- mib[5] = 0;
-- mib[6] = rtableid;
-+#if !defined(__FreeBSD__) /* FreeBSD has no table id. */
-+ mib[6] = kt->rtableid;
-+#endif
-
-+#if !defined(__FreeBSD__) /* FreeBSD has no table id. */
- if (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) {
-- if (rtableid != 0 && errno == EINVAL) /* table nonexistent */
-+#else
-+ if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) {
-+#endif
-+ if (kt->rtableid != 0 && errno == EINVAL)
-+ /* table nonexistent */
- return (0);
- log_warn("sysctl");
- return (-1);
- }
-- if ((buf = malloc(len)) == NULL) {
-- log_warn("fetchtable");
-- return (-1);
-- }
-- if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) {
-- log_warn("sysctl");
-- free(buf);
-- return (-1);
-+ if (len > 0) {
-+ if ((buf = malloc(len)) == NULL) {
-+ log_warn("fetchtable");
-+ return (-1);
-+ }
-+#if !defined(__FreeBSD__) /* FreeBSD has no table id. */
-+ if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) {
-+#else
-+ if (sysctl(mib, 6, buf, &len, NULL, 0) == -1) {
-+#endif
-+ log_warn("sysctl2");
-+ free(buf);
-+ return (-1);
-+ }
- }
-
- lim = buf + len;
-@@ -2186,7 +2809,11 @@ fetchtable(u_int rtableid, int connected
- rtm = (struct rt_msghdr *)next;
- if (rtm->rtm_version != RTM_VERSION)
- continue;
-+#if !defined(__FreeBSD__)
- sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
-+#else
-+ sa = (struct sockaddr *)(next + sizeof(struct rt_msghdr));
-+#endif
- get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
-
- if ((sa = rti_info[RTAX_DST]) == NULL)
-@@ -2205,7 +2832,11 @@ fetchtable(u_int rtableid, int connected
- }
-
- kr->r.flags = F_KERNEL;
-+#if defined(__FreeBSD__) /* no rtm_priority on FreeBSD */
-+ kr->r.priority = RTP_BGP;
-+#else
- kr->r.priority = rtm->rtm_priority;
-+#endif
- kr->r.ifindex = rtm->rtm_index;
- kr->r.prefix.s_addr =
- ((struct sockaddr_in *)sa)->sin_addr.s_addr;
-@@ -2223,8 +2854,12 @@ fetchtable(u_int rtableid, int connected
- break;
- kr->r.prefixlen =
- mask2prefixlen(sa_in->sin_addr.s_addr);
-- } else if (rtm->rtm_flags & RTF_HOST)
-+ } else if (rtm->rtm_flags & RTF_HOST) {
- kr->r.prefixlen = 32;
-+#if defined(__FreeBSD__) /* RTF_HOST means connected route */
-+ kr->r.flags |= F_CONNECTED;
-+#endif
-+ }
- else
- kr->r.prefixlen =
- prefixlen_classful(kr->r.prefix.s_addr);
-@@ -2238,11 +2873,25 @@ fetchtable(u_int rtableid, int connected
- }
-
- kr6->r.flags = F_KERNEL;
-+#if defined(__FreeBSD__) /* no rtm_priority on FreeBSD */
-+ kr6->r.priority = RTP_BGP;
-+#else
- kr6->r.priority = rtm->rtm_priority;
-+#endif
- kr6->r.ifindex = rtm->rtm_index;
- memcpy(&kr6->r.prefix,
- &((struct sockaddr_in6 *)sa)->sin6_addr,
- sizeof(kr6->r.prefix));
-+#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER)
-+ if (IN6_IS_ADDR_LINKLOCAL(&kr6->r.prefix)) {
-+ if (((struct sockaddr_in6 *)sa)->sin6_scope_id !=0)
-+ SET_IN6_LINKLOCAL_IFINDEX(kr6->r.prefix,
-+ ((struct sockaddr_in6 *)sa)->sin6_scope_id);
-+ else
-+ SET_IN6_LINKLOCAL_IFINDEX(kr6->r.prefix,
-+ rtm->rtm_index);
-+ }
-+#endif
-
- sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK];
- if (rtm->rtm_flags & RTF_STATIC)
-@@ -2257,8 +2906,12 @@ fetchtable(u_int rtableid, int connected
- if (sa_in6->sin6_len == 0)
- break;
- kr6->r.prefixlen = mask2prefixlen6(sa_in6);
-- } else if (rtm->rtm_flags & RTF_HOST)
-+ } else if (rtm->rtm_flags & RTF_HOST) {
- kr6->r.prefixlen = 128;
-+#if defined(__FreeBSD__) /* RTF_HOST means connected route */
-+ kr6->r.flags |= F_CONNECTED;
-+#endif
-+ }
- else
- fatalx("INET6 route without netmask");
- break;
-@@ -2280,6 +2933,13 @@ fetchtable(u_int rtableid, int connected
- memcpy(&kr6->r.nexthop,
- &((struct sockaddr_in6 *)gw)->sin6_addr,
- sizeof(kr6->r.nexthop));
-+#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER)
-+ if (IN6_IS_ADDR_LINKLOCAL(&kr6->r.nexthop) &&
-+ ((struct sockaddr_in6 *)gw)->sin6_scope_id != 0) {
-+ SET_IN6_LINKLOCAL_IFINDEX(kr6->r.nexthop,
-+ ((struct sockaddr_in6 *)gw)->sin6_scope_id);
-+ }
-+#endif
- break;
- case AF_LINK:
- if (sa->sa_family == AF_INET)
-@@ -2290,23 +2950,28 @@ fetchtable(u_int rtableid, int connected
- }
-
- if (sa->sa_family == AF_INET) {
-+#if !defined(__FreeBSD__) /* no rtm_priority on FreeBSD */
- if (rtm->rtm_priority == RTP_BGP) {
-- send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r);
-- free(kr);
-- } else if (connected_only &&
-- !(kr->r.flags & F_CONNECTED))
-+#else
-+ /* never delete route */
-+ if (0) {
-+#endif
-+ send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r);
- free(kr);
-- else
-- kroute_insert(kr);
-+ } else
-+ kroute_insert(kt, kr);
- } else if (sa->sa_family == AF_INET6) {
-+#if !defined(__FreeBSD__) /* no rtm_priority on FreeBSD */
- if (rtm->rtm_priority == RTP_BGP) {
-- send_rt6msg(kr_state.fd, RTM_DELETE, &kr6->r);
-- free(kr6);
-- } else if (connected_only &&
-- !(kr6->r.flags & F_CONNECTED))
-+#else
-+ /* never delete route */
-+ if (0) {
-+#endif
-+ send_rt6msg(kr_state.fd, RTM_DELETE, kt,
-+ &kr6->r);
- free(kr6);
-- else
-- kroute6_insert(kr6);
-+ } else
-+ kroute6_insert(kt, kr6);
- }
- }
- free(buf);
-@@ -2327,7 +2992,7 @@ fetchifs(int ifindex)
- mib[0] = CTL_NET;
- mib[1] = AF_ROUTE;
- mib[2] = 0;
-- mib[3] = AF_INET;
-+ mib[3] = AF_INET; /* AF does not matter but AF_INET is shorter */
- mib[4] = NET_RT_IFLIST;
- mib[5] = ifindex;
-
-@@ -2396,7 +3061,7 @@ dispatch_rtmsg(void)
- struct rt_msghdr *rtm;
- struct if_msghdr ifm;
- struct sockaddr *sa, *rti_info[RTAX_MAX];
-- int connected_only;
-+ struct ktable *kt;
-
- if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) {
- log_warn("dispatch_rtmsg: read error");
-@@ -2418,7 +3083,11 @@ dispatch_rtmsg(void)
- case RTM_ADD:
- case RTM_CHANGE:
- case RTM_DELETE:
-+#if !defined(__FreeBSD__)
- sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
-+#else
-+ sa = (struct sockaddr *)(next + sizeof(struct rt_msghdr));
-+#endif
- get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
-
- if (rtm->rtm_pid == kr_state.pid) /* cause by us */
-@@ -2430,16 +3099,14 @@ dispatch_rtmsg(void)
- if (rtm->rtm_flags & RTF_LLINFO) /* arp cache */
- continue;
-
-- connected_only = 0;
-- if (rtm->rtm_tableid != kr_state.rtableid) {
-- if (rtm->rtm_tableid == 0)
-- connected_only = 1;
-- else
-- continue;
-- }
-+#if !defined(__FreeBSD__) /* FreeBSD has no rtm_tableid. */
-+ if ((kt = ktable_get(rtm->rtm_tableid)) == NULL)
-+#else
-+ if ((kt = ktable_get(0)) == NULL)
-+#endif
-+ continue;
-
-- if (dispatch_rtmsg_addr(rtm, rti_info,
-- connected_only) == -1)
-+ if (dispatch_rtmsg_addr(rtm, rti_info, kt) == -1)
- return (-1);
- break;
- case RTM_IFINFO:
-@@ -2460,7 +3127,7 @@ dispatch_rtmsg(void)
-
- int
- dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr *rti_info[RTAX_MAX],
-- int connected_only)
-+ struct ktable *kt)
- {
- struct sockaddr *sa;
- struct sockaddr_in *sa_in;
-@@ -2468,7 +3135,7 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
- struct kroute_node *kr;
- struct kroute6_node *kr6;
- struct bgpd_addr prefix;
-- int flags, oflags, mpath = 0;
-+ int flags, oflags, mpath = 0, changed = 0;
- u_int16_t ifindex;
- u_int8_t prefixlen;
- u_int8_t prio;
-@@ -2494,31 +3161,54 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
- mpath = 1;
- #endif
-
-+#if !defined(__FreeBSD__) /* no rtm_priority on FreeBSD */
- prio = rtm->rtm_priority;
-- prefix.af = sa->sa_family;
-- switch (prefix.af) {
-+#else
-+ prio = RTP_BGP;
-+#endif
-+ switch (sa->sa_family) {
- case AF_INET:
-+ prefix.aid = AID_INET;
- prefix.v4.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
- sa_in = (struct sockaddr_in *)rti_info[RTAX_NETMASK];
- if (sa_in != NULL) {
- if (sa_in->sin_len != 0)
- prefixlen = mask2prefixlen(
- sa_in->sin_addr.s_addr);
-- } else if (rtm->rtm_flags & RTF_HOST)
-+ } else if (rtm->rtm_flags & RTF_HOST) {
- prefixlen = 32;
-+#if defined(__FreeBSD__) /* RTF_HOST means connected route */
-+ flags |= F_CONNECTED;
-+#endif
-+ }
- else
- prefixlen =
- prefixlen_classful(prefix.v4.s_addr);
- break;
- case AF_INET6:
-+ prefix.aid = AID_INET6;
- memcpy(&prefix.v6, &((struct sockaddr_in6 *)sa)->sin6_addr,
- sizeof(struct in6_addr));
-+#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER)
-+ if (IN6_IS_ADDR_LINKLOCAL(&prefix.v6) != 0) {
-+ if (((struct sockaddr_in6 *)sa)->sin6_scope_id !=0)
-+ SET_IN6_LINKLOCAL_IFINDEX(prefix.v6,
-+ ((struct sockaddr_in6 *)sa)->sin6_scope_id);
-+ else
-+ SET_IN6_LINKLOCAL_IFINDEX(prefix.v6,
-+ rtm->rtm_index);
-+ }
-+#endif
- sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK];
- if (sa_in6 != NULL) {
- if (sa_in6->sin6_len != 0)
- prefixlen = mask2prefixlen6(sa_in6);
-- } else if (rtm->rtm_flags & RTF_HOST)
-+ } else if (rtm->rtm_flags & RTF_HOST) {
- prefixlen = 128;
-+#if defined(__FreeBSD__) /* RTF_HOST means connected route */
-+ flags |= F_CONNECTED;
-+#endif
-+ }
- else
- fatalx("in6 net addr without netmask");
- break;
-@@ -2537,10 +3227,10 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
- }
-
- if (rtm->rtm_type == RTM_DELETE) {
-- switch (prefix.af) {
-- case AF_INET:
-+ switch (prefix.aid) {
-+ case AID_INET:
- sa_in = (struct sockaddr_in *)sa;
-- if ((kr = kroute_find(prefix.v4.s_addr,
-+ if ((kr = kroute_find(kt, prefix.v4.s_addr,
- prefixlen, prio)) == NULL)
- return (0);
- if (!(kr->r.flags & F_KERNEL))
-@@ -2554,12 +3244,12 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
- return (0);
- }
-
-- if (kroute_remove(kr) == -1)
-+ if (kroute_remove(kt, kr) == -1)
- return (-1);
- break;
-- case AF_INET6:
-+ case AID_INET6:
- sa_in6 = (struct sockaddr_in6 *)sa;
-- if ((kr6 = kroute6_find(&prefix.v6, prefixlen,
-+ if ((kr6 = kroute6_find(kt, &prefix.v6, prefixlen,
- prio)) == NULL)
- return (0);
- if (!(kr6->r.flags & F_KERNEL))
-@@ -2574,26 +3264,23 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
- return (0);
- }
-
-- if (kroute6_remove(kr6) == -1)
-+ if (kroute6_remove(kt, kr6) == -1)
- return (-1);
- break;
- }
- return (0);
- }
-
-- if (connected_only && !(flags & F_CONNECTED))
-- return (0);
--
- if (sa == NULL && !(flags & F_CONNECTED)) {
- log_warnx("dispatch_rtmsg no nexthop for %s/%u",
- log_addr(&prefix), prefixlen);
- return (0);
- }
-
-- switch (prefix.af) {
-- case AF_INET:
-+ switch (prefix.aid) {
-+ case AID_INET:
- sa_in = (struct sockaddr_in *)sa;
-- if ((kr = kroute_find(prefix.v4.s_addr, prefixlen,
-+ if ((kr = kroute_find(kt, prefix.v4.s_addr, prefixlen,
- prio)) != NULL) {
- if (kr->r.flags & F_KERNEL) {
- /* get the correct route */
-@@ -2605,30 +3292,38 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
- } else if (mpath && rtm->rtm_type == RTM_ADD)
- goto add4;
-
-- if (sa_in != NULL)
-+ if (sa_in != NULL) {
-+ if (kr->r.nexthop.s_addr !=
-+ sa_in->sin_addr.s_addr)
-+ changed = 1;
- kr->r.nexthop.s_addr =
- sa_in->sin_addr.s_addr;
-- else
-+ } else {
-+ if (kr->r.nexthop.s_addr != 0)
-+ changed = 1;
- kr->r.nexthop.s_addr = 0;
-+ }
-
- if (kr->r.flags & F_NEXTHOP)
- flags |= F_NEXTHOP;
- oflags = kr->r.flags;
-+ if (flags != oflags)
-+ changed = 1;
- kr->r.flags = flags;
- if ((oflags & F_CONNECTED) &&
- !(flags & F_CONNECTED)) {
- kif_kr_remove(kr);
- kr_redistribute(IMSG_NETWORK_REMOVE,
-- &kr->r);
-+ kt, &kr->r);
- }
- if ((flags & F_CONNECTED) &&
- !(oflags & F_CONNECTED)) {
- kif_kr_insert(kr);
- kr_redistribute(IMSG_NETWORK_ADD,
-- &kr->r);
-+ kt, &kr->r);
- }
-- if (kr->r.flags & F_NEXTHOP)
-- knexthop_track(kr);
-+ if (kr->r.flags & F_NEXTHOP && changed)
-+ knexthop_track(kt, kr);
- }
- } else if (rtm->rtm_type == RTM_CHANGE) {
- log_warnx("change req for %s/%u: not in table",
-@@ -2651,50 +3346,62 @@ add4:
- kr->r.ifindex = ifindex;
- kr->r.priority = prio;
-
-- kroute_insert(kr);
-+ kroute_insert(kt, kr);
- }
- break;
-- case AF_INET6:
-+ case AID_INET6:
- sa_in6 = (struct sockaddr_in6 *)sa;
-- if ((kr6 = kroute6_find(&prefix.v6, prefixlen, prio)) != NULL) {
-+ if ((kr6 = kroute6_find(kt, &prefix.v6, prefixlen, prio)) !=
-+ NULL) {
- if (kr6->r.flags & F_KERNEL) {
- /* get the correct route */
- if (mpath && rtm->rtm_type == RTM_CHANGE &&
- (kr6 = kroute6_matchgw(kr6, sa_in6)) ==
- NULL) {
- log_warnx("dispatch_rtmsg[change] "
-- "mpath route not found");
-+ "IPv6 mpath route not found");
- return (-1);
- } else if (mpath && rtm->rtm_type == RTM_ADD)
- goto add6;
-
-- if (sa_in6 != NULL)
-+ if (sa_in6 != NULL) {
-+ if (memcmp(&kr6->r.nexthop,
-+ &sa_in6->sin6_addr,
-+ sizeof(struct in6_addr)))
-+ changed = 1;
- memcpy(&kr6->r.nexthop,
- &sa_in6->sin6_addr,
- sizeof(struct in6_addr));
-- else
-+ } else {
-+ if (memcmp(&kr6->r.nexthop,
-+ &in6addr_any,
-+ sizeof(struct in6_addr)))
-+ changed = 1;
- memcpy(&kr6->r.nexthop,
- &in6addr_any,
- sizeof(struct in6_addr));
-+ }
-
- if (kr6->r.flags & F_NEXTHOP)
- flags |= F_NEXTHOP;
- oflags = kr6->r.flags;
-+ if (flags != oflags)
-+ changed = 1;
- kr6->r.flags = flags;
- if ((oflags & F_CONNECTED) &&
- !(flags & F_CONNECTED)) {
- kif_kr6_remove(kr6);
- kr_redistribute6(IMSG_NETWORK_REMOVE,
-- &kr6->r);
-+ kt, &kr6->r);
- }
- if ((flags & F_CONNECTED) &&
- !(oflags & F_CONNECTED)) {
- kif_kr6_insert(kr6);
- kr_redistribute6(IMSG_NETWORK_ADD,
-- &kr6->r);
-+ kt, &kr6->r);
- }
-- if (kr6->r.flags & F_NEXTHOP)
-- knexthop_track(kr6);
-+ if (kr6->r.flags & F_NEXTHOP && changed)
-+ knexthop_track(kt, kr6);
- }
- } else if (rtm->rtm_type == RTM_CHANGE) {
- log_warnx("change req for %s/%u: not in table",
-@@ -2719,8 +3426,12 @@ add6:
- kr6->r.flags = flags;
- kr6->r.ifindex = ifindex;
- kr6->r.priority = prio;
--
-- kroute6_insert(kr6);
-+#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER)
-+ if (IN6_IS_ADDR_LINKLOCAL(&kr6->r.nexthop))
-+ SET_IN6_LINKLOCAL_IFINDEX(kr6->r.nexthop,
-+ ifindex);
-+#endif
-+ kroute6_insert(kt, kr6);
- }
- break;
- }
diff --git a/net/openbgpd/files/patch-bgpd_log.c b/net/openbgpd/files/patch-bgpd_log.c
deleted file mode 100644
index 6860c0f7f940..000000000000
--- a/net/openbgpd/files/patch-bgpd_log.c
+++ /dev/null
@@ -1,117 +0,0 @@
-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]);
diff --git a/net/openbgpd/files/patch-bgpd_log.h b/net/openbgpd/files/patch-bgpd_log.h
deleted file mode 100644
index 3d0d94de2a2e..000000000000
--- a/net/openbgpd/files/patch-bgpd_log.h
+++ /dev/null
@@ -1,39 +0,0 @@
-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[] = {
diff --git a/net/openbgpd/files/patch-bgpd_mrt.c b/net/openbgpd/files/patch-bgpd_mrt.c
deleted file mode 100644
index 31546fcf96d0..000000000000
--- a/net/openbgpd/files/patch-bgpd_mrt.c
+++ /dev/null
@@ -1,864 +0,0 @@
-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 =
diff --git a/net/openbgpd/files/patch-bgpd_mrt.h b/net/openbgpd/files/patch-bgpd_mrt.h
deleted file mode 100644
index 0c9d835f5b78..000000000000
--- a/net/openbgpd/files/patch-bgpd_mrt.h
+++ /dev/null
@@ -1,287 +0,0 @@
-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
diff --git a/net/openbgpd/files/patch-bgpd_name2id.c b/net/openbgpd/files/patch-bgpd_name2id.c
deleted file mode 100644
index bf6cfbd067a8..000000000000
--- a/net/openbgpd/files/patch-bgpd_name2id.c
+++ /dev/null
@@ -1,14 +0,0 @@
-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>
diff --git a/net/openbgpd/files/patch-bgpd_parse.y b/net/openbgpd/files/patch-bgpd_parse.y
deleted file mode 100644
index 0f9160187aac..000000000000
--- a/net/openbgpd/files/patch-bgpd_parse.y
+++ /dev/null
@@ -1,1626 +0,0 @@
-Index: bgpd/parse.y
-===================================================================
-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/parse.y,v
-retrieving revision 1.1.1.8
-retrieving revision 1.12
-diff -u -p -r1.1.1.8 -r1.12
---- bgpd/parse.y 14 Feb 2010 20:19:57 -0000 1.1.1.8
-+++ bgpd/parse.y 8 Dec 2012 20:17:59 -0000 1.12
-@@ -1,4 +1,4 @@
--/* $OpenBSD: parse.y,v 1.231 2009/06/06 01:10:29 claudio Exp $ */
-+/* $OpenBSD: parse.y,v 1.264 2012/09/23 09:39:17 claudio Exp $ */
-
- /*
- * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
-@@ -25,7 +25,10 @@
- #include <sys/stat.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
--
-+#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */
-+#include <netmpls/mpls.h>
-+#endif
-+
- #include <ctype.h>
- #include <err.h>
- #include <unistd.h>
-@@ -33,6 +36,9 @@
- #include <limits.h>
- #include <stdarg.h>
- #include <stdio.h>
-+#if defined(__FreeBSD__)
-+#include <stdlib.h>
-+#endif
- #include <string.h>
- #include <syslog.h>
-
-@@ -74,10 +80,12 @@ char *symget(const char *);
-
- static struct bgpd_config *conf;
- static struct mrt_head *mrtconf;
--static struct network_head *netconf;
-+static struct network_head *netconf, *gnetconf;
- static struct peer *peer_l, *peer_l_old;
- static struct peer *curpeer;
- static struct peer *curgroup;
-+static struct rdomain *currdom;
-+static struct rdomain_head *rdom_l;
- static struct filter_head *filter_l;
- static struct filter_head *peerfilter_l;
- static struct filter_head *groupfilter_l;
-@@ -105,7 +113,7 @@ struct filter_match_l {
- struct filter_match m;
- struct filter_prefix_l *prefix_l;
- struct filter_as_l *as_l;
-- sa_family_t af;
-+ u_int8_t aid;
- } fmopts;
-
- struct peer *alloc_peer(void);
-@@ -113,8 +121,8 @@ struct peer *new_peer(void);
- struct peer *new_group(void);
- int add_mrtconfig(enum mrt_type, char *, time_t, struct peer *,
- char *);
--int add_rib(char *, u_int16_t);
--int find_rib(char *);
-+int add_rib(char *, u_int, u_int16_t);
-+struct rde_rib *find_rib(char *);
- int get_id(struct peer *);
- int expand_rule(struct filter_rule *, struct filter_peers_l *,
- struct filter_match_l *, struct filter_set_head *);
-@@ -123,12 +131,14 @@ int neighbor_consistent(struct peer *)
- int merge_filterset(struct filter_set_head *, struct filter_set *);
- void copy_filterset(struct filter_set_head *,
- struct filter_set_head *);
--void move_filterset(struct filter_set_head *,
-- struct filter_set_head *);
- struct filter_rule *get_rule(enum action_types);
-
- int getcommunity(char *);
--int parsecommunity(char *, int *, int *);
-+int parsecommunity(struct filter_community *, char *);
-+int parsesubtype(char *);
-+int parseextvalue(char *, u_int32_t *);
-+int parseextcommunity(struct filter_extcommunity *, char *,
-+ char *);
-
- typedef struct {
- union {
-@@ -159,29 +169,33 @@ typedef struct {
- %}
-
- %token AS ROUTERID HOLDTIME YMIN LISTEN ON FIBUPDATE RTABLE
-+%token RDOMAIN RD EXPORTTRGT IMPORTTRGT
- %token RDE RIB EVALUATE IGNORE COMPARE
- %token GROUP NEIGHBOR NETWORK
--%token REMOTEAS DESCR LOCALADDR MULTIHOP PASSIVE MAXPREFIX RESTART
--%token ANNOUNCE DEMOTE CONNECTRETRY
--%token ENFORCE NEIGHBORAS CAPABILITIES REFLECTOR DEPEND DOWN SOFTRECONFIG
--%token DUMP IN OUT
-+%token REMOTEAS DESCR LLIFACE LOCALADDR MULTIHOP PASSIVE MAXPREFIX RESTART
-+%token ANNOUNCE CAPABILITIES REFRESH AS4BYTE CONNECTRETRY
-+%token DEMOTE ENFORCE NEIGHBORAS REFLECTOR DEPEND DOWN SOFTRECONFIG
-+%token DUMP IN OUT SOCKET RESTRICTED
- %token LOG ROUTECOLL TRANSPARENT
- %token TCP MD5SIG PASSWORD KEY TTLSECURITY
- %token ALLOW DENY MATCH
- %token QUICK
- %token FROM TO ANY
- %token CONNECTED STATIC
--%token PREFIX PREFIXLEN SOURCEAS TRANSITAS PEERAS COMMUNITY DELETE
-+%token COMMUNITY EXTCOMMUNITY
-+%token PREFIX PREFIXLEN SOURCEAS TRANSITAS PEERAS DELETE MAXASLEN MAXASSEQ
- %token SET LOCALPREF MED METRIC NEXTHOP REJECT BLACKHOLE NOMODIFY SELF
--%token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL
-+%token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL ORIGIN
- %token ERROR INCLUDE
- %token IPSEC ESP AH SPI IKE
- %token IPV4 IPV6
- %token QUALIFY VIA
-+%token NE LE GE XRANGE
- %token <v.string> STRING
- %token <v.number> NUMBER
--%type <v.number> asnumber as4number optnumber yesno inout
--%type <v.number> espah family restart
-+%type <v.number> asnumber as4number optnumber
-+%type <v.number> espah family restart origincode nettype
-+%type <v.number> yesno inout restricted
- %type <v.string> string filter_rib
- %type <v.addr> address
- %type <v.prefix> prefix addrspec
-@@ -204,6 +218,7 @@ grammar : /* empty */
- | grammar include '\n'
- | grammar conf_main '\n'
- | grammar varset '\n'
-+ | grammar rdomain '\n'
- | grammar neighbor '\n'
- | grammar group '\n'
- | grammar filterrule '\n'
-@@ -211,8 +226,12 @@ grammar : /* empty */
- ;
-
- asnumber : NUMBER {
-- if ($1 < 0 || $1 >= ASNUM_MAX) {
-- yyerror("AS too big: max %u", ASNUM_MAX - 1);
-+ /*
-+ * Accroding to iana 65535 and 4294967295 are reserved
-+ * but enforcing this is not duty of the parser.
-+ */
-+ if ($1 < 0 || $1 > UINT_MAX) {
-+ yyerror("AS too big: max %u", UINT_MAX);
- YYERROR;
- }
- }
-@@ -274,6 +293,8 @@ yesno : STRING {
- else if (!strcmp($1, "no"))
- $$ = 0;
- else {
-+ yyerror("syntax error, "
-+ "either yes or no expected");
- free($1);
- YYERROR;
- }
-@@ -318,7 +339,7 @@ conf_main : AS as4number {
- conf->short_as = $3;
- }
- | ROUTERID address {
-- if ($2.af != AF_INET) {
-+ if ($2.aid != AID_INET) {
- yyerror("router-id must be an IPv4 address");
- YYERROR;
- }
-@@ -342,42 +363,25 @@ conf_main : AS as4number {
- }
- | LISTEN ON address {
- struct listen_addr *la;
-- struct sockaddr_in *in;
-- struct sockaddr_in6 *in6;
-
- if ((la = calloc(1, sizeof(struct listen_addr))) ==
- NULL)
- fatal("parse conf_main listen on calloc");
-
- la->fd = -1;
-- la->sa.ss_family = $3.af;
-- switch ($3.af) {
-- case AF_INET:
-- la->sa.ss_len = sizeof(struct sockaddr_in);
-- in = (struct sockaddr_in *)&la->sa;
-- in->sin_addr.s_addr = $3.v4.s_addr;
-- in->sin_port = htons(BGP_PORT);
-- break;
-- case AF_INET6:
-- la->sa.ss_len = sizeof(struct sockaddr_in6);
-- in6 = (struct sockaddr_in6 *)&la->sa;
-- memcpy(&in6->sin6_addr, &$3.v6,
-- sizeof(in6->sin6_addr));
-- in6->sin6_port = htons(BGP_PORT);
-- break;
-- default:
-- yyerror("king bula does not like family %u",
-- $3.af);
-- YYERROR;
-- }
--
-+ memcpy(&la->sa, addr2sa(&$3, BGP_PORT), sizeof(la->sa));
- TAILQ_INSERT_TAIL(listen_addrs, la, entry);
- }
- | FIBUPDATE yesno {
-+ struct rde_rib *rr;
-+ rr = find_rib("Loc-RIB");
-+ if (rr == NULL)
-+ fatalx("RTABLE can not find the main RIB!");
-+
- if ($2 == 0)
-- conf->flags |= BGPD_FLAG_NO_FIB_UPDATE;
-+ rr->flags |= F_RIB_NOFIBSYNC;
- else
-- conf->flags &= ~BGPD_FLAG_NO_FIB_UPDATE;
-+ rr->flags &= ~F_RIB_NOFIBSYNC;
- }
- | ROUTECOLL yesno {
- if ($2 == 1)
-@@ -386,7 +390,7 @@ conf_main : AS as4number {
- conf->flags &= ~BGPD_FLAG_NO_EVALUATE;
- }
- | RDE RIB STRING {
-- if (add_rib($3, F_RIB_NOFIB)) {
-+ if (add_rib($3, 0, F_RIB_NOFIB)) {
- free($3);
- YYERROR;
- }
-@@ -395,9 +399,27 @@ conf_main : AS as4number {
- | RDE RIB STRING yesno EVALUATE {
- if ($4) {
- free($3);
-+ yyerror("bad rde rib definition");
- YYERROR;
- }
-- if (!add_rib($3, F_RIB_NOEVALUATE)) {
-+ if (add_rib($3, 0, F_RIB_NOFIB | F_RIB_NOEVALUATE)) {
-+ free($3);
-+ YYERROR;
-+ }
-+ free($3);
-+ }
-+ | RDE RIB STRING RTABLE NUMBER {
-+ if (add_rib($3, $5, 0)) {
-+ free($3);
-+ YYERROR;
-+ }
-+ free($3);
-+ }
-+ | RDE RIB STRING RTABLE NUMBER FIBUPDATE yesno {
-+ int flags = 0;
-+ if ($7 == 0)
-+ flags = F_RIB_NOFIBSYNC;
-+ if (add_rib($3, $5, flags)) {
- free($3);
- YYERROR;
- }
-@@ -418,59 +440,7 @@ conf_main : AS as4number {
- }
- free($2);
- }
-- | NETWORK prefix filter_set {
-- struct network *n;
--
-- if ((n = calloc(1, sizeof(struct network))) == NULL)
-- fatal("new_network");
-- memcpy(&n->net.prefix, &$2.prefix,
-- sizeof(n->net.prefix));
-- n->net.prefixlen = $2.len;
-- move_filterset($3, &n->net.attrset);
-- free($3);
--
-- TAILQ_INSERT_TAIL(netconf, n, entry);
-- }
-- | NETWORK family STATIC filter_set {
-- if ($2 == AFI_IPv4) {
-- conf->flags |= BGPD_FLAG_REDIST_STATIC;
-- move_filterset($4, &conf->staticset);
-- } else if ($2 == AFI_IPv6) {
-- conf->flags |= BGPD_FLAG_REDIST6_STATIC;
-- move_filterset($4, &conf->staticset6);
-- } else {
-- yyerror("unknown family");
-- free($4);
-- YYERROR;
-- }
-- free($4);
-- }
-- | NETWORK family CONNECTED filter_set {
-- if ($2 == AFI_IPv4) {
-- conf->flags |= BGPD_FLAG_REDIST_CONNECTED;
-- move_filterset($4, &conf->connectset);
-- } else if ($2 == AFI_IPv6) {
-- conf->flags |= BGPD_FLAG_REDIST6_CONNECTED;
-- move_filterset($4, &conf->connectset6);
-- } else {
-- yyerror("unknown family");
-- free($4);
-- YYERROR;
-- }
-- free($4);
-- }
-- | NETWORK STATIC filter_set {
-- /* keep for compatibility till after next release */
-- conf->flags |= BGPD_FLAG_REDIST_STATIC;
-- move_filterset($3, &conf->staticset);
-- free($3);
-- }
-- | NETWORK CONNECTED filter_set {
-- /* keep for compatibility till after next release */
-- conf->flags |= BGPD_FLAG_REDIST_CONNECTED;
-- move_filterset($3, &conf->connectset);
-- free($3);
-- }
-+ | network
- | DUMP STRING STRING optnumber {
- int action;
-
-@@ -484,6 +454,8 @@ conf_main : AS as4number {
- action = MRT_TABLE_DUMP;
- else if (!strcmp($2, "table-mp"))
- action = MRT_TABLE_DUMP_MP;
-+ else if (!strcmp($2, "table-v2"))
-+ action = MRT_TABLE_DUMP_V2;
- else {
- yyerror("unknown mrt dump type");
- free($2);
-@@ -511,6 +483,8 @@ conf_main : AS as4number {
- action = MRT_TABLE_DUMP;
- else if (!strcmp($4, "table-mp"))
- action = MRT_TABLE_DUMP_MP;
-+ else if (!strcmp($4, "table-v2"))
-+ action = MRT_TABLE_DUMP_V2;
- else {
- yyerror("unknown mrt dump type");
- free($3);
-@@ -575,11 +549,20 @@ conf_main : AS as4number {
- free($4);
- }
- | RTABLE NUMBER {
-- if ($2 > RT_TABLEID_MAX || $2 < 0) {
-- yyerror("invalid rtable id");
-+#if defined(__FreeBSD__) /* FreeBSD does not support RTABLE */
-+ yyerror("rtable id not supported in FreeBSD, yet");
-+ YYERROR;
-+#else
-+ struct rde_rib *rr;
-+ if (ktable_exists($2, NULL) != 1) {
-+ yyerror("rtable id %lld does not exist", $2);
- YYERROR;
- }
-- conf->rtableid = $2;
-+ rr = find_rib("Loc-RIB");
-+ if (rr == NULL)
-+ fatalx("RTABLE can not find the main RIB!");
-+ rr->rtableid = $2;
-+#endif /* defined(__FreeBSD__) */
- }
- | CONNECTRETRY NUMBER {
- if ($2 > USHRT_MAX || $2 < 1) {
-@@ -588,6 +571,15 @@ conf_main : AS as4number {
- }
- conf->connectretry = $2;
- }
-+ | SOCKET STRING restricted {
-+ if ($3) {
-+ free(conf->rcsock);
-+ conf->rcsock = $2;
-+ } else {
-+ free(conf->csock);
-+ conf->csock = $2;
-+ }
-+ }
- ;
-
- mrtdump : DUMP STRING inout STRING optnumber {
-@@ -620,10 +612,47 @@ mrtdump : DUMP STRING inout STRING optn
- }
- ;
-
-+network : NETWORK prefix filter_set {
-+ struct network *n;
-+
-+ if ((n = calloc(1, sizeof(struct network))) == NULL)
-+ fatal("new_network");
-+ memcpy(&n->net.prefix, &$2.prefix,
-+ sizeof(n->net.prefix));
-+ n->net.prefixlen = $2.len;
-+ filterset_move($3, &n->net.attrset);
-+ free($3);
-+
-+ TAILQ_INSERT_TAIL(netconf, n, entry);
-+ }
-+ | NETWORK family nettype filter_set {
-+ struct network *n;
-+
-+ if ((n = calloc(1, sizeof(struct network))) == NULL)
-+ fatal("new_network");
-+ if (afi2aid($2, SAFI_UNICAST, &n->net.prefix.aid) ==
-+ -1) {
-+ yyerror("unknown family");
-+ filterset_free($4);
-+ free($4);
-+ YYERROR;
-+ }
-+ n->net.type = $3 ? NETWORK_STATIC : NETWORK_CONNECTED;
-+ filterset_move($4, &n->net.attrset);
-+ free($4);
-+
-+ TAILQ_INSERT_TAIL(netconf, n, entry);
-+ }
-+ ;
-+
- inout : IN { $$ = 1; }
- | OUT { $$ = 0; }
- ;
-
-+restricted : RESTRICTED { $$ = 1; }
-+ | /* nothing */ { $$ = 0; }
-+ ;
-+
- address : STRING {
- u_int8_t len;
-
-@@ -635,11 +664,11 @@ address : STRING {
- }
- free($1);
-
-- if (($$.af == AF_INET && len != 32) ||
-- ($$.af == AF_INET6 && len != 128)) {
-+ if (($$.aid == AID_INET && len != 32) ||
-+ ($$.aid == AID_INET6 && len != 128)) {
- /* unreachable */
- yyerror("got prefixlen %u, expected %u",
-- len, $$.af == AF_INET ? 32 : 128);
-+ len, $$.aid == AID_INET ? 32 : 128);
- YYERROR;
- }
- }
-@@ -653,7 +682,7 @@ prefix : STRING '/' NUMBER {
- free($1);
- YYERROR;
- }
-- if (asprintf(&s, "%s/%lld", $1, $3) == -1)
-+ if (asprintf(&s, "%s/%lld", $1, (long long int)$3) == -1)
- fatal(NULL);
- free($1);
-
-@@ -672,7 +701,7 @@ prefix : STRING '/' NUMBER {
- yyerror("bad prefix %lld/%lld", $1, $3);
- YYERROR;
- }
-- if (asprintf(&s, "%lld/%lld", $1, $3) == -1)
-+ if (asprintf(&s, "%lld/%lld", (long long int)$1, (long long int)$3) == -1)
- fatal(NULL);
-
- if (!host(s, &$$.prefix, &$$.len)) {
-@@ -686,7 +715,7 @@ prefix : STRING '/' NUMBER {
-
- addrspec : address {
- memcpy(&$$.prefix, &$1, sizeof(struct bgpd_addr));
-- if ($$.prefix.af == AF_INET)
-+ if ($$.prefix.aid == AID_INET)
- $$.len = 32;
- else
- $$.len = 128;
-@@ -705,14 +734,150 @@ optnumber : /* empty */ { $$ = 0; }
- | NUMBER
- ;
-
-+rdomain : RDOMAIN NUMBER optnl '{' optnl {
-+ if (ktable_exists($2, NULL) != 1) {
-+ yyerror("rdomain %lld does not exist", $2);
-+ YYERROR;
-+ }
-+ if (!(currdom = calloc(1, sizeof(struct rdomain))))
-+ fatal(NULL);
-+ currdom->rtableid = $2;
-+ TAILQ_INIT(&currdom->import);
-+ TAILQ_INIT(&currdom->export);
-+ TAILQ_INIT(&currdom->net_l);
-+ netconf = &currdom->net_l;
-+ }
-+ rdomainopts_l '}' {
-+ /* insert into list */
-+ SIMPLEQ_INSERT_TAIL(rdom_l, currdom, entry);
-+ currdom = NULL;
-+ netconf = gnetconf;
-+ }
-+
-+rdomainopts_l : rdomainopts_l rdomainoptsl
-+ | rdomainoptsl
-+ ;
-+
-+rdomainoptsl : rdomainopts nl
-+ ;
-+
-+rdomainopts : RD STRING {
-+ struct filter_extcommunity ext;
-+ u_int64_t rd;
-+
-+ if (parseextcommunity(&ext, "rt", $2) == -1) {
-+ free($2);
-+ YYERROR;
-+ }
-+ free($2);
-+ /*
-+ * RD is almost encode like an ext-community,
-+ * but only almost so convert here.
-+ */
-+ if (community_ext_conv(&ext, 0, &rd)) {
-+ yyerror("bad encoding of rd");
-+ YYERROR;
-+ }
-+ rd = betoh64(rd) & 0xffffffffffffULL;
-+ switch (ext.type) {
-+ case EXT_COMMUNITY_TWO_AS:
-+ rd |= (0ULL << 48);
-+ break;
-+ case EXT_COMMUNITY_IPV4:
-+ rd |= (1ULL << 48);
-+ break;
-+ case EXT_COMMUNITY_FOUR_AS:
-+ rd |= (2ULL << 48);
-+ break;
-+ default:
-+ yyerror("bad encoding of rd");
-+ YYERROR;
-+ }
-+ currdom->rd = htobe64(rd);
-+ }
-+ | EXPORTTRGT STRING STRING {
-+ struct filter_set *set;
-+
-+ if ((set = calloc(1, sizeof(struct filter_set))) ==
-+ NULL)
-+ fatal(NULL);
-+ set->type = ACTION_SET_EXT_COMMUNITY;
-+ if (parseextcommunity(&set->action.ext_community,
-+ $2, $3) == -1) {
-+ free($3);
-+ free($2);
-+ free(set);
-+ YYERROR;
-+ }
-+ free($3);
-+ free($2);
-+ TAILQ_INSERT_TAIL(&currdom->export, set, entry);
-+ }
-+ | IMPORTTRGT STRING STRING {
-+ struct filter_set *set;
-+
-+ if ((set = calloc(1, sizeof(struct filter_set))) ==
-+ NULL)
-+ fatal(NULL);
-+ set->type = ACTION_SET_EXT_COMMUNITY;
-+ if (parseextcommunity(&set->action.ext_community,
-+ $2, $3) == -1) {
-+ free($3);
-+ free($2);
-+ free(set);
-+ YYERROR;
-+ }
-+ free($3);
-+ free($2);
-+ TAILQ_INSERT_TAIL(&currdom->import, set, entry);
-+ }
-+ | DESCR string {
-+ if (strlcpy(currdom->descr, $2,
-+ sizeof(currdom->descr)) >=
-+ sizeof(currdom->descr)) {
-+ yyerror("descr \"%s\" too long: max %u",
-+ $2, sizeof(currdom->descr) - 1);
-+ free($2);
-+ YYERROR;
-+ }
-+ free($2);
-+ }
-+ | FIBUPDATE yesno {
-+ if ($2 == 0)
-+ currdom->flags |= F_RIB_NOFIBSYNC;
-+ else
-+ currdom->flags &= ~F_RIB_NOFIBSYNC;
-+ }
-+ | network
-+ | DEPEND ON STRING {
-+ /* XXX this is a hack */
-+ if (if_nametoindex($3) == 0) {
-+ yyerror("interface %s does not exist", $3);
-+ free($3);
-+ YYERROR;
-+ }
-+ strlcpy(currdom->ifmpe, $3, IFNAMSIZ);
-+ free($3);
-+ if (get_mpe_label(currdom)) {
-+ yyerror("failed to get mpls label from %s",
-+ currdom->ifmpe);
-+ YYERROR;
-+ }
-+ }
-+ ;
-+
- neighbor : { curpeer = new_peer(); }
- NEIGHBOR addrspec {
- memcpy(&curpeer->conf.remote_addr, &$3.prefix,
- sizeof(curpeer->conf.remote_addr));
- curpeer->conf.remote_masklen = $3.len;
-- if (($3.prefix.af == AF_INET && $3.len != 32) ||
-- ($3.prefix.af == AF_INET6 && $3.len != 128))
-+ if (($3.prefix.aid == AID_INET && $3.len != 32) ||
-+ ($3.prefix.aid == AID_INET6 && $3.len != 128))
- curpeer->conf.template = 1;
-+ if (curpeer->conf.capabilities.mp[
-+ curpeer->conf.remote_addr.aid] == -1)
-+ curpeer->conf.capabilities.mp[
-+ curpeer->conf.remote_addr.aid] = 1;
- if (get_id(curpeer)) {
- yyerror("get_id failed");
- YYERROR;
-@@ -802,6 +967,17 @@ peeropts : REMOTEAS as4number {
- }
- free($2);
- }
-+ | LLIFACE string {
-+ if (strlcpy(curpeer->conf.lliface, $2,
-+ sizeof(curpeer->conf.lliface)) >=
-+ sizeof(curpeer->conf.lliface)) {
-+ yyerror("lliface \"%s\" too long: max %u",
-+ $2, sizeof(curpeer->conf.lliface) - 1);
-+ free($2);
-+ YYERROR;
-+ }
-+ free($2);
-+ }
- | LOCALADDR address {
- memcpy(&curpeer->conf.local_addr, &$2,
- sizeof(curpeer->conf.local_addr));
-@@ -852,13 +1028,17 @@ peeropts : REMOTEAS as4number {
- curpeer->conf.min_holdtime = $3;
- }
- | ANNOUNCE family STRING {
-- u_int8_t safi;
-+ u_int8_t aid, safi;
-+ int8_t val = 1;
-
-- if (!strcmp($3, "none"))
-- safi = SAFI_NONE;
-- else if (!strcmp($3, "unicast"))
-+ if (!strcmp($3, "none")) {
- safi = SAFI_UNICAST;
-- else {
-+ val = 0;
-+ } else if (!strcmp($3, "unicast")) {
-+ safi = SAFI_UNICAST;
-+ } else if (!strcmp($3, "vpn")) {
-+ safi = SAFI_MPLSVPN;
-+ } else {
- yyerror("unknown/unsupported SAFI \"%s\"",
- $3);
- free($3);
-@@ -866,25 +1046,31 @@ peeropts : REMOTEAS as4number {
- }
- free($3);
-
-- switch ($2) {
-- case AFI_IPv4:
-- curpeer->conf.capabilities.mp_v4 = safi;
-- break;
-- case AFI_IPv6:
-- curpeer->conf.capabilities.mp_v6 = safi;
-- break;
-- default:
-- fatal("king bula sees borked AFI");
-+ if (afi2aid($2, safi, &aid) == -1) {
-+ yyerror("unknown AFI/SAFI pair");
-+ YYERROR;
- }
-+ curpeer->conf.capabilities.mp[aid] = val;
- }
- | ANNOUNCE CAPABILITIES yesno {
- curpeer->conf.announce_capa = $3;
- }
-+ | ANNOUNCE REFRESH yesno {
-+ curpeer->conf.capabilities.refresh = $3;
-+ }
-+ | ANNOUNCE RESTART yesno {
-+ curpeer->conf.capabilities.grestart.restart = $3;
-+ }
-+ | ANNOUNCE AS4BYTE yesno {
-+ curpeer->conf.capabilities.as4byte = $3;
-+ }
- | ANNOUNCE SELF {
- curpeer->conf.announce_type = ANNOUNCE_SELF;
- }
- | ANNOUNCE STRING {
-- if (!strcmp($2, "none"))
-+ if (!strcmp($2, "self"))
-+ curpeer->conf.announce_type = ANNOUNCE_SELF;
-+ else if (!strcmp($2, "none"))
- curpeer->conf.announce_type = ANNOUNCE_NONE;
- else if (!strcmp($2, "all"))
- curpeer->conf.announce_type = ANNOUNCE_ALL;
-@@ -1083,7 +1269,7 @@ peeropts : REMOTEAS as4number {
- curpeer->conf.reflector_client = 1;
- }
- | REFLECTOR address {
-- if ($2.af != AF_INET) {
-+ if ($2.aid != AID_INET) {
- yyerror("route reflector cluster-id must be "
- "an IPv4 address");
- YYERROR;
-@@ -1157,6 +1343,10 @@ family : IPV4 { $$ = AFI_IPv4; }
- | IPV6 { $$ = AFI_IPv6; }
- ;
-
-+nettype : STATIC { $$ = 1; },
-+ | CONNECTED { $$ = 0; }
-+ ;
-+
- espah : ESP { $$ = 1; }
- | AH { $$ = 0; }
- ;
-@@ -1336,12 +1526,12 @@ filter_prefix_l : filter_prefix { $$
- ;
-
- filter_prefix : prefix {
-- if (fmopts.af && fmopts.af != $1.prefix.af) {
-+ if (fmopts.aid && fmopts.aid != $1.prefix.aid) {
- yyerror("rules with mixed address families "
- "are not allowed");
- YYERROR;
- } else
-- fmopts.af = $1.prefix.af;
-+ fmopts.aid = $1.prefix.aid;
- if (($$ = calloc(1, sizeof(struct filter_prefix_l))) ==
- NULL)
- fatal(NULL);
-@@ -1410,6 +1600,12 @@ filter_as : as4number {
- fatal(NULL);
- $$->a.as = $1;
- }
-+ | NEIGHBORAS {
-+ if (($$ = calloc(1, sizeof(struct filter_as_l))) ==
-+ NULL)
-+ fatal(NULL);
-+ $$->a.flags = AS_FLAG_NEIGHBORAS;
-+ }
- ;
-
- filter_match_h : /* empty */ {
-@@ -1437,18 +1633,18 @@ filter_elm : filter_prefix_h {
- fmopts.prefix_l = $1;
- }
- | PREFIXLEN prefixlenop {
-- if (fmopts.af == 0) {
-+ if (fmopts.aid == 0) {
- yyerror("address family needs to be specified "
- "before \"prefixlen\"");
- YYERROR;
- }
-- if (fmopts.m.prefixlen.af) {
-+ if (fmopts.m.prefixlen.aid) {
- yyerror("\"prefixlen\" already specified");
- YYERROR;
- }
- memcpy(&fmopts.m.prefixlen, &$2,
- sizeof(fmopts.m.prefixlen));
-- fmopts.m.prefixlen.af = fmopts.af;
-+ fmopts.m.prefixlen.aid = fmopts.aid;
- }
- | filter_as_h {
- if (fmopts.as_l != NULL) {
-@@ -1457,32 +1653,93 @@ filter_elm : filter_prefix_h {
- }
- fmopts.as_l = $1;
- }
-+ | MAXASLEN NUMBER {
-+ if (fmopts.m.aslen.type != ASLEN_NONE) {
-+ yyerror("AS length filters already specified");
-+ YYERROR;
-+ }
-+ if ($2 < 0 || $2 > UINT_MAX) {
-+ yyerror("bad max-as-len %lld", $2);
-+ YYERROR;
-+ }
-+ fmopts.m.aslen.type = ASLEN_MAX;
-+ fmopts.m.aslen.aslen = $2;
-+ }
-+ | MAXASSEQ NUMBER {
-+ if (fmopts.m.aslen.type != ASLEN_NONE) {
-+ yyerror("AS length filters already specified");
-+ YYERROR;
-+ }
-+ if ($2 < 0 || $2 > UINT_MAX) {
-+ yyerror("bad max-as-seq %lld", $2);
-+ YYERROR;
-+ }
-+ fmopts.m.aslen.type = ASLEN_SEQ;
-+ fmopts.m.aslen.aslen = $2;
-+ }
- | COMMUNITY STRING {
- if (fmopts.m.community.as != COMMUNITY_UNSET) {
- yyerror("\"community\" already specified");
- free($2);
- YYERROR;
- }
-- if (parsecommunity($2, &fmopts.m.community.as,
-- &fmopts.m.community.type) == -1) {
-+ if (parsecommunity(&fmopts.m.community, $2) == -1) {
- free($2);
- YYERROR;
- }
- free($2);
- }
-+ | EXTCOMMUNITY STRING STRING {
-+ if (fmopts.m.ext_community.flags &
-+ EXT_COMMUNITY_FLAG_VALID) {
-+ yyerror("\"ext-community\" already specified");
-+ free($2);
-+ free($3);
-+ YYERROR;
-+ }
-+
-+ if (parseextcommunity(&fmopts.m.ext_community,
-+ $2, $3) == -1) {
-+ free($2);
-+ free($3);
-+ YYERROR;
-+ }
-+ free($2);
-+ free($3);
-+ }
- | IPV4 {
-- if (fmopts.af) {
-+ if (fmopts.aid) {
- yyerror("address family already specified");
- YYERROR;
- }
-- fmopts.af = AF_INET;
-+ fmopts.aid = AID_INET;
- }
- | IPV6 {
-- if (fmopts.af) {
-+ if (fmopts.aid) {
- yyerror("address family already specified");
- YYERROR;
- }
-- fmopts.af = AF_INET6;
-+ fmopts.aid = AID_INET6;
-+ }
-+ | NEXTHOP address {
-+ if (fmopts.m.nexthop.flags) {
-+ yyerror("nexthop already specified");
-+ YYERROR;
-+ }
-+ if (fmopts.aid && fmopts.aid != $2.aid) {
-+ yyerror("nexthop address family doesn't match "
-+ "rule address family");
-+ YYERROR;
-+ }
-+ fmopts.m.nexthop.addr = $2;
-+ fmopts.m.nexthop.flags = FILTER_NEXTHOP_ADDR;
-+ }
-+ | NEXTHOP NEIGHBOR {
-+ if (fmopts.m.nexthop.flags) {
-+ yyerror("nexthop already specified");
-+ YYERROR;
-+ }
-+ fmopts.m.nexthop.flags = FILTER_NEXTHOP_NEIGHBOR;
- }
- ;
-
-@@ -1588,7 +1845,7 @@ filter_set_opt : LOCALPREF NUMBER {
- }
- if (($$ = calloc(1, sizeof(struct filter_set))) == NULL)
- fatal(NULL);
-- if ($2 > 0) {
-+ if ($2 >= 0) {
- $$->type = ACTION_SET_MED;
- $$->action.metric = $2;
- } else {
-@@ -1623,7 +1880,7 @@ filter_set_opt : LOCALPREF NUMBER {
- }
- if (($$ = calloc(1, sizeof(struct filter_set))) == NULL)
- fatal(NULL);
-- if ($2 > 0) {
-+ if ($2 >= 0) {
- $$->type = ACTION_SET_MED;
- $$->action.metric = $2;
- } else {
-@@ -1782,8 +2039,7 @@ filter_set_opt : LOCALPREF NUMBER {
- else
- $$->type = ACTION_SET_COMMUNITY;
-
-- if (parsecommunity($3, &$$->action.community.as,
-- &$$->action.community.type) == -1) {
-+ if (parsecommunity(&$$->action.community, $3) == -1) {
- free($3);
- free($$);
- YYERROR;
-@@ -1796,40 +2052,62 @@ filter_set_opt : LOCALPREF NUMBER {
- free($$);
- YYERROR;
- }
-- /* Don't allow setting of unknown well-known types */
-- if ($$->action.community.as == COMMUNITY_WELLKNOWN) {
-- switch ($$->action.community.type) {
-- case COMMUNITY_NO_EXPORT:
-- case COMMUNITY_NO_ADVERTISE:
-- case COMMUNITY_NO_EXPSUBCONFED:
-- case COMMUNITY_NO_PEER:
-- /* valid */
-- break;
-- default:
-- /* unknown */
-- yyerror("Invalid well-known community");
-- free($$);
-- YYERROR;
-- break;
-- }
-+ }
-+ | EXTCOMMUNITY delete STRING STRING {
-+ if (($$ = calloc(1, sizeof(struct filter_set))) == NULL)
-+ fatal(NULL);
-+ if ($2)
-+ $$->type = ACTION_DEL_EXT_COMMUNITY;
-+ else
-+ $$->type = ACTION_SET_EXT_COMMUNITY;
-+
-+ if (parseextcommunity(&$$->action.ext_community,
-+ $3, $4) == -1) {
-+ free($3);
-+ free($4);
-+ free($$);
-+ YYERROR;
- }
-+ free($3);
-+ free($4);
-+ }
-+ | ORIGIN origincode {
-+ if (($$ = calloc(1, sizeof(struct filter_set))) == NULL)
-+ fatal(NULL);
-+ $$->type = ACTION_SET_ORIGIN;
-+ $$->action.origin = $2;
- }
- ;
-
-+origincode : string {
-+ if (!strcmp($1, "egp"))
-+ $$ = ORIGIN_EGP;
-+ else if (!strcmp($1, "igp"))
-+ $$ = ORIGIN_IGP;
-+ else if (!strcmp($1, "incomplete"))
-+ $$ = ORIGIN_INCOMPLETE;
-+ else {
-+ yyerror("unknown origin \"%s\"", $1);
-+ free($1);
-+ YYERROR;
-+ }
-+ free($1);
-+ };
-+
- comma : ","
- | /* empty */
- ;
-
- unaryop : '=' { $$ = OP_EQ; }
-- | '!' '=' { $$ = OP_NE; }
-- | '<' '=' { $$ = OP_LE; }
-+ | NE { $$ = OP_NE; }
-+ | LE { $$ = OP_LE; }
- | '<' { $$ = OP_LT; }
-- | '>' '=' { $$ = OP_GE; }
-+ | GE { $$ = OP_GE; }
- | '>' { $$ = OP_GT; }
- ;
-
- binaryop : '-' { $$ = OP_RANGE; }
-- | '>' '<' { $$ = OP_XRANGE; }
-+ | XRANGE { $$ = OP_XRANGE; }
- ;
-
- %%
-@@ -1873,6 +2151,7 @@ lookup(char *s)
- { "allow", ALLOW},
- { "announce", ANNOUNCE},
- { "any", ANY},
-+ { "as-4byte", AS4BYTE },
- { "blackhole", BLACKHOLE},
- { "capabilities", CAPABILITIES},
- { "community", COMMUNITY},
-@@ -1889,16 +2168,22 @@ lookup(char *s)
- { "enforce", ENFORCE},
- { "esp", ESP},
- { "evaluate", EVALUATE},
-+ { "export-target", EXPORTTRGT},
-+ { "ext-community", EXTCOMMUNITY},
- { "fib-update", FIBUPDATE},
- { "from", FROM},
- { "group", GROUP},
- { "holdtime", HOLDTIME},
- { "ignore", IGNORE},
- { "ike", IKE},
-+ { "import-target", IMPORTTRGT},
- { "in", IN},
- { "include", INCLUDE},
- { "inet", IPV4},
- { "inet6", IPV6},
-+#if defined(IPV6_LINKLOCAL_PEER)
-+ { "interface", LLIFACE},
-+#endif
- { "ipsec", IPSEC},
- { "key", KEY},
- { "listen", LISTEN},
-@@ -1906,6 +2191,8 @@ lookup(char *s)
- { "localpref", LOCALPREF},
- { "log", LOG},
- { "match", MATCH},
-+ { "max-as-len", MAXASLEN},
-+ { "max-as-seq", MAXASSEQ},
- { "max-prefix", MAXPREFIX},
- { "md5sig", MD5SIG},
- { "med", MED},
-@@ -1918,6 +2205,7 @@ lookup(char *s)
- { "nexthop", NEXTHOP},
- { "no-modify", NOMODIFY},
- { "on", ON},
-+ { "origin", ORIGIN},
- { "out", OUT},
- { "passive", PASSIVE},
- { "password", PASSWORD},
-@@ -1929,10 +2217,14 @@ lookup(char *s)
- { "prepend-self", PREPEND_SELF},
- { "qualify", QUALIFY},
- { "quick", QUICK},
-+ { "rd", RD},
- { "rde", RDE},
-+ { "rdomain", RDOMAIN},
-+ { "refresh", REFRESH },
- { "reject", REJECT},
- { "remote-as", REMOTEAS},
- { "restart", RESTART},
-+ { "restricted", RESTRICTED},
- { "rib", RIB},
- { "route-collector", ROUTECOLL},
- { "route-reflector", REFLECTOR},
-@@ -1941,6 +2233,7 @@ lookup(char *s)
- { "rtlabel", RTLABEL},
- { "self", SELF},
- { "set", SET},
-+ { "socket", SOCKET },
- { "softreconfig", SOFTRECONFIG},
- { "source-as", SOURCEAS},
- { "spi", SPI},
-@@ -2117,9 +2410,10 @@ top:
- return (0);
- if (next == quotec || c == ' ' || c == '\t')
- c = next;
-- else if (next == '\n')
-+ else if (next == '\n') {
-+ file->lineno++;
- continue;
-- else
-+ } else
- lungetc(next);
- } else if (c == quotec) {
- *p = '\0';
-@@ -2135,6 +2429,26 @@ top:
- if (yylval.v.string == NULL)
- fatal("yylex: strdup");
- return (STRING);
-+ case '!':
-+ next = lgetc(0);
-+ if (next == '=')
-+ return (NE);
-+ lungetc(next);
-+ break;
-+ case '<':
-+ next = lgetc(0);
-+ if (next == '=')
-+ return (LE);
-+ lungetc(next);
-+ break;
-+ case '>':
-+ next = lgetc(0);
-+ if (next == '<')
-+ return (XRANGE);
-+ else if (next == '=')
-+ return (GE);
-+ lungetc(next);
-+ break;
- }
-
- #define allowed_to_end_number(x) \
-@@ -2274,18 +2588,21 @@ popfile(void)
- int
- parse_config(char *filename, struct bgpd_config *xconf,
- struct mrt_head *xmconf, struct peer **xpeers, struct network_head *nc,
-- struct filter_head *xfilter_l)
-+ struct filter_head *xfilter_l, struct rdomain_head *xrdom_l)
- {
- struct sym *sym, *next;
- struct peer *p, *pnext;
- struct listen_addr *la;
- struct network *n;
- struct filter_rule *r;
-+ struct rde_rib *rr;
-+ struct rdomain *rd;
- int errors = 0;
-
- if ((conf = calloc(1, sizeof(struct bgpd_config))) == NULL)
- fatal(NULL);
- conf->opts = xconf->opts;
-+ conf->csock = strdup(SOCKET_NAME);
-
- if ((file = pushfile(filename, 1)) == NULL) {
- free(conf);
-@@ -2316,13 +2633,15 @@ parse_config(char *filename, struct bgpd
- id = 1;
-
- /* network list is always empty in the parent */
-- netconf = nc;
-+ gnetconf = netconf = nc;
- TAILQ_INIT(netconf);
- /* init the empty filter list for later */
- TAILQ_INIT(xfilter_l);
-+ SIMPLEQ_INIT(xrdom_l);
-+ rdom_l = xrdom_l;
-
-- add_rib("Adj-RIB-In", F_RIB_NOEVALUATE);
-- add_rib("Loc-RIB", 0);
-+ add_rib("Adj-RIB-In", 0, F_RIB_NOFIB | F_RIB_NOEVALUATE);
-+ add_rib("Loc-RIB", 0, 0);
-
- yyparse();
- errors = file->errors;
-@@ -2344,6 +2663,9 @@ parse_config(char *filename, struct bgpd
-
- if (errors) {
- /* XXX more leaks in this case */
-+ free(conf->csock);
-+ free(conf->rcsock);
-+
- while ((la = TAILQ_FIRST(listen_addrs)) != NULL) {
- TAILQ_REMOVE(listen_addrs, la, entry);
- free(la);
-@@ -2357,23 +2679,44 @@ parse_config(char *filename, struct bgpd
-
- while ((n = TAILQ_FIRST(netconf)) != NULL) {
- TAILQ_REMOVE(netconf, n, entry);
-+ filterset_free(&n->net.attrset);
- free(n);
- }
-
- while ((r = TAILQ_FIRST(filter_l)) != NULL) {
- TAILQ_REMOVE(filter_l, r, entry);
-+ filterset_free(&r->set);
- free(r);
- }
-
- while ((r = TAILQ_FIRST(peerfilter_l)) != NULL) {
- TAILQ_REMOVE(peerfilter_l, r, entry);
-+ filterset_free(&r->set);
- free(r);
- }
-
- while ((r = TAILQ_FIRST(groupfilter_l)) != NULL) {
- TAILQ_REMOVE(groupfilter_l, r, entry);
-+ filterset_free(&r->set);
- free(r);
- }
-+ while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) {
-+ SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
-+ free(rr);
-+ }
-+ while ((rd = SIMPLEQ_FIRST(rdom_l)) != NULL) {
-+ SIMPLEQ_REMOVE_HEAD(rdom_l, entry);
-+ filterset_free(&rd->export);
-+ filterset_free(&rd->import);
-+
-+ while ((n = TAILQ_FIRST(&rd->net_l)) != NULL) {
-+ TAILQ_REMOVE(&rd->net_l, n, entry);
-+ filterset_free(&n->net.attrset);
-+ free(n);
-+ }
-+
-+ free(rd);
-+ }
- } else {
- errors += merge_config(xconf, conf, peer_l, listen_addrs);
- errors += mrt_mergeconfig(xmconf, mrtconf);
-@@ -2505,27 +2848,27 @@ getcommunity(char *s)
- }
-
- int
--parsecommunity(char *s, int *as, int *type)
-+parsecommunity(struct filter_community *c, char *s)
- {
- char *p;
-- int i;
-+ int i, as;
-
- /* Well-known communities */
- if (strcasecmp(s, "NO_EXPORT") == 0) {
-- *as = COMMUNITY_WELLKNOWN;
-- *type = COMMUNITY_NO_EXPORT;
-+ c->as = COMMUNITY_WELLKNOWN;
-+ c->type = COMMUNITY_NO_EXPORT;
- return (0);
- } else if (strcasecmp(s, "NO_ADVERTISE") == 0) {
-- *as = COMMUNITY_WELLKNOWN;
-- *type = COMMUNITY_NO_ADVERTISE;
-+ c->as = COMMUNITY_WELLKNOWN;
-+ c->type = COMMUNITY_NO_ADVERTISE;
- return (0);
- } else if (strcasecmp(s, "NO_EXPORT_SUBCONFED") == 0) {
-- *as = COMMUNITY_WELLKNOWN;
-- *type = COMMUNITY_NO_EXPSUBCONFED;
-+ c->as = COMMUNITY_WELLKNOWN;
-+ c->type = COMMUNITY_NO_EXPSUBCONFED;
- return (0);
- } else if (strcasecmp(s, "NO_PEER") == 0) {
-- *as = COMMUNITY_WELLKNOWN;
-- *type = COMMUNITY_NO_PEER;
-+ c->as = COMMUNITY_WELLKNOWN;
-+ c->type = COMMUNITY_NO_PEER;
- return (0);
- }
-
-@@ -2537,23 +2880,176 @@ parsecommunity(char *s, int *as, int *ty
-
- if ((i = getcommunity(s)) == COMMUNITY_ERROR)
- return (-1);
-- if (i == USHRT_MAX) {
-+ if (i == COMMUNITY_WELLKNOWN) {
- yyerror("Bad community AS number");
- return (-1);
- }
-- *as = i;
-+ as = i;
-
- if ((i = getcommunity(p)) == COMMUNITY_ERROR)
- return (-1);
-- *type = i;
-+ c->as = as;
-+ c->type = i;
-
- return (0);
- }
-
-+int
-+parsesubtype(char *type)
-+{
-+ /* this has to be sorted always */
-+ static const struct keywords keywords[] = {
-+ { "bdc", EXT_COMMUNITY_BGP_COLLECT },
-+ { "odi", EXT_COMMUNITY_OSPF_DOM_ID },
-+ { "ori", EXT_COMMUNITY_OSPF_RTR_ID },
-+ { "ort", EXT_COMMUNITY_OSPF_RTR_TYPE },
-+ { "rt", EXT_COMMUNITY_ROUTE_TGT },
-+ { "soo", EXT_CUMMUNITY_ROUTE_ORIG }
-+ };
-+ const struct keywords *p;
-+
-+ p = bsearch(type, keywords, sizeof(keywords)/sizeof(keywords[0]),
-+ sizeof(keywords[0]), kw_cmp);
-+
-+ if (p)
-+ return (p->k_val);
-+ else
-+ return (-1);
-+}
-+
-+int
-+parseextvalue(char *s, u_int32_t *v)
-+{
-+ const char *errstr;
-+ char *p;
-+ struct in_addr ip;
-+ u_int32_t uvalh = 0, uval;
-+
-+ if ((p = strchr(s, '.')) == NULL) {
-+ /* AS_PLAIN number (4 or 2 byte) */
-+ uval = strtonum(s, 0, UINT_MAX, &errstr);
-+ if (errstr) {
-+ yyerror("Bad ext-community %s is %s", s, errstr);
-+ return (-1);
-+ }
-+ *v = uval;
-+ if (uval > USHRT_MAX)
-+ return (EXT_COMMUNITY_FOUR_AS);
-+ else
-+ return (EXT_COMMUNITY_TWO_AS);
-+ } else if (strchr(p + 1, '.') == NULL) {
-+ /* AS_DOT number (4-byte) */
-+ *p++ = '\0';
-+ uvalh = strtonum(s, 0, USHRT_MAX, &errstr);
-+ if (errstr) {
-+ yyerror("Bad ext-community %s is %s", s, errstr);
-+ return (-1);
-+ }
-+ uval = strtonum(p, 0, USHRT_MAX, &errstr);
-+ if (errstr) {
-+ yyerror("Bad ext-community %s is %s", p, errstr);
-+ return (-1);
-+ }
-+ *v = uval | (uvalh << 16);
-+ return (EXT_COMMUNITY_FOUR_AS);
-+ } else {
-+ /* more then one dot -> IP address */
-+ if (inet_aton(s, &ip) == 0) {
-+ yyerror("Bad ext-community %s not parseable", s);
-+ return (-1);
-+ }
-+ *v = ip.s_addr;
-+ return (EXT_COMMUNITY_IPV4);
-+ }
-+ return (-1);
-+}
-+
-+int
-+parseextcommunity(struct filter_extcommunity *c, char *t, char *s)
-+{
-+ const struct ext_comm_pairs iana[] = IANA_EXT_COMMUNITIES;
-+ const char *errstr;
-+ u_int64_t ullval = 0;
-+ u_int32_t uval;
-+ char *p, *ep;
-+ unsigned int i;
-+ int type, subtype;
-+
-+ if ((subtype = parsesubtype(t)) == -1) {
-+ yyerror("Bad ext-community unknown type");
-+ return (-1);
-+ }
-+
-+ if ((p = strchr(s, ':')) == NULL) {
-+ type = EXT_COMMUNITY_OPAQUE,
-+ errno = 0;
-+ ullval = strtoull(s, &ep, 0);
-+ if (s[0] == '\0' || *ep != '\0') {
-+ yyerror("Bad ext-community bad value");
-+ return (-1);
-+ }
-+ if (errno == ERANGE && ullval > EXT_COMMUNITY_OPAQUE_MAX) {
-+ yyerror("Bad ext-community value to big");
-+ return (-1);
-+ }
-+ c->data.ext_opaq = ullval;
-+ } else {
-+ *p++ = '\0';
-+ if ((type = parseextvalue(s, &uval)) == -1)
-+ return (-1);
-+ switch (type) {
-+ case EXT_COMMUNITY_TWO_AS:
-+ ullval = strtonum(p, 0, UINT_MAX, &errstr);
-+ break;
-+ case EXT_COMMUNITY_IPV4:
-+ case EXT_COMMUNITY_FOUR_AS:
-+ ullval = strtonum(p, 0, USHRT_MAX, &errstr);
-+ break;
-+ default:
-+ fatalx("parseextcommunity: unexpected result");
-+ }
-+ if (errstr) {
-+ yyerror("Bad ext-community %s is %s", p,
-+ errstr);
-+ return (-1);
-+ }
-+ switch (type) {
-+ case EXT_COMMUNITY_TWO_AS:
-+ c->data.ext_as.as = uval;
-+ c->data.ext_as.val = ullval;
-+ break;
-+ case EXT_COMMUNITY_IPV4:
-+ c->data.ext_ip.addr.s_addr = uval;
-+ c->data.ext_ip.val = ullval;
-+ break;
-+ case EXT_COMMUNITY_FOUR_AS:
-+ c->data.ext_as4.as4 = uval;
-+ c->data.ext_as4.val = ullval;
-+ break;
-+ }
-+ }
-+ c->type = type;
-+ c->subtype = subtype;
-+
-+ /* verify type/subtype combo */
-+ for (i = 0; i < sizeof(iana)/sizeof(iana[0]); i++) {
-+ if (iana[i].type == type && iana[i].subtype == subtype) {
-+ if (iana[i].transitive)
-+ c->type |= EXT_COMMUNITY_TRANSITIVE;
-+ c->flags |= EXT_COMMUNITY_FLAG_VALID;
-+ return (0);
-+ }
-+ }
-+
-+ yyerror("Bad ext-community bad format for type");
-+ return (-1);
-+}
-+
- struct peer *
- alloc_peer(void)
- {
- struct peer *p;
-+ u_int8_t i;
-
- if ((p = calloc(1, sizeof(struct peer))) == NULL)
- fatal("new_peer");
-@@ -2564,11 +3060,11 @@ alloc_peer(void)
- p->conf.distance = 1;
- p->conf.announce_type = ANNOUNCE_UNDEF;
- p->conf.announce_capa = 1;
-- p->conf.capabilities.mp_v4 = SAFI_UNICAST;
-- p->conf.capabilities.mp_v6 = SAFI_NONE;
-+ for (i = 0; i < AID_MAX; i++)
-+ p->conf.capabilities.mp[i] = -1;
- p->conf.capabilities.refresh = 1;
-- p->conf.capabilities.restart = 0;
-- p->conf.capabilities.as4byte = 0;
-+ p->conf.capabilities.grestart.restart = 1;
-+ p->conf.capabilities.as4byte = 1;
- p->conf.local_as = conf->as;
- p->conf.local_short_as = conf->short_as;
- p->conf.softreconfig_in = 1;
-@@ -2592,6 +3088,9 @@ new_peer(void)
- if (strlcpy(p->conf.descr, curgroup->conf.descr,
- sizeof(p->conf.descr)) >= sizeof(p->conf.descr))
- fatalx("new_peer descr strlcpy");
-+ if (strlcpy(p->conf.lliface, curgroup->conf.lliface,
-+ sizeof(p->conf.lliface)) >= sizeof(p->conf.lliface))
-+ fatalx("new_peer lliface strlcpy");
- p->conf.groupid = curgroup->conf.id;
- p->conf.local_as = curgroup->conf.local_as;
- p->conf.local_short_as = curgroup->conf.local_short_as;
-@@ -2674,39 +3173,52 @@ add_mrtconfig(enum mrt_type type, char *
- }
-
- int
--add_rib(char *name, u_int16_t flags)
-+add_rib(char *name, u_int rtableid, u_int16_t flags)
- {
- struct rde_rib *rr;
-+ u_int rdom;
-
-- if (find_rib(name)) {
-- yyerror("rib \"%s\" allready exists.", name);
-- return (-1);
-- }
--
-- if ((rr = calloc(1, sizeof(*rr))) == NULL) {
-- log_warn("add_rib");
-- return (-1);
-+ if ((rr = find_rib(name)) == NULL) {
-+ if ((rr = calloc(1, sizeof(*rr))) == NULL) {
-+ log_warn("add_rib");
-+ return (-1);
-+ }
- }
- if (strlcpy(rr->name, name, sizeof(rr->name)) >= sizeof(rr->name)) {
- yyerror("rib name \"%s\" too long: max %u",
- name, sizeof(rr->name) - 1);
-+ free(rr);
- return (-1);
- }
- rr->flags |= flags;
-+ if ((rr->flags & F_RIB_HASNOFIB) == 0) {
-+ if (ktable_exists(rtableid, &rdom) != 1) {
-+ yyerror("rtable id %lld does not exist", rtableid);
-+ free(rr);
-+ return (-1);
-+ }
-+ if (rdom != 0) {
-+ yyerror("rtable %lld does not belong to rdomain 0",
-+ rtableid);
-+ free(rr);
-+ return (-1);
-+ }
-+ rr->rtableid = rtableid;
-+ }
- SIMPLEQ_INSERT_TAIL(&ribnames, rr, entry);
- return (0);
- }
-
--int
-+struct rde_rib *
- find_rib(char *name)
- {
- struct rde_rib *rr;
-
- SIMPLEQ_FOREACH(rr, &ribnames, entry) {
- if (!strcmp(rr->name, name))
-- return (1);
-+ return (rr);
- }
-- return (0);
-+ return (NULL);
- }
-
- int
-@@ -2715,7 +3227,7 @@ get_id(struct peer *newpeer)
- struct peer *p;
-
- for (p = peer_l_old; p != NULL; p = p->next)
-- if (newpeer->conf.remote_addr.af) {
-+ if (newpeer->conf.remote_addr.aid) {
- if (!memcmp(&p->conf.remote_addr,
- &newpeer->conf.remote_addr,
- sizeof(p->conf.remote_addr))) {
-@@ -2856,9 +3368,11 @@ str2key(char *s, char *dest, size_t max_
- int
- neighbor_consistent(struct peer *p)
- {
-+ u_int8_t i;
-+
- /* local-address and peer's address: same address family */
-- if (p->conf.local_addr.af &&
-- p->conf.local_addr.af != p->conf.remote_addr.af) {
-+ if (p->conf.local_addr.aid &&
-+ p->conf.local_addr.aid != p->conf.remote_addr.aid) {
- yyerror("local-address and neighbor address "
- "must be of the same address family");
- return (-1);
-@@ -2869,7 +3383,7 @@ neighbor_consistent(struct peer *p)
- p->conf.auth.method == AUTH_IPSEC_IKE_AH ||
- p->conf.auth.method == AUTH_IPSEC_MANUAL_ESP ||
- p->conf.auth.method == AUTH_IPSEC_MANUAL_AH) &&
-- !p->conf.local_addr.af) {
-+ !p->conf.local_addr.aid) {
- yyerror("neighbors with any form of IPsec configured "
- "need local-address to be specified");
- return (-1);
-@@ -2889,18 +3403,14 @@ neighbor_consistent(struct peer *p)
- return (-1);
- }
-
-- /* for testing: enable 4-byte AS number capability if necessary */
-- if (conf->as > USHRT_MAX || p->conf.remote_as > USHRT_MAX)
-- p->conf.capabilities.as4byte = 1;
--
- /* set default values if they where undefined */
- p->conf.ebgp = (p->conf.remote_as != conf->as);
- if (p->conf.announce_type == ANNOUNCE_UNDEF)
-- p->conf.announce_type = p->conf.ebgp == 0 ?
-- ANNOUNCE_ALL : ANNOUNCE_SELF;
-+ p->conf.announce_type = p->conf.ebgp ?
-+ ANNOUNCE_SELF : ANNOUNCE_ALL;
- if (p->conf.enforce_as == ENFORCE_AS_UNDEF)
-- p->conf.enforce_as = p->conf.ebgp == 0 ?
-- ENFORCE_AS_OFF : ENFORCE_AS_ON;
-+ p->conf.enforce_as = p->conf.ebgp ?
-+ ENFORCE_AS_ON : ENFORCE_AS_OFF;
-
- /* EBGP neighbors are not allowed in route reflector clusters */
- if (p->conf.reflector_client && p->conf.ebgp) {
-@@ -2909,6 +3419,11 @@ neighbor_consistent(struct peer *p)
- return (-1);
- }
-
-+ /* the default MP capability is NONE */
-+ for (i = 0; i < AID_MAX; i++)
-+ if (p->conf.capabilities.mp[i] == -1)
-+ p->conf.capabilities.mp[i] = 0;
-+
- return (0);
- }
-
-@@ -2927,6 +3442,11 @@ merge_filterset(struct filter_set_head *
- yyerror("community is already set");
- else if (s->type == ACTION_DEL_COMMUNITY)
- yyerror("community will already be deleted");
-+ else if (s->type == ACTION_SET_EXT_COMMUNITY)
-+ yyerror("ext-community is already set");
-+ else if (s->type == ACTION_DEL_EXT_COMMUNITY)
-+ yyerror(
-+ "ext-community will already be deleted");
- else
- yyerror("redefining set parameter %s",
- filterset_name(s->type));
-@@ -2953,9 +3473,18 @@ merge_filterset(struct filter_set_head *
- return (0);
- }
- break;
-+ case ACTION_SET_EXT_COMMUNITY:
-+ case ACTION_DEL_EXT_COMMUNITY:
-+ if (memcmp(&s->action.ext_community,
-+ &t->action.ext_community,
-+ sizeof(s->action.ext_community)) < 0) {
-+ TAILQ_INSERT_BEFORE(t, s, entry);
-+ return (0);
-+ }
-+ break;
- case ACTION_SET_NEXTHOP:
-- if (s->action.nexthop.af <
-- t->action.nexthop.af) {
-+ if (s->action.nexthop.aid <
-+ t->action.nexthop.aid) {
- TAILQ_INSERT_BEFORE(t, s, entry);
- return (0);
- }
-@@ -2985,22 +3514,6 @@ copy_filterset(struct filter_set_head *s
- }
- }
-
--void
--move_filterset(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);
-- }
--}
--
- struct filter_rule *
- get_rule(enum action_types type)
- {
diff --git a/net/openbgpd/files/patch-bgpd_pfkey.c b/net/openbgpd/files/patch-bgpd_pfkey.c
deleted file mode 100644
index 224298fadf0d..000000000000
--- a/net/openbgpd/files/patch-bgpd_pfkey.c
+++ /dev/null
@@ -1,471 +0,0 @@
-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);
- }
diff --git a/net/openbgpd/files/patch-bgpd_pftable.c b/net/openbgpd/files/patch-bgpd_pftable.c
deleted file mode 100644
index ee6a1ea2750c..000000000000
--- a/net/openbgpd/files/patch-bgpd_pftable.c
+++ /dev/null
@@ -1,17 +0,0 @@
-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++;
diff --git a/net/openbgpd/files/patch-bgpd_printconf.c b/net/openbgpd/files/patch-bgpd_printconf.c
deleted file mode 100644
index 9b00e1efa386..000000000000
--- a/net/openbgpd/files/patch-bgpd_printconf.c
+++ /dev/null
@@ -1,439 +0,0 @@
-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);
diff --git a/net/openbgpd/files/patch-bgpd_rde.c b/net/openbgpd/files/patch-bgpd_rde.c
deleted file mode 100644
index 76761d859f1d..000000000000
--- a/net/openbgpd/files/patch-bgpd_rde.c
+++ /dev/null
@@ -1,2614 +0,0 @@
-Index: bgpd/rde.c
-===================================================================
-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde.c,v
-retrieving revision 1.1.1.8
-retrieving revision 1.12
-diff -u -p -r1.1.1.8 -r1.12
---- bgpd/rde.c 14 Feb 2010 20:19:57 -0000 1.1.1.8
-+++ bgpd/rde.c 16 May 2014 00:36:26 -0000 1.12
-@@ -1,4 +1,4 @@
--/* $OpenBSD: rde.c,v 1.264 2009/06/29 12:22:16 claudio Exp $ */
-+/* $OpenBSD: rde.c,v 1.320 2012/09/18 09:45:51 claudio Exp $ */
-
- /*
- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
-@@ -18,10 +18,11 @@
-
- #include <sys/types.h>
- #include <sys/socket.h>
-+#include <sys/time.h>
-+#include <sys/resource.h>
-
- #include <errno.h>
- #include <ifaddrs.h>
--#include <limits.h>
- #include <pwd.h>
- #include <poll.h>
- #include <signal.h>
-@@ -50,13 +51,18 @@ void rde_update_withdraw(struct rde_pe
- u_int8_t);
- int rde_attr_parse(u_char *, u_int16_t, struct rde_peer *,
- struct rde_aspath *, struct mpattr *);
-+int rde_attr_add(struct rde_aspath *, u_char *, u_int16_t);
- u_int8_t rde_attr_missing(struct rde_aspath *, int, u_int16_t);
--int rde_get_mp_nexthop(u_char *, u_int16_t, u_int16_t,
-- struct rde_aspath *);
-+int rde_get_mp_nexthop(u_char *, u_int16_t, u_int8_t,
-+ struct rde_aspath *, struct rde_peer *);
-+int rde_update_extract_prefix(u_char *, u_int16_t, void *,
-+ u_int8_t, u_int8_t);
- int rde_update_get_prefix(u_char *, u_int16_t, struct bgpd_addr *,
- u_int8_t *);
- int rde_update_get_prefix6(u_char *, u_int16_t, struct bgpd_addr *,
- u_int8_t *);
-+int rde_update_get_vpn4(u_char *, u_int16_t, struct bgpd_addr *,
-+ u_int8_t *);
- void rde_update_err(struct rde_peer *, u_int8_t , u_int8_t,
- void *, u_int16_t);
- void rde_update_log(const char *, u_int16_t,
-@@ -78,11 +84,15 @@ void rde_dump_ctx_new(struct ctl_show_
- void rde_dump_mrt_new(struct mrt *, pid_t, int);
- void rde_dump_done(void *);
-
-+int rde_rdomain_import(struct rde_aspath *, struct rdomain *);
- void rde_up_dump_upcall(struct rib_entry *, void *);
- void rde_softreconfig_out(struct rib_entry *, void *);
- void rde_softreconfig_in(struct rib_entry *, void *);
-+void rde_softreconfig_load(struct rib_entry *, void *);
-+void rde_softreconfig_load_peer(struct rib_entry *, void *);
-+void rde_softreconfig_unload_peer(struct rib_entry *, void *);
- void rde_update_queue_runner(void);
--void rde_update6_queue_runner(void);
-+void rde_update6_queue_runner(u_int8_t);
-
- void peer_init(u_int32_t);
- void peer_shutdown(void);
-@@ -91,10 +101,12 @@ struct rde_peer *peer_add(u_int32_t, str
- struct rde_peer *peer_get(u_int32_t);
- void peer_up(u_int32_t, struct session_up *);
- void peer_down(u_int32_t);
--void peer_dump(u_int32_t, u_int16_t, u_int8_t);
--void peer_send_eor(struct rde_peer *, u_int16_t, u_int16_t);
-+void peer_flush(struct rde_peer *, u_int8_t);
-+void peer_stale(u_int32_t, u_int8_t);
-+void peer_recv_eor(struct rde_peer *, u_int8_t);
-+void peer_dump(u_int32_t, u_int8_t);
-+void peer_send_eor(struct rde_peer *, u_int8_t);
-
--void network_init(struct network_head *);
- void network_add(struct network_config *, int);
- void network_delete(struct network_config *, int);
- void network_dump_upcall(struct rib_entry *, void *);
-@@ -108,6 +120,7 @@ time_t reloadtime;
- struct rde_peer_head peerlist;
- struct rde_peer *peerself;
- struct filter_head *rules_l, *newrules;
-+struct rdomain_head *rdomains_l, *newdomains;
- struct imsgbuf *ibuf_se;
- struct imsgbuf *ibuf_se_ctl;
- struct imsgbuf *ibuf_main;
-@@ -120,11 +133,12 @@ struct rde_dump_ctx {
- };
-
- struct rde_mrt_ctx {
-- struct mrt mrt;
-- struct rib_context ribctx;
-+ struct mrt mrt;
-+ struct rib_context ribctx;
-+ LIST_ENTRY(rde_mrt_ctx) entry;
- };
-
--struct mrt_head rde_mrts = LIST_HEAD_INITIALIZER(rde_mrts);
-+LIST_HEAD(, rde_mrt_ctx) rde_mrts = LIST_HEAD_INITIALIZER(rde_mrts);
- u_int rde_mrt_cnt;
-
- void
-@@ -144,24 +158,17 @@ u_int32_t attrhashsize = 512;
- u_int32_t nexthophashsize = 64;
-
- pid_t
--rde_main(struct bgpd_config *config, struct peer *peer_l,
-- struct network_head *net_l, struct filter_head *rules,
-- struct mrt_head *mrt_l, struct rib_names *rib_n, int pipe_m2r[2],
-- int pipe_s2r[2], int pipe_m2s[2], int pipe_s2rctl[2], int debug)
-+rde_main(int pipe_m2r[2], int pipe_s2r[2], int pipe_m2s[2], int pipe_s2rctl[2],
-+ int debug)
- {
- pid_t pid;
- struct passwd *pw;
-- struct peer *p;
-- struct listen_addr *la;
- struct pollfd *pfd = NULL;
-- struct filter_rule *f;
-- struct filter_set *set;
-- struct nexthop *nh;
-- struct rde_rib *rr;
-- struct mrt *mrt, *xmrt;
-+ struct rde_mrt_ctx *mctx, *xmctx;
- void *newp;
- u_int pfd_elms = 0, i, j;
- int timeout;
-+ u_int8_t aid;
-
- switch (pid = fork()) {
- case -1:
-@@ -172,8 +179,6 @@ rde_main(struct bgpd_config *config, str
- return (pid);
- }
-
-- conf = config;
--
- if ((pw = getpwnam(BGPD_USER)) == NULL)
- fatal("getpwnam");
-
-@@ -194,6 +199,8 @@ rde_main(struct bgpd_config *config, str
- signal(SIGINT, rde_sighdlr);
- signal(SIGPIPE, SIG_IGN);
- signal(SIGHUP, SIG_IGN);
-+ signal(SIGALRM, SIG_IGN);
-+ signal(SIGUSR1, SIG_IGN);
-
- close(pipe_s2r[0]);
- close(pipe_s2rctl[0]);
-@@ -210,50 +217,25 @@ rde_main(struct bgpd_config *config, str
- imsg_init(ibuf_se_ctl, pipe_s2rctl[1]);
- imsg_init(ibuf_main, pipe_m2r[1]);
-
-- /* peer list, mrt list and listener list are not used in the RDE */
-- while ((p = peer_l) != NULL) {
-- peer_l = p->next;
-- free(p);
-- }
--
-- while ((mrt = LIST_FIRST(mrt_l)) != NULL) {
-- LIST_REMOVE(mrt, entry);
-- free(mrt);
-- }
--
-- while ((la = TAILQ_FIRST(config->listen_addrs)) != NULL) {
-- TAILQ_REMOVE(config->listen_addrs, la, entry);
-- close(la->fd);
-- free(la);
-- }
-- free(config->listen_addrs);
--
- pt_init();
-- while ((rr = SIMPLEQ_FIRST(&ribnames))) {
-- SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
-- rib_new(-1, rr->name, rr->flags);
-- free(rr);
-- }
- path_init(pathhashsize);
- aspath_init(pathhashsize);
- attr_init(attrhashsize);
- nexthop_init(nexthophashsize);
- peer_init(peerhashsize);
-- rules_l = rules;
-- network_init(net_l);
-
-+ rules_l = calloc(1, sizeof(struct filter_head));
-+ if (rules_l == NULL)
-+ fatal(NULL);
-+ TAILQ_INIT(rules_l);
-+ rdomains_l = calloc(1, sizeof(struct rdomain_head));
-+ if (rdomains_l == NULL)
-+ fatal(NULL);
-+ SIMPLEQ_INIT(rdomains_l);
-+ if ((conf = calloc(1, sizeof(struct bgpd_config))) == NULL)
-+ fatal(NULL);
- log_info("route decision engine ready");
-
-- TAILQ_FOREACH(f, rules, entry) {
-- f->peer.ribid = rib_find(f->rib);
-- TAILQ_FOREACH(set, &f->set, entry) {
-- if (set->type == ACTION_SET_NEXTHOP) {
-- nh = nexthop_get(&set->action.nexthop);
-- nh->refcnt++;
-- }
-- }
-- }
--
- while (rde_quit == 0) {
- if (pfd_elms < PFD_PIPE_COUNT + rde_mrt_cnt) {
- if ((newp = realloc(pfd, sizeof(struct pollfd) *
-@@ -287,11 +269,18 @@ rde_main(struct bgpd_config *config, str
- timeout = 0;
-
- i = PFD_PIPE_COUNT;
-- LIST_FOREACH(mrt, &rde_mrts, entry) {
-- if (mrt->wbuf.queued) {
-- pfd[i].fd = mrt->wbuf.fd;
-+ for (mctx = LIST_FIRST(&rde_mrts); mctx != 0; mctx = xmctx) {
-+ xmctx = LIST_NEXT(mctx, entry);
-+ if (mctx->mrt.wbuf.queued) {
-+ pfd[i].fd = mctx->mrt.wbuf.fd;
- pfd[i].events = POLLOUT;
- i++;
-+ } else if (mctx->mrt.state == MRT_STATE_REMOVE) {
-+ close(mctx->mrt.wbuf.fd);
-+ LIST_REMOVE(&mctx->ribctx, entry);
-+ LIST_REMOVE(mctx, entry);
-+ free(mctx);
-+ rde_mrt_cnt--;
- }
- }
-
-@@ -325,24 +314,17 @@ rde_main(struct bgpd_config *config, str
- if (pfd[PFD_PIPE_SESSION_CTL].revents & POLLIN)
- rde_dispatch_imsg_session(ibuf_se_ctl);
-
-- for (j = PFD_PIPE_COUNT, mrt = LIST_FIRST(&rde_mrts);
-- j < i && mrt != 0; j++) {
-- xmrt = LIST_NEXT(mrt, entry);
-- if (pfd[j].fd == mrt->wbuf.fd &&
-+ for (j = PFD_PIPE_COUNT, mctx = LIST_FIRST(&rde_mrts);
-+ j < i && mctx != 0; j++) {
-+ if (pfd[j].fd == mctx->mrt.wbuf.fd &&
- pfd[j].revents & POLLOUT)
-- mrt_write(mrt);
-- if (mrt->wbuf.queued == 0 &&
-- mrt->state == MRT_STATE_REMOVE) {
-- close(mrt->wbuf.fd);
-- LIST_REMOVE(mrt, entry);
-- free(mrt);
-- rde_mrt_cnt--;
-- }
-- mrt = xmrt;
-+ mrt_write(&mctx->mrt);
-+ mctx = LIST_NEXT(mctx, entry);
- }
-
- rde_update_queue_runner();
-- rde_update6_queue_runner();
-+ for (aid = AID_INET6; aid < AID_MAX; aid++)
-+ rde_update6_queue_runner(aid);
- if (ibuf_se_ctl->w.queued <= 0)
- rib_dump_runner();
- }
-@@ -351,11 +333,12 @@ rde_main(struct bgpd_config *config, str
- if (debug)
- rde_shutdown();
-
-- while ((mrt = LIST_FIRST(&rde_mrts)) != NULL) {
-- msgbuf_clear(&mrt->wbuf);
-- close(mrt->wbuf.fd);
-- LIST_REMOVE(mrt, entry);
-- free(mrt);
-+ while ((mctx = LIST_FIRST(&rde_mrts)) != NULL) {
-+ msgbuf_clear(&mctx->mrt.wbuf);
-+ close(mctx->mrt.wbuf.fd);
-+ LIST_REMOVE(&mctx->ribctx, entry);
-+ LIST_REMOVE(mctx, entry);
-+ free(mctx);
- }
-
- msgbuf_clear(&ibuf_se->w);
-@@ -378,13 +361,18 @@ rde_dispatch_imsg_session(struct imsgbuf
- struct imsg imsg;
- struct peer p;
- struct peer_config pconf;
-- struct rrefresh r;
-- struct rde_peer *peer;
- struct session_up sup;
-+ struct ctl_show_rib csr;
- struct ctl_show_rib_request req;
-+ struct rde_peer *peer;
-+ struct rde_aspath *asp;
- struct filter_set *s;
- struct nexthop *nh;
-- int n;
-+ u_int8_t *asdata;
-+ ssize_t n;
-+ int verbose;
-+ u_int16_t len;
-+ u_int8_t aid;
-
- if ((n = imsg_read(ibuf)) == -1)
- fatal("rde_dispatch_imsg_session: imsg_read error");
-@@ -422,13 +410,56 @@ rde_dispatch_imsg_session(struct imsgbuf
- case IMSG_SESSION_DOWN:
- peer_down(imsg.hdr.peerid);
- break;
-+ case IMSG_SESSION_STALE:
-+ if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(aid)) {
-+ log_warnx("rde_dispatch: wrong imsg len");
-+ break;
-+ }
-+ memcpy(&aid, imsg.data, sizeof(aid));
-+ if (aid >= AID_MAX)
-+ fatalx("IMSG_SESSION_STALE: bad AID");
-+ peer_stale(imsg.hdr.peerid, aid);
-+ break;
-+ case IMSG_SESSION_FLUSH:
-+ if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(aid)) {
-+ log_warnx("rde_dispatch: wrong imsg len");
-+ break;
-+ }
-+ memcpy(&aid, imsg.data, sizeof(aid));
-+ if (aid >= AID_MAX)
-+ fatalx("IMSG_SESSION_FLUSH: bad AID");
-+ if ((peer = peer_get(imsg.hdr.peerid)) == NULL) {
-+ log_warnx("rde_dispatch: unknown peer id %d",
-+ imsg.hdr.peerid);
-+ break;
-+ }
-+ peer_flush(peer, aid);
-+ break;
-+ case IMSG_SESSION_RESTARTED:
-+ if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(aid)) {
-+ log_warnx("rde_dispatch: wrong imsg len");
-+ break;
-+ }
-+ memcpy(&aid, imsg.data, sizeof(aid));
-+ if (aid >= AID_MAX)
-+ fatalx("IMSG_SESSION_RESTARTED: bad AID");
-+ if ((peer = peer_get(imsg.hdr.peerid)) == NULL) {
-+ log_warnx("rde_dispatch: unknown peer id %d",
-+ imsg.hdr.peerid);
-+ break;
-+ }
-+ if (peer->staletime[aid])
-+ peer_flush(peer, aid);
-+ break;
- case IMSG_REFRESH:
-- if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(r)) {
-+ if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(aid)) {
- log_warnx("rde_dispatch: wrong imsg len");
- break;
- }
-- memcpy(&r, imsg.data, sizeof(r));
-- peer_dump(imsg.hdr.peerid, r.afi, r.safi);
-+ memcpy(&aid, imsg.data, sizeof(aid));
-+ if (aid >= AID_MAX)
-+ fatalx("IMSG_REFRESH: bad AID");
-+ peer_dump(imsg.hdr.peerid, aid);
- break;
- case IMSG_NETWORK_ADD:
- if (imsg.hdr.len - IMSG_HEADER_SIZE !=
-@@ -440,23 +471,68 @@ rde_dispatch_imsg_session(struct imsgbuf
- TAILQ_INIT(&netconf_s.attrset);
- session_set = &netconf_s.attrset;
- break;
-+ case IMSG_NETWORK_ASPATH:
-+ if (imsg.hdr.len - IMSG_HEADER_SIZE <
-+ sizeof(struct ctl_show_rib)) {
-+ log_warnx("rde_dispatch: wrong imsg len");
-+ bzero(&netconf_s, sizeof(netconf_s));
-+ break;
-+ }
-+ asdata = imsg.data;
-+ asdata += sizeof(struct ctl_show_rib);
-+ memcpy(&csr, imsg.data, sizeof(csr));
-+ if (csr.aspath_len + sizeof(csr) > imsg.hdr.len -
-+ IMSG_HEADER_SIZE) {
-+ log_warnx("rde_dispatch: wrong aspath len");
-+ bzero(&netconf_s, sizeof(netconf_s));
-+ break;
-+ }
-+ asp = path_get();
-+ asp->lpref = csr.local_pref;
-+ asp->med = csr.med;
-+ asp->weight = csr.weight;
-+ asp->flags = csr.flags;
-+ asp->origin = csr.origin;
-+ asp->flags |= F_PREFIX_ANNOUNCED | F_ANN_DYNAMIC;
-+ asp->aspath = aspath_get(asdata, csr.aspath_len);
-+ netconf_s.asp = asp;
-+ break;
-+ case IMSG_NETWORK_ATTR:
-+ if (imsg.hdr.len <= IMSG_HEADER_SIZE) {
-+ log_warnx("rde_dispatch: wrong imsg len");
-+ break;
-+ }
-+ /* parse path attributes */
-+ len = imsg.hdr.len - IMSG_HEADER_SIZE;
-+ asp = netconf_s.asp;
-+ if (rde_attr_add(asp, imsg.data, len) == -1) {
-+ log_warnx("rde_dispatch: bad network "
-+ "attribute");
-+ path_put(asp);
-+ bzero(&netconf_s, sizeof(netconf_s));
-+ break;
-+ }
-+ break;
- case IMSG_NETWORK_DONE:
- if (imsg.hdr.len != IMSG_HEADER_SIZE) {
- log_warnx("rde_dispatch: wrong imsg len");
- break;
- }
- session_set = NULL;
-- switch (netconf_s.prefix.af) {
-- case AF_INET:
-+ switch (netconf_s.prefix.aid) {
-+ case AID_INET:
- if (netconf_s.prefixlen > 32)
- goto badnet;
- network_add(&netconf_s, 0);
- break;
-- case AF_INET6:
-+ case AID_INET6:
- if (netconf_s.prefixlen > 128)
- goto badnet;
- network_add(&netconf_s, 0);
- break;
-+ case 0:
-+ /* something failed beforehands */
-+ break;
- default:
- badnet:
- log_warnx("rde_dispatch: bad network");
-@@ -528,10 +604,14 @@ badnet:
- peer->prefix_rcvd_update;
- p.stats.prefix_rcvd_withdraw =
- peer->prefix_rcvd_withdraw;
-+ p.stats.prefix_rcvd_eor =
-+ peer->prefix_rcvd_eor;
- p.stats.prefix_sent_update =
- peer->prefix_sent_update;
- p.stats.prefix_sent_withdraw =
- peer->prefix_sent_withdraw;
-+ p.stats.prefix_sent_eor =
-+ peer->prefix_sent_eor;
- }
- imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NEIGHBOR, 0,
- imsg.hdr.pid, -1, &p, sizeof(struct peer));
-@@ -544,6 +624,11 @@ badnet:
- imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_RIB_MEM, 0,
- imsg.hdr.pid, -1, &rdemem, sizeof(rdemem));
- break;
-+ case IMSG_CTL_LOG_VERBOSE:
-+ /* already checked by SE */
-+ memcpy(&verbose, imsg.data, sizeof(verbose));
-+ log_verbose(verbose);
-+ break;
- default:
- break;
- }
-@@ -554,14 +639,17 @@ badnet:
- void
- rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
- {
-+ static struct rdomain *rd;
- struct imsg imsg;
- struct mrt xmrt;
- struct rde_rib rn;
- struct rde_peer *peer;
-+ struct peer_config *pconf;
- struct filter_rule *r;
- struct filter_set *s;
- struct nexthop *nh;
-- int n, fd, reconf_in = 0, reconf_out = 0;
-+ int n, fd, reconf_in = 0, reconf_out = 0,
-+ reconf_rib = 0;
- u_int16_t rid;
-
- if ((n = imsg_read(ibuf)) == -1)
-@@ -576,20 +664,12 @@ rde_dispatch_imsg_parent(struct imsgbuf
- break;
-
- switch (imsg.hdr.type) {
-- case IMSG_RECONF_CONF:
-- reloadtime = time(NULL);
-- newrules = calloc(1, sizeof(struct filter_head));
-- if (newrules == NULL)
-- fatal(NULL);
-- TAILQ_INIT(newrules);
-- if ((nconf = malloc(sizeof(struct bgpd_config))) ==
-- NULL)
-- fatal(NULL);
-- memcpy(nconf, imsg.data, sizeof(struct bgpd_config));
-- for (rid = 0; rid < rib_size; rid++)
-- ribs[rid].state = RIB_DELETE;
-- break;
- case IMSG_NETWORK_ADD:
-+ if (imsg.hdr.len - IMSG_HEADER_SIZE !=
-+ sizeof(struct network_config)) {
-+ log_warnx("rde_dispatch: wrong imsg len");
-+ break;
-+ }
- memcpy(&netconf_p, imsg.data, sizeof(netconf_p));
- TAILQ_INIT(&netconf_p.attrset);
- parent_set = &netconf_p.attrset;
-@@ -608,6 +688,26 @@ rde_dispatch_imsg_parent(struct imsgbuf
- TAILQ_INIT(&netconf_p.attrset);
- network_delete(&netconf_p, 1);
- break;
-+ case IMSG_RECONF_CONF:
-+ if (imsg.hdr.len - IMSG_HEADER_SIZE !=
-+ sizeof(struct bgpd_config))
-+ fatalx("IMSG_RECONF_CONF bad len");
-+ reloadtime = time(NULL);
-+ newrules = calloc(1, sizeof(struct filter_head));
-+ if (newrules == NULL)
-+ fatal(NULL);
-+ TAILQ_INIT(newrules);
-+ newdomains = calloc(1, sizeof(struct rdomain_head));
-+ if (newdomains == NULL)
-+ fatal(NULL);
-+ SIMPLEQ_INIT(newdomains);
-+ if ((nconf = malloc(sizeof(struct bgpd_config))) ==
-+ NULL)
-+ fatal(NULL);
-+ memcpy(nconf, imsg.data, sizeof(struct bgpd_config));
-+ for (rid = 0; rid < rib_size; rid++)
-+ ribs[rid].state = RECONF_DELETE;
-+ break;
- case IMSG_RECONF_RIB:
- if (imsg.hdr.len - IMSG_HEADER_SIZE !=
- sizeof(struct rde_rib))
-@@ -615,9 +715,26 @@ rde_dispatch_imsg_parent(struct imsgbuf
- memcpy(&rn, imsg.data, sizeof(rn));
- rid = rib_find(rn.name);
- if (rid == RIB_FAILED)
-- rib_new(-1, rn.name, rn.flags);
-- else
-- ribs[rid].state = RIB_ACTIVE;
-+ rib_new(rn.name, rn.rtableid, rn.flags);
-+ else if (ribs[rid].rtableid != rn.rtableid ||
-+ (ribs[rid].flags & F_RIB_HASNOFIB) !=
-+ (rn.flags & F_RIB_HASNOFIB)) {
-+ /* Big hammer in the F_RIB_NOFIB case but
-+ * not often enough used to optimise it more. */
-+ rib_free(&ribs[rid]);
-+ rib_new(rn.name, rn.rtableid, rn.flags);
-+ } else
-+ ribs[rid].state = RECONF_KEEP;
-+ break;
-+ case IMSG_RECONF_PEER:
-+ if (imsg.hdr.len - IMSG_HEADER_SIZE !=
-+ sizeof(struct peer_config))
-+ fatalx("IMSG_RECONF_PEER bad len");
-+ if ((peer = peer_get(imsg.hdr.peerid)) == NULL)
-+ break;
-+ pconf = imsg.data;
-+ strlcpy(peer->conf.rib, pconf->rib,
-+ sizeof(peer->conf.rib));
- break;
- case IMSG_RECONF_FILTER:
- if (imsg.hdr.len - IMSG_HEADER_SIZE !=
-@@ -631,12 +748,42 @@ rde_dispatch_imsg_parent(struct imsgbuf
- parent_set = &r->set;
- TAILQ_INSERT_TAIL(newrules, r, entry);
- break;
-+ case IMSG_RECONF_RDOMAIN:
-+ if (imsg.hdr.len - IMSG_HEADER_SIZE !=
-+ sizeof(struct rdomain))
-+ fatalx("IMSG_RECONF_RDOMAIN bad len");
-+ if ((rd = malloc(sizeof(struct rdomain))) == NULL)
-+ fatal(NULL);
-+ memcpy(rd, imsg.data, sizeof(struct rdomain));
-+ TAILQ_INIT(&rd->import);
-+ TAILQ_INIT(&rd->export);
-+ SIMPLEQ_INSERT_TAIL(newdomains, rd, entry);
-+ break;
-+ case IMSG_RECONF_RDOMAIN_EXPORT:
-+ if (rd == NULL) {
-+ log_warnx("rde_dispatch_imsg_parent: "
-+ "IMSG_RECONF_RDOMAIN_EXPORT unexpected");
-+ break;
-+ }
-+ parent_set = &rd->export;
-+ break;
-+ case IMSG_RECONF_RDOMAIN_IMPORT:
-+ if (rd == NULL) {
-+ log_warnx("rde_dispatch_imsg_parent: "
-+ "IMSG_RECONF_RDOMAIN_IMPORT unexpected");
-+ break;
-+ }
-+ parent_set = &rd->import;
-+ break;
-+ case IMSG_RECONF_RDOMAIN_DONE:
-+ parent_set = NULL;
-+ break;
- case IMSG_RECONF_DONE:
- if (nconf == NULL)
- fatalx("got IMSG_RECONF_DONE but no config");
- if ((nconf->flags & BGPD_FLAG_NO_EVALUATE)
- != (conf->flags & BGPD_FLAG_NO_EVALUATE)) {
-- log_warnx( "change to/from route-collector "
-+ log_warnx("change to/from route-collector "
- "mode ignored");
- if (conf->flags & BGPD_FLAG_NO_EVALUATE)
- nconf->flags |= BGPD_FLAG_NO_EVALUATE;
-@@ -644,10 +791,27 @@ rde_dispatch_imsg_parent(struct imsgbuf
- nconf->flags &= ~BGPD_FLAG_NO_EVALUATE;
- }
- memcpy(conf, nconf, sizeof(struct bgpd_config));
-+ conf->listen_addrs = NULL;
-+ conf->csock = NULL;
-+ conf->rcsock = NULL;
- free(nconf);
- nconf = NULL;
- parent_set = NULL;
-- prefix_network_clean(peerself, reloadtime, 0);
-+ /* sync peerself with conf */
-+ peerself->remote_bgpid = ntohl(conf->bgpid);
-+ peerself->conf.local_as = conf->as;
-+ peerself->conf.remote_as = conf->as;
-+ peerself->short_as = conf->short_as;
-+
-+ /* apply new set of rdomain, sync will be done later */
-+ while ((rd = SIMPLEQ_FIRST(rdomains_l)) != NULL) {
-+ SIMPLEQ_REMOVE_HEAD(rdomains_l, entry);
-+ filterset_free(&rd->import);
-+ filterset_free(&rd->export);
-+ free(rd);
-+ }
-+ free(rdomains_l);
-+ rdomains_l = newdomains;
-
- /* check if filter changed */
- LIST_FOREACH(peer, &peerlist, peer_l) {
-@@ -655,30 +819,59 @@ rde_dispatch_imsg_parent(struct imsgbuf
- continue;
- peer->reconf_out = 0;
- peer->reconf_in = 0;
-- if (peer->conf.softreconfig_out &&
-- !rde_filter_equal(rules_l, newrules, peer,
-- DIR_OUT)) {
-- peer->reconf_out = 1;
-- reconf_out = 1;
-- }
-+ peer->reconf_rib = 0;
- if (peer->conf.softreconfig_in &&
- !rde_filter_equal(rules_l, newrules, peer,
- DIR_IN)) {
- peer->reconf_in = 1;
- reconf_in = 1;
- }
-+ if (peer->ribid != rib_find(peer->conf.rib)) {
-+ rib_dump(&ribs[peer->ribid],
-+ rde_softreconfig_unload_peer, peer,
-+ AID_UNSPEC);
-+ peer->ribid = rib_find(peer->conf.rib);
-+ peer->reconf_rib = 1;
-+ reconf_rib = 1;
-+ continue;
-+ }
-+ if (peer->conf.softreconfig_out &&
-+ !rde_filter_equal(rules_l, newrules, peer,
-+ DIR_OUT)) {
-+ peer->reconf_out = 1;
-+ reconf_out = 1;
-+ }
- }
-- /* XXX this needs rework anyway */
-- /* sync local-RIB first */
-+ /* bring ribs in sync before softreconfig dance */
-+ for (rid = 0; rid < rib_size; rid++) {
-+ if (ribs[rid].state == RECONF_DELETE)
-+ rib_free(&ribs[rid]);
-+ else if (ribs[rid].state == RECONF_REINIT)
-+ rib_dump(&ribs[0],
-+ rde_softreconfig_load, &ribs[rid],
-+ AID_UNSPEC);
-+ }
-+ /* sync local-RIBs first */
- if (reconf_in)
- rib_dump(&ribs[0], rde_softreconfig_in, NULL,
-- AF_UNSPEC);
-+ AID_UNSPEC);
- /* then sync peers */
- if (reconf_out) {
- int i;
-- for (i = 1; i < rib_size; i++)
-+ for (i = 1; i < rib_size; i++) {
-+ if (ribs[i].state == RECONF_REINIT)
-+ /* already synced by _load */
-+ continue;
- rib_dump(&ribs[i], rde_softreconfig_out,
-- NULL, AF_UNSPEC);
-+ NULL, AID_UNSPEC);
-+ }
-+ }
-+ if (reconf_rib) {
-+ LIST_FOREACH(peer, &peerlist, peer_l) {
-+ rib_dump(&ribs[peer->ribid],
-+ rde_softreconfig_load_peer,
-+ peer, AID_UNSPEC);
-+ }
- }
-
- while ((r = TAILQ_FIRST(rules_l)) != NULL) {
-@@ -688,16 +881,18 @@ rde_dispatch_imsg_parent(struct imsgbuf
- }
- free(rules_l);
- rules_l = newrules;
-- for (rid = 0; rid < rib_size; rid++) {
-- if (ribs[rid].state == RIB_DELETE)
-- rib_free(&ribs[rid]);
-- }
-+
- log_info("RDE reconfigured");
-+ imsg_compose(ibuf_main, IMSG_RECONF_DONE, 0, 0,
-+ -1, NULL, 0);
- break;
- case IMSG_NEXTHOP_UPDATE:
- nexthop_update(imsg.data);
- break;
- case IMSG_FILTER_SET:
-+ if (imsg.hdr.len > IMSG_HEADER_SIZE +
-+ sizeof(struct filter_set))
-+ fatalx("IMSG_RECONF_CONF bad len");
- if (parent_set == NULL) {
- log_warnx("rde_dispatch_imsg_parent: "
- "IMSG_FILTER_SET unexpected");
-@@ -725,7 +920,8 @@ rde_dispatch_imsg_parent(struct imsgbuf
- log_warnx("expected to receive fd for mrt dump "
- "but didn't receive any");
- else if (xmrt.type == MRT_TABLE_DUMP ||
-- xmrt.type == MRT_TABLE_DUMP_MP) {
-+ xmrt.type == MRT_TABLE_DUMP_MP ||
-+ xmrt.type == MRT_TABLE_DUMP_V2) {
- rde_dump_mrt_new(&xmrt, imsg.hdr.pid, fd);
- } else
- close(fd);
-@@ -744,6 +940,8 @@ rde_dispatch_imsg_parent(struct imsgbuf
- int
- rde_update_dispatch(struct imsg *imsg)
- {
-+ struct bgpd_addr prefix;
-+ struct mpattr mpa;
- struct rde_peer *peer;
- struct rde_aspath *asp = NULL;
- u_char *p, *mpp = NULL;
-@@ -752,9 +950,8 @@ rde_update_dispatch(struct imsg *imsg)
- u_int16_t withdrawn_len;
- u_int16_t attrpath_len;
- u_int16_t nlri_len;
-- u_int8_t prefixlen, safi, subtype;
-- struct bgpd_addr prefix;
-- struct mpattr mpa;
-+ u_int8_t aid, prefixlen, safi, subtype;
-+ u_int32_t fas;
-
- peer = peer_get(imsg->hdr.peerid);
- if (peer == NULL) /* unknown peer, cannot happen */
-@@ -810,26 +1007,21 @@ rde_update_dispatch(struct imsg *imsg)
- goto done;
- }
-
-- /*
-- * if either ATTR_AS4_AGGREGATOR or ATTR_AS4_PATH is present
-- * try to fixup the attributes.
-- * XXX do not fixup if F_ATTR_LOOP is set.
-- */
-- if (asp->flags & F_ATTR_AS4BYTE_NEW &&
-- !(asp->flags & F_ATTR_LOOP))
-- rde_as4byte_fixup(peer, asp);
-+ rde_as4byte_fixup(peer, asp);
-
- /* enforce remote AS if requested */
- if (asp->flags & F_ATTR_ASPATH &&
-- peer->conf.enforce_as == ENFORCE_AS_ON)
-- if (peer->conf.remote_as !=
-- aspath_neighbor(asp->aspath)) {
-- log_peer_warnx(&peer->conf, "bad path, "
-- "enforce remote-as enabled");
-- rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH,
-+ peer->conf.enforce_as == ENFORCE_AS_ON) {
-+ fas = aspath_neighbor(asp->aspath);
-+ if (peer->conf.remote_as != fas) {
-+ log_peer_warnx(&peer->conf, "bad path, "
-+ "starting with %s, "
-+ "enforce neighbor-as enabled", log_as(fas));
-+ rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH,
- NULL, 0);
-- goto done;
-+ goto done;
- }
-+ }
-
- rde_reflector(peer, asp);
- }
-@@ -860,9 +1052,9 @@ rde_update_dispatch(struct imsg *imsg)
- p += pos;
- len -= pos;
-
-- if (peer->capa_received.mp_v4 == SAFI_NONE &&
-- peer->capa_received.mp_v6 != SAFI_NONE) {
-- log_peer_warnx(&peer->conf, "bad AFI, IPv4 disabled");
-+ if (peer->capa.mp[AID_INET] == 0) {
-+ log_peer_warnx(&peer->conf,
-+ "bad withdraw, %s disabled", aid2str(AID_INET));
- rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR,
- NULL, 0);
- goto done;
-@@ -879,6 +1071,10 @@ rde_update_dispatch(struct imsg *imsg)
- ERR_UPD_ATTRLIST, NULL, 0);
- return (-1);
- }
-+ if (withdrawn_len == 0) {
-+ /* EoR marker */
-+ peer_recv_eor(peer, AID_INET);
-+ }
- return (0);
- }
-
-@@ -892,15 +1088,30 @@ rde_update_dispatch(struct imsg *imsg)
- afi = ntohs(afi);
- safi = *mpp++;
- mplen--;
-- switch (afi) {
-- case AFI_IPv6:
-- if (peer->capa_received.mp_v6 == SAFI_NONE) {
-- log_peer_warnx(&peer->conf, "bad AFI, "
-- "IPv6 disabled");
-- rde_update_err(peer, ERR_UPDATE,
-- ERR_UPD_OPTATTR, NULL, 0);
-- goto done;
-- }
-+
-+ if (afi2aid(afi, safi, &aid) == -1) {
-+ log_peer_warnx(&peer->conf,
-+ "bad AFI/SAFI pair in withdraw");
-+ rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR,
-+ NULL, 0);
-+ goto done;
-+ }
-+
-+ if (peer->capa.mp[aid] == 0) {
-+ log_peer_warnx(&peer->conf,
-+ "bad withdraw, %s disabled", aid2str(aid));
-+ rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR,
-+ NULL, 0);
-+ goto done;
-+ }
-+
-+ if ((asp->flags & ~F_ATTR_MP_UNREACH) == 0 && mplen == 0) {
-+ /* EoR marker */
-+ peer_recv_eor(peer, aid);
-+ }
-+
-+ switch (aid) {
-+ case AID_INET6:
- while (mplen > 0) {
- if ((pos = rde_update_get_prefix6(mpp, mplen,
- &prefix, &prefixlen)) == -1) {
-@@ -926,6 +1137,32 @@ rde_update_dispatch(struct imsg *imsg)
- rde_update_withdraw(peer, &prefix, prefixlen);
- }
- break;
-+ case AID_VPN_IPv4:
-+ while (mplen > 0) {
-+ if ((pos = rde_update_get_vpn4(mpp, mplen,
-+ &prefix, &prefixlen)) == -1) {
-+ log_peer_warnx(&peer->conf,
-+ "bad VPNv4 withdraw prefix");
-+ rde_update_err(peer, ERR_UPDATE,
-+ ERR_UPD_OPTATTR,
-+ mpa.unreach, mpa.unreach_len);
-+ goto done;
-+ }
-+ if (prefixlen > 32) {
-+ log_peer_warnx(&peer->conf,
-+ "bad VPNv4 withdraw prefix");
-+ rde_update_err(peer, ERR_UPDATE,
-+ ERR_UPD_OPTATTR,
-+ mpa.unreach, mpa.unreach_len);
-+ goto done;
-+ }
-+
-+ mpp += pos;
-+ mplen -= pos;
-+
-+ rde_update_withdraw(peer, &prefix, prefixlen);
-+ }
-+ break;
- default:
- /* silently ignore unsupported multiprotocol AF */
- break;
-@@ -963,9 +1200,9 @@ rde_update_dispatch(struct imsg *imsg)
- p += pos;
- nlri_len -= pos;
-
-- if (peer->capa_received.mp_v4 == SAFI_NONE &&
-- peer->capa_received.mp_v6 != SAFI_NONE) {
-- log_peer_warnx(&peer->conf, "bad AFI, IPv4 disabled");
-+ if (peer->capa.mp[AID_INET] == 0) {
-+ log_peer_warnx(&peer->conf,
-+ "bad update, %s disabled", aid2str(AID_INET));
- rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR,
- NULL, 0);
- goto done;
-@@ -995,6 +1232,22 @@ rde_update_dispatch(struct imsg *imsg)
- safi = *mpp++;
- mplen--;
-
-+ if (afi2aid(afi, safi, &aid) == -1) {
-+ log_peer_warnx(&peer->conf,
-+ "bad AFI/SAFI pair in update");
-+ rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR,
-+ NULL, 0);
-+ goto done;
-+ }
-+
-+ if (peer->capa.mp[aid] == 0) {
-+ log_peer_warnx(&peer->conf,
-+ "bad update, %s disabled", aid2str(aid));
-+ rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR,
-+ NULL, 0);
-+ goto done;
-+ }
-+
- /*
- * this works because asp is not linked.
- * But first unlock the previously locked nexthop.
-@@ -1004,8 +1257,8 @@ rde_update_dispatch(struct imsg *imsg)
- (void)nexthop_delete(asp->nexthop);
- asp->nexthop = NULL;
- }
-- if ((pos = rde_get_mp_nexthop(mpp, mplen, afi, asp)) == -1) {
-- log_peer_warnx(&peer->conf, "bad IPv6 nlri prefix");
-+ if ((pos = rde_get_mp_nexthop(mpp, mplen, aid, asp, peer)) == -1) {
-+ log_peer_warnx(&peer->conf, "bad nlri prefix");
- rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR,
- mpa.reach, mpa.reach_len);
- goto done;
-@@ -1013,16 +1266,8 @@ rde_update_dispatch(struct imsg *imsg)
- mpp += pos;
- mplen -= pos;
-
-- switch (afi) {
-- case AFI_IPv6:
-- if (peer->capa_received.mp_v6 == SAFI_NONE) {
-- log_peer_warnx(&peer->conf, "bad AFI, "
-- "IPv6 disabled");
-- rde_update_err(peer, ERR_UPDATE,
-- ERR_UPD_OPTATTR, NULL, 0);
-- goto done;
-- }
--
-+ switch (aid) {
-+ case AID_INET6:
- while (mplen > 0) {
- if ((pos = rde_update_get_prefix6(mpp, mplen,
- &prefix, &prefixlen)) == -1) {
-@@ -1058,6 +1303,42 @@ rde_update_dispatch(struct imsg *imsg)
-
- }
- break;
-+ case AID_VPN_IPv4:
-+ while (mplen > 0) {
-+ if ((pos = rde_update_get_vpn4(mpp, mplen,
-+ &prefix, &prefixlen)) == -1) {
-+ log_peer_warnx(&peer->conf,
-+ "bad VPNv4 nlri prefix");
-+ rde_update_err(peer, ERR_UPDATE,
-+ ERR_UPD_OPTATTR,
-+ mpa.reach, mpa.reach_len);
-+ goto done;
-+ }
-+ if (prefixlen > 32) {
-+ rde_update_err(peer, ERR_UPDATE,
-+ ERR_UPD_OPTATTR,
-+ mpa.reach, mpa.reach_len);
-+ goto done;
-+ }
-+
-+ mpp += pos;
-+ mplen -= pos;
-+
-+ rde_update_update(peer, asp, &prefix,
-+ prefixlen);
-+
-+ /* max prefix checker */
-+ if (peer->conf.max_prefix &&
-+ peer->prefix_cnt >= peer->conf.max_prefix) {
-+ log_peer_warnx(&peer->conf,
-+ "prefix limit reached");
-+ rde_update_err(peer, ERR_CEASE,
-+ ERR_CEASE_MAX_PREFIX, NULL, 0);
-+ goto done;
-+ }
-+
-+ }
-+ break;
- default:
- /* silently ignore unsupported multiprotocol AF */
- break;
-@@ -1085,7 +1366,8 @@ rde_update_update(struct rde_peer *peer,
- struct bgpd_addr *prefix, u_int8_t prefixlen)
- {
- struct rde_aspath *fasp;
-- int r = 0;
-+ enum filter_actions action;
-+ int r = 0, f = 0;
- u_int16_t i;
-
- peer->prefix_rcvd_update++;
-@@ -1095,18 +1377,24 @@ rde_update_update(struct rde_peer *peer,
-
- for (i = 1; i < rib_size; i++) {
- /* input filter */
-- if (rde_filter(i, &fasp, rules_l, peer, asp, prefix, prefixlen,
-- peer, DIR_IN) == ACTION_DENY)
-- goto done;
-+ action = rde_filter(i, &fasp, rules_l, peer, asp, prefix,
-+ prefixlen, peer, DIR_IN);
-
- if (fasp == NULL)
- fasp = asp;
-
-- rde_update_log("update", i, peer, &fasp->nexthop->exit_nexthop,
-- prefix, prefixlen);
-- r += path_update(&ribs[i], peer, fasp, prefix, prefixlen);
-+ if (action == ACTION_ALLOW) {
-+ rde_update_log("update", i, peer,
-+ &fasp->nexthop->exit_nexthop, prefix, prefixlen);
-+ r += path_update(&ribs[i], peer, fasp, prefix,
-+ prefixlen);
-+ } else if (prefix_remove(&ribs[i], peer, prefix, prefixlen,
-+ 0)) {
-+ rde_update_log("filtered withdraw", i, peer,
-+ NULL, prefix, prefixlen);
-+ f++;
-+ }
-
--done:
- /* free modified aspath */
- if (fasp != asp)
- path_put(fasp);
-@@ -1114,6 +1402,8 @@ done:
-
- if (r)
- peer->prefix_cnt++;
-+ else if (f)
-+ peer->prefix_cnt--;
- }
-
- void
-@@ -1152,7 +1442,7 @@ rde_update_withdraw(struct rde_peer *pee
- } while (0)
-
- #define CHECK_FLAGS(s, t, m) \
-- (((s) & ~(ATTR_EXTLEN | (m))) == (t))
-+ (((s) & ~(ATTR_DEFMASK | (m))) == (t))
-
- int
- rde_attr_parse(u_char *p, u_int16_t len, struct rde_peer *peer,
-@@ -1161,6 +1451,7 @@ rde_attr_parse(u_char *p, u_int16_t len,
- struct bgpd_addr nexthop;
- u_char *op = p, *npath;
- u_int32_t tmp32;
-+ int err;
- u_int16_t attr_len, nlen;
- u_int16_t plen = 0;
- u_int8_t flags;
-@@ -1195,6 +1486,7 @@ bad_len:
- switch (type) {
- case ATTR_UNDEF:
- /* ignore and drop path attributes with a type code of 0 */
-+ plen += attr_len;
- break;
- case ATTR_ORIGIN:
- if (attr_len != 1)
-@@ -1220,7 +1512,17 @@ bad_flags:
- case ATTR_ASPATH:
- if (!CHECK_FLAGS(flags, ATTR_WELL_KNOWN, 0))
- goto bad_flags;
-- if (aspath_verify(p, attr_len, rde_as4byte(peer)) != 0) {
-+ err = aspath_verify(p, attr_len, rde_as4byte(peer));
-+ if (err == AS_ERR_SOFT) {
-+ /*
-+ * soft errors like unexpected segment types are
-+ * not considered fatal and the path is just
-+ * marked invalid.
-+ */
-+ a->flags |= F_ATTR_PARSE_ERR;
-+ log_peer_warnx(&peer->conf, "bad ASPATH, "
-+ "path invalidated and prefix withdrawn");
-+ } else if (err != 0) {
- rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH,
- NULL, 0);
- return (-1);
-@@ -1248,7 +1550,7 @@ bad_flags:
- a->flags |= F_ATTR_NEXTHOP;
-
- bzero(&nexthop, sizeof(nexthop));
-- nexthop.af = AF_INET;
-+ nexthop.aid = AID_INET;
- UPD_READ(&nexthop.v4.s_addr, p, plen, 4);
- /*
- * Check if the nexthop is a valid IP address. We consider
-@@ -1305,9 +1607,21 @@ bad_flags:
- goto optattr;
- case ATTR_AGGREGATOR:
- if ((!rde_as4byte(peer) && attr_len != 6) ||
-- (rde_as4byte(peer) && attr_len != 8))
-- goto bad_len;
-- if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, 0))
-+ (rde_as4byte(peer) && attr_len != 8)) {
-+ /*
-+ * ignore attribute in case of error as per
-+ * draft-ietf-idr-optional-transitive-00.txt
-+ * but only if partial bit is set
-+ */
-+ if ((flags & ATTR_PARTIAL) == 0)
-+ goto bad_len;
-+ log_peer_warnx(&peer->conf, "bad AGGREGATOR, "
-+ "partial attribute ignored");
-+ plen += attr_len;
-+ break;
-+ }
-+ if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE,
-+ ATTR_PARTIAL))
- goto bad_flags;
- if (!rde_as4byte(peer)) {
- /* need to inflate aggregator AS to 4-byte */
-@@ -1323,8 +1637,35 @@ bad_flags:
- /* 4-byte ready server take the default route */
- goto optattr;
- case ATTR_COMMUNITIES:
-- if ((attr_len & 0x3) != 0)
-- goto bad_len;
-+ if (attr_len % 4 != 0) {
-+ /*
-+ * mark update as bad and withdraw all routes as per
-+ * draft-ietf-idr-optional-transitive-00.txt
-+ * but only if partial bit is set
-+ */
-+ if ((flags & ATTR_PARTIAL) == 0)
-+ goto bad_len;
-+ a->flags |= F_ATTR_PARSE_ERR;
-+ log_peer_warnx(&peer->conf, "bad COMMUNITIES, "
-+ "path invalidated and prefix withdrawn");
-+ }
-+ if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE,
-+ ATTR_PARTIAL))
-+ goto bad_flags;
-+ goto optattr;
-+ case ATTR_EXT_COMMUNITIES:
-+ if (attr_len % 8 != 0) {
-+ /*
-+ * mark update as bad and withdraw all routes as per
-+ * draft-ietf-idr-optional-transitive-00.txt
-+ * but only if partial bit is set
-+ */
-+ if ((flags & ATTR_PARTIAL) == 0)
-+ goto bad_len;
-+ a->flags |= F_ATTR_PARSE_ERR;
-+ log_peer_warnx(&peer->conf, "bad EXT_COMMUNITIES, "
-+ "path invalidated and prefix withdrawn");
-+ }
- if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE,
- ATTR_PARTIAL))
- goto bad_flags;
-@@ -1336,7 +1677,7 @@ bad_flags:
- goto bad_flags;
- goto optattr;
- case ATTR_CLUSTER_LIST:
-- if ((attr_len & 0x3) != 0)
-+ if (attr_len % 4 != 0)
- goto bad_len;
- if (!CHECK_FLAGS(flags, ATTR_OPTIONAL, 0))
- goto bad_flags;
-@@ -1370,8 +1711,15 @@ bad_flags:
- plen += attr_len;
- break;
- case ATTR_AS4_AGGREGATOR:
-- if (attr_len != 8)
-- goto bad_len;
-+ if (attr_len != 8) {
-+ /* see ATTR_AGGREGATOR ... */
-+ if ((flags & ATTR_PARTIAL) == 0)
-+ goto bad_len;
-+ log_peer_warnx(&peer->conf, "bad AS4_AGGREGATOR, "
-+ "partial attribute ignored");
-+ plen += attr_len;
-+ break;
-+ }
- if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE,
- ATTR_PARTIAL))
- goto bad_flags;
-@@ -1381,20 +1729,31 @@ bad_flags:
- if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE,
- ATTR_PARTIAL))
- goto bad_flags;
-- if (aspath_verify(p, attr_len, 1) != 0) {
-+ if ((err = aspath_verify(p, attr_len, 1)) != 0) {
- /*
- * XXX RFC does not specify how to handle errors.
- * XXX Instead of dropping the session because of a
-- * XXX bad path just mark the full update as not
-- * XXX loop-free the update is no longer eligible and
-- * XXX will not be considered for routing or
-- * XXX redistribution. Something better is needed.
-+ * XXX bad path just mark the full update as having
-+ * XXX a parse error which makes the update no longer
-+ * XXX eligible and will not be considered for routing
-+ * XXX or redistribution.
-+ * XXX We follow draft-ietf-idr-optional-transitive
-+ * XXX by looking at the partial bit.
-+ * XXX Consider soft errors similar to a partial attr.
- */
-- a->flags |= F_ATTR_LOOP;
-- goto optattr;
-- }
-- a->flags |= F_ATTR_AS4BYTE_NEW;
-- goto optattr;
-+ if (flags & ATTR_PARTIAL || err == AS_ERR_SOFT) {
-+ a->flags |= F_ATTR_PARSE_ERR;
-+ log_peer_warnx(&peer->conf, "bad AS4_PATH, "
-+ "path invalidated and prefix withdrawn");
-+ goto optattr;
-+ } else {
-+ rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH,
-+ NULL, 0);
-+ return (-1);
-+ }
-+ }
-+ a->flags |= F_ATTR_AS4BYTE_NEW;
-+ goto optattr;
- default:
- if ((flags & ATTR_OPTIONAL) == 0) {
- rde_update_err(peer, ERR_UPDATE, ERR_UPD_UNKNWN_WK_ATTR,
-@@ -1415,6 +1774,42 @@ bad_list:
-
- return (plen);
- }
-+
-+int
-+rde_attr_add(struct rde_aspath *a, u_char *p, u_int16_t len)
-+{
-+ u_int16_t attr_len;
-+ u_int16_t plen = 0;
-+ u_int8_t flags;
-+ u_int8_t type;
-+ u_int8_t tmp8;
-+
-+ if (a == NULL) /* no aspath, nothing to do */
-+ return (0);
-+ if (len < 3)
-+ return (-1);
-+
-+ UPD_READ(&flags, p, plen, 1);
-+ UPD_READ(&type, p, plen, 1);
-+
-+ if (flags & ATTR_EXTLEN) {
-+ if (len - plen < 2)
-+ return (-1);
-+ UPD_READ(&attr_len, p, plen, 2);
-+ attr_len = ntohs(attr_len);
-+ } else {
-+ UPD_READ(&tmp8, p, plen, 1);
-+ attr_len = tmp8;
-+ }
-+
-+ if (len - plen < attr_len)
-+ return (-1);
-+
-+ if (attr_optadd(a, flags, type, p, attr_len) == -1)
-+ return (-1);
-+ return (0);
-+}
-+
- #undef UPD_READ
- #undef CHECK_FLAGS
-
-@@ -1440,8 +1835,8 @@ rde_attr_missing(struct rde_aspath *a, i
- }
-
- int
--rde_get_mp_nexthop(u_char *data, u_int16_t len, u_int16_t afi,
-- struct rde_aspath *asp)
-+rde_get_mp_nexthop(u_char *data, u_int16_t len, u_int8_t aid,
-+ struct rde_aspath *asp, struct rde_peer *peer)
- {
- struct bgpd_addr nexthop;
- u_int8_t totlen, nhlen;
-@@ -1457,8 +1852,9 @@ rde_get_mp_nexthop(u_char *data, u_int16
- return (-1);
-
- bzero(&nexthop, sizeof(nexthop));
-- switch (afi) {
-- case AFI_IPv6:
-+ nexthop.aid = aid;
-+ switch (aid) {
-+ case AID_INET6:
- /*
- * RFC2545 describes that there may be a link-local
- * address carried in nexthop. Yikes!
-@@ -1471,72 +1867,144 @@ rde_get_mp_nexthop(u_char *data, u_int16
- log_warnx("bad multiprotocol nexthop, bad size");
- return (-1);
- }
-- nexthop.af = AF_INET6;
- memcpy(&nexthop.v6.s6_addr, data, 16);
-- asp->nexthop = nexthop_get(&nexthop);
-+#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER)
-+ if (IN6_IS_ADDR_LINKLOCAL(&nexthop.v6) &&
-+ peer->conf.lliface[0]) {
-+ int ifindex;
-+
-+ ifindex = if_nametoindex(peer->conf.lliface);
-+ if (ifindex != 0) {
-+ SET_IN6_LINKLOCAL_IFINDEX(nexthop.v6, ifindex);
-+ nexthop.scope_id = ifindex;
-+ } else
-+ log_warnx("bad interface: %s", peer->conf.lliface);
-+ }
-+#endif
-+ break;
-+ case AID_VPN_IPv4:
- /*
-- * lock the nexthop because it is not yet linked else
-- * withdraws may remove this nexthop which in turn would
-- * cause a use after free error.
-+ * Neither RFC4364 nor RFC3107 specify the format of the
-+ * nexthop in an explicit way. The quality of RFC went down
-+ * the toilet the larger the number got.
-+ * RFC4364 is very confusing about VPN-IPv4 address and the
-+ * VPN-IPv4 prefix that carries also a MPLS label.
-+ * So the nexthop is a 12-byte address with a 64bit RD and
-+ * an IPv4 address following. In the nexthop case the RD can
-+ * be ignored.
-+ * Since the nexthop has to be in the main IPv4 table just
-+ * create an AID_INET nexthop. So we don't need to handle
-+ * AID_VPN_IPv4 in nexthop and kroute.
- */
-- asp->nexthop->refcnt++;
--
-- /* ignore reserved (old SNPA) field as per RFC 4760 */
-- totlen += nhlen + 1;
-- data += nhlen + 1;
--
-- return (totlen);
-- default:
-- log_warnx("bad multiprotocol nexthop, bad AF");
-+ if (nhlen != 12) {
-+ log_warnx("bad multiprotocol nexthop, bad size");
-+ return (-1);
-+ }
-+ data += sizeof(u_int64_t);
-+ nexthop.aid = AID_INET;
-+ memcpy(&nexthop.v4, data, sizeof(nexthop.v4));
- break;
-+ default:
-+ log_warnx("bad multiprotocol nexthop, bad AID");
-+ return (-1);
- }
-
-- return (-1);
-+ asp->nexthop = nexthop_get(&nexthop);
-+ /*
-+ * lock the nexthop because it is not yet linked else
-+ * withdraws may remove this nexthop which in turn would
-+ * cause a use after free error.
-+ */
-+ asp->nexthop->refcnt++;
-+
-+ /* ignore reserved (old SNPA) field as per RFC4760 */
-+ totlen += nhlen + 1;
-+ data += nhlen + 1;
-+
-+ return (totlen);
-+}
-+
-+int
-+rde_update_extract_prefix(u_char *p, u_int16_t len, void *va,
-+ u_int8_t pfxlen, u_int8_t max)
-+{
-+ static u_char addrmask[] = {
-+ 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
-+ u_char *a = va;
-+ int i;
-+ u_int16_t plen = 0;
-+
-+ for (i = 0; pfxlen && i < max; i++) {
-+ if (len <= plen)
-+ return (-1);
-+ if (pfxlen < 8) {
-+ a[i] = *p++ & addrmask[pfxlen];
-+ plen++;
-+ break;
-+ } else {
-+ a[i] = *p++;
-+ plen++;
-+ pfxlen -= 8;
-+ }
-+ }
-+ return (plen);
- }
-
- int
- rde_update_get_prefix(u_char *p, u_int16_t len, struct bgpd_addr *prefix,
- u_int8_t *prefixlen)
- {
-- int i;
-- u_int8_t pfxlen;
-- u_int16_t plen;
-- union {
-- struct in_addr a32;
-- u_int8_t a8[4];
-- } addr;
-+ u_int8_t pfxlen;
-+ int plen;
-
- if (len < 1)
- return (-1);
-
-- memcpy(&pfxlen, p, 1);
-- p += 1;
-- plen = 1;
-+ pfxlen = *p++;
-+ len--;
-
- bzero(prefix, sizeof(struct bgpd_addr));
-- addr.a32.s_addr = 0;
-- for (i = 0; i <= 3; i++) {
-- if (pfxlen > i * 8) {
-- if (len - plen < 1)
-- return (-1);
-- memcpy(&addr.a8[i], p++, 1);
-- plen++;
-- }
-- }
-- prefix->af = AF_INET;
-- prefix->v4.s_addr = addr.a32.s_addr;
-+ prefix->aid = AID_INET;
- *prefixlen = pfxlen;
-
-- return (plen);
-+ if ((plen = rde_update_extract_prefix(p, len, &prefix->v4, pfxlen,
-+ sizeof(prefix->v4))) == -1)
-+ return (-1);
-+
-+ return (plen + 1); /* pfxlen needs to be added */
- }
-
- int
- rde_update_get_prefix6(u_char *p, u_int16_t len, struct bgpd_addr *prefix,
- u_int8_t *prefixlen)
- {
-- int i;
-+ int plen;
- u_int8_t pfxlen;
-- u_int16_t plen;
-+
-+ if (len < 1)
-+ return (-1);
-+
-+ pfxlen = *p++;
-+ len--;
-+
-+ bzero(prefix, sizeof(struct bgpd_addr));
-+ prefix->aid = AID_INET6;
-+ *prefixlen = pfxlen;
-+
-+ if ((plen = rde_update_extract_prefix(p, len, &prefix->v6, pfxlen,
-+ sizeof(prefix->v6))) == -1)
-+ return (-1);
-+
-+ return (plen + 1); /* pfxlen needs to be added */
-+}
-+
-+int
-+rde_update_get_vpn4(u_char *p, u_int16_t len, struct bgpd_addr *prefix,
-+ u_int8_t *prefixlen)
-+{
-+ int rv, done = 0;
-+ u_int8_t pfxlen;
-+ u_int16_t plen;
-
- if (len < 1)
- return (-1);
-@@ -1546,25 +2014,50 @@ rde_update_get_prefix6(u_char *p, u_int1
- plen = 1;
-
- bzero(prefix, sizeof(struct bgpd_addr));
-- for (i = 0; i <= 15; i++) {
-- if (pfxlen > i * 8) {
-- if (len - plen < 1)
-- return (-1);
-- memcpy(&prefix->v6.s6_addr[i], p++, 1);
-- plen++;
-- }
-- }
-- prefix->af = AF_INET6;
-+
-+ /* label stack */
-+ do {
-+ if (len - plen < 3 || pfxlen < 3 * 8)
-+ return (-1);
-+ if (prefix->vpn4.labellen + 3U >
-+ sizeof(prefix->vpn4.labelstack))
-+ return (-1);
-+ prefix->vpn4.labelstack[prefix->vpn4.labellen++] = *p++;
-+ prefix->vpn4.labelstack[prefix->vpn4.labellen++] = *p++;
-+ prefix->vpn4.labelstack[prefix->vpn4.labellen] = *p++;
-+ if (prefix->vpn4.labelstack[prefix->vpn4.labellen] &
-+ BGP_MPLS_BOS)
-+ done = 1;
-+ prefix->vpn4.labellen++;
-+ plen += 3;
-+ pfxlen -= 3 * 8;
-+ } while (!done);
-+
-+ /* RD */
-+ if (len - plen < (int)sizeof(u_int64_t) ||
-+ pfxlen < sizeof(u_int64_t) * 8)
-+ return (-1);
-+ memcpy(&prefix->vpn4.rd, p, sizeof(u_int64_t));
-+ pfxlen -= sizeof(u_int64_t) * 8;
-+ p += sizeof(u_int64_t);
-+ plen += sizeof(u_int64_t);
-+
-+ /* prefix */
-+ prefix->aid = AID_VPN_IPv4;
- *prefixlen = pfxlen;
-
-- return (plen);
-+ if ((rv = rde_update_extract_prefix(p, len, &prefix->vpn4.addr,
-+ pfxlen, sizeof(prefix->vpn4.addr))) == -1)
-+ return (-1);
-+
-+ return (plen + rv);
- }
-
- void
- rde_update_err(struct rde_peer *peer, u_int8_t error, u_int8_t suberr,
- void *data, u_int16_t size)
- {
-- struct buf *wbuf;
-+ struct ibuf *wbuf;
-
- if ((wbuf = imsg_create(ibuf_se, IMSG_UPDATE_ERR, peer->conf.id, 0,
- size + sizeof(error) + sizeof(suberr))) == NULL)
-@@ -1616,16 +2109,30 @@ rde_as4byte_fixup(struct rde_peer *peer,
- struct attr *nasp, *naggr, *oaggr;
- u_int32_t as;
-
-+ /*
-+ * if either ATTR_AS4_AGGREGATOR or ATTR_AS4_PATH is present
-+ * try to fixup the attributes.
-+ * Do not fixup if F_ATTR_PARSE_ERR is set.
-+ */
-+ if (!(a->flags & F_ATTR_AS4BYTE_NEW) || a->flags & F_ATTR_PARSE_ERR)
-+ return;
-+
- /* first get the attributes */
- nasp = attr_optget(a, ATTR_AS4_PATH);
- naggr = attr_optget(a, ATTR_AS4_AGGREGATOR);
-
- if (rde_as4byte(peer)) {
- /* NEW session using 4-byte ASNs */
-- if (nasp)
-+ if (nasp) {
-+ log_peer_warnx(&peer->conf, "uses 4-byte ASN "
-+ "but sent AS4_PATH attribute.");
- attr_free(a, nasp);
-- if (naggr)
-+ }
-+ if (naggr) {
-+ log_peer_warnx(&peer->conf, "uses 4-byte ASN "
-+ "but sent AS4_AGGREGATOR attribute.");
- attr_free(a, naggr);
-+ }
- return;
- }
- /* OLD session using 2-byte ASNs */
-@@ -1669,6 +2176,10 @@ rde_reflector(struct rde_peer *peer, str
- u_int16_t len;
- u_int32_t id;
-
-+ /* do not consider updates with parse errors */
-+ if (asp->flags & F_ATTR_PARSE_ERR)
-+ return;
-+
- /* check for originator id if eq router_id drop */
- if ((a = attr_optget(asp, ATTR_ORIGINATOR_ID)) != NULL) {
- if (memcmp(&conf->bgpid, a->data, sizeof(conf->bgpid)) == 0) {
-@@ -1677,10 +2188,10 @@ rde_reflector(struct rde_peer *peer, str
- return;
- }
- } else if (conf->flags & BGPD_FLAG_REFLECTOR) {
-- if (peer->conf.ebgp == 0)
-- id = htonl(peer->remote_bgpid);
-- else
-+ if (peer->conf.ebgp)
- id = conf->bgpid;
-+ else
-+ id = htonl(peer->remote_bgpid);
- if (attr_optadd(asp, ATTR_OPTIONAL, ATTR_ORIGINATOR_ID,
- &id, sizeof(u_int32_t)) == -1)
- fatalx("attr_optadd failed but impossible");
-@@ -1724,17 +2235,17 @@ void
- rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags)
- {
- struct ctl_show_rib rib;
-- struct buf *wbuf;
-+ struct ibuf *wbuf;
- struct attr *a;
- void *bp;
-+ time_t staletime;
- u_int8_t l;
-
- bzero(&rib, sizeof(rib));
- rib.lastchange = p->lastchange;
- rib.local_pref = asp->lpref;
- rib.med = asp->med;
-- rib.prefix_cnt = asp->prefix_cnt;
-- rib.active_cnt = asp->active_cnt;
-+ rib.weight = asp->weight;
- strlcpy(rib.descr, asp->peer->conf.descr, sizeof(rib.descr));
- memcpy(&rib.remote_addr, &asp->peer->remote_addr,
- sizeof(rib.remote_addr));
-@@ -1748,23 +2259,26 @@ rde_dump_rib_as(struct prefix *p, struct
- /* announced network may have a NULL nexthop */
- bzero(&rib.true_nexthop, sizeof(rib.true_nexthop));
- bzero(&rib.exit_nexthop, sizeof(rib.exit_nexthop));
-- rib.true_nexthop.af = p->prefix->af;
-- rib.exit_nexthop.af = p->prefix->af;
-+ rib.true_nexthop.aid = p->prefix->aid;
-+ rib.exit_nexthop.aid = p->prefix->aid;
- }
- pt_getaddr(p->prefix, &rib.prefix);
- rib.prefixlen = p->prefix->prefixlen;
- rib.origin = asp->origin;
- rib.flags = 0;
- if (p->rib->active == p)
-- rib.flags |= F_RIB_ACTIVE;
-- if (asp->peer->conf.ebgp == 0)
-- rib.flags |= F_RIB_INTERNAL;
-+ rib.flags |= F_PREF_ACTIVE;
-+ if (!asp->peer->conf.ebgp)
-+ rib.flags |= F_PREF_INTERNAL;
- if (asp->flags & F_PREFIX_ANNOUNCED)
-- rib.flags |= F_RIB_ANNOUNCE;
-+ rib.flags |= F_PREF_ANNOUNCE;
- if (asp->nexthop == NULL || asp->nexthop->state == NEXTHOP_REACH)
-- rib.flags |= F_RIB_ELIGIBLE;
-+ rib.flags |= F_PREF_ELIGIBLE;
- if (asp->flags & F_ATTR_LOOP)
-- rib.flags &= ~F_RIB_ELIGIBLE;
-+ rib.flags &= ~F_PREF_ELIGIBLE;
-+ staletime = asp->peer->staletime[p->prefix->aid];
-+ if (staletime && p->lastchange <= staletime)
-+ rib.flags |= F_PREF_STALE;
- rib.aspath_len = aspath_length(asp->aspath);
-
- if ((wbuf = imsg_create(ibuf_se_ctl, IMSG_CTL_SHOW_RIB, 0, pid,
-@@ -1784,13 +2298,13 @@ rde_dump_rib_as(struct prefix *p, struct
- IMSG_CTL_SHOW_RIB_ATTR, 0, pid,
- attr_optlen(a))) == NULL)
- return;
-- if ((bp = buf_reserve(wbuf, attr_optlen(a))) == NULL) {
-- buf_free(wbuf);
-+ if ((bp = ibuf_reserve(wbuf, attr_optlen(a))) == NULL) {
-+ ibuf_free(wbuf);
- return;
- }
- if (attr_write(bp, attr_optlen(a), a->flags,
- a->type, a->data, a->len) == -1) {
-- buf_free(wbuf);
-+ ibuf_free(wbuf);
- return;
- }
- imsg_close(ibuf_se_ctl, wbuf);
-@@ -1828,17 +2342,20 @@ rde_dump_filter(struct prefix *p, struct
- {
- struct rde_peer *peer;
-
-- if (req->flags & F_CTL_ADJ_IN ||
-+ if (req->flags & F_CTL_ADJ_IN ||
- !(req->flags & (F_CTL_ADJ_IN|F_CTL_ADJ_OUT))) {
- if (req->peerid && req->peerid != p->aspath->peer->conf.id)
- return;
-- if (req->type == IMSG_CTL_SHOW_RIB_AS &&
-- !aspath_match(p->aspath->aspath, req->as.type, req->as.as))
-+ if (req->type == IMSG_CTL_SHOW_RIB_AS &&
-+ !aspath_match(p->aspath->aspath->data,
-+ p->aspath->aspath->len, req->as.type, req->as.as))
- return;
- if (req->type == IMSG_CTL_SHOW_RIB_COMMUNITY &&
-- !rde_filter_community(p->aspath, req->community.as,
-+ !community_match(p->aspath, req->community.as,
- req->community.type))
- return;
-+ if ((req->flags & F_CTL_ACTIVE) && p->rib->active != p)
-+ return;
- rde_dump_rib_as(p, p->aspath, req->pid, req->flags);
- } else if (req->flags & F_CTL_ADJ_OUT) {
- if (p->rib->active != p)
-@@ -1872,7 +2389,7 @@ rde_dump_prefix_upcall(struct rib_entry
-
- pt = re->prefix;
- pt_getaddr(pt, &addr);
-- if (addr.af != ctx->req.prefix.af)
-+ if (addr.aid != ctx->req.prefix.aid)
- return;
- if (ctx->req.prefixlen > pt->prefixlen)
- return;
-@@ -1889,6 +2406,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req
- struct rib_entry *re;
- u_int error;
- u_int16_t id;
-+ u_int8_t hostplen = 0;
-
- if ((ctx = calloc(1, sizeof(*ctx))) == NULL) {
- log_warn("rde_dump_ctx_new");
-@@ -1902,6 +2420,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req
- error = CTL_RES_NOSUCHPEER;
- imsg_compose(ibuf_se_ctl, IMSG_CTL_RESULT, 0, pid, -1, &error,
- sizeof(error));
-+ free(ctx);
- return;
- }
-
-@@ -1924,7 +2443,18 @@ rde_dump_ctx_new(struct ctl_show_rib_req
- ctx->ribctx.ctx_upcall = rde_dump_prefix_upcall;
- break;
- }
-- if (req->prefixlen == 32)
-+ switch (req->prefix.aid) {
-+ case AID_INET:
-+ case AID_VPN_IPv4:
-+ hostplen = 32;
-+ break;
-+ case AID_INET6:
-+ hostplen = 128;
-+ break;
-+ default:
-+ fatalx("rde_dump_ctx_new: unknown af");
-+ }
-+ if (req->prefixlen == hostplen)
- re = rib_lookup(&ribs[id], &req->prefix);
- else
- re = rib_get(&ribs[id], &req->prefix, req->prefixlen);
-@@ -1937,7 +2467,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req
- }
- ctx->ribctx.ctx_done = rde_dump_done;
- ctx->ribctx.ctx_arg = ctx;
-- ctx->ribctx.ctx_af = ctx->req.af;
-+ ctx->ribctx.ctx_aid = ctx->req.aid;
- rib_dump_r(&ctx->ribctx);
- }
-
-@@ -1971,13 +2501,17 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t
- free(ctx);
- return;
- }
-+
-+ if (ctx->mrt.type == MRT_TABLE_DUMP_V2)
-+ mrt_dump_v2_hdr(&ctx->mrt, conf, &peerlist);
-+
- ctx->ribctx.ctx_count = RDE_RUNNER_ROUNDS;
- ctx->ribctx.ctx_rib = &ribs[id];
- ctx->ribctx.ctx_upcall = mrt_dump_upcall;
-- ctx->ribctx.ctx_done = mrt_dump_done;
-+ ctx->ribctx.ctx_done = mrt_done;
- ctx->ribctx.ctx_arg = &ctx->mrt;
-- ctx->ribctx.ctx_af = AF_UNSPEC;
-- LIST_INSERT_HEAD(&rde_mrts, &ctx->mrt, entry);
-+ ctx->ribctx.ctx_aid = AID_UNSPEC;
-+ LIST_INSERT_HEAD(&rde_mrts, ctx, entry);
- rde_mrt_cnt++;
- rib_dump_r(&ctx->ribctx);
- }
-@@ -1985,13 +2519,25 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t
- /*
- * kroute specific functions
- */
-+int
-+rde_rdomain_import(struct rde_aspath *asp, struct rdomain *rd)
-+{
-+ struct filter_set *s;
-+
-+ TAILQ_FOREACH(s, &rd->import, entry) {
-+ if (community_ext_match(asp, &s->action.ext_community, 0))
-+ return (1);
-+ }
-+ return (0);
-+}
-+
- void
--rde_send_kroute(struct prefix *new, struct prefix *old)
-+rde_send_kroute(struct prefix *new, struct prefix *old, u_int16_t ribid)
- {
-- struct kroute_label kl;
-- struct kroute6_label kl6;
-+ struct kroute_full kr;
- struct bgpd_addr addr;
- struct prefix *p;
-+ struct rdomain *rd;
- enum imsg_type type;
-
- /*
-@@ -2011,43 +2557,43 @@ rde_send_kroute(struct prefix *new, stru
- }
-
- pt_getaddr(p->prefix, &addr);
-- switch (addr.af) {
-- case AF_INET:
-- bzero(&kl, sizeof(kl));
-- kl.kr.prefix.s_addr = addr.v4.s_addr;
-- kl.kr.prefixlen = p->prefix->prefixlen;
-- if (p->aspath->flags & F_NEXTHOP_REJECT)
-- kl.kr.flags |= F_REJECT;
-- if (p->aspath->flags & F_NEXTHOP_BLACKHOLE)
-- kl.kr.flags |= F_BLACKHOLE;
-- if (type == IMSG_KROUTE_CHANGE)
-- kl.kr.nexthop.s_addr =
-- p->aspath->nexthop->true_nexthop.v4.s_addr;
-- strlcpy(kl.label, rtlabel_id2name(p->aspath->rtlabelid),
-- sizeof(kl.label));
-- if (imsg_compose(ibuf_main, type, 0, 0, -1, &kl,
-- sizeof(kl)) == -1)
-- fatal("imsg_compose error");
-+ bzero(&kr, sizeof(kr));
-+ memcpy(&kr.prefix, &addr, sizeof(kr.prefix));
-+ kr.prefixlen = p->prefix->prefixlen;
-+ if (p->aspath->flags & F_NEXTHOP_REJECT)
-+ kr.flags |= F_REJECT;
-+ if (p->aspath->flags & F_NEXTHOP_BLACKHOLE)
-+ kr.flags |= F_BLACKHOLE;
-+ if (type == IMSG_KROUTE_CHANGE)
-+ memcpy(&kr.nexthop, &p->aspath->nexthop->true_nexthop,
-+ sizeof(kr.nexthop));
-+ strlcpy(kr.label, rtlabel_id2name(p->aspath->rtlabelid),
-+ sizeof(kr.label));
-+
-+ switch (addr.aid) {
-+ case AID_VPN_IPv4:
-+ if (ribid != 1)
-+ /* not Loc-RIB, no update for VPNs */
-+ break;
-+
-+ SIMPLEQ_FOREACH(rd, rdomains_l, entry) {
-+ if (!rde_rdomain_import(p->aspath, rd))
-+ continue;
-+ /* must send exit_nexthop so that correct MPLS tunnel
-+ * is chosen
-+ */
-+ if (type == IMSG_KROUTE_CHANGE)
-+ memcpy(&kr.nexthop,
-+ &p->aspath->nexthop->exit_nexthop,
-+ sizeof(kr.nexthop));
-+ if (imsg_compose(ibuf_main, type, rd->rtableid, 0, -1,
-+ &kr, sizeof(kr)) == -1)
-+ fatal("imsg_compose error");
-+ }
- break;
-- case AF_INET6:
-- bzero(&kl6, sizeof(kl6));
-- memcpy(&kl6.kr.prefix, &addr.v6, sizeof(struct in6_addr));
-- kl6.kr.prefixlen = p->prefix->prefixlen;
-- if (p->aspath->flags & F_NEXTHOP_REJECT)
-- kl6.kr.flags |= F_REJECT;
-- if (p->aspath->flags & F_NEXTHOP_BLACKHOLE)
-- kl6.kr.flags |= F_BLACKHOLE;
-- if (type == IMSG_KROUTE_CHANGE) {
-- type = IMSG_KROUTE6_CHANGE;
-- memcpy(&kl6.kr.nexthop,
-- &p->aspath->nexthop->true_nexthop.v6,
-- sizeof(struct in6_addr));
-- } else
-- type = IMSG_KROUTE6_DELETE;
-- strlcpy(kl6.label, rtlabel_id2name(p->aspath->rtlabelid),
-- sizeof(kl6.label));
-- if (imsg_compose(ibuf_main, type, 0, 0, -1, &kl6,
-- sizeof(kl6)) == -1)
-+ default:
-+ if (imsg_compose(ibuf_main, type, ribs[ribid].rtableid, 0, -1,
-+ &kr, sizeof(kr)) == -1)
- fatal("imsg_compose error");
- break;
- }
-@@ -2098,7 +2644,6 @@ rde_send_pftable_commit(void)
- void
- rde_send_nexthop(struct bgpd_addr *next, int valid)
- {
-- size_t size;
- int type;
-
- if (valid)
-@@ -2106,8 +2651,6 @@ rde_send_nexthop(struct bgpd_addr *next,
- else
- type = IMSG_NEXTHOP_REMOVE;
-
-- size = sizeof(struct bgpd_addr);
--
- if (imsg_compose(ibuf_main, type, 0, 0, -1, next,
- sizeof(struct bgpd_addr)) == -1)
- fatal("imsg_compose error");
-@@ -2201,6 +2744,10 @@ rde_softreconfig_in(struct rib_entry *re
- continue;
-
- for (i = 1; i < rib_size; i++) {
-+ /* only active ribs need a softreconfig rerun */
-+ if (ribs[i].state != RECONF_KEEP)
-+ continue;
-+
- /* check if prefix changed */
- oa = rde_filter(i, &oasp, rules_l, peer, asp, &addr,
- pt->prefixlen, peer, DIR_IN);
-@@ -2228,7 +2775,7 @@ rde_softreconfig_in(struct rib_entry *re
- if (path_compare(nasp, oasp) == 0)
- goto done;
- /* send update */
-- path_update(&ribs[1], peer, nasp, &addr,
-+ path_update(&ribs[i], peer, nasp, &addr,
- pt->prefixlen);
- }
-
-@@ -2241,6 +2788,104 @@ done:
- }
- }
-
-+void
-+rde_softreconfig_load(struct rib_entry *re, void *ptr)
-+{
-+ struct rib *rib = ptr;
-+ struct prefix *p, *np;
-+ struct pt_entry *pt;
-+ struct rde_peer *peer;
-+ struct rde_aspath *asp, *nasp;
-+ enum filter_actions action;
-+ struct bgpd_addr addr;
-+
-+ pt = re->prefix;
-+ pt_getaddr(pt, &addr);
-+ for (p = LIST_FIRST(&re->prefix_h); p != NULL; p = np) {
-+ np = LIST_NEXT(p, rib_l);
-+
-+ /* store aspath as prefix may change till we're done */
-+ asp = p->aspath;
-+ peer = asp->peer;
-+
-+ action = rde_filter(rib->id, &nasp, newrules, peer, asp, &addr,
-+ pt->prefixlen, peer, DIR_IN);
-+ nasp = nasp != NULL ? nasp : asp;
-+
-+ if (action == ACTION_ALLOW) {
-+ /* update Local-RIB */
-+ path_update(rib, peer, nasp, &addr, pt->prefixlen);
-+ }
-+
-+ if (nasp != asp)
-+ path_put(nasp);
-+ }
-+}
-+
-+void
-+rde_softreconfig_load_peer(struct rib_entry *re, void *ptr)
-+{
-+ struct rde_peer *peer = ptr;
-+ struct prefix *p = re->active;
-+ struct pt_entry *pt;
-+ struct rde_aspath *nasp;
-+ enum filter_actions na;
-+ struct bgpd_addr addr;
-+
-+ pt = re->prefix;
-+ pt_getaddr(pt, &addr);
-+
-+ /* check if prefix was announced */
-+ if (up_test_update(peer, p) != 1)
-+ return;
-+
-+ na = rde_filter(re->ribid, &nasp, newrules, peer, p->aspath,
-+ &addr, pt->prefixlen, p->aspath->peer, DIR_OUT);
-+ nasp = nasp != NULL ? nasp : p->aspath;
-+
-+ if (na == ACTION_DENY)
-+ /* nothing todo */
-+ goto done;
-+
-+ /* send update */
-+ up_generate(peer, nasp, &addr, pt->prefixlen);
-+done:
-+ if (nasp != p->aspath)
-+ path_put(nasp);
-+}
-+
-+void
-+rde_softreconfig_unload_peer(struct rib_entry *re, void *ptr)
-+{
-+ struct rde_peer *peer = ptr;
-+ struct prefix *p = re->active;
-+ struct pt_entry *pt;
-+ struct rde_aspath *oasp;
-+ enum filter_actions oa;
-+ struct bgpd_addr addr;
-+
-+ pt = re->prefix;
-+ pt_getaddr(pt, &addr);
-+
-+ /* check if prefix was announced */
-+ if (up_test_update(peer, p) != 1)
-+ return;
-+
-+ oa = rde_filter(re->ribid, &oasp, rules_l, peer, p->aspath,
-+ &addr, pt->prefixlen, p->aspath->peer, DIR_OUT);
-+ oasp = oasp != NULL ? oasp : p->aspath;
-+
-+ if (oa == ACTION_DENY)
-+ /* nothing todo */
-+ goto done;
-+
-+ /* send withdraw */
-+ up_generate(peer, NULL, &addr, pt->prefixlen);
-+done:
-+ if (oasp != p->aspath)
-+ path_put(oasp);
-+}
-+
- /*
- * update specific functions
- */
-@@ -2252,7 +2897,7 @@ rde_up_dump_upcall(struct rib_entry *re,
- struct rde_peer *peer = ptr;
-
- if (re->ribid != peer->ribid)
-- fatalx("King Bula: monsterous evil horror.");
-+ fatalx("King Bula: monstrous evil horror.");
- if (re->active == NULL)
- return;
- up_generate_updates(rules_l, peer, re->active, NULL);
-@@ -2265,7 +2910,7 @@ rde_generate_updates(u_int16_t ribid, st
-
- /*
- * If old is != NULL we know it was active and should be removed.
-- * If new is != NULL we know it is reachable and then we should
-+ * If new is != NULL we know it is reachable and then we should
- * generate an update.
- */
- if (old == NULL && new == NULL)
-@@ -2286,7 +2931,7 @@ void
- rde_update_queue_runner(void)
- {
- struct rde_peer *peer;
-- int r, sent, max = RDE_RUNNER_ROUNDS;
-+ int r, sent, max = RDE_RUNNER_ROUNDS, eor = 0;
- u_int16_t len, wd_len, wpos;
-
- len = sizeof(queue_buf) - MSGSIZE_HEADER;
-@@ -2300,7 +2945,7 @@ rde_update_queue_runner(void)
- /* first withdraws */
- wpos = 2; /* reserve space for the length field */
- r = up_dump_prefix(queue_buf + wpos, len - wpos - 2,
-- &peer->withdraws, peer);
-+ &peer->withdraws[AID_INET], peer);
- wd_len = r;
- /* write withdraws length filed */
- wd_len = htons(wd_len);
-@@ -2310,31 +2955,49 @@ rde_update_queue_runner(void)
- /* now bgp path attributes */
- r = up_dump_attrnlri(queue_buf + wpos, len - wpos,
- peer);
-- wpos += r;
--
-- if (wpos == 4)
-- /*
-- * No packet to send. The 4 bytes are the
-- * needed withdraw and path attribute length.
-- */
-- continue;
-+ switch (r) {
-+ case -1:
-+ eor = 1;
-+ if (wd_len == 0) {
-+ /* no withdraws queued just send EoR */
-+ peer_send_eor(peer, AID_INET);
-+ continue;
-+ }
-+ break;
-+ case 2:
-+ if (wd_len == 0) {
-+ /*
-+ * No packet to send. No withdraws and
-+ * no path attributes. Skip.
-+ */
-+ continue;
-+ }
-+ /* FALLTHROUGH */
-+ default:
-+ wpos += r;
-+ break;
-+ }
-
- /* finally send message to SE */
- if (imsg_compose(ibuf_se, IMSG_UPDATE, peer->conf.id,
- 0, -1, queue_buf, wpos) == -1)
- fatal("imsg_compose error");
- sent++;
-+ if (eor) {
-+ eor = 0;
-+ peer_send_eor(peer, AID_INET);
-+ }
- }
- max -= sent;
- } while (sent != 0 && max > 0);
- }
-
- void
--rde_update6_queue_runner(void)
-+rde_update6_queue_runner(u_int8_t aid)
- {
- struct rde_peer *peer;
- u_char *b;
-- int sent, max = RDE_RUNNER_ROUNDS / 2;
-+ int r, sent, max = RDE_RUNNER_ROUNDS / 2;
- u_int16_t len;
-
- /* first withdraws ... */
-@@ -2346,7 +3009,7 @@ rde_update6_queue_runner(void)
- if (peer->state != PEER_UP)
- continue;
- len = sizeof(queue_buf) - MSGSIZE_HEADER;
-- b = up_dump_mp_unreach(queue_buf, &len, peer);
-+ b = up_dump_mp_unreach(queue_buf, &len, peer, aid);
-
- if (b == NULL)
- continue;
-@@ -2369,10 +3032,18 @@ rde_update6_queue_runner(void)
- if (peer->state != PEER_UP)
- continue;
- len = sizeof(queue_buf) - MSGSIZE_HEADER;
-- b = up_dump_mp_reach(queue_buf, &len, peer);
--
-- if (b == NULL)
-+ r = up_dump_mp_reach(queue_buf, &len, peer, aid);
-+ switch (r) {
-+ case -2:
-+ continue;
-+ case -1:
-+ peer_send_eor(peer, aid);
- continue;
-+ default:
-+ b = queue_buf + r;
-+ break;
-+ }
-+
- /* finally send message to SE */
- if (imsg_compose(ibuf_se, IMSG_UPDATE, peer->conf.id,
- 0, -1, b, len) == -1)
-@@ -2411,7 +3082,7 @@ rde_decisionflags(void)
- int
- rde_as4byte(struct rde_peer *peer)
- {
-- return (peer->capa_announced.as4byte && peer->capa_received.as4byte);
-+ return (peer->capa.as4byte);
- }
-
- /*
-@@ -2429,7 +3100,6 @@ void
- peer_init(u_int32_t hashsize)
- {
- struct peer_config pc;
-- struct in_addr id;
- u_int32_t hs, i;
-
- for (hs = 1; hs < hashsize; hs <<= 1)
-@@ -2445,17 +3115,13 @@ peer_init(u_int32_t hashsize)
- peertable.peer_hashmask = hs - 1;
-
- bzero(&pc, sizeof(pc));
-- pc.remote_as = conf->as;
-- id.s_addr = conf->bgpid;
-- snprintf(pc.descr, sizeof(pc.descr), "LOCAL: ID %s", inet_ntoa(id));
-+ snprintf(pc.descr, sizeof(pc.descr), "LOCAL");
-
- peerself = peer_add(0, &pc);
- if (peerself == NULL)
- fatalx("peer_init add self");
-
- peerself->state = PEER_UP;
-- peerself->remote_bgpid = ntohl(conf->bgpid);
-- peerself->short_as = conf->short_as;
- }
-
- void
-@@ -2534,14 +3200,10 @@ peer_localaddrs(struct rde_peer *peer, s
- if (ifa->ifa_addr->sa_family ==
- match->ifa_addr->sa_family)
- ifa = match;
-- peer->local_v4_addr.af = AF_INET;
-- peer->local_v4_addr.v4.s_addr =
-- ((struct sockaddr_in *)ifa->ifa_addr)->
-- sin_addr.s_addr;
-+ sa2addr(ifa->ifa_addr, &peer->local_v4_addr);
- break;
- }
- }
--
- for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
- if (ifa->ifa_addr->sa_family == AF_INET6 &&
- strcmp(ifa->ifa_name, match->ifa_name) == 0) {
-@@ -2559,13 +3221,7 @@ peer_localaddrs(struct rde_peer *peer, s
- &((struct sockaddr_in6 *)ifa->
- ifa_addr)->sin6_addr))
- continue;
-- peer->local_v6_addr.af = AF_INET6;
-- memcpy(&peer->local_v6_addr.v6,
-- &((struct sockaddr_in6 *)ifa->ifa_addr)->
-- sin6_addr, sizeof(struct in6_addr));
-- peer->local_v6_addr.scope_id =
-- ((struct sockaddr_in6 *)ifa->ifa_addr)->
-- sin6_scope_id;
-+ sa2addr(ifa->ifa_addr, &peer->local_v6_addr);
- break;
- }
- }
-@@ -2577,23 +3233,22 @@ void
- peer_up(u_int32_t id, struct session_up *sup)
- {
- struct rde_peer *peer;
-+ u_int8_t i;
-
- peer = peer_get(id);
- if (peer == NULL) {
-- log_warnx("peer_up: peer id %d already exists", id);
-+ log_warnx("peer_up: unknown peer id %d", id);
- return;
- }
-
-- if (peer->state != PEER_DOWN && peer->state != PEER_NONE)
-+ if (peer->state != PEER_DOWN && peer->state != PEER_NONE &&
-+ peer->state != PEER_UP)
- fatalx("peer_up: bad state");
- peer->remote_bgpid = ntohl(sup->remote_bgpid);
- peer->short_as = sup->short_as;
- memcpy(&peer->remote_addr, &sup->remote_addr,
- sizeof(peer->remote_addr));
-- memcpy(&peer->capa_announced, &sup->capa_announced,
-- sizeof(peer->capa_announced));
-- memcpy(&peer->capa_received, &sup->capa_received,
-- sizeof(peer->capa_received));
-+ memcpy(&peer->capa, &sup->capa, sizeof(peer->capa));
-
- peer_localaddrs(peer, &sup->local_addr);
-
-@@ -2607,7 +3262,10 @@ peer_up(u_int32_t id, struct session_up
- */
- return;
-
-- peer_dump(id, AFI_ALL, SAFI_ALL);
-+ for (i = 0; i < AID_MAX; i++) {
-+ if (peer->capa.mp[i] == 1)
-+ peer_dump(id, i);
-+ }
- }
-
- void
-@@ -2641,43 +3299,90 @@ peer_down(u_int32_t id)
- free(peer);
- }
-
-+/*
-+ * Flush all routes older then staletime. If staletime is 0 all routes will
-+ * be flushed.
-+ */
-+void
-+peer_flush(struct rde_peer *peer, u_int8_t aid)
-+{
-+ struct rde_aspath *asp, *nasp;
-+
-+ /* walk through per peer RIB list and remove all stale prefixes. */
-+ for (asp = LIST_FIRST(&peer->path_h); asp != NULL; asp = nasp) {
-+ nasp = LIST_NEXT(asp, peer_l);
-+ path_remove_stale(asp, aid);
-+ }
-+
-+ /* Deletions are performed in path_remove() */
-+ rde_send_pftable_commit();
-+
-+ /* flushed no need to keep staletime */
-+ peer->staletime[aid] = 0;
-+}
-+
- void
--peer_dump(u_int32_t id, u_int16_t afi, u_int8_t safi)
-+peer_stale(u_int32_t id, u_int8_t aid)
- {
- struct rde_peer *peer;
-+ time_t now;
-
- peer = peer_get(id);
- if (peer == NULL) {
-- log_warnx("peer_down: unknown peer id %d", id);
-+ log_warnx("peer_stale: unknown peer id %d", id);
- return;
- }
-
-- if (afi == AFI_ALL || afi == AFI_IPv4)
-- if (safi == SAFI_ALL || safi == SAFI_UNICAST) {
-- if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE)
-- up_generate_default(rules_l, peer, AF_INET);
-- else
-- rib_dump(&ribs[peer->ribid], rde_up_dump_upcall,
-- peer, AF_INET);
-- }
-- if (afi == AFI_ALL || afi == AFI_IPv6)
-- if (safi == SAFI_ALL || safi == SAFI_UNICAST) {
-- if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE)
-- up_generate_default(rules_l, peer, AF_INET6);
-- else
-- rib_dump(&ribs[peer->ribid], rde_up_dump_upcall,
-- peer, AF_INET6);
-- }
-+ if (peer->staletime[aid])
-+ peer_flush(peer, aid);
-+ peer->staletime[aid] = now = time(NULL);
-
-- if (peer->capa_received.restart && peer->capa_announced.restart)
-- peer_send_eor(peer, afi, safi);
-+ /* make sure new prefixes start on a higher timestamp */
-+ do {
-+ sleep(1);
-+ } while (now >= time(NULL));
- }
-
--/* End-of-RIB marker, draft-ietf-idr-restart-13.txt */
- void
--peer_send_eor(struct rde_peer *peer, u_int16_t afi, u_int16_t safi)
-+peer_dump(u_int32_t id, u_int8_t aid)
- {
-- if (afi == AFI_IPv4 && safi == SAFI_UNICAST) {
-+ struct rde_peer *peer;
-+
-+ peer = peer_get(id);
-+ if (peer == NULL) {
-+ log_warnx("peer_dump: unknown peer id %d", id);
-+ return;
-+ }
-+
-+ if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE)
-+ up_generate_default(rules_l, peer, aid);
-+ else
-+ rib_dump(&ribs[peer->ribid], rde_up_dump_upcall, peer, aid);
-+ if (peer->capa.grestart.restart)
-+ up_generate_marker(peer, aid);
-+}
-+
-+/* End-of-RIB marker, RFC 4724 */
-+void
-+peer_recv_eor(struct rde_peer *peer, u_int8_t aid)
-+{
-+ peer->prefix_rcvd_eor++;
-+
-+ /* First notify SE to remove possible race with the timeout. */
-+ if (imsg_compose(ibuf_se, IMSG_SESSION_RESTARTED, peer->conf.id,
-+ 0, -1, &aid, sizeof(aid)) == -1)
-+ fatal("imsg_compose error");
-+}
-+
-+void
-+peer_send_eor(struct rde_peer *peer, u_int8_t aid)
-+{
-+ u_int16_t afi;
-+ u_int8_t safi;
-+
-+ peer->prefix_sent_eor++;
-+
-+ if (aid == AID_INET) {
- u_char null[4];
-
- bzero(&null, 4);
-@@ -2688,6 +3393,9 @@ peer_send_eor(struct rde_peer *peer, u_i
- u_int16_t i;
- u_char buf[10];
-
-+ if (aid2afi(aid, &afi, &safi) == -1)
-+ fatalx("peer_send_eor: bad AID");
-+
- i = 0; /* v4 withdrawn len */
- bcopy(&i, &buf[0], sizeof(i));
- i = htons(6); /* path attr len */
-@@ -2709,39 +3417,61 @@ peer_send_eor(struct rde_peer *peer, u_i
- * network announcement stuff
- */
- void
--network_init(struct network_head *net_l)
--{
-- struct network *n;
--
-- reloadtime = time(NULL);
--
-- while ((n = TAILQ_FIRST(net_l)) != NULL) {
-- TAILQ_REMOVE(net_l, n, entry);
-- network_add(&n->net, 1);
-- free(n);
-- }
--}
--
--void
- network_add(struct network_config *nc, int flagstatic)
- {
-+ struct rdomain *rd;
- struct rde_aspath *asp;
-+ struct filter_set_head *vpnset = NULL;
-+ in_addr_t prefix4;
- u_int16_t i;
-
-- asp = path_get();
-- asp->aspath = aspath_get(NULL, 0);
-- asp->origin = ORIGIN_IGP;
-- asp->flags = F_ATTR_ORIGIN | F_ATTR_ASPATH |
-- F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED;
-- /* the nexthop is unset unless a default set overrides it */
-+ if (nc->rtableid) {
-+ SIMPLEQ_FOREACH(rd, rdomains_l, entry) {
-+ if (rd->rtableid != nc->rtableid)
-+ continue;
-+ switch (nc->prefix.aid) {
-+ case AID_INET:
-+ prefix4 = nc->prefix.v4.s_addr;
-+ bzero(&nc->prefix, sizeof(nc->prefix));
-+ nc->prefix.aid = AID_VPN_IPv4;
-+ nc->prefix.vpn4.rd = rd->rd;
-+ nc->prefix.vpn4.addr.s_addr = prefix4;
-+ nc->prefix.vpn4.labellen = 3;
-+ nc->prefix.vpn4.labelstack[0] =
-+ (rd->label >> 12) & 0xff;
-+ nc->prefix.vpn4.labelstack[1] =
-+ (rd->label >> 4) & 0xff;
-+ nc->prefix.vpn4.labelstack[2] =
-+ (rd->label << 4) & 0xf0;
-+ nc->prefix.vpn4.labelstack[2] |= BGP_MPLS_BOS;
-+ vpnset = &rd->export;
-+ break;
-+ default:
-+ log_warnx("unable to VPNize prefix");
-+ filterset_free(&nc->attrset);
-+ return;
-+ }
-+ }
-+ }
-+
-+ if (nc->type == NETWORK_MRTCLONE) {
-+ asp = nc->asp;
-+ } else {
-+ asp = path_get();
-+ asp->aspath = aspath_get(NULL, 0);
-+ asp->origin = ORIGIN_IGP;
-+ asp->flags = F_ATTR_ORIGIN | F_ATTR_ASPATH |
-+ F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED;
-+ /* the nexthop is unset unless a default set overrides it */
-+ }
- if (!flagstatic)
- asp->flags |= F_ANN_DYNAMIC;
--
-- rde_apply_set(asp, &nc->attrset, nc->prefix.af, peerself, peerself);
-+ rde_apply_set(asp, &nc->attrset, nc->prefix.aid, peerself, peerself);
-+ if (vpnset)
-+ rde_apply_set(asp, vpnset, nc->prefix.aid, peerself, peerself);
- for (i = 1; i < rib_size; i++)
- path_update(&ribs[i], peerself, asp, &nc->prefix,
- nc->prefixlen);
--
- path_put(asp);
- filterset_free(&nc->attrset);
- }
-@@ -2749,12 +3479,41 @@ network_add(struct network_config *nc, i
- void
- network_delete(struct network_config *nc, int flagstatic)
- {
-- u_int32_t flags = F_PREFIX_ANNOUNCED;
-- u_int32_t i;
-+ struct rdomain *rd;
-+ in_addr_t prefix4;
-+ u_int32_t flags = F_PREFIX_ANNOUNCED;
-+ u_int32_t i;
-
- if (!flagstatic)
- flags |= F_ANN_DYNAMIC;
-
-+ if (nc->rtableid) {
-+ SIMPLEQ_FOREACH(rd, rdomains_l, entry) {
-+ if (rd->rtableid != nc->rtableid)
-+ continue;
-+ switch (nc->prefix.aid) {
-+ case AID_INET:
-+ prefix4 = nc->prefix.v4.s_addr;
-+ bzero(&nc->prefix, sizeof(nc->prefix));
-+ nc->prefix.aid = AID_VPN_IPv4;
-+ nc->prefix.vpn4.rd = rd->rd;
-+ nc->prefix.vpn4.addr.s_addr = prefix4;
-+ nc->prefix.vpn4.labellen = 3;
-+ nc->prefix.vpn4.labelstack[0] =
-+ (rd->label >> 12) & 0xff;
-+ nc->prefix.vpn4.labelstack[1] =
-+ (rd->label >> 4) & 0xff;
-+ nc->prefix.vpn4.labelstack[2] =
-+ (rd->label << 4) & 0xf0;
-+ nc->prefix.vpn4.labelstack[2] |= BGP_MPLS_BOS;
-+ break;
-+ default:
-+ log_warnx("unable to VPNize prefix");
-+ return;
-+ }
-+ }
-+ }
-+
- for (i = rib_size - 1; i > 0; i--)
- prefix_remove(&ribs[i], peerself, &nc->prefix, nc->prefixlen,
- flags);
-@@ -2764,38 +3523,31 @@ void
- network_dump_upcall(struct rib_entry *re, void *ptr)
- {
- struct prefix *p;
-- struct kroute k;
-- struct kroute6 k6;
-+ struct kroute_full k;
- struct bgpd_addr addr;
- struct rde_dump_ctx *ctx = ptr;
-
- LIST_FOREACH(p, &re->prefix_h, rib_l) {
- if (!(p->aspath->flags & F_PREFIX_ANNOUNCED))
- continue;
-- if (p->prefix->af == AF_INET) {
-- bzero(&k, sizeof(k));
-- pt_getaddr(p->prefix, &addr);
-- k.prefix.s_addr = addr.v4.s_addr;
-- k.prefixlen = p->prefix->prefixlen;
-- if (p->aspath->peer == peerself)
-- k.flags = F_KERNEL;
-- if (imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NETWORK, 0,
-- ctx->req.pid, -1, &k, sizeof(k)) == -1)
-- log_warnx("network_dump_upcall: "
-- "imsg_compose error");
-- }
-- if (p->prefix->af == AF_INET6) {
-- bzero(&k6, sizeof(k6));
-- pt_getaddr(p->prefix, &addr);
-- memcpy(&k6.prefix, &addr.v6, sizeof(k6.prefix));
-- k6.prefixlen = p->prefix->prefixlen;
-- if (p->aspath->peer == peerself)
-- k6.flags = F_KERNEL;
-- if (imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NETWORK6, 0,
-- ctx->req.pid, -1, &k6, sizeof(k6)) == -1)
-- log_warnx("network_dump_upcall: "
-- "imsg_compose error");
-- }
-+ pt_getaddr(p->prefix, &addr);
-+
-+ bzero(&k, sizeof(k));
-+ memcpy(&k.prefix, &addr, sizeof(k.prefix));
-+ if (p->aspath->nexthop == NULL ||
-+ p->aspath->nexthop->state != NEXTHOP_REACH)
-+ k.nexthop.aid = k.prefix.aid;
-+ else
-+ memcpy(&k.nexthop, &p->aspath->nexthop->true_nexthop,
-+ sizeof(k.nexthop));
-+ k.prefixlen = p->prefix->prefixlen;
-+ k.flags = F_KERNEL;
-+ if ((p->aspath->flags & F_ANN_DYNAMIC) == 0)
-+ k.flags = F_STATIC;
-+ if (imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NETWORK, 0,
-+ ctx->req.pid, -1, &k, sizeof(k)) == -1)
-+ log_warnx("network_dump_upcall: "
-+ "imsg_compose error");
- }
- }
-
-@@ -2841,10 +3593,10 @@ sa_cmp(struct bgpd_addr *a, struct socka
- struct sockaddr_in *in_b;
- struct sockaddr_in6 *in6_b;
-
-- if (a->af != b->sa_family)
-+ if (aid2af(a->aid) != b->sa_family)
- return (1);
-
-- switch (a->af) {
-+ switch (b->sa_family) {
- case AF_INET:
- in_b = (struct sockaddr_in *)b;
- if (a->v4.s_addr != in_b->sin_addr.s_addr)
-@@ -2855,10 +3607,11 @@ sa_cmp(struct bgpd_addr *a, struct socka
- #ifdef __KAME__
- /* directly stolen from sbin/ifconfig/ifconfig.c */
- if (IN6_IS_ADDR_LINKLOCAL(&in6_b->sin6_addr)) {
-- in6_b->sin6_scope_id =
-- ntohs(*(u_int16_t *)&in6_b->sin6_addr.s6_addr[2]);
-- in6_b->sin6_addr.s6_addr[2] =
-- in6_b->sin6_addr.s6_addr[3] = 0;
-+ if (in6_b->sin6_scope_id == 0) {
-+ in6_b->sin6_scope_id =
-+ IN6_LINKLOCAL_IFINDEX(in6_b->sin6_addr);
-+ }
-+ SET_IN6_LINKLOCAL_IFINDEX(in6_b->sin6_addr, 0);
- }
- #endif
- if (bcmp(&a->v6, &in6_b->sin6_addr,
diff --git a/net/openbgpd/files/patch-bgpd_rde.h b/net/openbgpd/files/patch-bgpd_rde.h
deleted file mode 100644
index ba7d2d095891..000000000000
--- a/net/openbgpd/files/patch-bgpd_rde.h
+++ /dev/null
@@ -1,361 +0,0 @@
-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__ */
diff --git a/net/openbgpd/files/patch-bgpd_rde_attr.c b/net/openbgpd/files/patch-bgpd_rde_attr.c
deleted file mode 100644
index 2c0192abe5da..000000000000
--- a/net/openbgpd/files/patch-bgpd_rde_attr.c
+++ /dev/null
@@ -1,562 +0,0 @@
-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);
-+}
diff --git a/net/openbgpd/files/patch-bgpd_rde_decide.c b/net/openbgpd/files/patch-bgpd_rde_decide.c
deleted file mode 100644
index c9d27af5dbef..000000000000
--- a/net/openbgpd/files/patch-bgpd_rde_decide.c
+++ /dev/null
@@ -1,133 +0,0 @@
-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)
diff --git a/net/openbgpd/files/patch-bgpd_rde_filter.c b/net/openbgpd/files/patch-bgpd_rde_filter.c
deleted file mode 100644
index c17d9fc5fdbf..000000000000
--- a/net/openbgpd/files/patch-bgpd_rde_filter.c
+++ /dev/null
@@ -1,297 +0,0 @@
-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 */
- }
diff --git a/net/openbgpd/files/patch-bgpd_rde_prefix.c b/net/openbgpd/files/patch-bgpd_rde_prefix.c
deleted file mode 100644
index daea5cf62272..000000000000
--- a/net/openbgpd/files/patch-bgpd_rde_prefix.c
+++ /dev/null
@@ -1,301 +0,0 @@
-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);
- }
diff --git a/net/openbgpd/files/patch-bgpd_rde_rib.c b/net/openbgpd/files/patch-bgpd_rde_rib.c
deleted file mode 100644
index 2fe781c69c4b..000000000000
--- a/net/openbgpd/files/patch-bgpd_rde_rib.c
+++ /dev/null
@@ -1,513 +0,0 @@
-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:
diff --git a/net/openbgpd/files/patch-bgpd_rde_update.c b/net/openbgpd/files/patch-bgpd_rde_update.c
deleted file mode 100644
index ccd9601dcd3d..000000000000
--- a/net/openbgpd/files/patch-bgpd_rde_update.c
+++ /dev/null
@@ -1,644 +0,0 @@
-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);
- }
--
diff --git a/net/openbgpd/files/patch-bgpd_session.c b/net/openbgpd/files/patch-bgpd_session.c
deleted file mode 100644
index 66c05a92aec0..000000000000
--- a/net/openbgpd/files/patch-bgpd_session.c
+++ /dev/null
@@ -1,2075 +0,0 @@
-Index: bgpd/session.c
-===================================================================
-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/session.c,v
-retrieving revision 1.1.1.8
-retrieving revision 1.13
-diff -u -p -r1.1.1.8 -r1.13
---- bgpd/session.c 14 Feb 2010 20:19:57 -0000 1.1.1.8
-+++ bgpd/session.c 8 Dec 2012 20:17:59 -0000 1.13
-@@ -1,4 +1,4 @@
--/* $OpenBSD: session.c,v 1.293 2009/06/07 05:56:24 eric Exp $ */
-+/* $OpenBSD: session.c,v 1.325 2012/09/18 09:45:50 claudio Exp $ */
-
- /*
- * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
-@@ -21,18 +21,21 @@
-
- #include <sys/mman.h>
- #include <sys/socket.h>
-+#include <sys/time.h>
-+#include <sys/resource.h>
- #include <sys/un.h>
-+#include <sys/queue.h>
- #include <net/if_types.h>
- #include <netinet/in.h>
- #include <netinet/in_systm.h>
- #include <netinet/ip.h>
- #include <netinet/tcp.h>
-+#include <netinet/tcp_var.h>
- #include <arpa/inet.h>
-
- #include <err.h>
- #include <errno.h>
- #include <fcntl.h>
--#include <limits.h>
- #include <poll.h>
- #include <pwd.h>
- #include <signal.h>
-@@ -50,7 +53,12 @@
- #define PFD_PIPE_ROUTE_CTL 2
- #define PFD_SOCK_CTL 3
- #define PFD_SOCK_RCTL 4
--#define PFD_LISTENERS_START 5
-+#define PFD_SOCK_PFKEY 5
-+#define PFD_LISTENERS_START 6
-+
-+#if defined(__FreeBSD__) /* FreeBSD has no LINK_STATE_IS_UP macro. */
-+#define LINK_STATE_IS_UP(_s) ((_s) >= LINK_STATE_UP)
-+#endif /* defined(__FreeBSD__) */
-
- void session_sighdlr(int);
- int setup_listeners(u_int *);
-@@ -65,9 +73,9 @@ void session_accept(int);
- int session_connect(struct peer *);
- void session_tcp_established(struct peer *);
- void session_capa_ann_none(struct peer *);
--int session_capa_add(struct peer *, struct buf *, u_int8_t, u_int8_t,
-- u_int8_t *);
--int session_capa_add_mp(struct buf *, u_int16_t, u_int8_t);
-+int session_capa_add(struct ibuf *, u_int8_t, u_int8_t);
-+int session_capa_add_mp(struct ibuf *, u_int8_t);
-+int session_capa_add_gr(struct peer *, struct ibuf *, u_int8_t);
- struct bgp_msg *session_newmsg(enum msg_type, u_int16_t);
- int session_sendmsg(struct bgp_msg *, struct peer *);
- void session_open(struct peer *);
-@@ -75,30 +83,34 @@ void session_keepalive(struct peer *);
- void session_update(u_int32_t, void *, size_t);
- void session_notification(struct peer *, u_int8_t, u_int8_t, void *,
- ssize_t);
--void session_rrefresh(struct peer *, u_int16_t, u_int8_t);
-+void session_rrefresh(struct peer *, u_int8_t);
-+int session_graceful_restart(struct peer *);
-+int session_graceful_is_restarting(struct peer *);
-+int session_graceful_stop(struct peer *);
- int session_dispatch_msg(struct pollfd *, struct peer *);
-+int session_process_msg(struct peer *);
- int parse_header(struct peer *, u_char *, u_int16_t *, u_int8_t *);
- int parse_open(struct peer *);
- int parse_update(struct peer *);
- int parse_refresh(struct peer *);
- int parse_notification(struct peer *);
- int parse_capabilities(struct peer *, u_char *, u_int16_t, u_int32_t *);
-+int capa_neg_calc(struct peer *);
- void session_dispatch_imsg(struct imsgbuf *, int, u_int *);
- void session_up(struct peer *);
- void session_down(struct peer *);
- void session_demote(struct peer *, int);
-
--int la_cmp(struct listen_addr *, struct listen_addr *);
--struct peer *getpeerbyip(struct sockaddr *);
--int session_match_mask(struct peer *, struct sockaddr *);
--struct peer *getpeerbyid(u_int32_t);
--static struct sockaddr *addr2sa(struct bgpd_addr *, u_int16_t);
-+int la_cmp(struct listen_addr *, struct listen_addr *);
-+struct peer *getpeerbyip(struct sockaddr *);
-+int session_match_mask(struct peer *, struct bgpd_addr *);
-+struct peer *getpeerbyid(u_int32_t);
-
--struct bgpd_config *conf, *nconf = NULL;
-+struct bgpd_config *conf, *nconf;
- struct bgpd_sysdep sysdep;
--struct peer *npeers;
--volatile sig_atomic_t session_quit = 0;
--int pending_reconf = 0;
-+struct peer *peers, *npeers;
-+volatile sig_atomic_t session_quit;
-+int pending_reconf;
- int csock = -1, rcsock = -1;
- u_int peer_cnt;
- struct imsgbuf *ibuf_rde;
-@@ -106,6 +118,7 @@ struct imsgbuf *ibuf_rde_ctl;
- struct imsgbuf *ibuf_main;
-
- struct mrt_head mrthead;
-+time_t pauseaccept;
-
- void
- session_sighdlr(int sig)
-@@ -125,6 +138,22 @@ setup_listeners(u_int *la_cnt)
- int opt;
- struct listen_addr *la;
- u_int cnt = 0;
-+#if defined(__FreeBSD__)
-+ int s;
-+
-+ /* Check if TCP_MD5SIG is supported. */
-+ s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
-+ if (s < 0)
-+ fatal("socket open for TCP_MD5SIG check");
-+ opt = TF_SIGNATURE;
-+ if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, &opt, sizeof(opt)) == -1) {
-+ if (errno == ENOPROTOOPT || errno == EINVAL)
-+ sysdep.no_md5sig = 1;
-+ else
-+ fatal("setsockopt TCP_MD5SIG");
-+ }
-+ close(s);
-+#endif /* defined(__FreeBSD__) */
-
- TAILQ_FOREACH(la, conf->listen_addrs, entry) {
- la->reconf = RECONF_NONE;
-@@ -140,6 +169,7 @@ setup_listeners(u_int *la_cnt)
- }
-
- opt = 1;
-+#if !defined(__FreeBSD__)
- if (setsockopt(la->fd, IPPROTO_TCP, TCP_MD5SIG,
- &opt, sizeof(opt)) == -1) {
- if (errno == ENOPROTOOPT) { /* system w/o md5sig */
-@@ -148,6 +178,7 @@ setup_listeners(u_int *la_cnt)
- } else
- fatal("setsockopt TCP_MD5SIG");
- }
-+#endif /* !defined(__FreeBSD__) */
-
- /* set ttl to 255 so that ttl-security works */
- if (la->sa.ss_family == AF_INET && setsockopt(la->fd,
-@@ -175,12 +206,10 @@ setup_listeners(u_int *la_cnt)
- }
-
- pid_t
--session_main(struct bgpd_config *config, struct peer *cpeers,
-- struct network_head *net_l, struct filter_head *rules,
-- struct mrt_head *m_l, struct rib_names *rib_l, int pipe_m2s[2],
-- int pipe_s2r[2], int pipe_m2r[2], int pipe_s2rctl[2])
-+session_main(int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2],
-+ int pipe_s2rctl[2])
- {
-- int nfds, timeout;
-+ int nfds, timeout, pfkeysock;
- unsigned int i, j, idx_peers, idx_listeners, idx_mrts;
- pid_t pid;
- u_int pfd_elms = 0, peer_l_elms = 0, mrt_l_elms = 0;
-@@ -189,19 +218,13 @@ session_main(struct bgpd_config *config,
- u_int32_t ctl_queued;
- struct passwd *pw;
- struct peer *p, **peer_l = NULL, *last, *next;
-- struct network *net;
-- struct mrt *m, **mrt_l = NULL;
-- struct filter_rule *r;
-+ struct mrt *m, *xm, **mrt_l = NULL;
- struct pollfd *pfd = NULL;
- struct ctl_conn *ctl_conn;
- struct listen_addr *la;
-- struct rde_rib *rr;
- void *newp;
- short events;
-
-- conf = config;
-- peers = cpeers;
--
- switch (pid = fork()) {
- case -1:
- fatal("cannot fork");
-@@ -211,13 +234,6 @@ session_main(struct bgpd_config *config,
- return (pid);
- }
-
-- /* control socket is outside chroot */
-- if ((csock = control_init(0, conf->csock)) == -1)
-- fatalx("control socket setup failed");
-- if (conf->rcsock != NULL &&
-- (rcsock = control_init(1, conf->rcsock)) == -1)
-- fatalx("control socket setup failed");
--
- if ((pw = getpwnam(BGPD_USER)) == NULL)
- fatal(NULL);
-
-@@ -228,29 +244,25 @@ session_main(struct bgpd_config *config,
-
- setproctitle("session engine");
- bgpd_process = PROC_SE;
--
-- if (pfkey_init(&sysdep) == -1)
-- fatalx("pfkey setup failed");
-+ pfkeysock = pfkey_init(&sysdep);
-
- if (setgroups(1, &pw->pw_gid) ||
- setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
- setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
- fatal("can't drop privileges");
-
-- listener_cnt = 0;
-- setup_listeners(&listener_cnt);
--
- signal(SIGTERM, session_sighdlr);
- signal(SIGINT, session_sighdlr);
- signal(SIGPIPE, SIG_IGN);
- signal(SIGHUP, SIG_IGN);
-- log_info("session engine ready");
-+ signal(SIGALRM, SIG_IGN);
-+ signal(SIGUSR1, SIG_IGN);
-+
- close(pipe_m2s[0]);
- close(pipe_s2r[1]);
- close(pipe_s2rctl[1]);
- close(pipe_m2r[0]);
- close(pipe_m2r[1]);
-- init_conf(conf);
- if ((ibuf_rde = malloc(sizeof(struct imsgbuf))) == NULL ||
- (ibuf_rde_ctl = malloc(sizeof(struct imsgbuf))) == NULL ||
- (ibuf_main = malloc(sizeof(struct imsgbuf))) == NULL)
-@@ -258,37 +270,21 @@ session_main(struct bgpd_config *config,
- imsg_init(ibuf_rde, pipe_s2r[0]);
- imsg_init(ibuf_rde_ctl, pipe_s2rctl[0]);
- imsg_init(ibuf_main, pipe_m2s[1]);
-+
- TAILQ_INIT(&ctl_conns);
-- control_listen(csock);
-- control_listen(rcsock);
- LIST_INIT(&mrthead);
-+ listener_cnt = 0;
- peer_cnt = 0;
- ctl_cnt = 0;
-
-- /* filter rules are not used in the SE */
-- while ((r = TAILQ_FIRST(rules)) != NULL) {
-- TAILQ_REMOVE(rules, r, entry);
-- free(r);
-- }
-- free(rules);
--
-- /* network list is not used in the SE */
-- while ((net = TAILQ_FIRST(net_l)) != NULL) {
-- TAILQ_REMOVE(net_l, net, entry);
-- filterset_free(&net->net.attrset);
-- free(net);
-- }
-+ if ((conf = calloc(1, sizeof(struct bgpd_config))) == NULL)
-+ fatal(NULL);
-+ if ((conf->listen_addrs = calloc(1, sizeof(struct listen_addrs))) ==
-+ NULL)
-+ fatal(NULL);
-+ TAILQ_INIT(conf->listen_addrs);
-
-- /* main mrt list is not used in the SE */
-- while ((m = LIST_FIRST(m_l)) != NULL) {
-- LIST_REMOVE(m, entry);
-- free(m);
-- }
-- /* rib names not used in the SE */
-- while ((rr = SIMPLEQ_FIRST(&ribnames))) {
-- SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
-- free(rr);
-- }
-+ log_info("session engine ready");
-
- while (session_quit == 0) {
- /* check for peers to be initialized or deleted */
-@@ -308,8 +304,9 @@ session_main(struct bgpd_config *config,
-
- /* reinit due? */
- if (p->conf.reconf_action == RECONF_REINIT) {
-- bgp_fsm(p, EVNT_STOP);
-- timer_set(p, Timer_IdleHold, 0);
-+ session_stop(p, ERR_CEASE_ADMIN_RESET);
-+ if (!p->conf.down)
-+ timer_set(p, Timer_IdleHold, 0);
- }
-
- /* deletion due? */
-@@ -317,7 +314,7 @@ session_main(struct bgpd_config *config,
- if (p->demoted)
- session_demote(p, -1);
- p->conf.demote_group[0] = 0;
-- bgp_fsm(p, EVNT_STOP);
-+ session_stop(p, ERR_CEASE_PEER_UNCONF);
- log_peer_warnx(&p->conf, "removed");
- if (last != NULL)
- last->next = next;
-@@ -346,9 +343,17 @@ session_main(struct bgpd_config *config,
- }
-
- mrt_cnt = 0;
-- LIST_FOREACH(m, &mrthead, entry)
-+ for (m = LIST_FIRST(&mrthead); m != NULL; m = xm) {
-+ xm = LIST_NEXT(m, entry);
-+ if (m->state == MRT_STATE_REMOVE) {
-+ mrt_clean(m);
-+ LIST_REMOVE(m, entry);
-+ free(m);
-+ continue;
-+ }
- if (m->wbuf.queued)
- mrt_cnt++;
-+ }
-
- if (mrt_cnt > mrt_l_elms) {
- if ((newp = realloc(mrt_l, sizeof(struct mrt *) *
-@@ -394,18 +399,31 @@ session_main(struct bgpd_config *config,
- if (ctl_queued < SESSION_CTL_QUEUE_MAX)
- /*
- * Do not act as unlimited buffer. Don't read in more
-- * messages if the ctl sockets are getting full.
-+ * messages if the ctl sockets are getting full.
- */
- pfd[PFD_PIPE_ROUTE_CTL].events = POLLIN;
-- pfd[PFD_SOCK_CTL].fd = csock;
-- pfd[PFD_SOCK_CTL].events = POLLIN;
-- pfd[PFD_SOCK_RCTL].fd = rcsock;
-- pfd[PFD_SOCK_RCTL].events = POLLIN;
--
-+ if (pauseaccept == 0) {
-+ pfd[PFD_SOCK_CTL].fd = csock;
-+ pfd[PFD_SOCK_CTL].events = POLLIN;
-+ pfd[PFD_SOCK_RCTL].fd = rcsock;
-+ pfd[PFD_SOCK_RCTL].events = POLLIN;
-+ } else {
-+ pfd[PFD_SOCK_CTL].fd = -1;
-+ pfd[PFD_SOCK_RCTL].fd = -1;
-+ }
-+ pfd[PFD_SOCK_PFKEY].fd = pfkeysock;
-+#if !defined(__FreeBSD__)
-+ pfd[PFD_SOCK_PFKEY].events = POLLIN;
-+#else
-+ pfd[PFD_SOCK_PFKEY].events = 0;
-+#endif
- i = PFD_LISTENERS_START;
- TAILQ_FOREACH(la, conf->listen_addrs, entry) {
-- pfd[i].fd = la->fd;
-- pfd[i].events = POLLIN;
-+ if (pauseaccept == 0) {
-+ pfd[i].fd = la->fd;
-+ pfd[i].events = POLLIN;
-+ } else
-+ pfd[i].fd = -1;
- i++;
- }
- idx_listeners = i;
-@@ -450,6 +468,10 @@ session_main(struct bgpd_config *config,
- p->state == STATE_ESTABLISHED)
- session_demote(p, -1);
- break;
-+ case Timer_RestartTimeout:
-+ timer_stop(p, Timer_RestartTimeout);
-+ session_graceful_stop(p);
-+ break;
- default:
- fatalx("King Bula lost in time");
- }
-@@ -462,6 +484,9 @@ session_main(struct bgpd_config *config,
- events = POLLIN;
- if (p->wbuf.queued > 0 || p->state == STATE_CONNECT)
- events |= POLLOUT;
-+ /* is there still work to do? */
-+ if (p->rbuf && p->rbuf->wpos)
-+ timeout = 0;
-
- /* poll events */
- if (p->fd != -1 && events != 0) {
-@@ -492,12 +517,21 @@ session_main(struct bgpd_config *config,
- i++;
- }
-
-+ if (pauseaccept && timeout > 1)
-+ timeout = 1;
- if (timeout < 0)
- timeout = 0;
- if ((nfds = poll(pfd, i, timeout * 1000)) == -1)
- if (errno != EINTR)
- fatal("poll error");
-
-+ /*
-+ * If we previously saw fd exhaustion, we stop accept()
-+ * for 1 second to throttle the accept() loop.
-+ */
-+ if (pauseaccept && getmonotime() > pauseaccept + 1)
-+ pauseaccept = 0;
-+
- if (nfds > 0 && pfd[PFD_PIPE_MAIN].revents & POLLOUT)
- if (msgbuf_write(&ibuf_main->w) < 0)
- fatal("pipe write error");
-@@ -534,6 +568,14 @@ session_main(struct bgpd_config *config,
- ctl_cnt += control_accept(rcsock, 1);
- }
-
-+ if (nfds > 0 && pfd[PFD_SOCK_PFKEY].revents & POLLIN) {
-+ nfds--;
-+ if (pfkey_read(pfkeysock, NULL) == -1) {
-+ log_warnx("pfkey_read failed, exiting...");
-+ session_quit = 1;
-+ }
-+ }
-+
- for (j = PFD_LISTENERS_START; nfds > 0 && j < idx_listeners;
- j++)
- if (pfd[j].revents & POLLIN) {
-@@ -545,6 +587,10 @@ session_main(struct bgpd_config *config,
- nfds -= session_dispatch_msg(&pfd[j],
- peer_l[j - idx_listeners]);
-
-+ for (p = peers; p != NULL; p = p->next)
-+ if (p->rbuf && p->rbuf->wpos)
-+ session_process_msg(p);
-+
- for (; nfds > 0 && j < idx_mrts; j++)
- if (pfd[j].revents & POLLOUT) {
- nfds--;
-@@ -557,7 +603,7 @@ session_main(struct bgpd_config *config,
-
- while ((p = peers) != NULL) {
- peers = p->next;
-- bgp_fsm(p, EVNT_STOP);
-+ session_stop(p, ERR_CEASE_ADMIN_DOWN);
- pfkey_remove(p);
- free(p);
- }
-@@ -643,10 +689,9 @@ bgp_fsm(struct peer *peer, enum session_
- timer_stop(peer, Timer_IdleHold);
-
- /* allocate read buffer */
-- peer->rbuf = calloc(1, sizeof(struct buf_read));
-+ peer->rbuf = calloc(1, sizeof(struct ibuf_read));
- if (peer->rbuf == NULL)
- fatal(NULL);
-- peer->rbuf->wpos = 0;
-
- /* init write buffer */
- msgbuf_init(&peer->wbuf);
-@@ -746,7 +791,6 @@ bgp_fsm(struct peer *peer, enum session_
- /* ignore */
- break;
- case EVNT_STOP:
-- session_notification(peer, ERR_CEASE, 0, NULL, 0);
- change_state(peer, STATE_IDLE, event);
- break;
- case EVNT_CON_CLOSED:
-@@ -780,7 +824,8 @@ bgp_fsm(struct peer *peer, enum session_
- change_state(peer, STATE_IDLE, event);
- break;
- default:
-- session_notification(peer, ERR_FSM, 0, NULL, 0);
-+ session_notification(peer,
-+ ERR_FSM, ERR_FSM_UNEX_OPENSENT, NULL, 0);
- change_state(peer, STATE_IDLE, event);
- break;
- }
-@@ -791,7 +836,6 @@ bgp_fsm(struct peer *peer, enum session_
- /* ignore */
- break;
- case EVNT_STOP:
-- session_notification(peer, ERR_CEASE, 0, NULL, 0);
- change_state(peer, STATE_IDLE, event);
- break;
- case EVNT_CON_CLOSED:
-@@ -815,7 +859,8 @@ bgp_fsm(struct peer *peer, enum session_
- change_state(peer, STATE_IDLE, event);
- break;
- default:
-- session_notification(peer, ERR_FSM, 0, NULL, 0);
-+ session_notification(peer,
-+ ERR_FSM, ERR_FSM_UNEX_OPENCONFIRM, NULL, 0);
- change_state(peer, STATE_IDLE, event);
- break;
- }
-@@ -826,7 +871,6 @@ bgp_fsm(struct peer *peer, enum session_
- /* ignore */
- break;
- case EVNT_STOP:
-- session_notification(peer, ERR_CEASE, 0, NULL, 0);
- change_state(peer, STATE_IDLE, event);
- break;
- case EVNT_CON_CLOSED:
-@@ -856,7 +900,8 @@ bgp_fsm(struct peer *peer, enum session_
- change_state(peer, STATE_IDLE, event);
- break;
- default:
-- session_notification(peer, ERR_FSM, 0, NULL, 0);
-+ session_notification(peer,
-+ ERR_FSM, ERR_FSM_UNEX_ESTABLISHED, NULL, 0);
- change_state(peer, STATE_IDLE, event);
- break;
- }
-@@ -885,9 +930,10 @@ start_timer_keepalive(struct peer *peer)
- void
- session_close_connection(struct peer *peer)
- {
-- if (peer->fd != -1)
-+ if (peer->fd != -1) {
- close(peer->fd);
--
-+ pauseaccept = 0;
-+ }
- peer->fd = peer->wbuf.fd = -1;
- }
-
-@@ -923,20 +969,31 @@ change_state(struct peer *peer, enum ses
- timer_stop(peer, Timer_ConnectRetry);
- timer_stop(peer, Timer_Keepalive);
- timer_stop(peer, Timer_Hold);
-+ timer_stop(peer, Timer_IdleHold);
- timer_stop(peer, Timer_IdleHoldReset);
- session_close_connection(peer);
- msgbuf_clear(&peer->wbuf);
- free(peer->rbuf);
- peer->rbuf = NULL;
- bzero(&peer->capa.peer, sizeof(peer->capa.peer));
-- if (peer->state == STATE_ESTABLISHED)
-- session_down(peer);
-+
- if (event != EVNT_STOP) {
- timer_set(peer, Timer_IdleHold, peer->IdleHoldTime);
- if (event != EVNT_NONE &&
- peer->IdleHoldTime < MAX_IDLE_HOLD/2)
- peer->IdleHoldTime *= 2;
- }
-+ if (peer->state == STATE_ESTABLISHED) {
-+ if (peer->capa.neg.grestart.restart == 2 &&
-+ (event == EVNT_CON_CLOSED ||
-+ event == EVNT_CON_FATAL)) {
-+ /* don't punish graceful restart */
-+ timer_set(peer, Timer_IdleHold, 0);
-+ peer->IdleHoldTime /= 2;
-+ session_graceful_restart(peer);
-+ } else
-+ session_down(peer);
-+ }
- if (peer->state == STATE_NONE ||
- peer->state == STATE_ESTABLISHED) {
- /* initialize capability negotiation structures */
-@@ -947,6 +1004,20 @@ change_state(struct peer *peer, enum ses
- }
- break;
- case STATE_CONNECT:
-+ if (peer->state == STATE_ESTABLISHED &&
-+ peer->capa.neg.grestart.restart == 2) {
-+ /* do the graceful restart dance */
-+ session_graceful_restart(peer);
-+ peer->holdtime = INTERVAL_HOLD_INITIAL;
-+ timer_stop(peer, Timer_ConnectRetry);
-+ timer_stop(peer, Timer_Keepalive);
-+ timer_stop(peer, Timer_Hold);
-+ timer_stop(peer, Timer_IdleHold);
-+ timer_stop(peer, Timer_IdleHoldReset);
-+ session_close_connection(peer);
-+ msgbuf_clear(&peer->wbuf);
-+ bzero(&peer->capa.peer, sizeof(peer->capa.peer));
-+ }
- break;
- case STATE_ACTIVE:
- break;
-@@ -990,7 +1061,10 @@ session_accept(int listenfd)
- len = sizeof(cliaddr);
- if ((connfd = accept(listenfd,
- (struct sockaddr *)&cliaddr, &len)) == -1) {
-- if (errno == EWOULDBLOCK || errno == EINTR)
-+ if (errno == ENFILE || errno == EMFILE) {
-+ pauseaccept = getmonotime();
-+ return;
-+ } else if (errno == EWOULDBLOCK || errno == EINTR)
- return;
- else
- log_warn("accept");
-@@ -1017,6 +1091,7 @@ session_accept(int listenfd)
- }
- }
-
-+open:
- if (p->conf.auth.method != AUTH_NONE && sysdep.no_pfkey) {
- log_peer_warnx(&p->conf,
- "ipsec or md5sig configured but not available");
-@@ -1049,6 +1124,13 @@ session_accept(int listenfd)
- }
- session_socket_blockmode(connfd, BM_NONBLOCK);
- bgp_fsm(p, EVNT_CON_OPEN);
-+ return;
-+ } else if (p != NULL && p->state == STATE_ESTABLISHED &&
-+ p->capa.neg.grestart.restart == 2) {
-+ /* first do the graceful restart dance */
-+ change_state(p, STATE_CONNECT, EVNT_CON_CLOSED);
-+ /* then do part of the open dance */
-+ goto open;
- } else {
- log_conn_attempt(p, (struct sockaddr *)&cliaddr);
- close(connfd);
-@@ -1069,7 +1151,7 @@ session_connect(struct peer *peer)
- if (peer->fd != -1)
- return (-1);
-
-- if ((peer->fd = socket(peer->conf.remote_addr.af, SOCK_STREAM,
-+ if ((peer->fd = socket(aid2af(peer->conf.remote_addr.aid), SOCK_STREAM,
- IPPROTO_TCP)) == -1) {
- log_peer_warn(&peer->conf, "session_connect socket");
- bgp_fsm(peer, EVNT_CON_OPENFAIL);
-@@ -1100,8 +1182,7 @@ session_connect(struct peer *peer)
- peer->wbuf.fd = peer->fd;
-
- /* if update source is set we need to bind() */
-- if (peer->conf.local_addr.af) {
-- sa = addr2sa(&peer->conf.local_addr, 0);
-+ if ((sa = addr2sa(&peer->conf.local_addr, 0)) != NULL) {
- if (bind(peer->fd, sa, sa->sa_len) == -1) {
- log_peer_warn(&peer->conf, "session_connect bind");
- bgp_fsm(peer, EVNT_CON_OPENFAIL);
-@@ -1139,42 +1220,50 @@ session_setup_socket(struct peer *p)
- int nodelay = 1;
- int bsize;
-
-- if (p->conf.ebgp && p->conf.remote_addr.af == AF_INET) {
-- /* set TTL to foreign router's distance - 1=direct n=multihop
-- with ttlsec, we always use 255 */
-- if (p->conf.ttlsec) {
-- ttl = 256 - p->conf.distance;
-- if (setsockopt(p->fd, IPPROTO_IP, IP_MINTTL, &ttl,
-+ switch (p->conf.remote_addr.aid) {
-+ case AID_INET:
-+ /* set precedence, see RFC 1771 appendix 5 */
-+ if (setsockopt(p->fd, IPPROTO_IP, IP_TOS, &pre, sizeof(pre)) ==
-+ -1) {
-+ log_peer_warn(&p->conf,
-+ "session_setup_socket setsockopt TOS");
-+ return (-1);
-+ }
-+
-+ if (p->conf.ebgp) {
-+ /* set TTL to foreign router's distance
-+ 1=direct n=multihop with ttlsec, we always use 255 */
-+ if (p->conf.ttlsec) {
-+ ttl = 256 - p->conf.distance;
-+ if (setsockopt(p->fd, IPPROTO_IP, IP_MINTTL,
-+ &ttl, sizeof(ttl)) == -1) {
-+ log_peer_warn(&p->conf,
-+ "session_setup_socket: "
-+ "setsockopt MINTTL");
-+ return (-1);
-+ }
-+ ttl = 255;
-+ }
-+
-+ if (setsockopt(p->fd, IPPROTO_IP, IP_TTL, &ttl,
- sizeof(ttl)) == -1) {
- log_peer_warn(&p->conf,
-- "session_setup_socket setsockopt MINTTL");
-+ "session_setup_socket setsockopt TTL");
- return (-1);
- }
-- ttl = 255;
-- }
--
-- if (setsockopt(p->fd, IPPROTO_IP, IP_TTL, &ttl,
-- sizeof(ttl)) == -1) {
-- log_peer_warn(&p->conf,
-- "session_setup_socket setsockopt TTL");
-- return (-1);
- }
-- }
--
-- if (p->conf.ebgp && p->conf.remote_addr.af == AF_INET6)
-- /* set hoplimit to foreign router's distance */
-- if (setsockopt(p->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,
-- sizeof(ttl)) == -1) {
-- log_peer_warn(&p->conf,
-- "session_setup_socket setsockopt hoplimit");
-- return (-1);
-+ break;
-+ case AID_INET6:
-+ if (p->conf.ebgp) {
-+ /* set hoplimit to foreign router's distance */
-+ if (setsockopt(p->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
-+ &ttl, sizeof(ttl)) == -1) {
-+ log_peer_warn(&p->conf,
-+ "session_setup_socket setsockopt hoplimit");
-+ return (-1);
-+ }
- }
--
-- /* if ttlsec is in use, set minttl */
-- if (p->conf.ttlsec) {
-- ttl = 256 - p->conf.distance;
-- setsockopt(p->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl));
--
-+ break;
- }
-
- /* set TCP_NODELAY */
-@@ -1185,24 +1274,18 @@ session_setup_socket(struct peer *p)
- return (-1);
- }
-
-- /* set precedence, see RFC 1771 appendix 5 */
-- if (p->conf.remote_addr.af == AF_INET &&
-- setsockopt(p->fd, IPPROTO_IP, IP_TOS, &pre, sizeof(pre)) == -1) {
-- log_peer_warn(&p->conf,
-- "session_setup_socket setsockopt TOS");
-- return (-1);
-- }
--
- /* only increase bufsize (and thus window) if md5 or ipsec is in use */
- if (p->conf.auth.method != AUTH_NONE) {
- /* try to increase bufsize. no biggie if it fails */
- bsize = 65535;
-- while (setsockopt(p->fd, SOL_SOCKET, SO_RCVBUF, &bsize,
-- sizeof(bsize)) == -1)
-+ while (bsize > 8192 &&
-+ setsockopt(p->fd, SOL_SOCKET, SO_RCVBUF, &bsize,
-+ sizeof(bsize)) == -1 && errno != EINVAL)
- bsize /= 2;
- bsize = 65535;
-- while (setsockopt(p->fd, SOL_SOCKET, SO_SNDBUF, &bsize,
-- sizeof(bsize)) == -1)
-+ while (bsize > 8192 &&
-+ setsockopt(p->fd, SOL_SOCKET, SO_SNDBUF, &bsize,
-+ sizeof(bsize)) == -1 && errno != EINVAL)
- bsize /= 2;
- }
-
-@@ -1244,40 +1327,56 @@ session_tcp_established(struct peer *pee
- void
- session_capa_ann_none(struct peer *peer)
- {
-- peer->capa.ann.mp_v4 = SAFI_NONE;
-- peer->capa.ann.mp_v4 = SAFI_NONE;
-- peer->capa.ann.refresh = 0;
-- peer->capa.ann.restart = 0;
-- peer->capa.ann.as4byte = 0;
-+ bzero(&peer->capa.ann, sizeof(peer->capa.ann));
- }
-
- int
--session_capa_add(struct peer *p, struct buf *opb, u_int8_t capa_code,
-- u_int8_t capa_len, u_int8_t *optparamlen)
--{
-- u_int8_t op_type, op_len, tot_len, errs = 0;
--
-- op_type = OPT_PARAM_CAPABILITIES;
-- op_len = sizeof(capa_code) + sizeof(capa_len) + capa_len;
-- tot_len = sizeof(op_type) + sizeof(op_len) + op_len;
-- errs += buf_add(opb, &op_type, sizeof(op_type));
-- errs += buf_add(opb, &op_len, sizeof(op_len));
-- errs += buf_add(opb, &capa_code, sizeof(capa_code));
-- errs += buf_add(opb, &capa_len, sizeof(capa_len));
-- *optparamlen += tot_len;
-+session_capa_add(struct ibuf *opb, u_int8_t capa_code, u_int8_t capa_len)
-+{
-+ int errs = 0;
-+
-+ errs += ibuf_add(opb, &capa_code, sizeof(capa_code));
-+ errs += ibuf_add(opb, &capa_len, sizeof(capa_len));
- return (errs);
- }
-
- int
--session_capa_add_mp(struct buf *buf, u_int16_t afi, u_int8_t safi)
-+session_capa_add_mp(struct ibuf *buf, u_int8_t aid)
- {
-- u_int8_t pad = 0;
-+ u_int8_t safi, pad = 0;
-+ u_int16_t afi;
- int errs = 0;
-
-+ if (aid2afi(aid, &afi, &safi) == -1)
-+ fatalx("session_capa_add_mp: bad afi/safi pair");
-+ afi = htons(afi);
-+ errs += ibuf_add(buf, &afi, sizeof(afi));
-+ errs += ibuf_add(buf, &pad, sizeof(pad));
-+ errs += ibuf_add(buf, &safi, sizeof(safi));
-+
-+ return (errs);
-+}
-+
-+int
-+session_capa_add_gr(struct peer *p, struct ibuf *b, u_int8_t aid)
-+{
-+ u_int errs = 0;
-+ u_int16_t afi;
-+ u_int8_t flags, safi;
-+
-+ if (aid2afi(aid, &afi, &safi)) {
-+ log_warn("session_capa_add_gr: bad AID");
-+ return (1);
-+ }
-+ if (p->capa.neg.grestart.flags[aid] & CAPA_GR_RESTARTING)
-+ flags = CAPA_GR_F_FLAG;
-+ else
-+ flags = 0;
-+
- afi = htons(afi);
-- errs += buf_add(buf, &afi, sizeof(afi));
-- errs += buf_add(buf, &pad, sizeof(pad));
-- errs += buf_add(buf, &safi, sizeof(safi));
-+ errs += ibuf_add(b, &afi, sizeof(afi));
-+ errs += ibuf_add(b, &safi, sizeof(safi));
-+ errs += ibuf_add(b, &flags, sizeof(flags));
-
- return (errs);
- }
-@@ -1287,23 +1386,22 @@ session_newmsg(enum msg_type msgtype, u_
- {
- struct bgp_msg *msg;
- struct msg_header hdr;
-- struct buf *buf;
-+ struct ibuf *buf;
- int errs = 0;
-
- memset(&hdr.marker, 0xff, sizeof(hdr.marker));
- hdr.len = htons(len);
- hdr.type = msgtype;
-
-- if ((buf = buf_open(len)) == NULL)
-+ if ((buf = ibuf_open(len)) == NULL)
- return (NULL);
-
-- errs += buf_add(buf, &hdr.marker, sizeof(hdr.marker));
-- errs += buf_add(buf, &hdr.len, sizeof(hdr.len));
-- errs += buf_add(buf, &hdr.type, sizeof(hdr.type));
--
-- if (errs > 0 ||
-- (msg = calloc(1, sizeof(*msg))) == NULL) {
-- buf_free(buf);
-+ errs += ibuf_add(buf, &hdr.marker, sizeof(hdr.marker));
-+ errs += ibuf_add(buf, &hdr.len, sizeof(hdr.len));
-+ errs += ibuf_add(buf, &hdr.type, sizeof(hdr.type));
-+
-+ if (errs || (msg = calloc(1, sizeof(*msg))) == NULL) {
-+ ibuf_free(buf);
- return (NULL);
- }
-
-@@ -1329,7 +1427,7 @@ session_sendmsg(struct bgp_msg *msg, str
- mrt_dump_bgp_msg(mrt, msg->buf->buf, msg->len, p);
- }
-
-- buf_close(&p->wbuf, msg->buf);
-+ ibuf_close(&p->wbuf, msg->buf);
- free(msg);
- return (0);
- }
-@@ -1338,40 +1436,70 @@ void
- session_open(struct peer *p)
- {
- struct bgp_msg *buf;
-- struct buf *opb;
-+ struct ibuf *opb;
- struct msg_open msg;
- u_int16_t len;
-- u_int8_t optparamlen = 0;
-- u_int errs = 0;
-+ u_int8_t i, op_type, optparamlen = 0;
-+ int errs = 0;
-+ int mpcapa = 0;
-
-
-- if ((opb = buf_dynamic(0, MAX_PKTSIZE - MSGSIZE_OPEN_MIN)) == NULL) {
-+ if ((opb = ibuf_dynamic(0, UCHAR_MAX - sizeof(op_type) -
-+ sizeof(optparamlen))) == NULL) {
- bgp_fsm(p, EVNT_CON_FATAL);
- return;
- }
-
- /* multiprotocol extensions, RFC 4760 */
-- if (p->capa.ann.mp_v4) { /* 4 bytes data */
-- errs += session_capa_add(p, opb, CAPA_MP, 4, &optparamlen);
-- errs += session_capa_add_mp(opb, AFI_IPv4, p->capa.ann.mp_v4);
-- }
-- if (p->capa.ann.mp_v6) { /* 4 bytes data */
-- errs += session_capa_add(p, opb, CAPA_MP, 4, &optparamlen);
-- errs += session_capa_add_mp(opb, AFI_IPv6, p->capa.ann.mp_v6);
-- }
-+ for (i = 0; i < AID_MAX; i++)
-+ if (p->capa.ann.mp[i]) { /* 4 bytes data */
-+ errs += session_capa_add(opb, CAPA_MP, 4);
-+ errs += session_capa_add_mp(opb, i);
-+ mpcapa++;
-+ }
-
- /* route refresh, RFC 2918 */
- if (p->capa.ann.refresh) /* no data */
-- errs += session_capa_add(p, opb, CAPA_REFRESH, 0, &optparamlen);
-+ errs += session_capa_add(opb, CAPA_REFRESH, 0);
-
-- /* End-of-RIB marker, RFC 4724 */
-- if (p->capa.ann.restart) { /* 2 bytes data */
-- u_char c[2];
--
-- bzero(&c, 2);
-- c[0] = 0x80; /* we're always restarting */
-- errs += session_capa_add(p, opb, CAPA_RESTART, 2, &optparamlen);
-- errs += buf_add(opb, &c, 2);
-+ /* graceful restart and End-of-RIB marker, RFC 4724 */
-+ if (p->capa.ann.grestart.restart) {
-+ int rst = 0;
-+ u_int16_t hdr;
-+ u_int8_t grlen;
-+
-+ if (mpcapa) {
-+ grlen = 2 + 4 * mpcapa;
-+ for (i = 0; i < AID_MAX; i++) {
-+ if (p->capa.neg.grestart.flags[i] &
-+ CAPA_GR_RESTARTING)
-+ rst++;
-+ }
-+ } else { /* AID_INET */
-+ grlen = 2 + 4;
-+ if (p->capa.neg.grestart.flags[AID_INET] &
-+ CAPA_GR_RESTARTING)
-+ rst++;
-+ }
-+
-+ hdr = conf->holdtime; /* default timeout */
-+ /* if client does graceful restart don't set R flag */
-+ if (!rst)
-+ hdr |= CAPA_GR_R_FLAG;
-+ hdr = htons(hdr);
-+
-+ errs += session_capa_add(opb, CAPA_RESTART, grlen);
-+ errs += ibuf_add(opb, &hdr, sizeof(hdr));
-+
-+ if (mpcapa) {
-+ for (i = 0; i < AID_MAX; i++) {
-+ if (p->capa.ann.mp[i]) {
-+ errs += session_capa_add_gr(p, opb, i);
-+ }
-+ }
-+ } else { /* AID_INET */
-+ errs += session_capa_add_gr(p, opb, AID_INET);
-+ }
- }
-
- /* 4-bytes AS numbers, draft-ietf-idr-as4bytes-13 */
-@@ -1379,13 +1507,17 @@ session_open(struct peer *p)
- u_int32_t nas;
-
- nas = htonl(conf->as);
-- errs += session_capa_add(p, opb, CAPA_AS4BYTE, 4, &optparamlen);
-- errs += buf_add(opb, &nas, 4);
-+ errs += session_capa_add(opb, CAPA_AS4BYTE, sizeof(nas));
-+ errs += ibuf_add(opb, &nas, sizeof(nas));
- }
-
-+ if (ibuf_size(opb))
-+ optparamlen = ibuf_size(opb) + sizeof(op_type) +
-+ sizeof(optparamlen);
-+
- len = MSGSIZE_OPEN_MIN + optparamlen;
- if (errs || (buf = session_newmsg(OPEN, len)) == NULL) {
-- buf_free(opb);
-+ ibuf_free(opb);
- bgp_fsm(p, EVNT_CON_FATAL);
- return;
- }
-@@ -1399,19 +1531,24 @@ session_open(struct peer *p)
- msg.bgpid = conf->bgpid; /* is already in network byte order */
- msg.optparamlen = optparamlen;
-
-- errs += buf_add(buf->buf, &msg.version, sizeof(msg.version));
-- errs += buf_add(buf->buf, &msg.myas, sizeof(msg.myas));
-- errs += buf_add(buf->buf, &msg.holdtime, sizeof(msg.holdtime));
-- errs += buf_add(buf->buf, &msg.bgpid, sizeof(msg.bgpid));
-- errs += buf_add(buf->buf, &msg.optparamlen, sizeof(msg.optparamlen));
--
-- if (optparamlen)
-- errs += buf_add(buf->buf, opb->buf, optparamlen);
-+ errs += ibuf_add(buf->buf, &msg.version, sizeof(msg.version));
-+ errs += ibuf_add(buf->buf, &msg.myas, sizeof(msg.myas));
-+ errs += ibuf_add(buf->buf, &msg.holdtime, sizeof(msg.holdtime));
-+ errs += ibuf_add(buf->buf, &msg.bgpid, sizeof(msg.bgpid));
-+ errs += ibuf_add(buf->buf, &msg.optparamlen, sizeof(msg.optparamlen));
-+
-+ if (optparamlen) {
-+ op_type = OPT_PARAM_CAPABILITIES;
-+ optparamlen = ibuf_size(opb);
-+ errs += ibuf_add(buf->buf, &op_type, sizeof(op_type));
-+ errs += ibuf_add(buf->buf, &optparamlen, sizeof(optparamlen));
-+ errs += ibuf_add(buf->buf, opb->buf, ibuf_size(opb));
-+ }
-
-- buf_free(opb);
-+ ibuf_free(opb);
-
-- if (errs > 0) {
-- buf_free(buf->buf);
-+ if (errs) {
-+ ibuf_free(buf->buf);
- free(buf);
- bgp_fsm(p, EVNT_CON_FATAL);
- return;
-@@ -1459,8 +1596,8 @@ session_update(u_int32_t peerid, void *d
- return;
- }
-
-- if (buf_add(buf->buf, data, datalen)) {
-- buf_free(buf->buf);
-+ if (ibuf_add(buf->buf, data, datalen)) {
-+ ibuf_free(buf->buf);
- free(buf);
- bgp_fsm(p, EVNT_CON_FATAL);
- return;
-@@ -1480,29 +1617,27 @@ session_notification(struct peer *p, u_i
- void *data, ssize_t datalen)
- {
- struct bgp_msg *buf;
-- u_int errs = 0;
-- u_int8_t null8 = 0;
-+ int errs = 0;
-
- if (p->stats.last_sent_errcode) /* some notification already sent */
- return;
-
-+ log_notification(p, errcode, subcode, data, datalen, "sending");
-+
- if ((buf = session_newmsg(NOTIFICATION,
- MSGSIZE_NOTIFICATION_MIN + datalen)) == NULL) {
- bgp_fsm(p, EVNT_CON_FATAL);
- return;
- }
-
-- errs += buf_add(buf->buf, &errcode, sizeof(errcode));
-- if (errcode == ERR_CEASE)
-- errs += buf_add(buf->buf, &null8, sizeof(null8));
-- else
-- errs += buf_add(buf->buf, &subcode, sizeof(subcode));
-+ errs += ibuf_add(buf->buf, &errcode, sizeof(errcode));
-+ errs += ibuf_add(buf->buf, &subcode, sizeof(subcode));
-
- if (datalen > 0)
-- errs += buf_add(buf->buf, data, datalen);
-+ errs += ibuf_add(buf->buf, data, datalen);
-
-- if (errs > 0) {
-- buf_free(buf->buf);
-+ if (errs) {
-+ ibuf_free(buf->buf);
- free(buf);
- bgp_fsm(p, EVNT_CON_FATAL);
- return;
-@@ -1521,23 +1656,29 @@ session_notification(struct peer *p, u_i
- int
- session_neighbor_rrefresh(struct peer *p)
- {
-+ u_int8_t i;
-+
- if (!p->capa.peer.refresh)
- return (-1);
-
-- if (p->capa.peer.mp_v4 != SAFI_NONE)
-- session_rrefresh(p, AFI_IPv4, p->capa.peer.mp_v4);
-- if (p->capa.peer.mp_v6 != SAFI_NONE)
-- session_rrefresh(p, AFI_IPv6, p->capa.peer.mp_v6);
-+ for (i = 0; i < AID_MAX; i++) {
-+ if (p->capa.peer.mp[i] != 0)
-+ session_rrefresh(p, i);
-+ }
-
- return (0);
- }
-
- void
--session_rrefresh(struct peer *p, u_int16_t afi, u_int8_t safi)
-+session_rrefresh(struct peer *p, u_int8_t aid)
- {
- struct bgp_msg *buf;
- int errs = 0;
-- u_int8_t null8 = 0;
-+ u_int16_t afi;
-+ u_int8_t safi, null8 = 0;
-+
-+ if (aid2afi(aid, &afi, &safi) == -1)
-+ fatalx("session_rrefresh: bad afi/safi pair");
-
- if ((buf = session_newmsg(RREFRESH, MSGSIZE_RREFRESH)) == NULL) {
- bgp_fsm(p, EVNT_CON_FATAL);
-@@ -1545,12 +1686,12 @@ session_rrefresh(struct peer *p, u_int16
- }
-
- afi = htons(afi);
-- errs += buf_add(buf->buf, &afi, sizeof(afi));
-- errs += buf_add(buf->buf, &null8, sizeof(null8));
-- errs += buf_add(buf->buf, &safi, sizeof(safi));
-+ errs += ibuf_add(buf->buf, &afi, sizeof(afi));
-+ errs += ibuf_add(buf->buf, &null8, sizeof(null8));
-+ errs += ibuf_add(buf->buf, &safi, sizeof(safi));
-
-- if (errs > 0) {
-- buf_free(buf->buf);
-+ if (errs) {
-+ ibuf_free(buf->buf);
- free(buf);
- bgp_fsm(p, EVNT_CON_FATAL);
- return;
-@@ -1565,13 +1706,74 @@ session_rrefresh(struct peer *p, u_int16
- }
-
- int
-+session_graceful_restart(struct peer *p)
-+{
-+ u_int8_t i;
-+
-+ timer_set(p, Timer_RestartTimeout, p->capa.neg.grestart.timeout);
-+
-+ for (i = 0; i < AID_MAX; i++) {
-+ if (p->capa.neg.grestart.flags[i] & CAPA_GR_PRESENT) {
-+ if (imsg_compose(ibuf_rde, IMSG_SESSION_STALE,
-+ p->conf.id, 0, -1, &i, sizeof(i)) == -1)
-+ return (-1);
-+ log_peer_warnx(&p->conf,
-+ "graceful restart of %s, keeping routes",
-+ aid2str(i));
-+ p->capa.neg.grestart.flags[i] |= CAPA_GR_RESTARTING;
-+ } else if (p->capa.neg.mp[i]) {
-+ if (imsg_compose(ibuf_rde, IMSG_SESSION_FLUSH,
-+ p->conf.id, 0, -1, &i, sizeof(i)) == -1)
-+ return (-1);
-+ log_peer_warnx(&p->conf,
-+ "graceful restart of %s, flushing routes",
-+ aid2str(i));
-+ }
-+ }
-+ return (0);
-+}
-+
-+int
-+session_graceful_is_restarting(struct peer *p)
-+{
-+ u_int8_t i;
-+
-+ for (i = 0; i < AID_MAX; i++)
-+ if (p->capa.neg.grestart.flags[i] & CAPA_GR_RESTARTING)
-+ return (1);
-+ return (0);
-+}
-+
-+int
-+session_graceful_stop(struct peer *p)
-+{
-+ u_int8_t i;
-+
-+ for (i = 0; i < AID_MAX; i++) {
-+ /*
-+ * Only flush if the peer is restarting and the peer indicated
-+ * it hold the forwarding state. In all other cases the
-+ * session was already flushed when the session came up.
-+ */
-+ if (p->capa.neg.grestart.flags[i] & CAPA_GR_RESTARTING &&
-+ p->capa.neg.grestart.flags[i] & CAPA_GR_FORWARD) {
-+ log_peer_warnx(&p->conf, "graceful restart of %s, "
-+ "time-out, flushing", aid2str(i));
-+ if (imsg_compose(ibuf_rde, IMSG_SESSION_FLUSH,
-+ p->conf.id, 0, -1, &i, sizeof(i)) == -1)
-+ return (-1);
-+ }
-+ p->capa.neg.grestart.flags[i] &= ~CAPA_GR_RESTARTING;
-+ }
-+ return (0);
-+}
-+
-+int
- session_dispatch_msg(struct pollfd *pfd, struct peer *p)
- {
-- ssize_t n, rpos, av, left;
-+ ssize_t n;
- socklen_t len;
-- int error, processed = 0;
-- u_int16_t msglen;
-- u_int8_t msgtype;
-+ int error;
-
- if (p->state == STATE_CONNECT) {
- if (pfd->revents & POLLOUT) {
-@@ -1641,71 +1843,83 @@ session_dispatch_msg(struct pollfd *pfd,
- return (1);
- }
-
-- rpos = 0;
-- av = p->rbuf->wpos + n;
-+ p->rbuf->wpos += n;
- p->stats.last_read = time(NULL);
-+ return (1);
-+ }
-+ return (0);
-+}
-
-- /*
-- * session might drop to IDLE -> buffers deallocated
-- * we MUST check rbuf != NULL before use
-- */
-- for (;;) {
-- if (rpos + MSGSIZE_HEADER > av)
-- break;
-- if (p->rbuf == NULL)
-- break;
-- if (parse_header(p, p->rbuf->buf + rpos, &msglen,
-- &msgtype) == -1)
-- return (0);
-- if (rpos + msglen > av)
-- break;
-- p->rbuf->rptr = p->rbuf->buf + rpos;
--
-- switch (msgtype) {
-- case OPEN:
-- bgp_fsm(p, EVNT_RCVD_OPEN);
-- p->stats.msg_rcvd_open++;
-- break;
-- case UPDATE:
-- bgp_fsm(p, EVNT_RCVD_UPDATE);
-- p->stats.msg_rcvd_update++;
-- break;
-- case NOTIFICATION:
-- bgp_fsm(p, EVNT_RCVD_NOTIFICATION);
-- p->stats.msg_rcvd_notification++;
-- break;
-- case KEEPALIVE:
-- bgp_fsm(p, EVNT_RCVD_KEEPALIVE);
-- p->stats.msg_rcvd_keepalive++;
-- break;
-- case RREFRESH:
-- parse_refresh(p);
-- p->stats.msg_rcvd_rrefresh++;
-- break;
-- default: /* cannot happen */
-- session_notification(p, ERR_HEADER,
-- ERR_HDR_TYPE, &msgtype, 1);
-- log_warnx("received message with "
-- "unknown type %u", msgtype);
-- bgp_fsm(p, EVNT_CON_FATAL);
-- }
-- rpos += msglen;
-- if (++processed > MSG_PROCESS_LIMIT)
-- break;
-- }
-- if (p->rbuf == NULL)
-- return (1);
-+int
-+session_process_msg(struct peer *p)
-+{
-+ ssize_t rpos, av, left;
-+ int processed = 0;
-+ u_int16_t msglen;
-+ u_int8_t msgtype;
-
-- if (rpos < av) {
-- left = av - rpos;
-- memcpy(&p->rbuf->buf, p->rbuf->buf + rpos, left);
-- p->rbuf->wpos = left;
-- } else
-- p->rbuf->wpos = 0;
-+ rpos = 0;
-+ av = p->rbuf->wpos;
-
-- return (1);
-+ /*
-+ * session might drop to IDLE -> buffers deallocated
-+ * we MUST check rbuf != NULL before use
-+ */
-+ for (;;) {
-+ if (rpos + MSGSIZE_HEADER > av)
-+ break;
-+ if (p->rbuf == NULL)
-+ break;
-+ if (parse_header(p, p->rbuf->buf + rpos, &msglen,
-+ &msgtype) == -1)
-+ return (0);
-+ if (rpos + msglen > av)
-+ break;
-+ p->rbuf->rptr = p->rbuf->buf + rpos;
-+
-+ switch (msgtype) {
-+ case OPEN:
-+ bgp_fsm(p, EVNT_RCVD_OPEN);
-+ p->stats.msg_rcvd_open++;
-+ break;
-+ case UPDATE:
-+ bgp_fsm(p, EVNT_RCVD_UPDATE);
-+ p->stats.msg_rcvd_update++;
-+ break;
-+ case NOTIFICATION:
-+ bgp_fsm(p, EVNT_RCVD_NOTIFICATION);
-+ p->stats.msg_rcvd_notification++;
-+ break;
-+ case KEEPALIVE:
-+ bgp_fsm(p, EVNT_RCVD_KEEPALIVE);
-+ p->stats.msg_rcvd_keepalive++;
-+ break;
-+ case RREFRESH:
-+ parse_refresh(p);
-+ p->stats.msg_rcvd_rrefresh++;
-+ break;
-+ default: /* cannot happen */
-+ session_notification(p, ERR_HEADER, ERR_HDR_TYPE,
-+ &msgtype, 1);
-+ log_warnx("received message with unknown type %u",
-+ msgtype);
-+ bgp_fsm(p, EVNT_CON_FATAL);
-+ }
-+ rpos += msglen;
-+ if (++processed > MSG_PROCESS_LIMIT)
-+ break;
- }
-- return (0);
-+ if (p->rbuf == NULL)
-+ return (1);
-+
-+ if (rpos < av) {
-+ left = av - rpos;
-+ memcpy(&p->rbuf->buf, p->rbuf->buf + rpos, left);
-+ p->rbuf->wpos = left;
-+ } else
-+ p->rbuf->wpos = 0;
-+
-+ return (1);
- }
-
- int
-@@ -1853,12 +2067,6 @@ parse_open(struct peer *peer)
- p += sizeof(short_as);
- as = peer->short_as = ntohs(short_as);
-
-- /* if remote-as is zero and it's a cloned neighbor, accept any */
-- if (peer->conf.cloned && !peer->conf.remote_as && as != AS_TRANS) {
-- peer->conf.remote_as = as;
-- peer->conf.ebgp = (peer->conf.remote_as != conf->as);
-- }
--
- memcpy(&oholdtime, p, sizeof(oholdtime));
- p += sizeof(oholdtime);
-
-@@ -1966,6 +2174,15 @@ parse_open(struct peer *peer)
- }
- }
-
-+ /* if remote-as is zero and it's a cloned neighbor, accept any */
-+ if (peer->conf.cloned && !peer->conf.remote_as && as != AS_TRANS) {
-+ peer->conf.remote_as = as;
-+ peer->conf.ebgp = (peer->conf.remote_as != conf->as);
-+ if (!peer->conf.ebgp)
-+ /* force enforce_as off for iBGP sessions */
-+ peer->conf.enforce_as = ENFORCE_AS_OFF;
-+ }
-+
- if (peer->conf.remote_as != as) {
- log_peer_warnx(&peer->conf, "peer sent wrong AS %s",
- log_as(as));
-@@ -1974,6 +2191,14 @@ parse_open(struct peer *peer)
- return (-1);
- }
-
-+ if (capa_neg_calc(peer) == -1) {
-+ log_peer_warnx(&peer->conf,
-+ "capability negotiation calculation failed");
-+ session_notification(peer, ERR_OPEN, 0, NULL, 0);
-+ change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN);
-+ return (-1);
-+ }
-+
- return (0);
- }
-
-@@ -2008,24 +2233,35 @@ int
- parse_refresh(struct peer *peer)
- {
- u_char *p;
-- struct rrefresh r;
-+ u_int16_t afi;
-+ u_int8_t aid, safi;
-
- p = peer->rbuf->rptr;
- p += MSGSIZE_HEADER; /* header is already checked */
-
-+ /*
-+ * We could check if we actually announced the capability but
-+ * as long as the message is correctly encoded we don't care.
-+ */
-+
- /* afi, 2 byte */
-- memcpy(&r.afi, p, sizeof(r.afi));
-- r.afi = ntohs(r.afi);
-+ memcpy(&afi, p, sizeof(afi));
-+ afi = ntohs(afi);
- p += 2;
- /* reserved, 1 byte */
- p += 1;
- /* safi, 1 byte */
-- memcpy(&r.safi, p, sizeof(r.safi));
-+ memcpy(&safi, p, sizeof(safi));
-
- /* afi/safi unchecked - unrecognized values will be ignored anyway */
-+ if (afi2aid(afi, safi, &aid) == -1) {
-+ log_peer_warnx(&peer->conf, "peer sent bad refresh, "
-+ "invalid afi/safi pair");
-+ return (0);
-+ }
-
-- if (imsg_compose(ibuf_rde, IMSG_REFRESH, peer->conf.id, 0, -1, &r,
-- sizeof(r)) == -1)
-+ if (imsg_compose(ibuf_rde, IMSG_REFRESH, peer->conf.id, 0, -1, &aid,
-+ sizeof(aid)) == -1)
- return (-1);
-
- return (0);
-@@ -2035,11 +2271,12 @@ int
- parse_notification(struct peer *peer)
- {
- u_char *p;
-+ u_int16_t datalen;
- u_int8_t errcode;
- u_int8_t subcode;
-- u_int16_t datalen;
- u_int8_t capa_code;
- u_int8_t capa_len;
-+ u_int8_t i;
-
- /* just log */
- p = peer->rbuf->rptr;
-@@ -2059,7 +2296,7 @@ parse_notification(struct peer *peer)
- p += sizeof(subcode);
- datalen -= sizeof(subcode);
-
-- log_notification(peer, errcode, subcode, p, datalen);
-+ log_notification(peer, errcode, subcode, p, datalen, "received");
- peer->errcnt++;
-
- if (errcode == ERR_OPEN && subcode == ERR_OPEN_CAPA) {
-@@ -2094,8 +2331,8 @@ parse_notification(struct peer *peer)
- datalen -= capa_len;
- switch (capa_code) {
- case CAPA_MP:
-- peer->capa.ann.mp_v4 = SAFI_NONE;
-- peer->capa.ann.mp_v6 = SAFI_NONE;
-+ for (i = 0; i < AID_MAX; i++)
-+ peer->capa.ann.mp[i] = 0;
- log_peer_warnx(&peer->conf,
- "disabling multiprotocol capability");
- break;
-@@ -2105,7 +2342,7 @@ parse_notification(struct peer *peer)
- "disabling route refresh capability");
- break;
- case CAPA_RESTART:
-- peer->capa.ann.restart = 0;
-+ peer->capa.ann.grestart.restart = 0;
- log_peer_warnx(&peer->conf,
- "disabling restart capability");
- break;
-@@ -2139,19 +2376,23 @@ parse_notification(struct peer *peer)
- int
- parse_capabilities(struct peer *peer, u_char *d, u_int16_t dlen, u_int32_t *as)
- {
-+ u_char *capa_val;
-+ u_int32_t remote_as;
- u_int16_t len;
-+ u_int16_t afi;
-+ u_int16_t gr_header;
-+ u_int8_t safi;
-+ u_int8_t aid;
-+ u_int8_t gr_flags;
- u_int8_t capa_code;
- u_int8_t capa_len;
-- u_char *capa_val;
-- u_int16_t mp_afi;
-- u_int8_t mp_safi;
-- u_int32_t remote_as;
-+ u_int8_t i;
-
- len = dlen;
- while (len > 0) {
- if (len < 2) {
-- log_peer_warnx(&peer->conf, "parse_capabilities: "
-- "expect len >= 2, len is %u", len);
-+ log_peer_warnx(&peer->conf, "Bad capabilities attr "
-+ "length: %u, too short", len);
- return (-1);
- }
- memcpy(&capa_code, d, sizeof(capa_code));
-@@ -2163,7 +2404,7 @@ parse_capabilities(struct peer *peer, u_
- if (capa_len > 0) {
- if (len < capa_len) {
- log_peer_warnx(&peer->conf,
-- "parse_capabilities: "
-+ "Bad capabilities attr length: "
- "len %u smaller than capa_len %u",
- len, capa_len);
- return (-1);
-@@ -2178,47 +2419,82 @@ parse_capabilities(struct peer *peer, u_
- case CAPA_MP: /* RFC 4760 */
- if (capa_len != 4) {
- log_peer_warnx(&peer->conf,
-- "parse_capabilities: "
-- "expect len 4, len is %u", capa_len);
-- return (-1);
-- }
-- memcpy(&mp_afi, capa_val, sizeof(mp_afi));
-- mp_afi = ntohs(mp_afi);
-- memcpy(&mp_safi, capa_val + 3, sizeof(mp_safi));
-- switch (mp_afi) {
-- case AFI_IPv4:
-- if (mp_safi < 1 || mp_safi > 3)
-- log_peer_warnx(&peer->conf,
-- "parse_capabilities: AFI IPv4, "
-- "mp_safi %u unknown", mp_safi);
-- else
-- peer->capa.peer.mp_v4 = mp_safi;
-+ "Bad multi protocol capability length: "
-+ "%u", capa_len);
- break;
-- case AFI_IPv6:
-- if (mp_safi < 1 || mp_safi > 3)
-- log_peer_warnx(&peer->conf,
-- "parse_capabilities: AFI IPv6, "
-- "mp_safi %u unknown", mp_safi);
-- else
-- peer->capa.peer.mp_v6 = mp_safi;
-- break;
-- default: /* ignore */
-+ }
-+ memcpy(&afi, capa_val, sizeof(afi));
-+ afi = ntohs(afi);
-+ memcpy(&safi, capa_val + 3, sizeof(safi));
-+ if (afi2aid(afi, safi, &aid) == -1) {
-+ log_peer_warnx(&peer->conf,
-+ "Received multi protocol capability: "
-+ " unknown AFI %u, safi %u pair",
-+ afi, safi);
- break;
- }
-+ peer->capa.peer.mp[aid] = 1;
- break;
- case CAPA_REFRESH:
- peer->capa.peer.refresh = 1;
- break;
- case CAPA_RESTART:
-- peer->capa.peer.restart = 1;
-- /* we don't care about the further restart capas yet */
-+ if (capa_len == 2) {
-+ /* peer only supports EoR marker */
-+ peer->capa.peer.grestart.restart = 1;
-+ peer->capa.peer.grestart.timeout = 0;
-+ break;
-+ } else if (capa_len % 4 != 2) {
-+ log_peer_warnx(&peer->conf,
-+ "Bad graceful restart capability length: "
-+ "%u", capa_len);
-+ peer->capa.peer.grestart.restart = 0;
-+ peer->capa.peer.grestart.timeout = 0;
-+ break;
-+ }
-+
-+ memcpy(&gr_header, capa_val, sizeof(gr_header));
-+ gr_header = ntohs(gr_header);
-+ peer->capa.peer.grestart.timeout =
-+ gr_header & CAPA_GR_TIMEMASK;
-+ if (peer->capa.peer.grestart.timeout == 0) {
-+ log_peer_warnx(&peer->conf, "Received "
-+ "graceful restart timeout is zero");
-+ peer->capa.peer.grestart.restart = 0;
-+ break;
-+ }
-+
-+ for (i = 2; i <= capa_len - 4; i += 4) {
-+ memcpy(&afi, capa_val + i, sizeof(afi));
-+ afi = ntohs(afi);
-+ memcpy(&safi, capa_val + i + 2, sizeof(safi));
-+ if (afi2aid(afi, safi, &aid) == -1) {
-+ log_peer_warnx(&peer->conf,
-+ "Received graceful restart capa: "
-+ " unknown AFI %u, safi %u pair",
-+ afi, safi);
-+ continue;
-+ }
-+ memcpy(&gr_flags, capa_val + i + 3,
-+ sizeof(gr_flags));
-+ peer->capa.peer.grestart.flags[aid] |=
-+ CAPA_GR_PRESENT;
-+ if (gr_flags & CAPA_GR_F_FLAG)
-+ peer->capa.peer.grestart.flags[aid] |=
-+ CAPA_GR_FORWARD;
-+ if (gr_header & CAPA_GR_R_FLAG)
-+ peer->capa.peer.grestart.flags[aid] |=
-+ CAPA_GR_RESTART;
-+ peer->capa.peer.grestart.restart = 2;
-+ }
- break;
- case CAPA_AS4BYTE:
- if (capa_len != 4) {
- log_peer_warnx(&peer->conf,
-- "parse_capabilities: "
-- "expect len 4, len is %u", capa_len);
-- return (-1);
-+ "Bad AS4BYTE capability length: "
-+ "%u", capa_len);
-+ peer->capa.peer.as4byte = 0;
-+ break;
- }
- memcpy(&remote_as, capa_val, sizeof(remote_as));
- *as = ntohl(remote_as);
-@@ -2232,6 +2508,66 @@ parse_capabilities(struct peer *peer, u_
- return (0);
- }
-
-+int
-+capa_neg_calc(struct peer *p)
-+{
-+ u_int8_t i, hasmp = 0;
-+
-+ /* refresh: does not realy matter here, use peer setting */
-+ p->capa.neg.refresh = p->capa.peer.refresh;
-+
-+ /* as4byte: both side must announce capability */
-+ if (p->capa.ann.as4byte && p->capa.peer.as4byte)
-+ p->capa.neg.as4byte = 1;
-+ else
-+ p->capa.neg.as4byte = 0;
-+
-+ /* MP: both side must announce capability */
-+ for (i = 0; i < AID_MAX; i++) {
-+ if (p->capa.ann.mp[i] && p->capa.peer.mp[i]) {
-+ p->capa.neg.mp[i] = 1;
-+ hasmp = 1;
-+ } else
-+ p->capa.neg.mp[i] = 0;
-+ }
-+ /* if no MP capability present default to IPv4 unicast mode */
-+ if (!hasmp)
-+ p->capa.neg.mp[AID_INET] = 1;
-+
-+ /*
-+ * graceful restart: only the peer capabilities are of interest here.
-+ * It is necessary to compare the new values with the previous ones
-+ * and act acordingly. AFI/SAFI that are not part in the MP capability
-+ * are treated as not being present.
-+ */
-+
-+ for (i = 0; i < AID_MAX; i++) {
-+ /* disable GR if the AFI/SAFI is not present */
-+ if (p->capa.peer.grestart.flags[i] & CAPA_GR_PRESENT &&
-+ p->capa.neg.mp[i] == 0)
-+ p->capa.peer.grestart.flags[i] = 0; /* disable */
-+ /* look at current GR state and decide what to do */
-+ if (p->capa.neg.grestart.flags[i] & CAPA_GR_RESTARTING) {
-+ if (!(p->capa.peer.grestart.flags[i] &
-+ CAPA_GR_FORWARD)) {
-+ if (imsg_compose(ibuf_rde, IMSG_SESSION_FLUSH,
-+ p->conf.id, 0, -1, &i, sizeof(i)) == -1)
-+ return (-1);
-+ log_peer_warnx(&p->conf, "graceful restart of "
-+ "%s, not restarted, flushing", aid2str(i));
-+ }
-+ p->capa.neg.grestart.flags[i] =
-+ p->capa.peer.grestart.flags[i] | CAPA_GR_RESTARTING;
-+ } else
-+ p->capa.neg.grestart.flags[i] =
-+ p->capa.peer.grestart.flags[i];
-+ }
-+ p->capa.neg.grestart.timeout = p->capa.peer.grestart.timeout;
-+ p->capa.neg.grestart.restart = p->capa.peer.grestart.restart;
-+
-+ return (0);
-+}
-+
- void
- session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
- {
-@@ -2244,8 +2580,8 @@ session_dispatch_imsg(struct imsgbuf *ib
- struct kif *kif;
- u_char *data;
- enum reconf_action reconf;
-- int n, depend_ok;
-- u_int8_t errcode, subcode;
-+ int n, depend_ok, restricted;
-+ u_int8_t aid, errcode, subcode;
-
- if ((n = imsg_read(ibuf)) == -1)
- fatal("session_dispatch_imsg: imsg_read error");
-@@ -2332,15 +2668,42 @@ session_dispatch_imsg(struct imsgbuf *ib
- }
-
- break;
-+ case IMSG_RECONF_CTRL:
-+ if (idx != PFD_PIPE_MAIN)
-+ fatalx("reconf request not from parent");
-+ if (imsg.hdr.len != IMSG_HEADER_SIZE +
-+ sizeof(restricted))
-+ fatalx("IFINFO imsg with wrong len");
-+ memcpy(&restricted, imsg.data, sizeof(restricted));
-+ if (imsg.fd == -1) {
-+ log_warnx("expected to receive fd for control "
-+ "socket but didn't receive any");
-+ break;
-+ }
-+ if (restricted) {
-+ control_shutdown(rcsock);
-+ rcsock = imsg.fd;
-+ control_listen(rcsock);
-+ } else {
-+ control_shutdown(csock);
-+ csock = imsg.fd;
-+ control_listen(csock);
-+ }
-+ break;
- case IMSG_RECONF_DONE:
- if (idx != PFD_PIPE_MAIN)
- fatalx("reconf request not from parent");
- if (nconf == NULL)
- fatalx("got IMSG_RECONF_DONE but no config");
-+ conf->flags = nconf->flags;
-+ conf->log = nconf->log;
-+ conf->bgpid = nconf->bgpid;
-+ conf->clusterid = nconf->clusterid;
- conf->as = nconf->as;
-+ conf->short_as = nconf->short_as;
- conf->holdtime = nconf->holdtime;
-- conf->bgpid = nconf->bgpid;
- conf->min_holdtime = nconf->min_holdtime;
-+ conf->connectretry = nconf->connectretry;
-
- /* add new peers */
- for (p = npeers; p != NULL; p = next) {
-@@ -2388,6 +2751,8 @@ session_dispatch_imsg(struct imsgbuf *ib
- nconf = NULL;
- pending_reconf = 0;
- log_info("SE reconfigured");
-+ imsg_compose(ibuf_main, IMSG_RECONF_DONE, 0, 0,
-+ -1, NULL, 0);
- break;
- case IMSG_IFINFO:
- if (idx != PFD_PIPE_MAIN)
-@@ -2397,9 +2762,7 @@ session_dispatch_imsg(struct imsgbuf *ib
- fatalx("IFINFO imsg with wrong len");
- kif = imsg.data;
- depend_ok = (kif->flags & IFF_UP) &&
-- (LINK_STATE_IS_UP(kif->link_state) ||
-- (kif->link_state == LINK_STATE_UNKNOWN &&
-- kif->media_type != IFT_CARP));
-+ LINK_STATE_IS_UP(kif->link_state);
-
- for (p = peers; p != NULL; p = p->next)
- if (!strcmp(p->conf.if_depend, kif->ifname)) {
-@@ -2408,7 +2771,8 @@ session_dispatch_imsg(struct imsgbuf *ib
- bgp_fsm(p, EVNT_START);
- } else if (!depend_ok && p->depend_ok) {
- p->depend_ok = depend_ok;
-- bgp_fsm(p, EVNT_STOP);
-+ session_stop(p,
-+ ERR_CEASE_OTHER_CHANGE);
- }
- }
- break;
-@@ -2456,10 +2820,10 @@ session_dispatch_imsg(struct imsgbuf *ib
- }
- break;
- case IMSG_CTL_KROUTE:
-- case IMSG_CTL_KROUTE6:
- 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_MAIN)
- fatalx("ctl kroute request not from parent");
- control_imsg_relay(&imsg);
-@@ -2469,7 +2833,6 @@ session_dispatch_imsg(struct imsgbuf *ib
- case IMSG_CTL_SHOW_RIB_ATTR:
- case IMSG_CTL_SHOW_RIB_MEM:
- case IMSG_CTL_SHOW_NETWORK:
-- case IMSG_CTL_SHOW_NETWORK6:
- case IMSG_CTL_SHOW_NEIGHBOR:
- if (idx != PFD_PIPE_ROUTE_CTL)
- fatalx("ctl rib request not from RDE");
-@@ -2531,6 +2894,40 @@ session_dispatch_imsg(struct imsgbuf *ib
- break;
- }
- break;
-+ case IMSG_SESSION_RESTARTED:
-+ if (idx != PFD_PIPE_ROUTE)
-+ fatalx("update request not from RDE");
-+ if (imsg.hdr.len < IMSG_HEADER_SIZE + sizeof(aid)) {
-+ log_warnx("RDE sent invalid restart msg");
-+ break;
-+ }
-+ if ((p = getpeerbyid(imsg.hdr.peerid)) == NULL) {
-+ log_warnx("no such peer: id=%u",
-+ imsg.hdr.peerid);
-+ break;
-+ }
-+ memcpy(&aid, imsg.data, sizeof(aid));
-+ if (aid >= AID_MAX)
-+ fatalx("IMSG_SESSION_RESTARTED: bad AID");
-+ if (p->capa.neg.grestart.flags[aid] &
-+ CAPA_GR_RESTARTING &&
-+ p->capa.neg.grestart.flags[aid] &
-+ CAPA_GR_FORWARD) {
-+ log_peer_warnx(&p->conf,
-+ "graceful restart of %s finished",
-+ aid2str(aid));
-+ p->capa.neg.grestart.flags[aid] &=
-+ ~CAPA_GR_RESTARTING;
-+ timer_stop(p, Timer_RestartTimeout);
-+
-+ /* signal back to RDE to cleanup stale routes */
-+ if (imsg_compose(ibuf_rde,
-+ IMSG_SESSION_RESTARTED, imsg.hdr.peerid, 0,
-+ -1, &aid, sizeof(aid)) == -1)
-+ fatal("imsg_compose: "
-+ "IMSG_SESSION_RESTARTED");
-+ }
-+ break;
- default:
- break;
- }
-@@ -2612,29 +3009,23 @@ getpeerbydesc(const char *descr)
- struct peer *
- getpeerbyip(struct sockaddr *ip)
- {
-+ struct bgpd_addr addr;
- struct peer *p, *newpeer, *loose = NULL;
- u_int32_t id;
-
-+ sa2addr(ip, &addr);
-+
- /* we might want a more effective way to find peers by IP */
- for (p = peers; p != NULL; p = p->next)
- if (!p->conf.template &&
-- p->conf.remote_addr.af == ip->sa_family) {
-- if (p->conf.remote_addr.af == AF_INET &&
-- p->conf.remote_addr.v4.s_addr ==
-- ((struct sockaddr_in *)ip)->sin_addr.s_addr)
-- return (p);
-- if (p->conf.remote_addr.af == AF_INET6 &&
-- !bcmp(&p->conf.remote_addr.v6,
-- &((struct sockaddr_in6 *)ip)->sin6_addr,
-- sizeof(p->conf.remote_addr.v6)))
-- return (p);
-- }
-+ !memcmp(&addr, &p->conf.remote_addr, sizeof(addr)))
-+ return (p);
-
- /* try template matching */
- for (p = peers; p != NULL; p = p->next)
- if (p->conf.template &&
-- p->conf.remote_addr.af == ip->sa_family &&
-- session_match_mask(p, ip))
-+ p->conf.remote_addr.aid == addr.aid &&
-+ session_match_mask(p, &addr))
- if (loose == NULL || loose->conf.remote_masklen <
- p->conf.remote_masklen)
- loose = p;
-@@ -2653,21 +3044,19 @@ getpeerbyip(struct sockaddr *ip)
- break;
- }
- }
-- if (newpeer->conf.remote_addr.af == AF_INET) {
-- newpeer->conf.remote_addr.v4.s_addr =
-- ((struct sockaddr_in *)ip)->sin_addr.s_addr;
-+ sa2addr(ip, &newpeer->conf.remote_addr);
-+ switch (ip->sa_family) {
-+ case AF_INET:
- newpeer->conf.remote_masklen = 32;
-- }
-- if (newpeer->conf.remote_addr.af == AF_INET6) {
-- memcpy(&p->conf.remote_addr.v6,
-- &((struct sockaddr_in6 *)ip)->sin6_addr,
-- sizeof(newpeer->conf.remote_addr.v6));
-+ break;
-+ case AF_INET6:
- newpeer->conf.remote_masklen = 128;
-+ break;
- }
- newpeer->conf.template = 0;
- newpeer->conf.cloned = 1;
- newpeer->state = newpeer->prev_state = STATE_NONE;
-- newpeer->conf.reconf_action = RECONF_REINIT;
-+ newpeer->conf.reconf_action = RECONF_KEEP;
- newpeer->rbuf = NULL;
- init_peer(newpeer);
- bgp_fsm(newpeer, EVNT_START);
-@@ -2680,40 +3069,24 @@ getpeerbyip(struct sockaddr *ip)
- }
-
- int
--session_match_mask(struct peer *p, struct sockaddr *ip)
-+session_match_mask(struct peer *p, struct bgpd_addr *a)
- {
-- int i;
- in_addr_t v4mask;
-- struct in6_addr *in;
-- struct in6_addr mask;
-+ struct in6_addr masked;
-
-- if (p->conf.remote_addr.af == AF_INET) {
-+ switch (p->conf.remote_addr.aid) {
-+ case AID_INET:
- v4mask = htonl(prefixlen2mask(p->conf.remote_masklen));
-- if (p->conf.remote_addr.v4.s_addr ==
-- ((((struct sockaddr_in *)ip)->sin_addr.s_addr) & v4mask))
-+ if (p->conf.remote_addr.v4.s_addr == (a->v4.s_addr & v4mask))
- return (1);
-- else
-- return (0);
-- }
--
-- if (p->conf.remote_addr.af == AF_INET6) {
-- bzero(&mask, sizeof(mask));
-- for (i = 0; i < p->conf.remote_masklen / 8; i++)
-- mask.s6_addr[i] = 0xff;
-- i = p->conf.remote_masklen % 8;
-- if (i)
-- mask.s6_addr[p->conf.remote_masklen / 8] = 0xff00 >> i;
--
-- in = &((struct sockaddr_in6 *)ip)->sin6_addr;
--
-- for (i = 0; i < 16; i++)
-- if ((in->s6_addr[i] & mask.s6_addr[i]) !=
-- p->conf.remote_addr.addr8[i])
-- return (0);
-+ return (0);
-+ case AID_INET6:
-+ inet6applymask(&masked, &a->v6, p->conf.remote_masklen);
-
-- return (1);
-+ if (!memcmp(&masked, &p->conf.remote_addr.v6, sizeof(masked)))
-+ return (1);
-+ return (0);
- }
--
- return (0);
- }
-
-@@ -2733,6 +3106,7 @@ getpeerbyid(u_int32_t peerid)
- void
- session_down(struct peer *peer)
- {
-+ bzero(&peer->capa.neg, sizeof(peer->capa.neg));
- peer->stats.last_updown = time(NULL);
- if (imsg_compose(ibuf_rde, IMSG_SESSION_DOWN, peer->conf.id, 0, -1,
- NULL, 0) == -1)
-@@ -2744,39 +3118,17 @@ session_up(struct peer *p)
- {
- struct session_up sup;
-
-- if (imsg_compose(ibuf_rde, IMSG_SESSION_ADD, p->conf.id, 0, -1,
-- &p->conf, sizeof(p->conf)) == -1)
-- fatalx("imsg_compose error");
-+ if (!session_graceful_is_restarting(p))
-+ if (imsg_compose(ibuf_rde, IMSG_SESSION_ADD, p->conf.id, 0, -1,
-+ &p->conf, sizeof(p->conf)) == -1)
-+ fatalx("imsg_compose error");
-
-- switch (p->sa_local.ss_family) {
-- case AF_INET:
-- sup.local_addr.af = AF_INET;
-- memcpy(&sup.local_addr.v4,
-- &((struct sockaddr_in *)&p->sa_local)->sin_addr,
-- sizeof(sup.local_addr.v4));
-- sup.remote_addr.af = AF_INET;
-- memcpy(&sup.remote_addr.v4,
-- &((struct sockaddr_in *)&p->sa_remote)->sin_addr,
-- sizeof(sup.remote_addr.v4));
-- break;
-- case AF_INET6:
-- sup.local_addr.af = AF_INET6;
-- memcpy(&sup.local_addr.v6,
-- &((struct sockaddr_in6 *)&p->sa_local)->sin6_addr,
-- sizeof(sup.local_addr.v6));
-- sup.remote_addr.af = AF_INET6;
-- memcpy(&sup.remote_addr.v6,
-- &((struct sockaddr_in6 *)&p->sa_remote)->sin6_addr,
-- sizeof(sup.remote_addr.v6));
-- break;
-- default:
-- fatalx("session_up: unsupported address family");
-- }
-+ sa2addr((struct sockaddr *)&p->sa_local, &sup.local_addr);
-+ sa2addr((struct sockaddr *)&p->sa_remote, &sup.remote_addr);
-
- sup.remote_bgpid = p->remote_bgpid;
- sup.short_as = p->short_as;
-- memcpy(&sup.capa_announced, &p->capa.ann, sizeof(sup.capa_announced));
-- memcpy(&sup.capa_received, &p->capa.peer, sizeof(sup.capa_received));
-+ memcpy(&sup.capa, &p->capa.neg, sizeof(sup.capa));
- p->stats.last_updown = time(NULL);
- if (imsg_compose(ibuf_rde, IMSG_SESSION_UP, p->conf.id, 0, -1,
- &sup, sizeof(sup)) == -1)
-@@ -2784,9 +3136,10 @@ session_up(struct peer *p)
- }
-
- int
--imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen)
-+imsg_compose_parent(int type, u_int32_t peerid, pid_t pid, void *data,
-+ u_int16_t datalen)
- {
-- return (imsg_compose(ibuf_main, type, 0, pid, -1, data, datalen));
-+ return (imsg_compose(ibuf_main, type, peerid, pid, -1, data, datalen));
- }
-
- int
-@@ -2795,34 +3148,6 @@ imsg_compose_rde(int type, pid_t pid, vo
- return (imsg_compose(ibuf_rde, type, 0, pid, -1, data, datalen));
- }
-
--static 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;
--
-- bzero(&ss, sizeof(ss));
-- switch (addr->af) {
-- case AF_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 AF_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
- session_demote(struct peer *p, int level)
- {
-@@ -2837,3 +3162,19 @@ session_demote(struct peer *p, int level
-
- p->demoted += level;
- }
-+
-+void
-+session_stop(struct peer *peer, u_int8_t subcode)
-+{
-+ switch (peer->state) {
-+ case STATE_OPENSENT:
-+ case STATE_OPENCONFIRM:
-+ case STATE_ESTABLISHED:
-+ session_notification(peer, ERR_CEASE, subcode, NULL, 0);
-+ break;
-+ default:
-+ /* session not open, no need to send notification */
-+ break;
-+ }
-+ bgp_fsm(peer, EVNT_STOP);
-+}
diff --git a/net/openbgpd/files/patch-bgpd_session.h b/net/openbgpd/files/patch-bgpd_session.h
deleted file mode 100644
index 6ffbd79abd1f..000000000000
--- a/net/openbgpd/files/patch-bgpd_session.h
+++ /dev/null
@@ -1,188 +0,0 @@
-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 *);
diff --git a/net/openbgpd/files/patch-bgpd_timer.c b/net/openbgpd/files/patch-bgpd_timer.c
deleted file mode 100644
index 1238897b94fa..000000000000
--- a/net/openbgpd/files/patch-bgpd_timer.c
+++ /dev/null
@@ -1,32 +0,0 @@
-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);
- }
diff --git a/net/openbgpd/files/patch-bgpd_util.c b/net/openbgpd/files/patch-bgpd_util.c
deleted file mode 100644
index 54e74ec9805f..000000000000
--- a/net/openbgpd/files/patch-bgpd_util.c
+++ /dev/null
@@ -1,440 +0,0 @@
-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;
-+ }
-+}
diff --git a/net/openbgpd/files/patch-openbsd-compat_fmt_scaled.c b/net/openbgpd/files/patch-openbsd-compat_fmt_scaled.c
deleted file mode 100644
index 65407211cbc8..000000000000
--- a/net/openbgpd/files/patch-openbsd-compat_fmt_scaled.c
+++ /dev/null
@@ -1,275 +0,0 @@
-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
diff --git a/net/openbgpd/files/patch-openbsd-compat_hash.h b/net/openbgpd/files/patch-openbsd-compat_hash.h
deleted file mode 100644
index 0ca34733d041..000000000000
--- a/net/openbgpd/files/patch-openbsd-compat_hash.h
+++ /dev/null
@@ -1,134 +0,0 @@
-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_ */
diff --git a/net/openbgpd/files/patch-openbsd-compat_if_media.h b/net/openbgpd/files/patch-openbsd-compat_if_media.h
deleted file mode 100644
index ffd56e0cd429..000000000000
--- a/net/openbgpd/files/patch-openbsd-compat_if_media.h
+++ /dev/null
@@ -1,619 +0,0 @@
-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_ */
diff --git a/net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c b/net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c
deleted file mode 100644
index 3db0ec22abe8..000000000000
--- a/net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c
+++ /dev/null
@@ -1,312 +0,0 @@
-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);
-+}
diff --git a/net/openbgpd/files/patch-openbsd-compat_imsg.c b/net/openbgpd/files/patch-openbsd-compat_imsg.c
deleted file mode 100644
index c23d5aa22060..000000000000
--- a/net/openbgpd/files/patch-openbsd-compat_imsg.c
+++ /dev/null
@@ -1,312 +0,0 @@
-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);
-+}
diff --git a/net/openbgpd/files/patch-openbsd-compat_imsg.h b/net/openbgpd/files/patch-openbsd-compat_imsg.h
deleted file mode 100644
index 91cf15ea1afd..000000000000
--- a/net/openbgpd/files/patch-openbsd-compat_imsg.h
+++ /dev/null
@@ -1,119 +0,0 @@
-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
diff --git a/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h b/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h
deleted file mode 100644
index 3855a8dd3f95..000000000000
--- a/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h
+++ /dev/null
@@ -1,98 +0,0 @@
-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 */
diff --git a/net/openbgpd/files/patch-openbsd-compat_util.h b/net/openbgpd/files/patch-openbsd-compat_util.h
deleted file mode 100644
index c2de585e338a..000000000000
--- a/net/openbgpd/files/patch-openbsd-compat_util.h
+++ /dev/null
@@ -1,126 +0,0 @@
-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_ */