aboutsummaryrefslogtreecommitdiffstats
path: root/net/openbgpd
diff options
context:
space:
mode:
authorhrs <hrs@FreeBSD.org>2012-10-14 03:40:42 +0800
committerhrs <hrs@FreeBSD.org>2012-10-14 03:40:42 +0800
commita61a5365ead208ada00d675357bae14f88cc400e (patch)
treee533d59b6703e89ff55f633cba2f2285d9b30e49 /net/openbgpd
parent11da10bd17c8f611d96a63b2d277fc92ff522503 (diff)
downloadfreebsd-ports-gnome-a61a5365ead208ada00d675357bae14f88cc400e.tar.gz
freebsd-ports-gnome-a61a5365ead208ada00d675357bae14f88cc400e.tar.zst
freebsd-ports-gnome-a61a5365ead208ada00d675357bae14f88cc400e.zip
Update to 5.2.20121014.
Feature safe: yes
Diffstat (limited to 'net/openbgpd')
-rw-r--r--net/openbgpd/Makefile14
-rw-r--r--net/openbgpd/files/patch-bgpctl_Makefile9
-rw-r--r--net/openbgpd/files/patch-bgpctl_bgpctl.8182
-rw-r--r--net/openbgpd/files/patch-bgpctl_bgpctl.c899
-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.c17
-rw-r--r--net/openbgpd/files/patch-bgpctl_irr_prefix.c8
-rw-r--r--net/openbgpd/files/patch-bgpctl_irrfilter.c12
-rw-r--r--net/openbgpd/files/patch-bgpctl_irrfilter.h8
-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.c212
-rw-r--r--net/openbgpd/files/patch-bgpctl_parser.h25
-rw-r--r--net/openbgpd/files/patch-bgpctl_whois.c12
-rw-r--r--net/openbgpd/files/patch-bgpd_Makefile13
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.8280
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.c100
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.conf.5160
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.h314
-rw-r--r--net/openbgpd/files/patch-bgpd_carp.c5
-rw-r--r--net/openbgpd/files/patch-bgpd_config.c8
-rw-r--r--net/openbgpd/files/patch-bgpd_control.c49
-rw-r--r--net/openbgpd/files/patch-bgpd_kroute.c716
-rw-r--r--net/openbgpd/files/patch-bgpd_log.c36
-rw-r--r--net/openbgpd/files/patch-bgpd_log.h39
-rw-r--r--net/openbgpd/files/patch-bgpd_mrt.c423
-rw-r--r--net/openbgpd/files/patch-bgpd_mrt.h253
-rw-r--r--net/openbgpd/files/patch-bgpd_name2id.c14
-rw-r--r--net/openbgpd/files/patch-bgpd_parse.y204
-rw-r--r--net/openbgpd/files/patch-bgpd_pfkey.c8
-rw-r--r--net/openbgpd/files/patch-bgpd_pftable.c12
-rw-r--r--net/openbgpd/files/patch-bgpd_printconf.c40
-rw-r--r--net/openbgpd/files/patch-bgpd_rde.c598
-rw-r--r--net/openbgpd/files/patch-bgpd_rde.h187
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_attr.c195
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_decide.c94
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_filter.c27
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_prefix.c8
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_rib.c254
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_update.c42
-rw-r--r--net/openbgpd/files/patch-bgpd_session.c888
-rw-r--r--net/openbgpd/files/patch-bgpd_session.h139
-rw-r--r--net/openbgpd/files/patch-bgpd_timer.c17
-rw-r--r--net/openbgpd/files/patch-bgpd_util.c147
-rw-r--r--net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h10
46 files changed, 6464 insertions, 1341 deletions
diff --git a/net/openbgpd/Makefile b/net/openbgpd/Makefile
index c4793d40fffc..cdf52e324282 100644
--- a/net/openbgpd/Makefile
+++ b/net/openbgpd/Makefile
@@ -1,13 +1,8 @@
-# New ports collection makefile for: openbgpd
-# Date created: May 10 2005
-# Whom: Florent Thoumie <flz@FreeBSD.org>
-#
+# Created by: Florent Thoumie <flz@FreeBSD.org>
# $FreeBSD$
-#
PORTNAME= openbgpd
-PORTVERSION= 4.9.20110612
-PORTREVISION= 1
+PORTVERSION= 5.2.20121014
CATEGORIES= net
MASTER_SITES= ${MASTER_SITE_OPENBSD}
MASTER_SITE_SUBDIR= OpenBGPD
@@ -20,8 +15,9 @@ COMMENT= Free implementation of the Border Gateway Protocol, Version 4
CONFLICTS= zebra-[0-9]* quagga-[0-9]*
-OPTIONS= IPV6LLPEER \
- "Support nexthop using IPv6 link-local address" on
+OPTIONS_DEFINE= IPV6LLPEER
+OPTIONS_DEFAULT=IPV6LLPEER
+IPV6LLPEER_DESC=Support nexthop using IPv6 link-local address
.include <bsd.port.pre.mk>
diff --git a/net/openbgpd/files/patch-bgpctl_Makefile b/net/openbgpd/files/patch-bgpctl_Makefile
index faca1083ecf9..572c0fcb8362 100644
--- a/net/openbgpd/files/patch-bgpctl_Makefile
+++ b/net/openbgpd/files/patch-bgpctl_Makefile
@@ -2,10 +2,10 @@ Index: bgpctl/Makefile
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/Makefile,v
retrieving revision 1.1.1.1
-retrieving revision 1.3
-diff -u -p -r1.1.1.1 -r1.3
+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 2 Jul 2011 16:06:35 -0000 1.3
++++ 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 $
@@ -16,7 +16,8 @@ diff -u -p -r1.1.1.1 -r1.3
-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
++SRCS+= irr_parser.c mrtparser.c
+SRCS+= fmt_scaled.c imsg.c imsg-buffer.c
CFLAGS+= -Wall
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
diff --git a/net/openbgpd/files/patch-bgpctl_bgpctl.8 b/net/openbgpd/files/patch-bgpctl_bgpctl.8
index a5305b3061b1..2e08c575981e 100644
--- a/net/openbgpd/files/patch-bgpctl_bgpctl.8
+++ b/net/openbgpd/files/patch-bgpctl_bgpctl.8
@@ -2,13 +2,13 @@ Index: bgpctl/bgpctl.8
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/bgpctl.8,v
retrieving revision 1.1.1.6
-retrieving revision 1.5
-diff -u -p -r1.1.1.6 -r1.5
+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 2 Jul 2011 16:06:35 -0000 1.5
++++ 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.52 2009/11/03 08:09:15 jmc Exp $
++.\" $OpenBSD: bgpctl.8,v 1.59 2012/05/27 20:49:42 jmc Exp $
.\"
.\" Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
.\"
@@ -17,7 +17,7 @@ diff -u -p -r1.1.1.6 -r1.5
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: June 6 2009 $
-+.Dd $Mdocdate: May 3 2010 $
++.Dd $Mdocdate: May 27 2012 $
.Dt BGPCTL 8
.Os
.Sh NAME
@@ -71,7 +71,7 @@ diff -u -p -r1.1.1.6 -r1.5
.It Cm neighbor Ar peer Cm up
Take the BGP session to the specified neighbor up.
.Ar peer
-@@ -98,8 +113,10 @@ Note that the neighbor is not obliged to
+@@ -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.
@@ -83,7 +83,18 @@ diff -u -p -r1.1.1.6 -r1.5
.It Cm network delete Ar prefix
Remove the specified prefix from the list of announced networks.
.It Cm network flush
-@@ -122,7 +139,7 @@ view of the Forwarding Information Base.
+ 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
@@ -92,7 +103,7 @@ diff -u -p -r1.1.1.6 -r1.5
.It Cm connected
Show only connected routes.
.It Cm static
-@@ -133,6 +150,14 @@ Show only routes originating from
+@@ -133,9 +157,81 @@ Show only routes originating from
itself.
.It Cm nexthop
Show only routes required to reach a BGP nexthop.
@@ -107,7 +118,138 @@ diff -u -p -r1.1.1.6 -r1.5
.El
.It Cm show interfaces
Show the interface states.
-@@ -243,10 +268,12 @@ and message counters.
++.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.
@@ -121,3 +263,25 @@ diff -u -p -r1.1.1.6 -r1.5
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
index 4497b055410f..54006c76dff3 100644
--- a/net/openbgpd/files/patch-bgpctl_bgpctl.c
+++ b/net/openbgpd/files/patch-bgpctl_bgpctl.c
@@ -2,13 +2,12 @@ Index: bgpctl/bgpctl.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/bgpctl.c,v
retrieving revision 1.1.1.7
-retrieving revision 1.8
-diff -u -p -r1.1.1.7 -r1.8
+diff -u -p -r1.1.1.7 bgpctl.c
--- bgpctl/bgpctl.c 14 Feb 2010 20:20:14 -0000 1.1.1.7
-+++ bgpctl/bgpctl.c 2 Jul 2011 16:06:35 -0000 1.8
++++ bgpctl/bgpctl.c 13 Oct 2012 18:49:31 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpctl.c,v 1.142 2009/06/06 06:33:15 eric Exp $ */
-+/* $OpenBSD: bgpctl.c,v 1.157 2010/03/08 17:02:19 claudio Exp $ */
++/* $OpenBSD: bgpctl.c,v 1.165 2012/09/12 05:57:10 claudio Exp $ */
/*
* Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
@@ -44,23 +43,25 @@ diff -u -p -r1.1.1.7 -r1.8
#include "bgpd.h"
#include "session.h"
-@@ -38,6 +50,10 @@
+@@ -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,
- NV_TIMERS
-@@ -50,12 +66,13 @@ int show_summary_msg(struct imsg *, in
+@@ -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);
@@ -70,7 +71,7 @@ diff -u -p -r1.1.1.7 -r1.8
void show_network_head(void);
void show_fib_flags(u_int16_t);
int show_fib_msg(struct imsg *);
-@@ -65,7 +82,7 @@ void show_interface_head(void);
+@@ -65,7 +84,7 @@ void show_interface_head(void);
int ift2ifm(int);
const char * get_media_descr(int);
const char * get_linkstate(int, int);
@@ -79,15 +80,34 @@ diff -u -p -r1.1.1.7 -r1.8
int show_interface_msg(struct imsg *);
void show_rib_summary_head(void);
void print_prefix(struct bgpd_addr *, u_int8_t, u_int8_t);
-@@ -74,7 +91,6 @@ void print_flags(u_int8_t, int);
+@@ -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 *);
-@@ -98,7 +114,7 @@ int
+ 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;
@@ -96,7 +116,7 @@ diff -u -p -r1.1.1.7 -r1.8
struct imsg imsg;
struct network_config net;
struct parse_result *res;
-@@ -128,8 +144,11 @@ main(int argc, char *argv[])
+@@ -128,8 +156,11 @@ main(int argc, char *argv[])
if ((res = parse(argc, argv)) == NULL)
exit(1);
@@ -109,7 +129,16 @@ diff -u -p -r1.1.1.7 -r1.8
memcpy(&neighbor.addr, &res->peeraddr, sizeof(neighbor.addr));
strlcpy(neighbor.descr, res->peerdesc, sizeof(neighbor.descr));
-@@ -164,24 +183,32 @@ main(int argc, char *argv[])
+@@ -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:
@@ -151,7 +180,7 @@ diff -u -p -r1.1.1.7 -r1.8
show_nexthop_head();
break;
case SHOW_INTERFACE:
-@@ -192,7 +219,7 @@ main(int argc, char *argv[])
+@@ -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);
@@ -160,7 +189,7 @@ diff -u -p -r1.1.1.7 -r1.8
imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1,
&neighbor, sizeof(neighbor));
else
-@@ -206,7 +233,7 @@ main(int argc, char *argv[])
+@@ -206,7 +245,7 @@ main(int argc, char *argv[])
memcpy(&ribreq.as, &res->as, sizeof(res->as));
type = IMSG_CTL_SHOW_RIB_AS;
}
@@ -169,16 +198,46 @@ diff -u -p -r1.1.1.7 -r1.8
memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr));
ribreq.prefixlen = res->prefixlen;
type = IMSG_CTL_SHOW_RIB_PREFIX;
-@@ -220,7 +247,7 @@ main(int argc, char *argv[])
- memcpy(&ribreq.neighbor, &neighbor,
- sizeof(ribreq.neighbor));
+@@ -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))
-@@ -237,12 +264,14 @@ main(int argc, char *argv[])
+ 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:
@@ -195,7 +254,7 @@ diff -u -p -r1.1.1.7 -r1.8
printf("decouple request sent.\n");
done = 1;
break;
-@@ -290,12 +319,21 @@ main(int argc, char *argv[])
+@@ -290,12 +351,40 @@ main(int argc, char *argv[])
break;
case NETWORK_SHOW:
bzero(&ribreq, sizeof(ribreq));
@@ -206,6 +265,25 @@ diff -u -p -r1.1.1.7 -r1.8
&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 */
@@ -218,7 +296,7 @@ diff -u -p -r1.1.1.7 -r1.8
}
while (ibuf->w.queued)
-@@ -304,13 +342,13 @@ main(int argc, char *argv[])
+@@ -304,13 +393,13 @@ main(int argc, char *argv[])
while (!done) {
if ((n = imsg_read(ibuf)) == -1)
@@ -234,7 +312,7 @@ diff -u -p -r1.1.1.7 -r1.8
if (n == 0)
break;
-@@ -329,6 +367,8 @@ main(int argc, char *argv[])
+@@ -329,6 +418,8 @@ main(int argc, char *argv[])
done = show_summary_terse_msg(&imsg, nodescr);
break;
case SHOW_FIB:
@@ -243,7 +321,7 @@ diff -u -p -r1.1.1.7 -r1.8
done = show_fib_msg(&imsg);
break;
case SHOW_NEXTHOP:
-@@ -356,9 +396,6 @@ main(int argc, char *argv[])
+@@ -356,9 +447,6 @@ main(int argc, char *argv[])
case SHOW_RIB_MEM:
done = show_rib_memory_msg(&imsg);
break;
@@ -253,16 +331,18 @@ diff -u -p -r1.1.1.7 -r1.8
case NEIGHBOR:
case NEIGHBOR_UP:
case NEIGHBOR_DOWN:
-@@ -373,6 +410,8 @@ main(int argc, char *argv[])
+@@ -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 +437,8 @@ fmt_peer(const char *descr, const struct
+@@ -398,8 +490,8 @@ fmt_peer(const char *descr, const struct
}
ip = log_addr(remote_addr);
@@ -273,7 +353,27 @@ diff -u -p -r1.1.1.7 -r1.8
if (asprintf(&p, "%s/%u", ip, masklen) == -1)
err(1, NULL);
} else {
-@@ -521,13 +560,15 @@ show_neighbor_msg(struct imsg *imsg, enu
+@@ -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;
@@ -291,7 +391,7 @@ diff -u -p -r1.1.1.7 -r1.8
p->conf.remote_masklen != 128)) {
if (asprintf(&s, "%s/%u",
log_addr(&p->conf.remote_addr),
-@@ -549,6 +590,10 @@ show_neighbor_msg(struct imsg *imsg, enu
+@@ -549,6 +643,10 @@ show_neighbor_msg(struct imsg *imsg, enu
printf(", Template");
if (p->conf.cloned)
printf(", Cloned");
@@ -302,7 +402,7 @@ diff -u -p -r1.1.1.7 -r1.8
printf("\n");
if (p->conf.descr[0])
printf(" Description: %s\n", p->conf.descr);
-@@ -563,17 +608,16 @@ show_neighbor_msg(struct imsg *imsg, enu
+@@ -563,22 +661,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);
@@ -313,7 +413,7 @@ diff -u -p -r1.1.1.7 -r1.8
+ if (p->capa.peer.mp[i])
+ hascapamp = 1;
+ if (hascapamp || p->capa.peer.refresh ||
-+ p->capa.peer.restart || p->capa.peer.as4byte) {
++ p->capa.peer.grestart.restart || p->capa.peer.as4byte) {
printf(" Neighbor capabilities:\n");
- if (p->capa.peer.mp_v4) {
- printf(" Multiprotocol extensions: IPv4");
@@ -329,7 +429,17 @@ diff -u -p -r1.1.1.7 -r1.8
}
if (p->capa.peer.refresh)
printf(" Route Refresh\n");
-@@ -633,20 +677,16 @@ show_neighbor_msg(struct imsg *imsg, enu
+- 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 +733,38 @@ show_neighbor_msg(struct imsg *imsg, enu
}
void
@@ -356,10 +466,67 @@ diff -u -p -r1.1.1.7 -r1.8
+ 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
-@@ -680,7 +720,7 @@ print_neighbor_msgstats(struct peer *p)
+@@ -654,17 +772,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 +791,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
@@ -368,7 +535,7 @@ diff -u -p -r1.1.1.7 -r1.8
{
printf(" %-20s ", name);
-@@ -745,6 +785,12 @@ show_fib_head(void)
+@@ -745,6 +865,12 @@ show_fib_head(void)
}
void
@@ -381,7 +548,7 @@ diff -u -p -r1.1.1.7 -r1.8
show_network_head(void)
{
printf("flags: S = Static\n");
-@@ -788,56 +834,44 @@ show_fib_flags(u_int16_t flags)
+@@ -788,56 +914,44 @@ show_fib_flags(u_int16_t flags)
int
show_fib_msg(struct imsg *imsg)
{
@@ -456,7 +623,7 @@ diff -u -p -r1.1.1.7 -r1.8
default:
break;
}
-@@ -848,35 +882,70 @@ show_fib_msg(struct imsg *imsg)
+@@ -848,35 +962,70 @@ show_fib_msg(struct imsg *imsg)
void
show_nexthop_head(void)
{
@@ -545,7 +712,7 @@ diff -u -p -r1.1.1.7 -r1.8
}
printf("\n");
break;
-@@ -898,9 +967,8 @@ show_interface_head(void)
+@@ -898,9 +1047,8 @@ show_interface_head(void)
"Link state");
}
@@ -557,7 +724,7 @@ diff -u -p -r1.1.1.7 -r1.8
const struct ifmedia_description
ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
-@@ -936,36 +1004,36 @@ get_media_descr(int media_type)
+@@ -936,36 +1084,36 @@ get_media_descr(int media_type)
const char *
get_linkstate(int media_type, int link_state)
{
@@ -566,9 +733,7 @@ diff -u -p -r1.1.1.7 -r1.8
-
- if (link_state == LINK_STATE_UNKNOWN)
- return ("unknown");
-+ const struct if_status_description *p;
-+ static char buf[8];
-
+-
- 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 ||
@@ -578,7 +743,9 @@ diff -u -p -r1.1.1.7 -r1.8
- 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))
@@ -597,26 +764,26 @@ diff -u -p -r1.1.1.7 -r1.8
+
if (baudrate > IF_Gbps(1))
- printf("%llu GBit/s", baudrate / IF_Gbps(1));
-+ snprintf(bbuf, sizeof(bbuf), "%llu G%s",
++ 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), "%llu M%s",
++ 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), "%llu K%s",
++ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " K%s",
+ baudrate / IF_Kbps(1), unit);
else
- printf("%llu Bit/s", baudrate);
-+ snprintf(bbuf, sizeof(bbuf), "%llu %s",
++ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " %s",
+ baudrate, unit);
+
+ return (bbuf);
}
int
-@@ -982,17 +1050,12 @@ show_interface_msg(struct imsg *imsg)
+@@ -982,17 +1130,12 @@ show_interface_msg(struct imsg *imsg)
printf("%-15s", k->flags & IFF_UP ? "UP" : "");
if ((ifms_type = ift2ifm(k->media_type)) != 0)
@@ -639,16 +806,21 @@ diff -u -p -r1.1.1.7 -r1.8
printf("\n");
break;
case IMSG_CTL_END:
-@@ -1011,7 +1074,7 @@ show_rib_summary_head(void)
- printf(
- "flags: * = Valid, > = Selected, I = via IBGP, A = Announced\n");
+@@ -1008,10 +1151,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 +1112,26 @@ print_flags(u_int8_t flags, int sum)
+@@ -1049,26 +1192,30 @@ print_flags(u_int8_t flags, int sum)
char *p = flagstr;
if (sum) {
@@ -659,6 +831,8 @@ diff -u -p -r1.1.1.7 -r1.8
+ 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)
@@ -673,6 +847,8 @@ diff -u -p -r1.1.1.7 -r1.8
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)
@@ -683,43 +859,192 @@ diff -u -p -r1.1.1.7 -r1.8
printf(", announced");
}
}
-@@ -1085,7 +1148,7 @@ show_rib_summary_msg(struct imsg *imsg)
- memcpy(&rib, imsg->data, sizeof(rib));
+@@ -1077,27 +1224,14 @@ int
+ show_rib_summary_msg(struct imsg *imsg)
+ {
+ struct ctl_show_rib rib;
+- char *aspath;
+ u_char *asdata;
- print_prefix(&rib.prefix, rib.prefixlen, rib.flags);
+ 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(" %-15s ", log_addr(&rib.exit_nexthop));
-
- printf(" %5u %5u ", rib.local_pref, rib.med);
+-
+- 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 +1246,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;
-@@ -1189,8 +1252,8 @@ show_rib_detail_msg(struct imsg *imsg, i
- case ATTR_AGGREGATOR:
- memcpy(&as, data, sizeof(as));
- memcpy(&id, data + sizeof(as), sizeof(id));
+ 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));
-+ printf(" Aggregator: %s [%s]\n",
-+ log_as(ntohl(as)), inet_ntoa(id));
- break;
- case ATTR_ORIGINATOR_ID:
- memcpy(&id, data, sizeof(id));
-@@ -1236,22 +1299,27 @@ fmt_mem(int64_t num)
- return (buf);
+- 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 +1272,128 @@ show_rib_detail_msg(struct imsg *imsg, i
+ return (0);
}
-+size_t pt_sizes[AID_MAX] = AID_PTSIZE;
+-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);
+
- int
- show_rib_memory_msg(struct imsg *imsg)
++ 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;
-+ size_t pts = 0;
-+ int i;
+- 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");
+- 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)));
@@ -727,29 +1052,137 @@ diff -u -p -r1.1.1.7 -r1.8
- printf("%10lld IPv6 network entries using "
- "%s of memory\n", (long long)stats.pt6_cnt,
- fmt_mem(stats.pt6_cnt * sizeof(struct pt_entry6)));
-+ 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)));
-@@ -1272,9 +1340,7 @@ show_rib_memory_msg(struct imsg *imsg)
- (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("%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) +
-+ 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) +
-@@ -1328,30 +1394,6 @@ show_community(u_char *data, u_int16_t l
+- 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 +1436,6 @@ show_community(u_char *data, u_int16_t l
}
}
@@ -780,7 +1213,7 @@ diff -u -p -r1.1.1.7 -r1.8
void
show_ext_community(u_char *data, u_int16_t len)
{
-@@ -1372,28 +1414,29 @@ show_ext_community(u_char *data, u_int16
+@@ -1372,34 +1456,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));
@@ -808,12 +1241,278 @@ diff -u -p -r1.1.1.7 -r1.8
memcpy(&ext, data + i, sizeof(ext));
ext = betoh64(ext) & 0xffffffffffffLL;
- printf("%s 0x%llx", get_ext_subtype(subtype), ext);
-+ printf("%s 0x%llx", log_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%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 +1620,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 +1823,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
new file mode 100644
index 000000000000..cf0e4a449c66
--- /dev/null
+++ b/net/openbgpd/files/patch-bgpctl_irr_asset.c
@@ -0,0 +1,14 @@
+Index: bgpctl/irr_asset.c
+===================================================================
+RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_asset.c,v
+retrieving revision 1.1.1.2
+retrieving revision 1.1.1.3
+diff -u -p -r1.1.1.2 -r1.1.1.3
+--- bgpctl/irr_asset.c 9 Jul 2009 16:49:55 -0000 1.1.1.2
++++ bgpctl/irr_asset.c 13 Oct 2012 18:22:52 -0000 1.1.1.3
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: irr_asset.c,v 1.8 2009/04/14 21:10:54 jj Exp $ */
++/* $OpenBSD: irr_asset.c,v 1.7 2007/03/31 12:46:55 henning Exp $ */
+
+ /*
+ * Copyright (c) 2007 Henning Brauer <henning@openbsd.org>
diff --git a/net/openbgpd/files/patch-bgpctl_irr_output.c b/net/openbgpd/files/patch-bgpctl_irr_output.c
new file mode 100644
index 000000000000..b611216c1928
--- /dev/null
+++ b/net/openbgpd/files/patch-bgpctl_irr_output.c
@@ -0,0 +1,14 @@
+Index: bgpctl/irr_output.c
+===================================================================
+RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_output.c,v
+retrieving revision 1.1.1.1
+retrieving revision 1.1.1.2
+diff -u -p -r1.1.1.1 -r1.1.1.2
+--- bgpctl/irr_output.c 30 Jun 2009 05:46:15 -0000 1.1.1.1
++++ bgpctl/irr_output.c 13 Oct 2012 18:22:52 -0000 1.1.1.2
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: irr_output.c,v 1.13 2007/03/05 17:28:21 henning Exp $ */
++/* $OpenBSD: irr_output.c,v 1.12 2007/03/05 15:02:05 henning Exp $ */
+
+ /*
+ * Copyright (c) 2007 Henning Brauer <henning@openbsd.org>
diff --git a/net/openbgpd/files/patch-bgpctl_irr_parser.c b/net/openbgpd/files/patch-bgpctl_irr_parser.c
index af140f8b0f82..2e445ea37809 100644
--- a/net/openbgpd/files/patch-bgpctl_irr_parser.c
+++ b/net/openbgpd/files/patch-bgpctl_irr_parser.c
@@ -2,10 +2,10 @@ 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.4
-diff -u -p -r1.1.1.5 -r1.4
+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 4 Feb 2010 16:22:26 -0000 1.4
++++ 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 $ */
@@ -29,7 +29,7 @@ diff -u -p -r1.1.1.5 -r1.4
&errstr);
if (errstr)
errx(1, "peering spec \"%s\": format "
-@@ -407,7 +408,8 @@ parse_asset(char *key, char *val)
+@@ -407,11 +408,13 @@ parse_asset(char *key, char *val)
int
parse_route(char *key, char *val)
{
@@ -38,4 +38,11 @@ diff -u -p -r1.1.1.5 -r1.4
+ /* ignore everything else */
return (0);
- /* route is single-value, but seen trailing , in the wild */
+- /* 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
index da541297f183..4c97de2a4c7d 100644
--- a/net/openbgpd/files/patch-bgpctl_irr_prefix.c
+++ b/net/openbgpd/files/patch-bgpctl_irr_prefix.c
@@ -2,13 +2,13 @@ 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.7
-diff -u -p -r1.1.1.5 -r1.1.1.7
+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 12 Jun 2011 10:44:54 -0000 1.1.1.7
++++ 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.18 2010/05/10 02:00:50 krw Exp $ */
++/* $OpenBSD: irr_prefix.c,v 1.17 2009/09/08 16:11:36 sthen Exp $ */
/*
* Copyright (c) 2007 Henning Brauer <henning@openbsd.org>
diff --git a/net/openbgpd/files/patch-bgpctl_irrfilter.c b/net/openbgpd/files/patch-bgpctl_irrfilter.c
index 458351db3f29..79c31fc722aa 100644
--- a/net/openbgpd/files/patch-bgpctl_irrfilter.c
+++ b/net/openbgpd/files/patch-bgpctl_irrfilter.c
@@ -2,10 +2,16 @@ Index: bgpctl/irrfilter.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irrfilter.c,v
retrieving revision 1.1.1.1
-retrieving revision 1.2
-diff -u -p -r1.1.1.1 -r1.2
+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 30 Jun 2009 06:40:06 -0000 1.2
++++ 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.
diff --git a/net/openbgpd/files/patch-bgpctl_irrfilter.h b/net/openbgpd/files/patch-bgpctl_irrfilter.h
index cc9b1df0799a..485b97320e58 100644
--- a/net/openbgpd/files/patch-bgpctl_irrfilter.h
+++ b/net/openbgpd/files/patch-bgpctl_irrfilter.h
@@ -2,13 +2,13 @@ Index: bgpctl/irrfilter.h
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irrfilter.h,v
retrieving revision 1.1.1.5
-retrieving revision 1.3
-diff -u -p -r1.1.1.5 -r1.3
+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 4 Feb 2010 16:22:26 -0000 1.3
++++ 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.9 2009/09/08 16:11:36 sthen Exp $ */
++/* $OpenBSD: irrfilter.h,v 1.8 2009/09/08 15:40:25 claudio Exp $ */
/*
* Copyright (c) 2007 Henning Brauer <henning@openbsd.org>
diff --git a/net/openbgpd/files/patch-bgpctl_mrtparser.c b/net/openbgpd/files/patch-bgpctl_mrtparser.c
new file mode 100644
index 000000000000..0d463c0064ef
--- /dev/null
+++ b/net/openbgpd/files/patch-bgpctl_mrtparser.c
@@ -0,0 +1,977 @@
+Index: bgpctl/mrtparser.c
+===================================================================
+RCS file: bgpctl/mrtparser.c
+diff -N bgpctl/mrtparser.c
+--- /dev/null 1 Jan 1970 00:00:00 -0000
++++ bgpctl/mrtparser.c 13 Oct 2012 18:22:53 -0000 1.1.1.1
+@@ -0,0 +1,970 @@
++/* $OpenBSD: mrtparser.c,v 1.2 2012/03/06 07:52:32 claudio Exp $ */
++/*
++ * Copyright (c) 2011 Claudio Jeker <claudio@openbsd.org>
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <err.h>
++#include <errno.h>
++#include <limits.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <unistd.h>
++
++#include "mrt.h"
++#include "mrtparser.h"
++
++void *mrt_read_msg(int, struct mrt_hdr *);
++size_t mrt_read_buf(int, void *, size_t);
++
++struct mrt_peer *mrt_parse_v2_peer(struct mrt_hdr *, void *);
++struct mrt_rib *mrt_parse_v2_rib(struct mrt_hdr *, void *);
++int mrt_parse_dump(struct mrt_hdr *, void *, struct mrt_peer **,
++ struct mrt_rib **);
++int mrt_parse_dump_mp(struct mrt_hdr *, void *, struct mrt_peer **,
++ struct mrt_rib **);
++int mrt_extract_attr(struct mrt_rib_entry *, u_char *, int, sa_family_t,
++ int);
++
++void mrt_free_peers(struct mrt_peer *);
++void mrt_free_rib(struct mrt_rib *);
++void mrt_free_bgp_state(struct mrt_bgp_state *);
++void mrt_free_bgp_msg(struct mrt_bgp_msg *);
++
++u_char *mrt_aspath_inflate(void *, u_int16_t, u_int16_t *);
++int mrt_extract_addr(void *, u_int, union mrt_addr *, sa_family_t);
++
++void *
++mrt_read_msg(int fd, struct mrt_hdr *hdr)
++{
++ void *buf;
++
++ bzero(hdr, sizeof(*hdr));
++ if (mrt_read_buf(fd, hdr, sizeof(*hdr)) != sizeof(*hdr))
++ return (NULL);
++
++ if ((buf = malloc(ntohl(hdr->length))) == NULL)
++ err(1, "malloc(%d)", hdr->length);
++
++ if (mrt_read_buf(fd, buf, ntohl(hdr->length)) != ntohl(hdr->length)) {
++ free(buf);
++ return (NULL);
++ }
++ return (buf);
++}
++
++size_t
++mrt_read_buf(int fd, void *buf, size_t len)
++{
++ char *b = buf;
++ ssize_t n;
++
++ while (len > 0) {
++ if ((n = read(fd, b, len)) == -1) {
++ if (errno == EINTR)
++ continue;
++ err(1, "read");
++ }
++ if (n == 0)
++ break;
++ b += n;
++ len -= n;
++ }
++
++ return (b - (char *)buf);
++}
++
++void
++mrt_parse(int fd, struct mrt_parser *p, int verbose)
++{
++ struct mrt_hdr h;
++ struct mrt_peer *pctx = NULL;
++ struct mrt_rib *r;
++ void *msg;
++
++ while ((msg = mrt_read_msg(fd, &h))) {
++ switch (ntohs(h.type)) {
++ case MSG_NULL:
++ case MSG_START:
++ case MSG_DIE:
++ case MSG_I_AM_DEAD:
++ case MSG_PEER_DOWN:
++ case MSG_PROTOCOL_BGP:
++ case MSG_PROTOCOL_IDRP:
++ case MSG_PROTOCOL_BGP4PLUS:
++ case MSG_PROTOCOL_BGP4PLUS1:
++ if (verbose)
++ printf("deprecated MRT type %d\n",
++ ntohs(h.type));
++ break;
++ case MSG_PROTOCOL_RIP:
++ case MSG_PROTOCOL_RIPNG:
++ case MSG_PROTOCOL_OSPF:
++ case MSG_PROTOCOL_ISIS_ET:
++ case MSG_PROTOCOL_ISIS:
++ case MSG_PROTOCOL_OSPFV3_ET:
++ case MSG_PROTOCOL_OSPFV3:
++ if (verbose)
++ printf("unsuported MRT type %d\n",
++ ntohs(h.type));
++ break;
++ case MSG_TABLE_DUMP:
++ switch (ntohs(h.subtype)) {
++ case MRT_DUMP_AFI_IP:
++ case MRT_DUMP_AFI_IPv6:
++ if (p->dump == NULL)
++ break;
++ if (mrt_parse_dump(&h, msg, &pctx, &r) == 0) {
++ p->dump(r, pctx, p->arg);
++ mrt_free_rib(r);
++ }
++ break;
++ default:
++ if (verbose)
++ printf("unknown AFI %d in table dump\n",
++ ntohs(h.subtype));
++ break;
++ }
++ break;
++ case MSG_TABLE_DUMP_V2:
++ switch (ntohs(h.subtype)) {
++ case MRT_DUMP_V2_PEER_INDEX_TABLE:
++ if (p->dump == NULL)
++ break;
++ if (pctx)
++ mrt_free_peers(pctx);
++ pctx = mrt_parse_v2_peer(&h, msg);
++ break;
++ case MRT_DUMP_V2_RIB_IPV4_UNICAST:
++ case MRT_DUMP_V2_RIB_IPV4_MULTICAST:
++ case MRT_DUMP_V2_RIB_IPV6_UNICAST:
++ case MRT_DUMP_V2_RIB_IPV6_MULTICAST:
++ case MRT_DUMP_V2_RIB_GENERIC:
++ if (p->dump == NULL)
++ break;
++ r = mrt_parse_v2_rib(&h, msg);
++ if (r) {
++ p->dump(r, pctx, p->arg);
++ mrt_free_rib(r);
++ }
++ break;
++ default:
++ if (verbose)
++ printf("unhandled BGP4MP subtype %d\n",
++ ntohs(h.subtype));
++ break;
++ }
++ break;
++ case MSG_PROTOCOL_BGP4MP_ET:
++ /* currently just ignore the microsec field */
++ msg = (char *)msg + sizeof(u_int32_t);
++ h.length -= sizeof(u_int32_t);
++ /* FALLTHROUGH */
++ case MSG_PROTOCOL_BGP4MP:
++ switch (ntohs(h.subtype)) {
++ case BGP4MP_STATE_CHANGE:
++ case BGP4MP_STATE_CHANGE_AS4:
++ /* XXX p->state(s, p->arg); */
++ errx(1, "BGP4MP subtype not yet implemented");
++ break;
++ case BGP4MP_MESSAGE:
++ case BGP4MP_MESSAGE_AS4:
++ case BGP4MP_MESSAGE_LOCAL:
++ case BGP4MP_MESSAGE_AS4_LOCAL:
++ /* XXX p->message(m, p->arg); */
++ errx(1, "BGP4MP subtype not yet implemented");
++ break;
++ case BGP4MP_ENTRY:
++ if (p->dump == NULL)
++ break;
++ if (mrt_parse_dump_mp(&h, msg, &pctx, &r) ==
++ 0) {
++ p->dump(r, pctx, p->arg);
++ mrt_free_rib(r);
++ }
++ break;
++ default:
++ if (verbose)
++ printf("unhandled BGP4MP subtype %d\n",
++ ntohs(h.subtype));
++ break;
++ }
++ break;
++ default:
++ if (verbose)
++ printf("unknown MRT type %d\n", ntohs(h.type));
++ break;
++ }
++ free(msg);
++ }
++ if (pctx)
++ mrt_free_peers(pctx);
++}
++
++struct mrt_peer *
++mrt_parse_v2_peer(struct mrt_hdr *hdr, void *msg)
++{
++ struct mrt_peer_entry *peers;
++ struct mrt_peer *p;
++ u_int8_t *b = msg;
++ u_int32_t bid, as4;
++ u_int16_t cnt, i, as2;
++ u_int len = ntohl(hdr->length);
++
++ if (len < 8) /* min msg size */
++ return NULL;
++
++ p = calloc(1, sizeof(struct mrt_peer));
++ if (p == NULL)
++ err(1, "calloc");
++
++ /* collector bgp id */
++ memcpy(&bid, b, sizeof(bid));
++ b += sizeof(bid);
++ len -= sizeof(bid);
++ p->bgp_id = ntohl(bid);
++
++ /* view name length */
++ memcpy(&cnt, b, sizeof(cnt));
++ b += sizeof(cnt);
++ len -= sizeof(cnt);
++ cnt = ntohs(cnt);
++
++ /* view name */
++ if (cnt > len)
++ goto fail;
++ if (cnt != 0) {
++ if ((p->view = malloc(cnt + 1)) == NULL)
++ err(1, "malloc");
++ memcpy(p->view, b, cnt);
++ p->view[cnt] = 0;
++ } else
++ if ((p->view = strdup("")) == NULL)
++ err(1, "strdup");
++ b += cnt;
++ len -= cnt;
++
++ /* peer_count */
++ if (len < sizeof(cnt))
++ goto fail;
++ memcpy(&cnt, b, sizeof(cnt));
++ b += sizeof(cnt);
++ len -= sizeof(cnt);
++ cnt = ntohs(cnt);
++
++ /* peer entries */
++ if ((peers = calloc(cnt, sizeof(struct mrt_peer_entry))) == NULL)
++ err(1, "calloc");
++ for (i = 0; i < cnt; i++) {
++ u_int8_t type;
++
++ if (len < sizeof(u_int8_t) + sizeof(u_int32_t))
++ goto fail;
++ type = *b++;
++ len -= 1;
++ memcpy(&bid, b, sizeof(bid));
++ b += sizeof(bid);
++ len -= sizeof(bid);
++ peers[i].bgp_id = ntohl(bid);
++
++ if (type & MRT_DUMP_V2_PEER_BIT_I) {
++ if (mrt_extract_addr(b, len, &peers[i].addr,
++ AF_INET6) == -1)
++ goto fail;
++ b += sizeof(struct in6_addr);
++ len -= sizeof(struct in6_addr);
++ } else {
++ if (mrt_extract_addr(b, len, &peers[i].addr,
++ AF_INET) == -1)
++ goto fail;
++ b += sizeof(struct in_addr);
++ len -= sizeof(struct in_addr);
++ }
++
++ if (type & MRT_DUMP_V2_PEER_BIT_A) {
++ memcpy(&as4, b, sizeof(as4));
++ b += sizeof(as4);
++ len -= sizeof(as4);
++ as4 = ntohl(as4);
++ } else {
++ memcpy(&as2, b, sizeof(as2));
++ b += sizeof(as2);
++ len -= sizeof(as2);
++ as4 = ntohs(as2);
++ }
++ peers[i].asnum = as4;
++ }
++ p->peers = peers;
++ p->npeers = cnt;
++ return (p);
++fail:
++ mrt_free_peers(p);
++ return (NULL);
++}
++
++struct mrt_rib *
++mrt_parse_v2_rib(struct mrt_hdr *hdr, void *msg)
++{
++ struct mrt_rib_entry *entries;
++ struct mrt_rib *r;
++ u_int8_t *b = msg;
++ u_int len = ntohl(hdr->length);
++ u_int32_t snum;
++ u_int16_t cnt, i;
++ u_int8_t plen;
++
++ if (len < sizeof(snum) + 1)
++ return NULL;
++
++ r = calloc(1, sizeof(struct mrt_rib));
++ if (r == NULL)
++ err(1, "calloc");
++
++ /* seq_num */
++ memcpy(&snum, b, sizeof(snum));
++ b += sizeof(snum);
++ len -= sizeof(snum);
++ r->seqnum = ntohl(snum);
++
++ switch (ntohs(hdr->subtype)) {
++ case MRT_DUMP_V2_RIB_IPV4_UNICAST:
++ case MRT_DUMP_V2_RIB_IPV4_MULTICAST:
++ plen = *b++;
++ len -= 1;
++ if (len < MRT_PREFIX_LEN(plen))
++ goto fail;
++ r->prefix.sin.sin_family = AF_INET;
++ r->prefix.sin.sin_len = sizeof(struct sockaddr_in);
++ memcpy(&r->prefix.sin.sin_addr, b, MRT_PREFIX_LEN(plen));
++ b += MRT_PREFIX_LEN(plen);
++ len -= MRT_PREFIX_LEN(plen);
++ r->prefixlen = plen;
++ break;
++ case MRT_DUMP_V2_RIB_IPV6_UNICAST:
++ case MRT_DUMP_V2_RIB_IPV6_MULTICAST:
++ plen = *b++;
++ len -= 1;
++ if (len < MRT_PREFIX_LEN(plen))
++ goto fail;
++ r->prefix.sin6.sin6_family = AF_INET6;
++ r->prefix.sin6.sin6_len = sizeof(struct sockaddr_in6);
++ memcpy(&r->prefix.sin6.sin6_addr, b, MRT_PREFIX_LEN(plen));
++ b += MRT_PREFIX_LEN(plen);
++ len -= MRT_PREFIX_LEN(plen);
++ r->prefixlen = plen;
++ break;
++ case MRT_DUMP_V2_RIB_GENERIC:
++ /* XXX unhandled */
++ errx(1, "MRT_DUMP_V2_RIB_GENERIC subtype not yet implemented");
++ goto fail;
++ }
++
++ /* entries count */
++ if (len < sizeof(cnt))
++ goto fail;
++ memcpy(&cnt, b, sizeof(cnt));
++ b += sizeof(cnt);
++ len -= sizeof(cnt);
++ cnt = ntohs(cnt);
++ r->nentries = cnt;
++
++ /* entries */
++ if ((entries = calloc(cnt, sizeof(struct mrt_rib_entry))) == NULL)
++ err(1, "calloc");
++ for (i = 0; i < cnt; i++) {
++ u_int32_t otm;
++ u_int16_t pix, alen;
++ if (len < 2 * sizeof(u_int16_t) + sizeof(u_int32_t))
++ goto fail;
++ /* peer index */
++ memcpy(&pix, b, sizeof(pix));
++ b += sizeof(pix);
++ len -= sizeof(pix);
++ entries[i].peer_idx = ntohs(pix);
++
++ /* originated */
++ memcpy(&otm, b, sizeof(otm));
++ b += sizeof(otm);
++ len -= sizeof(otm);
++ entries[i].originated = ntohl(otm);
++
++ /* attr_len */
++ memcpy(&alen, b, sizeof(alen));
++ b += sizeof(alen);
++ len -= sizeof(alen);
++ alen = ntohs(alen);
++
++ /* attr */
++ if (len < alen)
++ goto fail;
++ if (mrt_extract_attr(&entries[i], b, alen,
++ r->prefix.sa.sa_family, 1) == -1)
++ goto fail;
++ b += alen;
++ len -= alen;
++ }
++ r->entries = entries;
++ return (r);
++fail:
++ mrt_free_rib(r);
++ return (NULL);
++}
++
++int
++mrt_parse_dump(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp,
++ struct mrt_rib **rp)
++{
++ struct mrt_peer *p;
++ struct mrt_rib *r;
++ struct mrt_rib_entry *re;
++ u_int8_t *b = msg;
++ u_int len = ntohl(hdr->length);
++ u_int16_t asnum, alen;
++
++ if (*pp == NULL) {
++ *pp = calloc(1, sizeof(struct mrt_peer));
++ if (*pp == NULL)
++ err(1, "calloc");
++ (*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry));
++ if ((*pp)->peers == NULL)
++ err(1, "calloc");
++ (*pp)->npeers = 1;
++ }
++ p = *pp;
++
++ *rp = r = calloc(1, sizeof(struct mrt_rib));
++ if (r == NULL)
++ err(1, "calloc");
++ re = calloc(1, sizeof(struct mrt_rib_entry));
++ if (re == NULL)
++ err(1, "calloc");
++ r->nentries = 1;
++ r->entries = re;
++
++ if (len < 2 * sizeof(u_int16_t))
++ goto fail;
++ /* view */
++ b += sizeof(u_int16_t);
++ len -= sizeof(u_int16_t);
++ /* seqnum */
++ memcpy(&r->seqnum, b, sizeof(u_int16_t));
++ b += sizeof(u_int16_t);
++ len -= sizeof(u_int16_t);
++ r->seqnum = ntohs(r->seqnum);
++
++ switch (ntohs(hdr->subtype)) {
++ case MRT_DUMP_AFI_IP:
++ if (mrt_extract_addr(b, len, &r->prefix, AF_INET) == -1)
++ goto fail;
++ b += sizeof(struct in_addr);
++ len -= sizeof(struct in_addr);
++ break;
++ case MRT_DUMP_AFI_IPv6:
++ if (mrt_extract_addr(b, len, &r->prefix, AF_INET6) == -1)
++ goto fail;
++ b += sizeof(struct in6_addr);
++ len -= sizeof(struct in6_addr);
++ break;
++ }
++ if (len < 2 * sizeof(u_int32_t) + 2 * sizeof(u_int16_t) + 2)
++ goto fail;
++ r->prefixlen = *b++;
++ len -= 1;
++ /* status */
++ b += 1;
++ len -= 1;
++ /* originated */
++ memcpy(&re->originated, b, sizeof(u_int32_t));
++ b += sizeof(u_int32_t);
++ len -= sizeof(u_int32_t);
++ re->originated = ntohl(re->originated);
++ /* peer ip */
++ switch (ntohs(hdr->subtype)) {
++ case MRT_DUMP_AFI_IP:
++ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET) == -1)
++ goto fail;
++ b += sizeof(struct in_addr);
++ len -= sizeof(struct in_addr);
++ break;
++ case MRT_DUMP_AFI_IPv6:
++ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET6) == -1)
++ goto fail;
++ b += sizeof(struct in6_addr);
++ len -= sizeof(struct in6_addr);
++ break;
++ }
++ memcpy(&asnum, b, sizeof(asnum));
++ b += sizeof(asnum);
++ len -= sizeof(asnum);
++ p->peers->asnum = ntohs(asnum);
++
++ memcpy(&alen, b, sizeof(alen));
++ b += sizeof(alen);
++ len -= sizeof(alen);
++ alen = ntohs(alen);
++
++ /* attr */
++ if (len < alen)
++ goto fail;
++ if (mrt_extract_attr(re, b, alen, r->prefix.sa.sa_family, 0) == -1)
++ goto fail;
++ b += alen;
++ len -= alen;
++
++ return (0);
++fail:
++ mrt_free_rib(r);
++ return (-1);
++}
++
++int
++mrt_parse_dump_mp(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp,
++ struct mrt_rib **rp)
++{
++ struct mrt_peer *p;
++ struct mrt_rib *r;
++ struct mrt_rib_entry *re;
++ u_int8_t *b = msg;
++ u_int len = ntohl(hdr->length);
++ u_int16_t asnum, alen, afi;
++ u_int8_t safi, nhlen;
++ sa_family_t af;
++
++ if (*pp == NULL) {
++ *pp = calloc(1, sizeof(struct mrt_peer));
++ if (*pp == NULL)
++ err(1, "calloc");
++ (*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry));
++ if ((*pp)->peers == NULL)
++ err(1, "calloc");
++ (*pp)->npeers = 1;
++ }
++ p = *pp;
++
++ *rp = r = calloc(1, sizeof(struct mrt_rib));
++ if (r == NULL)
++ err(1, "calloc");
++ re = calloc(1, sizeof(struct mrt_rib_entry));
++ if (re == NULL)
++ err(1, "calloc");
++ r->nentries = 1;
++ r->entries = re;
++
++ if (len < 4 * sizeof(u_int16_t))
++ goto fail;
++ /* source AS */
++ b += sizeof(u_int16_t);
++ len -= sizeof(u_int16_t);
++ /* dest AS */
++ memcpy(&asnum, b, sizeof(asnum));
++ b += sizeof(asnum);
++ len -= sizeof(asnum);
++ p->peers->asnum = ntohs(asnum);
++ /* iface index */
++ b += sizeof(u_int16_t);
++ len -= sizeof(u_int16_t);
++ /* afi */
++ memcpy(&afi, b, sizeof(afi));
++ b += sizeof(afi);
++ len -= sizeof(afi);
++ afi = ntohs(afi);
++
++ /* source + dest ip */
++ switch (afi) {
++ case MRT_DUMP_AFI_IP:
++ if (len < 2 * sizeof(struct in_addr))
++ goto fail;
++ /* source IP */
++ b += sizeof(struct in_addr);
++ len -= sizeof(struct in_addr);
++ /* dest IP */
++ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET) == -1)
++ goto fail;
++ b += sizeof(struct in_addr);
++ len -= sizeof(struct in_addr);
++ break;
++ case MRT_DUMP_AFI_IPv6:
++ if (len < 2 * sizeof(struct in6_addr))
++ goto fail;
++ /* source IP */
++ b += sizeof(struct in6_addr);
++ len -= sizeof(struct in6_addr);
++ /* dest IP */
++ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET6) == -1)
++ goto fail;
++ b += sizeof(struct in6_addr);
++ len -= sizeof(struct in6_addr);
++ break;
++ }
++
++ if (len < 2 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t))
++ goto fail;
++ /* view + status */
++ b += 2 * sizeof(u_int16_t);
++ len -= 2 * sizeof(u_int16_t);
++ /* originated */
++ memcpy(&re->originated, b, sizeof(u_int32_t));
++ b += sizeof(u_int32_t);
++ len -= sizeof(u_int32_t);
++ re->originated = ntohl(re->originated);
++
++ /* afi */
++ memcpy(&afi, b, sizeof(afi));
++ b += sizeof(afi);
++ len -= sizeof(afi);
++ afi = ntohs(afi);
++
++ /* safi */
++ safi = *b++;
++ len -= 1;
++
++ switch (afi) {
++ case MRT_DUMP_AFI_IP:
++ if (safi == 1 || safi == 2) {
++ af = AF_INET;
++ break;
++ } else if (safi == 128) {
++ af = AF_VPNv4;
++ break;
++ }
++ goto fail;
++ case MRT_DUMP_AFI_IPv6:
++ if (safi != 1 && safi != 2)
++ goto fail;
++ af = AF_INET6;
++ break;
++ default:
++ goto fail;
++ }
++
++ /* nhlen */
++ nhlen = *b++;
++ len -= 1;
++
++ /* nexthop */
++ if (mrt_extract_addr(b, len, &re->nexthop, af) == -1)
++ goto fail;
++ if (len < nhlen)
++ goto fail;
++ b += nhlen;
++ len -= nhlen;
++
++ if (len < 1)
++ goto fail;
++ r->prefixlen = *b++;
++ len -= 1;
++
++ /* prefix */
++ switch (af) {
++ case AF_INET:
++ if (len < MRT_PREFIX_LEN(r->prefixlen))
++ goto fail;
++ r->prefix.sin.sin_family = AF_INET;
++ r->prefix.sin.sin_len = sizeof(struct sockaddr_in);
++ memcpy(&r->prefix.sin.sin_addr, b,
++ MRT_PREFIX_LEN(r->prefixlen));
++ b += MRT_PREFIX_LEN(r->prefixlen);
++ len -= MRT_PREFIX_LEN(r->prefixlen);
++ break;
++ case AF_INET6:
++ if (len < MRT_PREFIX_LEN(r->prefixlen))
++ goto fail;
++ r->prefix.sin6.sin6_family = AF_INET6;
++ r->prefix.sin6.sin6_len = sizeof(struct sockaddr_in6);
++ memcpy(&r->prefix.sin6.sin6_addr, b,
++ MRT_PREFIX_LEN(r->prefixlen));
++ b += MRT_PREFIX_LEN(r->prefixlen);
++ len -= MRT_PREFIX_LEN(r->prefixlen);
++ break;
++ case AF_VPNv4:
++ if (len < MRT_PREFIX_LEN(r->prefixlen))
++ goto fail;
++ errx(1, "AF_VPNv4 handling not yet implemented");
++ goto fail;
++ }
++
++ memcpy(&alen, b, sizeof(alen));
++ b += sizeof(alen);
++ len -= sizeof(alen);
++ alen = ntohs(alen);
++
++ /* attr */
++ if (len < alen)
++ goto fail;
++ if (mrt_extract_attr(re, b, alen, r->prefix.sa.sa_family, 0) == -1)
++ goto fail;
++ b += alen;
++ len -= alen;
++
++ return (0);
++fail:
++ mrt_free_rib(r);
++ return (-1);
++}
++
++int
++mrt_extract_attr(struct mrt_rib_entry *re, u_char *a, int alen, sa_family_t af,
++ int as4)
++{
++ struct mrt_attr *ap;
++ u_int32_t tmp;
++ u_int16_t attr_len;
++ u_int8_t type, flags, *attr;
++
++ do {
++ if (alen < 3)
++ return (-1);
++ attr = a;
++ flags = *a++;
++ alen -= 1;
++ type = *a++;
++ alen -= 1;
++
++ if (flags & MRT_ATTR_EXTLEN) {
++ if (alen < 2)
++ return (-1);
++ memcpy(&attr_len, a, sizeof(attr_len));
++ attr_len = ntohs(attr_len);
++ a += sizeof(attr_len);
++ alen -= sizeof(attr_len);
++ } else {
++ attr_len = *a++;
++ alen -= 1;
++ }
++ switch (type) {
++ case MRT_ATTR_ORIGIN:
++ if (attr_len != 1)
++ return (-1);
++ re->origin = *a;
++ break;
++ case MRT_ATTR_ASPATH:
++ if (as4) {
++ re->aspath_len = attr_len;
++ if ((re->aspath = malloc(attr_len)) == NULL)
++ err(1, "malloc");
++ memcpy(re->aspath, a, attr_len);
++ } else {
++ re->aspath = mrt_aspath_inflate(a, attr_len,
++ &re->aspath_len);
++ if (re->aspath == NULL)
++ return (-1);
++ }
++ break;
++ case MRT_ATTR_NEXTHOP:
++ if (attr_len != 4)
++ return (-1);
++ if (af != AF_INET)
++ break;
++ memcpy(&tmp, a, sizeof(tmp));
++ re->nexthop.sin.sin_len = sizeof(struct sockaddr_in);
++ re->nexthop.sin.sin_family = AF_INET;
++ re->nexthop.sin.sin_addr.s_addr = tmp;
++ break;
++ case MRT_ATTR_MED:
++ if (attr_len != 4)
++ return (-1);
++ memcpy(&tmp, a, sizeof(tmp));
++ re->med = ntohl(tmp);
++ break;
++ case MRT_ATTR_LOCALPREF:
++ if (attr_len != 4)
++ return (-1);
++ memcpy(&tmp, a, sizeof(tmp));
++ re->local_pref = ntohl(tmp);
++ break;
++ case MRT_ATTR_MP_REACH_NLRI:
++ /*
++ * XXX horrible hack:
++ * Once again IETF and the real world differ in the
++ * implementation. In short the abbreviated MP_NLRI
++ * hack in the standard is not used in real life.
++ * Detect the two cases by looking at the first byte
++ * of the payload (either the nexthop addr length (RFC)
++ * or the high byte of the AFI (old form)). If the
++ * first byte matches the expected nexthop length it
++ * is expected to be the RFC 6396 encoding.
++ */
++ if (*a != attr_len - 1) {
++ a += 3;
++ alen -= 3;
++ attr_len -= 3;
++ }
++ switch (af) {
++ case AF_INET6:
++ if (attr_len < sizeof(struct in6_addr) + 1)
++ return (-1);
++ re->nexthop.sin6.sin6_len =
++ sizeof(struct sockaddr_in6);
++ re->nexthop.sin6.sin6_family = AF_INET6;
++ memcpy(&re->nexthop.sin6.sin6_addr, a + 1,
++ sizeof(struct in6_addr));
++ break;
++ case AF_VPNv4:
++ if (attr_len < sizeof(u_int64_t) +
++ sizeof(struct in_addr))
++ return (-1);
++ re->nexthop.svpn4.sv_len =
++ sizeof(struct sockaddr_vpn4);
++ re->nexthop.svpn4.sv_family = AF_VPNv4;
++ memcpy(&tmp, a + 1 + sizeof(u_int64_t),
++ sizeof(tmp));
++ re->nexthop.svpn4.sv_addr.s_addr = tmp;
++ break;
++ }
++ break;
++ case MRT_ATTR_AS4PATH:
++ if (!as4) {
++ if (re->aspath)
++ free(re->aspath);
++ re->aspath_len = attr_len;
++ if ((re->aspath = malloc(attr_len)) == NULL)
++ err(1, "malloc");
++ memcpy(re->aspath, a, attr_len);
++ break;
++ }
++ /* FALLTHROUGH */
++ default:
++ re->nattrs++;
++ if (re->nattrs >= UCHAR_MAX)
++ err(1, "too many attributes");
++ ap = realloc(re->attrs,
++ re->nattrs * sizeof(struct mrt_attr));
++ if (ap == NULL)
++ err(1, "realloc");
++ re->attrs = ap;
++ ap = re->attrs + re->nattrs - 1;
++ ap->attr_len = a + attr_len - attr;
++ if ((ap->attr = malloc(ap->attr_len)) == NULL)
++ err(1, "malloc");
++ memcpy(ap->attr, attr, ap->attr_len);
++ break;
++ }
++ a += attr_len;
++ alen -= attr_len;
++ } while (alen > 0);
++
++ return (0);
++}
++
++void
++mrt_free_peers(struct mrt_peer *p)
++{
++ free(p->peers);
++ free(p->view);
++ free(p);
++}
++
++void
++mrt_free_rib(struct mrt_rib *r)
++{
++ u_int16_t i, j;
++
++ for (i = 0; i < r->nentries && r->entries; i++) {
++ for (j = 0; j < r->entries[i].nattrs; j++)
++ free(r->entries[i].attrs[j].attr);
++ free(r->entries[i].attrs);
++ free(r->entries[i].aspath);
++ }
++
++ free(r->entries);
++ free(r);
++}
++
++void
++mrt_free_bgp_state(struct mrt_bgp_state *s)
++{
++ free(s);
++}
++
++void
++mrt_free_bgp_msg(struct mrt_bgp_msg *m)
++{
++ free(m->msg);
++ free(m);
++}
++
++u_char *
++mrt_aspath_inflate(void *data, u_int16_t len, u_int16_t *newlen)
++{
++ u_int8_t *seg, *nseg, *ndata;
++ u_int16_t seg_size, olen, nlen;
++ u_int8_t seg_len;
++
++ /* first calculate the length of the aspath */
++ seg = data;
++ nlen = 0;
++ for (olen = len; olen > 0; olen -= seg_size, seg += seg_size) {
++ seg_len = seg[1];
++ seg_size = 2 + sizeof(u_int16_t) * seg_len;
++ nlen += 2 + sizeof(u_int32_t) * seg_len;
++
++ if (seg_size > olen)
++ return NULL;
++ }
++
++ *newlen = nlen;
++ if ((ndata = malloc(nlen)) == NULL)
++ err(1, "malloc");
++
++ /* then copy the aspath */
++ seg = data;
++ for (nseg = ndata; nseg < ndata + nlen; ) {
++ *nseg++ = *seg++;
++ *nseg++ = seg_len = *seg++;
++ for (; seg_len > 0; seg_len--) {
++ *nseg++ = 0;
++ *nseg++ = 0;
++ *nseg++ = *seg++;
++ *nseg++ = *seg++;
++ }
++ }
++
++ return (ndata);
++}
++
++int
++mrt_extract_addr(void *msg, u_int len, union mrt_addr *addr, sa_family_t af)
++{
++ u_int8_t *b = msg;
++
++ switch (af) {
++ case AF_INET:
++ if (len < sizeof(struct in_addr))
++ return (-1);
++ addr->sin.sin_family = AF_INET;
++ addr->sin.sin_len = sizeof(struct sockaddr_in);
++ memcpy(&addr->sin.sin_addr, b, sizeof(struct in_addr));
++ return sizeof(struct in_addr);
++ case AF_INET6:
++ if (len < sizeof(struct in6_addr))
++ return (-1);
++ addr->sin6.sin6_family = AF_INET6;
++ addr->sin6.sin6_len = sizeof(struct sockaddr_in6);
++ memcpy(&addr->sin6.sin6_addr, b, sizeof(struct in6_addr));
++ return sizeof(struct in6_addr);
++ case AF_VPNv4:
++ if (len < sizeof(u_int64_t) + sizeof(struct in_addr))
++ return (-1);
++ addr->svpn4.sv_len = sizeof(struct sockaddr_vpn4);
++ addr->svpn4.sv_family = AF_VPNv4;
++ memcpy(&addr->svpn4.sv_addr, b + sizeof(u_int64_t),
++ sizeof(struct in_addr));
++ return (sizeof(u_int64_t) + sizeof(struct in_addr));
++ default:
++ return (-1);
++ }
++}
diff --git a/net/openbgpd/files/patch-bgpctl_mrtparser.h b/net/openbgpd/files/patch-bgpctl_mrtparser.h
new file mode 100644
index 000000000000..2f11567e54f1
--- /dev/null
+++ b/net/openbgpd/files/patch-bgpctl_mrtparser.h
@@ -0,0 +1,122 @@
+Index: bgpctl/mrtparser.h
+===================================================================
+RCS file: bgpctl/mrtparser.h
+diff -N bgpctl/mrtparser.h
+--- /dev/null 1 Jan 1970 00:00:00 -0000
++++ bgpctl/mrtparser.h 13 Oct 2012 18:22:53 -0000 1.1.1.1
+@@ -0,0 +1,115 @@
++/* $OpenBSD$ */
++/*
++ * Copyright (c) 2011 Claudio Jeker <claudio@openbsd.org>
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++struct sockaddr_vpn4 {
++ u_int8_t sv_len;
++ sa_family_t sv_family;
++ u_int8_t sv_labellen;
++ u_int8_t sv_pad;
++ struct in_addr sv_addr;
++ u_int64_t sv_rd;
++ u_int8_t sv_label[21];
++ u_int8_t sv_pad2[3];
++};
++
++#define AF_VPNv4 250 /* XXX high enough to not cause issues */
++
++union mrt_addr {
++ struct sockaddr_in6 sin6;
++ struct sockaddr_in sin;
++ struct sockaddr_vpn4 svpn4;
++ struct sockaddr sa;
++};
++
++/* data structures for the MSG_TABLE_DUMP_V2 format */
++struct mrt_peer_entry {
++ union mrt_addr addr;
++ u_int32_t bgp_id;
++ u_int32_t asnum;
++};
++
++struct mrt_peer {
++ char *view;
++ struct mrt_peer_entry *peers;
++ u_int32_t bgp_id;
++ u_int16_t npeers;
++};
++
++struct mrt_attr {
++ void *attr;
++ size_t attr_len;
++};
++
++struct mrt_rib_entry {
++ void *aspath;
++ struct mrt_attr *attrs;
++ union mrt_addr nexthop;
++ time_t originated;
++ u_int32_t local_pref;
++ u_int32_t med;
++ u_int16_t peer_idx;
++ u_int16_t aspath_len;
++ u_int16_t nattrs;
++ u_int8_t origin;
++};
++
++struct mrt_rib {
++ struct mrt_rib_entry *entries;
++ union mrt_addr prefix;
++ u_int32_t seqnum;
++ u_int16_t nentries;
++ u_int8_t prefixlen;
++};
++
++/* data structures for the BGP4MP MESSAGE and STATE types */
++struct mrt_bgp_state {
++ union mrt_addr src;
++ union mrt_addr dst;
++ u_int32_t src_as;
++ u_int32_t dst_as;
++ u_int16_t old_state;
++ u_int16_t new_state;
++};
++
++struct mrt_bgp_msg {
++ union mrt_addr src;
++ union mrt_addr dst;
++ u_int32_t src_as;
++ u_int32_t dst_as;
++ u_int16_t msg_len;
++ void *msg;
++};
++
++#define MRT_ATTR_ORIGIN 1
++#define MRT_ATTR_ASPATH 2
++#define MRT_ATTR_NEXTHOP 3
++#define MRT_ATTR_MED 4
++#define MRT_ATTR_LOCALPREF 5
++#define MRT_ATTR_MP_REACH_NLRI 14
++#define MRT_ATTR_AS4PATH 17
++#define MRT_ATTR_EXTLEN 0x10
++
++#define MRT_PREFIX_LEN(x) ((((u_int)x) + 7) / 8)
++
++struct mrt_parser {
++ void (*dump)(struct mrt_rib *, struct mrt_peer *, void *);
++ void (*state)(struct mrt_bgp_state *, void *);
++ void (*message)(struct mrt_bgp_msg *, void *);
++ void *arg;
++};
++
++void mrt_parse(int, struct mrt_parser *, int);
diff --git a/net/openbgpd/files/patch-bgpctl_parser.c b/net/openbgpd/files/patch-bgpctl_parser.c
index 237c6ffc9b92..0ce85818b1eb 100644
--- a/net/openbgpd/files/patch-bgpctl_parser.c
+++ b/net/openbgpd/files/patch-bgpctl_parser.c
@@ -2,17 +2,17 @@ Index: bgpctl/parser.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/parser.c,v
retrieving revision 1.1.1.6
-retrieving revision 1.6
-diff -u -p -r1.1.1.6 -r1.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 2 Jul 2011 16:06:35 -0000 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.61 2010/03/08 17:02:19 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,6 +16,10 @@
+@@ -16,11 +16,16 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
@@ -23,17 +23,44 @@ diff -u -p -r1.1.1.6 -r1.6
#include <sys/types.h>
#include <sys/socket.h>
-@@ -52,7 +56,8 @@ enum token_type {
+ #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
++ RTABLE,
++ FILENAME
};
enum getopts {
-@@ -97,6 +102,9 @@ static const struct token t_prepself[];
+@@ -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[];
@@ -43,7 +70,7 @@ diff -u -p -r1.1.1.6 -r1.6
static const struct token t_main[] = {
{ KEYWORD, "reload", RELOAD, NULL},
-@@ -105,6 +113,7 @@ static const struct token t_main[] = {
+@@ -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},
@@ -51,15 +78,18 @@ diff -u -p -r1.1.1.6 -r1.6
{ ENDTOKEN, "", NONE, NULL}
};
-@@ -116,6 +125,7 @@ static const struct token t_show[] = {
+@@ -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,14 +138,15 @@ static const struct token t_show_summary
+ };
+
+@@ -128,24 +145,26 @@ static const struct token t_show_summary
};
static const struct token t_show_fib[] = {
@@ -83,7 +113,61 @@ diff -u -p -r1.1.1.6 -r1.6
};
static const struct token t_show_rib[] = {
-@@ -187,6 +198,7 @@ static const struct token t_show_neighbo
+ { 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},
@@ -91,7 +175,33 @@ diff -u -p -r1.1.1.6 -r1.6
{ ENDTOKEN, "", NONE, NULL}
};
-@@ -311,6 +323,22 @@ static const struct token t_irrfilter_op
+@@ -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}
};
@@ -114,34 +224,34 @@ diff -u -p -r1.1.1.6 -r1.6
static struct parse_result res;
const struct token *match_token(int *argc, char **argv[],
-@@ -404,15 +432,22 @@ match_token(int *argc, char **argv[], co
+@@ -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.aid = AID_INET;
-+ }
-+ if (!strcmp(word, "inet6") ||
-+ !strcasecmp(word, "IPv6")) {
match++;
t = &table[i];
- res.af = AF_INET;
-+ res.aid = AID_INET6;
++ res.aid = AID_INET;
}
- if (!strcmp(word, "inet6") || !strcmp(word, "IPv6")) {
-+ if (!strcasecmp(word, "VPNv4")) {
++ 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 +520,7 @@ match_token(int *argc, char **argv[], co
+@@ -485,6 +560,7 @@ match_token(int *argc, char **argv[], co
case PREPNBR:
case PREPSELF:
case WEIGHT:
@@ -149,7 +259,31 @@ diff -u -p -r1.1.1.6 -r1.6
if (word != NULL && strlen(word) > 0 &&
parse_number(word, &res, table[i].type)) {
match++;
-@@ -577,6 +613,9 @@ show_valid_args(const struct token table
+@@ -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;
@@ -159,7 +293,7 @@ diff -u -p -r1.1.1.6 -r1.6
case NEXTHOP:
fprintf(stderr, " <address>\n");
break;
-@@ -584,7 +623,7 @@ show_valid_args(const struct token table
+@@ -584,11 +680,14 @@ show_valid_args(const struct token table
fprintf(stderr, " <pftable>\n");
break;
case FAMILY:
@@ -168,7 +302,14 @@ diff -u -p -r1.1.1.6 -r1.6
break;
case GETOPT:
fprintf(stderr, " <options>\n");
-@@ -608,7 +647,7 @@ parse_addr(const char *word, struct bgpd
+ 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) {
@@ -177,7 +318,7 @@ diff -u -p -r1.1.1.6 -r1.6
addr->v4 = ina;
return (1);
}
-@@ -618,13 +657,7 @@ parse_addr(const char *word, struct bgpd
+@@ -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) {
@@ -192,7 +333,16 @@ diff -u -p -r1.1.1.6 -r1.6
freeaddrinfo(r);
return (1);
}
-@@ -663,15 +696,15 @@ parse_prefix(const char *word, struct bg
+@@ -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);
@@ -211,7 +361,7 @@ diff -u -p -r1.1.1.6 -r1.6
if (mask == -1)
mask = 128;
inet6applymask(&addr->v6, &addr->v6, mask);
-@@ -706,7 +739,7 @@ parse_asnum(const char *word, u_int32_t
+@@ -706,7 +799,7 @@ parse_asnum(const char *word, u_int32_t
if (errstr)
errx(1, "AS number is %s: %s", errstr, word);
} else {
@@ -220,7 +370,7 @@ diff -u -p -r1.1.1.6 -r1.6
if (errstr)
errx(1, "AS number is %s: %s", errstr, word);
}
-@@ -730,6 +763,11 @@ parse_number(const char *word, struct pa
+@@ -730,6 +823,11 @@ parse_number(const char *word, struct pa
errx(1, "number is %s: %s", errstr, word);
/* number was parseable */
@@ -232,7 +382,7 @@ diff -u -p -r1.1.1.6 -r1.6
if ((fs = calloc(1, sizeof(struct filter_set))) == NULL)
err(1, NULL);
switch (type) {
-@@ -882,8 +920,14 @@ bgpctl_getopt(int *argc, char **argv[],
+@@ -882,8 +980,14 @@ bgpctl_getopt(int *argc, char **argv[],
int ch;
optind = optreset = 1;
diff --git a/net/openbgpd/files/patch-bgpctl_parser.h b/net/openbgpd/files/patch-bgpctl_parser.h
index bf86d255a853..1d570c747a7c 100644
--- a/net/openbgpd/files/patch-bgpctl_parser.h
+++ b/net/openbgpd/files/patch-bgpctl_parser.h
@@ -2,25 +2,27 @@ 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.8
-diff -u -p -r1.1.1.6 -r1.1.1.8
+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 12 Jun 2011 10:44:54 -0000 1.1.1.8
++++ 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.22 2010/05/03 13:11: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,6 +29,7 @@ enum actions {
+@@ -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,
-@@ -37,6 +38,8 @@ enum actions {
+ SHOW_INTERFACE,
+@@ -37,6 +39,8 @@ enum actions {
FIB,
FIB_COUPLE,
FIB_DECOUPLE,
@@ -29,7 +31,15 @@ diff -u -p -r1.1.1.6 -r1.1.1.8
NEIGHBOR,
NEIGHBOR_UP,
NEIGHBOR_DOWN,
-@@ -59,9 +62,10 @@ struct parse_result {
+@@ -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;
@@ -39,6 +49,7 @@ diff -u -p -r1.1.1.6 -r1.1.1.8
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
index 3ae7685e7cc1..0e4b86c84b6e 100644
--- a/net/openbgpd/files/patch-bgpctl_whois.c
+++ b/net/openbgpd/files/patch-bgpctl_whois.c
@@ -2,16 +2,10 @@ 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.6
-diff -u -p -r1.1.1.5 -r1.1.1.6
+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 14 Feb 2010 20:27:21 -0000 1.1.1.6
-@@ -1,4 +1,4 @@
--/* $OpenBSD: whois.c,v 1.3 2007/03/05 16:43:24 henning Exp $ */
-+/* $OpenBSD: whois.c,v 1.4 2009/09/08 15:40:25 claudio Exp $ */
-
- /*
- * Copyright (c) 2007 Henning Brauer <henning@openbsd.org>
++++ bgpctl/whois.c 13 Oct 2012 18:22:54 -0000 1.1.1.7
@@ -68,7 +68,8 @@ char *qtype_opts[] = {
"",
"-T aut-num",
diff --git a/net/openbgpd/files/patch-bgpd_Makefile b/net/openbgpd/files/patch-bgpd_Makefile
index 9bc06ffb1090..f946c920b826 100644
--- a/net/openbgpd/files/patch-bgpd_Makefile
+++ b/net/openbgpd/files/patch-bgpd_Makefile
@@ -2,18 +2,17 @@ Index: bgpd/Makefile
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/Makefile,v
retrieving revision 1.1.1.2
-retrieving revision 1.8
-diff -u -p -r1.1.1.2 -r1.8
+retrieving revision 1.9
+diff -u -p -r1.1.1.2 -r1.9
--- bgpd/Makefile 9 Jul 2009 16:49:54 -0000 1.1.1.2
-+++ bgpd/Makefile 3 Jul 2011 04:46:36 -0000 1.8
++++ bgpd/Makefile 13 Oct 2012 18:36:00 -0000 1.9
@@ -1,15 +1,25 @@
--# $OpenBSD: Makefile,v 1.28 2009/06/25 14:14:54 deraadt Exp $
-+# $OpenBSD: Makefile,v 1.29 2010/05/26 16:44:32 nicm Exp $
-+
+ # $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 \
diff --git a/net/openbgpd/files/patch-bgpd_bgpd.8 b/net/openbgpd/files/patch-bgpd_bgpd.8
index e666cb96d92c..f59cd5269f2c 100644
--- a/net/openbgpd/files/patch-bgpd_bgpd.8
+++ b/net/openbgpd/files/patch-bgpd_bgpd.8
@@ -2,13 +2,13 @@ Index: bgpd/bgpd.8
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.8,v
retrieving revision 1.1.1.8
-retrieving revision 1.9
-diff -u -p -r1.1.1.8 -r1.9
+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 2 Jul 2011 16:06:38 -0000 1.9
++++ 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.33 2009/12/16 15:40:55 claudio Exp $
++.\" $OpenBSD: bgpd.8,v 1.45 2012/08/24 20:13:03 jmc Exp $
.\"
.\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
.\"
@@ -17,7 +17,7 @@ diff -u -p -r1.1.1.8 -r1.9
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: January 13 2009 $
-+.Dd $Mdocdate: June 27 2010 $
++.Dd $Mdocdate: August 24 2012 $
.Dt BGPD 8
.Os
.Sh NAME
@@ -35,13 +35,105 @@ diff -u -p -r1.1.1.8 -r1.9
.Ek
.Sh DESCRIPTION
.Nm
-@@ -42,15 +38,15 @@ concerning
+@@ -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.
- Please refer to that document for more information about BGP.
++.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
@@ -54,7 +146,7 @@ diff -u -p -r1.1.1.8 -r1.9
.Pp
See
.Xr rc 8
-@@ -117,25 +113,16 @@ Use
+@@ -117,25 +204,16 @@ Use
.Ar file
as the configuration file,
instead of the default
@@ -82,83 +174,175 @@ diff -u -p -r1.1.1.8 -r1.9
default
.Nm
configuration file
-@@ -150,9 +137,9 @@ control socket
+@@ -149,55 +227,144 @@ control socket
+ .Xr bgpctl 8 ,
.Xr bgplg 8 ,
.Xr bgplgsh 8
++.Sh STANDARDS
.Rs
-.%R RFC 1771
-+.%R RFC 4271
- .%T "A Border Gateway Protocol 4 (BGP-4)"
+-.%T "A Border Gateway Protocol 4 (BGP-4)"
-.%D March 1995
-+.%D January 2006
+-.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 1997
-@@ -165,6 +152,11 @@ control socket
+-.%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 2545
-+.%T "Use of BGP-4 Multiprotocol Extensions for IPv6 Inter-Domain Routing"
+-.%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
-+.Re
-+.Rs
- .%R RFC 2796
- .%T "BGP Route Reflection - An Alternative to Full Mesh IBGP"
- .%D April 2000
-@@ -175,11 +167,6 @@ control socket
++.%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
--.Re
--.Rs
- .%R RFC 3682
- .%T "The Generalized TTL Security Mechanism (GTSM)"
- .%D February 2004
-@@ -190,6 +177,21 @@ control socket
- .%D April 2004
++.%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"
++.%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
-+.%R RFC 4364
-+.%T "BGP/MPLS IP Virtual Private Networks (VPNs)"
-+.%D February 2006
++.%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
-+.%R RFC 4486
-+.%T "BGP Cease Notification Message Subcodes"
++.%A E. Chen
++.%A V. Gillet
+.%D April 2006
++.%R RFC 4486
++.%T Subcodes for BGP Cease Notification Message
+.Re
++.Pp
+.Rs
- .%R RFC 4760
- .%T "Multiprotocol Extensions for BGP-4"
++.%A T. Bates
++.%A R. Chandra
++.%A D. Katz
++.%A Y. Rekhter
.%D January 2007
-@@ -199,6 +201,21 @@ control socket
- .%T "BGP Support for Four-octet AS Number Space"
- .%D May 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
-+.%R RFC 5492
-+.%T "Capabilities Advertisement with BGP-4"
++.%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
-+.%R draft-ietf-idr-optional-transitive-00
-+.%T "Error Handling for Optional Transitive BGP Attributes"
+.%D April 2009
++.%R draft-ietf-idr-optional-transitive-00
++.%T Error Handling for Optional Transitive BGP Attributes
+.Re
++.Pp
+.Rs
-+.%R draft-ietf-idr-fsm-subcode-00
-+.%T "Subcodes for BGP Finite State Machine Error"
-+.%D September 2010
++.%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
- .Nm
diff --git a/net/openbgpd/files/patch-bgpd_bgpd.c b/net/openbgpd/files/patch-bgpd_bgpd.c
index 73190ce9b93f..43fb3eb010a2 100644
--- a/net/openbgpd/files/patch-bgpd_bgpd.c
+++ b/net/openbgpd/files/patch-bgpd_bgpd.c
@@ -2,12 +2,13 @@ Index: bgpd/bgpd.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.c,v
retrieving revision 1.1.1.7
-diff -u -p -r1.1.1.7 bgpd.c
+retrieving revision 1.1.1.11
+diff -u -p -r1.1.1.7 -r1.1.1.11
--- bgpd/bgpd.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/bgpd.c 3 Jul 2011 04:34:14 -0000
++++ bgpd/bgpd.c 13 Oct 2012 18:22:38 -0000 1.1.1.11
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.148 2009/06/07 00:30:23 claudio Exp $ */
-+/* $OpenBSD: bgpd.c,v 1.167 2011/05/01 10:42:28 claudio Exp $ */
++/* $OpenBSD: bgpd.c,v 1.168 2011/08/20 19:02:28 sthen Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -21,7 +22,7 @@ diff -u -p -r1.1.1.7 bgpd.c
#include "session.h"
void sighdlr(int);
-@@ -42,23 +42,22 @@ int main(int, char *[]);
+@@ -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 *,
@@ -47,6 +48,7 @@ diff -u -p -r1.1.1.7 bgpd.c
+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);
@@ -55,7 +57,7 @@ diff -u -p -r1.1.1.7 bgpd.c
void
sighdlr(int sig)
-@@ -86,8 +85,8 @@ usage(void)
+@@ -86,8 +86,8 @@ usage(void)
{
extern char *__progname;
@@ -66,7 +68,7 @@ diff -u -p -r1.1.1.7 bgpd.c
exit(1);
}
-@@ -101,15 +100,10 @@ int
+@@ -101,15 +101,10 @@ int
main(int argc, char *argv[])
{
struct bgpd_config conf;
@@ -83,13 +85,15 @@ diff -u -p -r1.1.1.7 bgpd.c
struct pollfd pfd[POLL_MAX];
pid_t io_pid = 0, rde_pid = 0, pid;
char *conffile;
-@@ -125,17 +119,11 @@ main(int argc, char *argv[])
+@@ -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);
@@ -102,7 +106,7 @@ diff -u -p -r1.1.1.7 bgpd.c
switch (ch) {
case 'c':
conf.opts |= BGPD_OPT_FORCE_DEMOTE;
-@@ -158,12 +146,7 @@ main(int argc, char *argv[])
+@@ -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;
@@ -116,7 +120,7 @@ diff -u -p -r1.1.1.7 bgpd.c
break;
default:
usage();
-@@ -176,24 +159,22 @@ main(int argc, char *argv[])
+@@ -176,24 +161,22 @@ main(int argc, char *argv[])
if (argc > 0)
usage();
@@ -151,7 +155,15 @@ diff -u -p -r1.1.1.7 bgpd.c
if (geteuid())
errx(1, "need root privileges");
-@@ -225,13 +206,9 @@ main(int argc, char *argv[])
+@@ -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);
@@ -167,7 +179,7 @@ diff -u -p -r1.1.1.7 bgpd.c
setproctitle("parent");
-@@ -254,33 +231,12 @@ main(int argc, char *argv[])
+@@ -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);
@@ -203,17 +215,27 @@ diff -u -p -r1.1.1.7 bgpd.c
while (quit == 0) {
bzero(pfd, sizeof(pfd));
pfd[PFD_PIPE_SESSION].fd = ibuf_se->fd;
-@@ -336,8 +292,7 @@ main(int argc, char *argv[])
+@@ -335,15 +294,16 @@ main(int argc, char *argv[])
+ u_int error;
reconfig = 0;
- log_info("rereading config");
+- 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;
-@@ -389,13 +344,13 @@ main(int argc, char *argv[])
+ 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);
}
@@ -233,7 +255,7 @@ diff -u -p -r1.1.1.7 bgpd.c
control_cleanup(conf.csock);
control_cleanup(conf.rcsock);
carp_demote_shutdown();
-@@ -413,6 +368,8 @@ main(int argc, char *argv[])
+@@ -413,6 +373,8 @@ main(int argc, char *argv[])
free(ibuf_se);
msgbuf_clear(&ibuf_rde->w);
free(ibuf_rde);
@@ -242,7 +264,7 @@ diff -u -p -r1.1.1.7 bgpd.c
log_info("Terminating");
return (0);
-@@ -452,27 +409,25 @@ send_filterset(struct imsgbuf *i, struct
+@@ -452,27 +414,32 @@ send_filterset(struct imsgbuf *i, struct
int
reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l,
@@ -260,6 +282,13 @@ diff -u -p -r1.1.1.7 bgpd.c
+ 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",
@@ -276,7 +305,7 @@ diff -u -p -r1.1.1.7 bgpd.c
prepare_listeners(conf);
/* start reconfiguration */
-@@ -483,12 +438,6 @@ reconfigure(char *conffile, struct bgpd_
+@@ -483,12 +450,6 @@ reconfigure(char *conffile, struct bgpd_
conf, sizeof(struct bgpd_config)) == -1)
return (-1);
@@ -289,7 +318,7 @@ diff -u -p -r1.1.1.7 bgpd.c
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 +445,104 @@ reconfigure(char *conffile, struct bgpd_
+@@ -496,51 +457,104 @@ reconfigure(char *conffile, struct bgpd_
la->fd = -1;
}
@@ -411,7 +440,7 @@ diff -u -p -r1.1.1.7 bgpd.c
/* mrt changes can be sent out of bound */
mrt_reconfigure(mrt_l);
return (0);
-@@ -550,8 +552,8 @@ int
+@@ -550,8 +564,8 @@ int
dispatch_imsg(struct imsgbuf *ibuf, int idx)
{
struct imsg imsg;
@@ -422,7 +451,7 @@ diff -u -p -r1.1.1.7 bgpd.c
if ((n = imsg_read(ibuf)) == -1)
return (-1);
-@@ -573,46 +575,39 @@ dispatch_imsg(struct imsgbuf *ibuf, int
+@@ -573,46 +587,39 @@ dispatch_imsg(struct imsgbuf *ibuf, int
case IMSG_KROUTE_CHANGE:
if (idx != PFD_PIPE_ROUTE)
log_warnx("route request not from RDE");
@@ -487,7 +516,17 @@ diff -u -p -r1.1.1.7 bgpd.c
break;
case IMSG_PFTABLE_ADD:
if (idx != PFD_PIPE_ROUTE)
-@@ -654,18 +649,19 @@ dispatch_imsg(struct imsgbuf *ibuf, int
+@@ -646,26 +653,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
@@ -509,7 +548,7 @@ diff -u -p -r1.1.1.7 bgpd.c
if (idx != PFD_PIPE_SESSION)
log_warnx("kroute request not from SE");
else
-@@ -692,6 +688,11 @@ dispatch_imsg(struct imsgbuf *ibuf, int
+@@ -692,6 +701,16 @@ dispatch_imsg(struct imsgbuf *ibuf, int
carp_demote_set(msg->demote_group, msg->level);
}
break;
@@ -518,10 +557,15 @@ diff -u -p -r1.1.1.7 bgpd.c
+ 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 +708,7 @@ send_nexthop_update(struct kroute_nextho
+@@ -707,7 +726,7 @@ send_nexthop_update(struct kroute_nextho
{
char *gw = NULL;
@@ -530,7 +574,7 @@ diff -u -p -r1.1.1.7 bgpd.c
if (asprintf(&gw, ": via %s",
log_addr(&msg->gateway)) == -1) {
log_warn("send_nexthop_update");
-@@ -717,7 +718,7 @@ send_nexthop_update(struct kroute_nextho
+@@ -717,7 +736,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" : "",
@@ -539,7 +583,7 @@ diff -u -p -r1.1.1.7 bgpd.c
free(gw);
-@@ -733,56 +734,20 @@ send_imsg_session(int type, pid_t pid, v
+@@ -733,56 +752,20 @@ send_imsg_session(int type, pid_t pid, v
}
int
@@ -600,7 +644,7 @@ diff -u -p -r1.1.1.7 bgpd.c
}
int
-@@ -810,3 +775,45 @@ bgpd_filternexthop(struct kroute *kr, st
+@@ -810,3 +793,45 @@ bgpd_filternexthop(struct kroute *kr, st
return (1);
}
diff --git a/net/openbgpd/files/patch-bgpd_bgpd.conf.5 b/net/openbgpd/files/patch-bgpd_bgpd.conf.5
index 3b8afd260fd6..306de76703d7 100644
--- a/net/openbgpd/files/patch-bgpd_bgpd.conf.5
+++ b/net/openbgpd/files/patch-bgpd_bgpd.conf.5
@@ -2,13 +2,13 @@ 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.8
-diff -u -p -r1.1.1.7 -r1.8
+retrieving revision 1.9
+diff -u -p -r1.1.1.7 -r1.9
--- bgpd/bgpd.conf.5 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/bgpd.conf.5 2 Jul 2011 16:06:38 -0000 1.8
++++ bgpd/bgpd.conf.5 13 Oct 2012 18:36:00 -0000 1.9
@@ -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.104 2010/03/05 15:25:00 claudio Exp $
++.\" $OpenBSD: bgpd.conf.5,v 1.120 2012/07/07 08:22:57 claudio Exp $
.\"
.\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
.\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -17,11 +17,11 @@ diff -u -p -r1.1.1.7 -r1.8
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: June 7 2009 $
-+.Dd $Mdocdate: October 23 2010 $
++.Dd $Mdocdate: July 7 2012 $
.Dt BGPD.CONF 5
.Os
.Sh NAME
-@@ -26,7 +26,7 @@
+@@ -26,11 +26,11 @@
The
.Xr bgpd 8
daemon implements the Border Gateway Protocol version 4 as described
@@ -30,6 +30,11 @@ diff -u -p -r1.1.1.7 -r1.8
.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
@@ -39,7 +44,35 @@ diff -u -p -r1.1.1.7 -r1.8
.It Sy Neighbors and Groups
.Xr bgpd 8
establishes sessions with
-@@ -93,7 +95,7 @@ Set the local
+@@ -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 .
@@ -48,12 +81,12 @@ diff -u -p -r1.1.1.7 -r1.8
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,13 +145,13 @@ The default is 120 seconds.
+@@ -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
++.Pq Ic table Ns | Ns Ic table-mp Ns | Ns Ic table-v2
.Ar file Op Ar timeout
.Xc
.It Xo
@@ -65,7 +98,31 @@ diff -u -p -r1.1.1.7 -r1.8
.Ar file Op Ar timeout
.Xc
Dump the RIB, a.k.a. the
-@@ -195,7 +197,7 @@ dump updates out "/tmp/updates-out-%H%M"
+ .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
@@ -74,7 +131,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Xc
If set to
.Ic no ,
-@@ -242,12 +244,12 @@ Log received and sent updates.
+@@ -242,12 +255,12 @@ Log received and sent updates.
.Xc
.It Xo
.Ic network
@@ -89,7 +146,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Ic connected Op Ic set ...\&
.Xc
Announce the specified network as belonging to our AS.
-@@ -278,7 +280,7 @@ section.
+@@ -278,7 +291,7 @@ section.
.Ic nexthop
.Ic qualify
.Ic via
@@ -98,7 +155,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Xc
If set to
.Ic bgp ,
-@@ -295,7 +297,7 @@ daemons like
+@@ -295,38 +308,47 @@ daemons like
.Ic rde
.Ic med
.Ic compare
@@ -107,7 +164,19 @@ diff -u -p -r1.1.1.7 -r1.8
.Xc
If set to
.Ic always ,
-@@ -313,20 +315,31 @@ is only compared between peers belonging
+ 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
@@ -142,7 +211,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Xc
If set to
.Ic evaluate ,
-@@ -339,7 +352,7 @@ The default is
+@@ -339,7 +361,7 @@ The default is
.Pp
.It Xo
.Ic route-collector
@@ -151,7 +220,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Xc
If set to
.Ic yes ,
-@@ -361,13 +374,24 @@ to the local machine.
+@@ -361,13 +383,24 @@ to the local machine.
Work with the given kernel routing table
instead of the default table,
.Ar 0 .
@@ -180,7 +249,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Xc
If set to
.Ic yes ,
-@@ -376,6 +400,111 @@ to EBGP neighbors are not prepended with
+@@ -376,6 +409,111 @@ to EBGP neighbors are not prepended with
The default is
.Ic no .
.El
@@ -270,13 +339,13 @@ diff -u -p -r1.1.1.7 -r1.8
+.Pp
+.It Ic rd Ar as-number Ns Li : Ns Ar local
+.It Ic rd Ar IP Ns Li : Ns Ar local
-+The Route Distinguishers uniquely identifies a set of VPN prefixes.
-+Only prefixes matching the
++The sole purpose of the Route Distinguisher
+.Ic rd
-+will be imported into the routing domain.
-+The purpose of the
++is to ensure that possible common prefixes are destinct between VPNs.
++The
+.Ic rd
-+is solely to allow one to create distinct routes to a common address prefix.
++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
@@ -292,7 +361,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Sh NEIGHBORS AND GROUPS
.Xr bgpd 8
establishes TCP connections to other BGP speakers called
-@@ -470,21 +599,35 @@ The default for IBGP peers is
+@@ -470,21 +608,35 @@ The default for IBGP peers is
.Pp
.It Xo
.Ic announce
@@ -334,7 +403,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Xc
If set to
.Ic no ,
-@@ -493,6 +636,29 @@ This can be helpful to connect to old or
+@@ -493,6 +645,29 @@ This can be helpful to connect to old or
The default is
.Ic yes .
.Pp
@@ -364,7 +433,7 @@ diff -u -p -r1.1.1.7 -r1.8
.It Ic demote Ar group
Increase the
.Xr carp 4
-@@ -504,7 +670,7 @@ The demotion counter will be increased a
+@@ -504,7 +679,7 @@ The demotion counter will be increased a
.Xr bgpd 8
starts and decreased
60 seconds after the session went to state
@@ -373,7 +442,7 @@ diff -u -p -r1.1.1.7 -r1.8
For neighbors added at runtime, the demotion counter is only increased after
the session has been
.Em ESTABLISHED
-@@ -548,8 +714,8 @@ Do not start the session when bgpd comes
+@@ -548,8 +723,8 @@ Do not start the session when bgpd comes
.Pp
.It Xo
.Ic dump
@@ -384,7 +453,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Ar file Op Ar timeout
.Xc
Do a peer specific MRT dump.
-@@ -564,7 +730,7 @@ section in
+@@ -564,7 +739,7 @@ section in
.Pp
.It Xo
.Ic enforce neighbor-as
@@ -393,7 +462,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Xc
If set to
.Ic yes ,
-@@ -589,10 +755,16 @@ Inherited from the global configuration
+@@ -589,10 +764,16 @@ Inherited from the global configuration
Set the minimal acceptable holdtime.
Inherited from the global configuration if not given.
.Pp
@@ -412,7 +481,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Ic spi Ar spi-number authspec Op Ar encspec
.Xc
Enable IPsec with static keying.
-@@ -627,7 +799,7 @@ Keys must be given in hexadecimal format
+@@ -627,7 +808,7 @@ Keys must be given in hexadecimal format
.Pp
.It Xo
.Ic ipsec
@@ -421,7 +490,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Ic ike
.Xc
Enable IPsec with dynamic keying.
-@@ -639,11 +811,11 @@ is responsible for managing the session
+@@ -639,11 +820,11 @@ is responsible for managing the session
With
.Xr isakmpd 8 ,
it is sufficient to copy the peer's public key, found in
@@ -435,7 +504,7 @@ diff -u -p -r1.1.1.7 -r1.8
The local public key must be copied to the peer in the same way.
As
.Xr bgpd 8
-@@ -698,7 +870,7 @@ Do not attempt to actively open a TCP co
+@@ -698,11 +879,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
@@ -444,7 +513,12 @@ diff -u -p -r1.1.1.7 -r1.8
Bind the neighbor to the specified RIB.
.Pp
.It Ic route-reflector Op Ar address
-@@ -732,8 +904,8 @@ These sets are rewritten into filter rul
+-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 +913,8 @@ These sets are rewritten into filter rul
.Pp
.It Xo
.Ic softreconfig
@@ -455,7 +529,7 @@ diff -u -p -r1.1.1.7 -r1.8
.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 +932,7 @@ tcp md5sig key deadbeef
+@@ -760,7 +941,7 @@ tcp md5sig key deadbeef
.Pp
.It Xo
.Ic transparent-as
@@ -464,7 +538,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Xc
If set to
.Ic yes ,
-@@ -772,7 +944,7 @@ setting.
+@@ -772,7 +953,7 @@ setting.
.Pp
.It Xo
.Ic ttl-security
@@ -473,7 +547,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Xc
Enable or disable ttl-security.
When enabled,
-@@ -849,6 +1021,10 @@ is matched against a part of the
+@@ -849,6 +1030,10 @@ is matched against a part of the
.Em AS path
specified by the
.Ar as-type .
@@ -484,7 +558,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Ar as-type
is one of the following operators:
.Pp
-@@ -917,7 +1093,32 @@ may be set to
+@@ -917,7 +1102,32 @@ may be set to
which is expanded to the current neighbor remote AS number.
.Pp
.It Xo
@@ -518,7 +592,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Ar peer
.Xc
This rule applies only to
-@@ -945,7 +1146,7 @@ if enclosed in curly brackets:
+@@ -945,7 +1155,7 @@ if enclosed in curly brackets:
deny from { 128.251.16.1, 251.128.16.2, group hojo }
.Ed
.Pp
@@ -527,7 +601,7 @@ diff -u -p -r1.1.1.7 -r1.8
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 +1154,24 @@ without specifying a
+@@ -953,6 +1163,24 @@ without specifying a
.Ic prefix
beforehand.
.Pp
@@ -552,7 +626,7 @@ diff -u -p -r1.1.1.7 -r1.8
.It Xo
.Ic prefix
.Ar address Ns Li / Ns Ar len
-@@ -1028,6 +1247,12 @@ matches a rule which has the
+@@ -1028,6 +1256,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
@@ -565,7 +639,7 @@ diff -u -p -r1.1.1.7 -r1.8
.It Ic set Ar attribute ...
All matching rules can set the
.Em AS path attributes
-@@ -1079,6 +1304,48 @@ Alternately, well-known communities may
+@@ -1079,6 +1313,48 @@ Alternately, well-known communities may
or
.Ic NO_PEER .
.Pp
@@ -614,7 +688,7 @@ diff -u -p -r1.1.1.7 -r1.8
.It Ic localpref Ar number
Set the
.Em LOCAL_PREF
-@@ -1108,6 +1375,20 @@ otherwise it will be set to
+@@ -1108,6 +1384,20 @@ otherwise it will be set to
.Ar number .
.Pp
.It Xo
@@ -635,7 +709,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Ic nexthop
.Sm off
.Po Ar address \*(Ba
-@@ -1157,9 +1438,8 @@ times to the
+@@ -1157,9 +1447,8 @@ times to the
.Em AS path .
.Pp
.It Ic rtlabel Ar label
@@ -647,7 +721,7 @@ diff -u -p -r1.1.1.7 -r1.8
.Pp
.It Ic weight Ar number
The
-@@ -1181,8 +1461,8 @@ For prefixes with equally long paths, th
+@@ -1181,8 +1470,8 @@ For prefixes with equally long paths, th
is selected.
.El
.Sh FILES
diff --git a/net/openbgpd/files/patch-bgpd_bgpd.h b/net/openbgpd/files/patch-bgpd_bgpd.h
index c374b981553c..a624b0796bd8 100644
--- a/net/openbgpd/files/patch-bgpd_bgpd.h
+++ b/net/openbgpd/files/patch-bgpd_bgpd.h
@@ -2,13 +2,13 @@ Index: bgpd/bgpd.h
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.h,v
retrieving revision 1.1.1.8
-retrieving revision 1.12
-diff -u -p -r1.1.1.8 -r1.12
+retrieving revision 1.13
+diff -u -p -r1.1.1.8 -r1.13
--- bgpd/bgpd.h 14 Feb 2010 20:19:57 -0000 1.1.1.8
-+++ bgpd/bgpd.h 2 Jul 2011 16:06:38 -0000 1.12
++++ bgpd/bgpd.h 13 Oct 2012 18:36:00 -0000 1.13
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.241 2009/06/12 16:42:53 claudio Exp $ */
-+/* $OpenBSD: bgpd.h,v 1.255 2010/04/06 13:25:08 claudio Exp $ */
++/* $OpenBSD: bgpd.h,v 1.272 2012/09/18 09:45:51 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -61,7 +61,7 @@ diff -u -p -r1.1.1.8 -r1.12
#define BGPD_FLAG_NEXTHOP_BGP 0x0080
#define BGPD_FLAG_NEXTHOP_DEFAULT 0x1000
#define BGPD_FLAG_DECISION_MASK 0x0f00
-@@ -83,6 +82,8 @@
+@@ -83,9 +82,12 @@
#define F_REJECT 0x0080
#define F_BLACKHOLE 0x0100
#define F_LONGER 0x0200
@@ -70,7 +70,11 @@ diff -u -p -r1.1.1.8 -r1.12
#define F_CTL_DETAIL 0x1000 /* only used by bgpctl */
#define F_CTL_ADJ_IN 0x2000
#define F_CTL_ADJ_OUT 0x4000
-@@ -109,18 +110,74 @@ enum reconf_action {
++#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
};
@@ -100,6 +104,7 @@ diff -u -p -r1.1.1.8 -r1.12
+#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 */ \
@@ -149,7 +154,7 @@ diff -u -p -r1.1.1.8 -r1.12
#define addr8 ba.addr8
#define addr16 ba.addr16
#define addr32 ba.addr32
-@@ -141,17 +198,12 @@ TAILQ_HEAD(listen_addrs, listen_addr);
+@@ -141,17 +200,12 @@ TAILQ_HEAD(listen_addrs, listen_addr);
TAILQ_HEAD(filter_set_head, filter_set);
struct bgpd_config {
@@ -167,7 +172,7 @@ diff -u -p -r1.1.1.8 -r1.12
u_int32_t bgpid;
u_int32_t clusterid;
u_int32_t as;
-@@ -205,11 +257,10 @@ struct peer_auth {
+@@ -205,12 +259,24 @@ struct peer_auth {
};
struct capabilities {
@@ -176,14 +181,38 @@ diff -u -p -r1.1.1.8 -r1.12
- 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 */
-+ int8_t mp[AID_MAX]; /* multiprotocol extensions, RFC 4760 */
-+ int8_t refresh; /* route refresh, RFC 2918 */
-+ int8_t restart; /* graceful restart, RFC 4724 */
-+ 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 {
-@@ -248,21 +299,31 @@ 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];
@@ -195,16 +224,21 @@ diff -u -p -r1.1.1.8 -r1.12
+enum network_type {
+ NETWORK_DEFAULT,
+ NETWORK_STATIC,
-+ NETWORK_CONNECTED
++ NETWORK_CONNECTED,
++ NETWORK_MRTCLONE
+};
+
struct network_config {
- struct bgpd_addr prefix;
- struct filter_set_head attrset;
-+ u_int rtableid;
-+ enum network_type type;
- u_int8_t prefixlen;
-+ u_int8_t old; /* used for reloading */
+- 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);
@@ -217,7 +251,7 @@ diff -u -p -r1.1.1.8 -r1.12
};
enum imsg_type {
-@@ -276,7 +337,6 @@ enum imsg_type {
+@@ -276,7 +354,6 @@ enum imsg_type {
IMSG_CTL_NEIGHBOR_CLEAR,
IMSG_CTL_NEIGHBOR_RREFRESH,
IMSG_CTL_KROUTE,
@@ -225,7 +259,7 @@ diff -u -p -r1.1.1.8 -r1.12
IMSG_CTL_KROUTE_ADDR,
IMSG_CTL_RESULT,
IMSG_CTL_SHOW_NEIGHBOR,
-@@ -288,10 +348,11 @@ enum imsg_type {
+@@ -288,11 +365,14 @@ enum imsg_type {
IMSG_CTL_SHOW_RIB_ATTR,
IMSG_CTL_SHOW_RIB_COMMUNITY,
IMSG_CTL_SHOW_NETWORK,
@@ -236,9 +270,12 @@ diff -u -p -r1.1.1.8 -r1.12
+ IMSG_CTL_LOG_VERBOSE,
+ IMSG_CTL_SHOW_FIB_TABLES,
IMSG_NETWORK_ADD,
++ IMSG_NETWORK_ASPATH,
++ IMSG_NETWORK_ATTR,
IMSG_NETWORK_REMOVE,
IMSG_NETWORK_FLUSH,
-@@ -302,6 +363,11 @@ enum imsg_type {
+ IMSG_NETWORK_DONE,
+@@ -302,19 +382,25 @@ enum imsg_type {
IMSG_RECONF_PEER,
IMSG_RECONF_FILTER,
IMSG_RECONF_LISTENER,
@@ -250,7 +287,14 @@ diff -u -p -r1.1.1.8 -r1.12
IMSG_RECONF_DONE,
IMSG_UPDATE,
IMSG_UPDATE_ERR,
-@@ -313,8 +379,6 @@ enum imsg_type {
+ 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,
@@ -259,7 +303,15 @@ diff -u -p -r1.1.1.8 -r1.12
IMSG_NEXTHOP_ADD,
IMSG_NEXTHOP_REMOVE,
IMSG_NEXTHOP_UPDATE,
-@@ -379,9 +443,43 @@ enum suberr_cease {
+@@ -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
};
@@ -303,7 +355,7 @@ diff -u -p -r1.1.1.8 -r1.12
u_int16_t flags;
u_int16_t labelid;
u_short ifindex;
-@@ -400,14 +498,12 @@ struct kroute6 {
+@@ -400,14 +521,12 @@ struct kroute6 {
};
struct kroute_nexthop {
@@ -320,7 +372,7 @@ diff -u -p -r1.1.1.8 -r1.12
};
struct kif {
-@@ -423,8 +519,7 @@ struct kif {
+@@ -423,8 +542,7 @@ struct kif {
struct session_up {
struct bgpd_addr local_addr;
struct bgpd_addr remote_addr;
@@ -330,7 +382,7 @@ diff -u -p -r1.1.1.8 -r1.12
u_int32_t remote_bgpid;
u_int16_t short_as;
};
-@@ -437,8 +532,13 @@ struct pftable_msg {
+@@ -437,8 +555,13 @@ struct pftable_msg {
struct ctl_show_nexthop {
struct bgpd_addr addr;
@@ -345,7 +397,7 @@ diff -u -p -r1.1.1.8 -r1.12
};
struct ctl_neighbor {
-@@ -447,20 +547,10 @@ struct ctl_neighbor {
+@@ -447,20 +570,11 @@ struct ctl_neighbor {
int show_timers;
};
@@ -367,10 +419,36 @@ diff -u -p -r1.1.1.8 -r1.12
+#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;
-@@ -498,16 +588,52 @@ enum as_spec {
+@@ -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
};
@@ -385,13 +463,13 @@ diff -u -p -r1.1.1.8 -r1.12
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 {
@@ -426,7 +504,7 @@ diff -u -p -r1.1.1.8 -r1.12
struct ctl_show_rib_request {
char rib[PEER_DESCR_LEN];
struct ctl_neighbor neighbor;
-@@ -518,8 +644,8 @@ struct ctl_show_rib_request {
+@@ -518,8 +659,8 @@ struct ctl_show_rib_request {
pid_t pid;
u_int16_t flags;
enum imsg_type type;
@@ -436,7 +514,7 @@ diff -u -p -r1.1.1.8 -r1.12
};
enum filter_actions {
-@@ -585,6 +711,28 @@ struct filter_peers {
+@@ -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 */
@@ -465,7 +543,7 @@ diff -u -p -r1.1.1.8 -r1.12
struct filter_prefix {
-@@ -594,16 +742,18 @@ struct filter_prefix {
+@@ -594,16 +757,18 @@ struct filter_prefix {
struct filter_prefixlen {
enum comp_ops op;
@@ -489,7 +567,7 @@ diff -u -p -r1.1.1.8 -r1.12
};
TAILQ_HEAD(filter_head, filter_rule);
-@@ -635,10 +785,13 @@ enum action_types {
+@@ -635,10 +800,13 @@ enum action_types {
ACTION_SET_NEXTHOP_SELF,
ACTION_SET_COMMUNITY,
ACTION_DEL_COMMUNITY,
@@ -504,7 +582,7 @@ diff -u -p -r1.1.1.8 -r1.12
};
struct filter_set {
-@@ -650,23 +803,53 @@ struct filter_set {
+@@ -650,23 +818,53 @@ struct filter_set {
int32_t relative;
struct bgpd_addr nexthop;
struct filter_community community;
@@ -530,7 +608,7 @@ diff -u -p -r1.1.1.8 -r1.12
+ u_int rtableid;
+ u_int label;
+ int flags;
-+};
+ };
+SIMPLEQ_HEAD(rdomain_head, rdomain);
+
+struct rde_rib {
@@ -539,7 +617,7 @@ diff -u -p -r1.1.1.8 -r1.12
+ u_int rtableid;
+ u_int16_t id;
+ u_int16_t flags;
- };
++};
+SIMPLEQ_HEAD(rib_names, rde_rib);
+extern struct rib_names ribnames;
+
@@ -563,7 +641,7 @@ diff -u -p -r1.1.1.8 -r1.12
int64_t nexthop_cnt;
int64_t aspath_cnt;
int64_t aspath_size;
-@@ -677,38 +860,29 @@ struct rde_memstats {
+@@ -677,82 +875,117 @@ struct rde_memstats {
int64_t attr_dcnt;
};
@@ -572,7 +650,39 @@ diff -u -p -r1.1.1.8 -r1.12
- char name[PEER_DESCR_LEN];
- u_int16_t id;
- u_int16_t flags;
--};
++/* macros for IPv6 link-local address */
++#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER)
++#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;
-
@@ -580,26 +690,32 @@ diff -u -p -r1.1.1.8 -r1.12
-#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
-+/* macros for IPv6 link-local address */
-+#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER)
-+#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
++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 */
@@ -610,13 +726,25 @@ diff -u -p -r1.1.1.8 -r1.12
+ struct filter_set_head *);
int bgpd_filternexthop(struct kroute *, struct kroute6 *);
- /* 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 *, ...);
-@@ -726,19 +900,22 @@ int cmdline_symset(char *);
+-/* 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 */
@@ -648,7 +776,57 @@ diff -u -p -r1.1.1.8 -r1.12
int kr_reload(void);
struct in6_addr *prefixlen2mask6(u_int8_t prefixlen);
-@@ -772,6 +949,8 @@ void pftable_ref(u_int16_t);
+-/* 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 +1001,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 *);
@@ -657,7 +835,7 @@ diff -u -p -r1.1.1.8 -r1.12
const char *filterset_name(enum action_types);
/* util.c */
-@@ -779,11 +958,20 @@ const char *log_addr(const struct bgpd_a
+@@ -779,11 +1024,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);
@@ -666,6 +844,10 @@ diff -u -p -r1.1.1.8 -r1.12
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);
diff --git a/net/openbgpd/files/patch-bgpd_carp.c b/net/openbgpd/files/patch-bgpd_carp.c
index 7ed50075cd5c..4a93258dc940 100644
--- a/net/openbgpd/files/patch-bgpd_carp.c
+++ b/net/openbgpd/files/patch-bgpd_carp.c
@@ -2,10 +2,9 @@ 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
+diff -u -p -r1.1.1.6 carp.c
--- 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
++++ bgpd/carp.c 13 Oct 2012 18:23:46 -0000
@@ -93,9 +93,8 @@ carp_demote_shutdown(void)
while ((c = TAILQ_FIRST(&carpgroups)) != NULL) {
diff --git a/net/openbgpd/files/patch-bgpd_config.c b/net/openbgpd/files/patch-bgpd_config.c
index 3df03c1b3795..fbd02e102483 100644
--- a/net/openbgpd/files/patch-bgpd_config.c
+++ b/net/openbgpd/files/patch-bgpd_config.c
@@ -2,13 +2,13 @@ Index: bgpd/config.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/config.c,v
retrieving revision 1.1.1.6
-retrieving revision 1.2
-diff -u -p -r1.1.1.6 -r1.2
+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 2 Jul 2011 16:06:38 -0000 1.2
++++ 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.56 2010/10/24 17:20:08 deraadt 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>
diff --git a/net/openbgpd/files/patch-bgpd_control.c b/net/openbgpd/files/patch-bgpd_control.c
index 09c2ac85a831..5d6bade713cc 100644
--- a/net/openbgpd/files/patch-bgpd_control.c
+++ b/net/openbgpd/files/patch-bgpd_control.c
@@ -2,13 +2,13 @@ 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.9
-diff -u -p -r1.1.1.7 -r1.1.1.9
+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 12 Jun 2011 10:44:24 -0000 1.1.1.9
++++ 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.70 2010/10/29 12:51:53 henning Exp $ */
++/* $OpenBSD: control.c,v 1.71 2012/04/12 17:26:09 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -21,11 +21,16 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
close(fd);
return (-1);
}
-@@ -123,14 +123,14 @@ control_accept(int listenfd, int restric
+@@ -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)
+- 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);
}
@@ -39,7 +44,16 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
close(connfd);
return (0);
}
-@@ -191,7 +191,8 @@ control_dispatch_msg(struct pollfd *pfd,
+@@ -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;
@@ -49,7 +63,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
struct peer *p;
struct ctl_neighbor *neighbor;
struct ctl_show_rib_request *ribreq;
-@@ -305,7 +306,8 @@ control_dispatch_msg(struct pollfd *pfd,
+@@ -305,7 +309,8 @@ control_dispatch_msg(struct pollfd *pfd,
break;
case IMSG_CTL_FIB_COUPLE:
case IMSG_CTL_FIB_DECOUPLE:
@@ -59,7 +73,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
break;
case IMSG_CTL_NEIGHBOR_UP:
case IMSG_CTL_NEIGHBOR_DOWN:
-@@ -328,13 +330,19 @@ control_dispatch_msg(struct pollfd *pfd,
+@@ -328,13 +333,19 @@ control_dispatch_msg(struct pollfd *pfd,
control_result(c, CTL_RES_OK);
break;
case IMSG_CTL_NEIGHBOR_DOWN:
@@ -83,7 +97,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
control_result(c, CTL_RES_OK);
break;
case IMSG_CTL_NEIGHBOR_RREFRESH:
-@@ -352,13 +360,19 @@ control_dispatch_msg(struct pollfd *pfd,
+@@ -352,13 +363,19 @@ control_dispatch_msg(struct pollfd *pfd,
"wrong length");
break;
case IMSG_CTL_RELOAD:
@@ -106,7 +120,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
break;
case IMSG_CTL_SHOW_RIB:
case IMSG_CTL_SHOW_RIB_AS:
-@@ -370,7 +384,7 @@ control_dispatch_msg(struct pollfd *pfd,
+@@ -370,7 +387,7 @@ control_dispatch_msg(struct pollfd *pfd,
neighbor->descr[PEER_DESCR_LEN - 1] = 0;
ribreq->peerid = 0;
p = NULL;
@@ -115,7 +129,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
p = getpeerbyaddr(&neighbor->addr);
if (p == NULL) {
control_result(c,
-@@ -397,8 +411,7 @@ control_dispatch_msg(struct pollfd *pfd,
+@@ -397,8 +414,7 @@ control_dispatch_msg(struct pollfd *pfd,
break;
}
if ((imsg.hdr.type == IMSG_CTL_SHOW_RIB_PREFIX)
@@ -125,7 +139,16 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
/* malformed request, must specify af */
control_result(c, CTL_RES_PARSE_ERROR);
break;
-@@ -425,6 +438,20 @@ control_dispatch_msg(struct pollfd *pfd,
+@@ -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;
diff --git a/net/openbgpd/files/patch-bgpd_kroute.c b/net/openbgpd/files/patch-bgpd_kroute.c
index 6f93029d60cd..963ad6653ce4 100644
--- a/net/openbgpd/files/patch-bgpd_kroute.c
+++ b/net/openbgpd/files/patch-bgpd_kroute.c
@@ -2,13 +2,13 @@ Index: bgpd/kroute.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/kroute.c,v
retrieving revision 1.1.1.7
-retrieving revision 1.12
-diff -u -p -r1.1.1.7 -r1.12
+retrieving revision 1.13
+diff -u -p -r1.1.1.7 -r1.13
--- bgpd/kroute.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/kroute.c 3 Jul 2011 04:46:36 -0000 1.12
++++ bgpd/kroute.c 13 Oct 2012 18:36:00 -0000 1.13
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.169 2009/06/25 15:54:22 claudio Exp $ */
-+/* $OpenBSD: kroute.c,v 1.176 2010/04/06 13:25:08 claudio Exp $ */
++/* $OpenBSD: kroute.c,v 1.189 2012/05/27 18:52:07 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -106,7 +106,7 @@ diff -u -p -r1.1.1.7 -r1.12
struct kif_node *kif_find(int);
int kif_insert(struct kif_node *);
-@@ -124,13 +148,15 @@ int kif_kr6_remove(struct kroute6_nod
+@@ -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 *);
@@ -118,6 +118,7 @@ diff -u -p -r1.1.1.7 -r1.12
+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 *,
@@ -128,7 +129,7 @@ diff -u -p -r1.1.1.7 -r1.12
u_int8_t prefixlen_classful(in_addr_t);
u_int8_t mask2prefixlen(in_addr_t);
u_int8_t mask2prefixlen6(struct sockaddr_in6 *);
-@@ -138,23 +164,20 @@ void get_rtaddrs(int, struct sockaddr *
+@@ -138,23 +165,20 @@ void get_rtaddrs(int, struct sockaddr *
void if_change(u_short, int, struct if_data *);
void if_announce(void *);
@@ -156,7 +157,7 @@ diff -u -p -r1.1.1.7 -r1.12
RB_PROTOTYPE(knexthop_tree, knexthop_node, entry, knexthop_compare)
RB_GENERATE(knexthop_tree, knexthop_node, entry, knexthop_compare)
-@@ -162,19 +185,21 @@ RB_HEAD(kif_tree, kif_node) kit;
+@@ -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)
@@ -182,7 +183,7 @@ diff -u -p -r1.1.1.7 -r1.12
if ((kr_state.fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) {
log_warn("kr_init: socket");
return (-1);
-@@ -198,194 +223,533 @@ kr_init(int fs, u_int rtableid)
+@@ -198,194 +224,533 @@ kr_init(int fs, u_int rtableid)
rcvbuf /= 2)
; /* nothing */
@@ -399,9 +400,10 @@ diff -u -p -r1.1.1.7 -r1.12
+ else if (kt->state == RECONF_REINIT)
+ kt->fib_sync = kt->fib_conf;
+ }
-+}
-+
-+int
+ }
+
+ int
+-kr_change(struct kroute_label *kl)
+ktable_exists(u_int rtableid, u_int *rdomid)
+{
+#if !defined(__FreeBSD__) /* FreeBSD does not have NET_RT_TABLE. */
@@ -431,10 +433,9 @@ diff -u -p -r1.1.1.7 -r1.12
+ *rdomid = 0;
+#endif
+ return (1);
- }
-
- int
--kr_change(struct kroute_label *kl)
++}
++
++int
+kr_change(u_int rtableid, struct kroute_full *kl)
+{
+ struct ktable *kt;
@@ -564,7 +565,8 @@ diff -u -p -r1.1.1.7 -r1.12
+ /* 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");
@@ -577,8 +579,7 @@ diff -u -p -r1.1.1.7 -r1.12
+ kr6->r.flags = kl->flags | F_BGPD_INSERTED;
+ kr6->r.priority = RTP_BGP;
+ kr6->r.labelid = labelid;
-
-- rtlabel_unref(kl->kr.labelid);
++
+ if (kroute6_insert(kt, kr6) == -1)
+ free(kr6);
+ } else {
@@ -700,15 +701,16 @@ diff -u -p -r1.1.1.7 -r1.12
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
+ return (0);
+ }
+
+ int
+-kr6_delete(struct kroute6_label *kl)
+kr_delete(u_int rtableid, struct kroute_full *kl)
+{
+ struct ktable *kt;
@@ -724,7 +726,7 @@ diff -u -p -r1.1.1.7 -r1.12
+ return (kr6_delete(kt, kl));
+ case AID_VPN_IPv4:
+ return (krVPN4_delete(kt, kl));
- }
++ }
+ log_warnx("kr_change: not handled AID");
+ return (-1);
+}
@@ -748,12 +750,11 @@ diff -u -p -r1.1.1.7 -r1.12
+
+ if (kroute_remove(kt, kr) == -1)
+ return (-1);
-
- return (0);
- }
-
- int
--kr6_delete(struct kroute6_label *kl)
++
++ return (0);
++}
++
++int
+kr6_delete(struct ktable *kt, struct kroute_full *kl)
{
struct kroute6_node *kr6;
@@ -804,7 +805,7 @@ diff -u -p -r1.1.1.7 -r1.12
return (-1);
return (0);
-@@ -394,53 +758,63 @@ kr6_delete(struct kroute6_label *kl)
+@@ -394,53 +759,63 @@ kr6_delete(struct kroute6_label *kl)
void
kr_shutdown(void)
{
@@ -888,7 +889,7 @@ diff -u -p -r1.1.1.7 -r1.12
}
int
-@@ -450,11 +824,16 @@ kr_dispatch_msg(void)
+@@ -450,41 +825,18 @@ kr_dispatch_msg(void)
}
int
@@ -905,46 +906,40 @@ diff -u -p -r1.1.1.7 -r1.12
+ }
+ if ((h = knexthop_find(kt, addr)) != NULL) {
/* should not happen... this is actually an error path */
- struct kroute_nexthop nh;
- struct kroute_node *k;
-@@ -463,25 +842,30 @@ kr_nexthop_add(struct bgpd_addr *addr)
- bzero(&nh, sizeof(nh));
- memcpy(&nh.nexthop, addr, sizeof(nh.nexthop));
- nh.valid = 1;
+- 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) {
-+ if (h->kroute != NULL && addr->aid == AID_INET) {
- k = h->kroute;
- nh.connected = k->r.flags & F_CONNECTED;
- if (k->r.nexthop.s_addr != 0) {
+- k = h->kroute;
+- nh.connected = k->r.flags & F_CONNECTED;
+- if (k->r.nexthop.s_addr != 0) {
- nh.gateway.af = AF_INET;
-+ nh.gateway.aid = AID_INET;
- nh.gateway.v4.s_addr =
- k->r.nexthop.s_addr;
- }
+- 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) {
-+ nh.net.aid = AID_INET;
-+ nh.net.v4.s_addr = k->r.prefix.s_addr;
-+ nh.netlen = k->r.prefixlen;
-+ } else if (h->kroute != NULL && addr->aid == AID_INET6) {
- k6 = h->kroute;
- nh.connected = k6->r.flags & F_CONNECTED;
- if (memcmp(&k6->r.nexthop, &in6addr_any,
- sizeof(struct in6_addr)) != 0) {
+- 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;
-+ nh.gateway.aid = AID_INET6;
- memcpy(&nh.gateway.v6, &k6->r.nexthop,
- sizeof(struct in6_addr));
- }
+- memcpy(&nh.gateway.v6, &k6->r.nexthop,
+- sizeof(struct in6_addr));
+- }
- memcpy(&nh.kr.kr6, &k6->r, sizeof(nh.kr.kr6));
-+ nh.net.aid = AID_INET6;
-+ memcpy(&nh.net.v6, &k6->r.nexthop,
-+ sizeof(struct in6_addr));
-+ nh.netlen = k6->r.prefixlen;
- }
-
- send_nexthop_update(&nh);
-@@ -492,7 +876,7 @@ kr_nexthop_add(struct bgpd_addr *addr)
+- }
+-
+- 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));
@@ -953,7 +948,7 @@ diff -u -p -r1.1.1.7 -r1.12
return (-1);
}
-@@ -500,19 +884,25 @@ kr_nexthop_add(struct bgpd_addr *addr)
+@@ -500,19 +852,26 @@ kr_nexthop_add(struct bgpd_addr *addr)
}
void
@@ -965,7 +960,8 @@ diff -u -p -r1.1.1.7 -r1.12
- if ((kn = knexthop_find(addr)) == NULL)
+ if ((kt = ktable_get(rtableid)) == NULL) {
-+ log_warnx("kr_nexthop_add: non-existent rtableid %d", rtableid);
++ log_warnx("kr_nexthop_delete: non-existent rtableid %d",
++ rtableid);
+ return;
+ }
+ if ((kn = knexthop_find(kt, addr)) == NULL)
@@ -982,7 +978,7 @@ diff -u -p -r1.1.1.7 -r1.12
struct kroute_node *kr, *kn;
struct kroute6_node *kr6, *kn6;
struct bgpd_addr *addr;
-@@ -521,6 +911,7 @@ kr_show_route(struct imsg *imsg)
+@@ -521,6 +880,7 @@ kr_show_route(struct imsg *imsg)
struct ctl_show_nexthop snh;
struct knexthop_node *h;
struct kif_node *kif;
@@ -990,7 +986,7 @@ diff -u -p -r1.1.1.7 -r1.12
u_short ifindex = 0;
switch (imsg->hdr.type) {
-@@ -528,70 +919,96 @@ kr_show_route(struct imsg *imsg)
+@@ -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");
@@ -1121,7 +1117,7 @@ diff -u -p -r1.1.1.7 -r1.12
ifindex = kr6->r.ifindex;
break;
}
-@@ -608,6 +1025,24 @@ kr_show_route(struct imsg *imsg)
+@@ -608,6 +994,24 @@ kr_show_route(struct imsg *imsg)
send_imsg_session(IMSG_CTL_SHOW_INTERFACE,
imsg->hdr.pid, &kif->k, sizeof(kif->k));
break;
@@ -1146,7 +1142,7 @@ diff -u -p -r1.1.1.7 -r1.12
default: /* nada */
break;
}
-@@ -628,21 +1063,146 @@ kr_ifinfo(char *ifname)
+@@ -628,21 +1032,152 @@ kr_ifinfo(char *ifname)
}
}
@@ -1185,11 +1181,14 @@ diff -u -p -r1.1.1.7 -r1.12
+ if (kr->flags & F_CONNECTED)
+ return (xn);
+ break;
++ case NETWORK_MRTCLONE:
++ /* can not happen */
++ break;
+ }
+ }
+ return (NULL);
+}
-+
+
+struct network *
+kr_net_match6(struct ktable *kt, struct kroute6 *kr6)
+{
@@ -1214,11 +1213,15 @@ diff -u -p -r1.1.1.7 -r1.12
+ if (kr6->flags & F_CONNECTED)
+ return (xn);
+ break;
++ case NETWORK_MRTCLONE:
++ /* can not happen */
++ break;
+ }
+ }
+ return (NULL);
+}
-+
+
+-LIST_HEAD(, redist_node) redistlist;
+struct network *
+kr_net_find(struct ktable *kt, struct network *n)
+{
@@ -1235,10 +1238,12 @@ diff -u -p -r1.1.1.7 -r1.12
+ }
+ return (NULL);
+}
-+
-+int
+
+ int
+-kr_redistribute(int type, struct kroute *kr)
+kr_net_reload(u_int rtableid, struct network_head *nh)
-+{
+ {
+- struct redist_node *rn;
+ struct network *n, *xn;
+ struct ktable *kt;
+
@@ -1263,7 +1268,7 @@ diff -u -p -r1.1.1.7 -r1.12
+ } 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) {
@@ -1275,16 +1280,13 @@ diff -u -p -r1.1.1.7 -r1.12
+ kr_net_delete(n);
+ }
+ }
-
--LIST_HEAD(, redist_node) redistlist;
++
+ return (0);
+}
-
- int
--kr_redistribute(int type, struct kroute *kr)
++
++int
+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;
@@ -1301,7 +1303,7 @@ diff -u -p -r1.1.1.7 -r1.12
if (!(kr->flags & F_KERNEL))
return (0);
-@@ -670,41 +1230,40 @@ kr_redistribute(int type, struct kroute
+@@ -670,41 +1205,40 @@ kr_redistribute(int type, struct kroute
if (kr->prefix.s_addr == INADDR_ANY && kr->prefixlen == 0)
return (0);
@@ -1374,7 +1376,7 @@ diff -u -p -r1.1.1.7 -r1.12
if (!(kr6->flags & F_KERNEL))
return (0);
-@@ -736,60 +1295,107 @@ kr_redistribute6(int type, struct kroute
+@@ -736,60 +1270,107 @@ kr_redistribute6(int type, struct kroute
* never allow ::/0 the default route can only be redistributed
* with announce default.
*/
@@ -1452,12 +1454,12 @@ diff -u -p -r1.1.1.7 -r1.12
+ for (rid = 0; rid < krt_size; rid++) {
+ if ((kt = ktable_get(rid)) == NULL)
+ continue;
++
++ RB_FOREACH(nh, knexthop_tree, KT2KNT(kt))
++ knexthop_validate(kt, nh);
- 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,
@@ -1521,7 +1523,7 @@ diff -u -p -r1.1.1.7 -r1.12
/*
* RB-tree compare functions
*/
-@@ -846,26 +1452,28 @@ kroute6_compare(struct kroute6_node *a,
+@@ -846,26 +1427,28 @@ kroute6_compare(struct kroute6_node *a,
int
knexthop_compare(struct knexthop_node *a, struct knexthop_node *b)
{
@@ -1566,7 +1568,7 @@ diff -u -p -r1.1.1.7 -r1.12
}
return (0);
-@@ -883,7 +1491,8 @@ kif_compare(struct kif_node *a, struct k
+@@ -883,7 +1466,8 @@ kif_compare(struct kif_node *a, struct k
*/
struct kroute_node *
@@ -1576,7 +1578,7 @@ diff -u -p -r1.1.1.7 -r1.12
{
struct kroute_node s;
struct kroute_node *kn, *tmp;
-@@ -892,15 +1501,15 @@ kroute_find(in_addr_t prefix, u_int8_t p
+@@ -892,15 +1476,15 @@ kroute_find(in_addr_t prefix, u_int8_t p
s.r.prefixlen = prefixlen;
s.r.priority = prio;
@@ -1595,7 +1597,7 @@ diff -u -p -r1.1.1.7 -r1.12
}
}
return (kn);
-@@ -927,13 +1536,13 @@ kroute_matchgw(struct kroute_node *kr, s
+@@ -927,13 +1511,13 @@ kroute_matchgw(struct kroute_node *kr, s
}
int
@@ -1611,7 +1613,11 @@ diff -u -p -r1.1.1.7 -r1.12
/* multipath route, add at end of list */
while (krm->next != NULL)
krm = krm->next;
-@@ -944,10 +1553,10 @@ kroute_insert(struct kroute_node *kr)
+@@ -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);
@@ -1625,7 +1631,7 @@ diff -u -p -r1.1.1.7 -r1.12
if (kr->r.flags & F_CONNECTED)
if (kif_kr_insert(kr) == -1)
-@@ -955,19 +1564,19 @@ kroute_insert(struct kroute_node *kr)
+@@ -955,19 +1540,19 @@ kroute_insert(struct kroute_node *kr)
if (krm == NULL)
/* redistribute multipath routes only once */
@@ -1648,7 +1654,7 @@ diff -u -p -r1.1.1.7 -r1.12
log_warnx("kroute_remove failed to find %s/%u",
inet_ntoa(kr->r.prefix), kr->r.prefixlen);
return (-1);
-@@ -975,13 +1584,14 @@ kroute_remove(struct kroute_node *kr)
+@@ -975,13 +1560,14 @@ kroute_remove(struct kroute_node *kr)
if (krm == kr) {
/* head element */
@@ -1665,11 +1671,13 @@ diff -u -p -r1.1.1.7 -r1.12
log_warnx("kroute_remove failed to add %s/%u",
inet_ntoa(kr->r.prefix), kr->r.prefixlen);
return (-1);
-@@ -1002,13 +1612,13 @@ kroute_remove(struct kroute_node *kr)
+@@ -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))
+- 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);
@@ -1682,7 +1690,7 @@ diff -u -p -r1.1.1.7 -r1.12
if (kr->r.flags & F_CONNECTED)
if (kif_kr_remove(kr) == -1) {
-@@ -1021,16 +1631,17 @@ kroute_remove(struct kroute_node *kr)
+@@ -1021,16 +1607,17 @@ kroute_remove(struct kroute_node *kr)
}
void
@@ -1704,7 +1712,7 @@ diff -u -p -r1.1.1.7 -r1.12
{
struct kroute6_node s;
struct kroute6_node *kn6, *tmp;
-@@ -1039,15 +1650,15 @@ kroute6_find(const struct in6_addr *pref
+@@ -1039,15 +1626,15 @@ kroute6_find(const struct in6_addr *pref
s.r.prefixlen = prefixlen;
s.r.priority = prio;
@@ -1724,7 +1732,7 @@ diff -u -p -r1.1.1.7 -r1.12
}
}
return (kn6);
-@@ -1065,7 +1676,7 @@ kroute6_matchgw(struct kroute6_node *kr,
+@@ -1065,7 +1652,7 @@ kroute6_matchgw(struct kroute6_node *kr,
memcpy(&nexthop, &sa_in6->sin6_addr, sizeof(nexthop));
while (kr) {
@@ -1733,7 +1741,7 @@ diff -u -p -r1.1.1.7 -r1.12
return (kr);
kr = kr->next;
}
-@@ -1074,13 +1685,13 @@ kroute6_matchgw(struct kroute6_node *kr,
+@@ -1074,13 +1661,13 @@ kroute6_matchgw(struct kroute6_node *kr,
}
int
@@ -1749,8 +1757,11 @@ diff -u -p -r1.1.1.7 -r1.12
/* multipath route, add at end of list */
while (krm->next != NULL)
krm = krm->next;
-@@ -1090,12 +1701,12 @@ kroute6_insert(struct kroute6_node *kr)
+@@ -1088,14 +1675,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)
@@ -1765,7 +1776,7 @@ diff -u -p -r1.1.1.7 -r1.12
}
if (kr->r.flags & F_CONNECTED)
-@@ -1104,19 +1715,19 @@ kroute6_insert(struct kroute6_node *kr)
+@@ -1104,19 +1692,19 @@ kroute6_insert(struct kroute6_node *kr)
if (krm == NULL)
/* redistribute multipath routes only once */
@@ -1788,7 +1799,7 @@ diff -u -p -r1.1.1.7 -r1.12
log_warnx("kroute6_remove failed for %s/%u",
log_in6addr(&kr->r.prefix), kr->r.prefixlen);
return (-1);
-@@ -1124,13 +1735,14 @@ kroute6_remove(struct kroute6_node *kr)
+@@ -1124,13 +1712,14 @@ kroute6_remove(struct kroute6_node *kr)
if (krm == kr) {
/* head element */
@@ -1805,11 +1816,13 @@ diff -u -p -r1.1.1.7 -r1.12
log_warnx("kroute6_remove failed to add %s/%u",
log_in6addr(&kr->r.prefix),
kr->r.prefixlen);
-@@ -1152,13 +1764,13 @@ kroute6_remove(struct kroute6_node *kr)
+@@ -1151,14 +1740,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))
+- 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);
@@ -1822,7 +1835,7 @@ diff -u -p -r1.1.1.7 -r1.12
if (kr->r.flags & F_CONNECTED)
if (kif_kr6_remove(kr) == -1) {
-@@ -1171,45 +1783,46 @@ kroute6_remove(struct kroute6_node *kr)
+@@ -1171,45 +1760,46 @@ kroute6_remove(struct kroute6_node *kr)
}
void
@@ -1880,7 +1893,7 @@ diff -u -p -r1.1.1.7 -r1.12
log_warnx("knexthop_remove failed for %s",
log_addr(&kn->nexthop));
return (-1);
-@@ -1220,12 +1833,12 @@ knexthop_remove(struct knexthop_node *kn
+@@ -1220,12 +1810,12 @@ knexthop_remove(struct knexthop_node *kn
}
void
@@ -1896,7 +1909,7 @@ diff -u -p -r1.1.1.7 -r1.12
}
struct kif_node *
-@@ -1257,6 +1870,7 @@ kif_insert(struct kif_node *kif)
+@@ -1257,6 +1847,7 @@ kif_insert(struct kif_node *kif)
int
kif_remove(struct kif_node *kif)
{
@@ -1904,7 +1917,7 @@ diff -u -p -r1.1.1.7 -r1.12
struct kif_kr *kkr;
struct kif_kr6 *kkr6;
-@@ -1265,20 +1879,23 @@ kif_remove(struct kif_node *kif)
+@@ -1265,20 +1856,23 @@ kif_remove(struct kif_node *kif)
return (-1);
}
@@ -1931,81 +1944,95 @@ diff -u -p -r1.1.1.7 -r1.12
free(kif);
return (0);
}
-@@ -1473,25 +2090,25 @@ kroute6_validate(struct kroute6 *kr)
+@@ -1473,113 +2067,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;
+- struct kroute_nexthop n;
+- int was_valid = 0;
- if (kn->nexthop.af == AF_INET && (kr = kn->kroute) != NULL)
-+ if (kn->nexthop.aid == AID_INET && (kr = kn->kroute) != NULL)
- was_valid = kroute_validate(&kr->r);
+- was_valid = kroute_validate(&kr->r);
- if (kn->nexthop.af == AF_INET6 && (kr6 = kn->kroute) != NULL)
-+ if (kn->nexthop.aid == AID_INET6 && (kr6 = kn->kroute) != NULL)
- was_valid = kroute6_validate(&kr6->r);
-
- bzero(&n, sizeof(n));
- memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop));
-- kroute_detach_nexthop(kn);
+- 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) {
-+ switch (kn->nexthop.aid) {
-+ case AID_INET:
-+ if ((kr = kroute_match(kt, kn->nexthop.v4.s_addr, 0)) == NULL) {
- if (was_valid)
- send_nexthop_update(&n);
- } else { /* match */
-@@ -1500,8 +2117,10 @@ knexthop_validate(struct knexthop_node *
- n.connected = kr->r.flags & F_CONNECTED;
- if ((n.gateway.v4.s_addr =
- kr->r.nexthop.s_addr) != 0)
+- 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));
-+ n.gateway.aid = AID_INET;
-+ n.net.aid = AID_INET;
-+ n.net.v4.s_addr = kr->r.prefix.s_addr;
-+ n.netlen = kr->r.prefixlen;
- send_nexthop_update(&n);
- } else /* down */
- if (was_valid)
-@@ -1511,8 +2130,8 @@ knexthop_validate(struct knexthop_node *
+- 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) {
-+ case AID_INET6:
-+ if ((kr6 = kroute6_match(kt, &kn->nexthop.v6, 0)) == NULL) {
- if (was_valid)
- send_nexthop_update(&n);
- } else { /* match */
-@@ -1521,11 +2140,14 @@ knexthop_validate(struct knexthop_node *
- n.connected = kr6->r.flags & F_CONNECTED;
- if (memcmp(&kr6->r.nexthop, &in6addr_any,
- sizeof(struct in6_addr)) != 0) {
+- 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;
-+ n.gateway.aid = AID_INET6;
- memcpy(&n.gateway.v6, &kr6->r.nexthop,
- sizeof(struct in6_addr));
- }
+- memcpy(&n.gateway.v6, &kr6->r.nexthop,
+- sizeof(struct in6_addr));
+- }
- memcpy(&n.kr.kr6, &kr6->r, sizeof(n.kr.kr6));
-+ n.net.aid = AID_INET6;
-+ memcpy(&n.net.v6, &kr6->r.nexthop,
-+ sizeof(struct in6_addr));
-+ n.netlen = kr6->r.prefixlen;
- send_nexthop_update(&n);
- } else /* down */
- if (was_valid)
-@@ -1539,39 +2161,44 @@ knexthop_validate(struct knexthop_node *
+- 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
@@ -2013,56 +2040,90 @@ diff -u -p -r1.1.1.7 -r1.12
+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;
+- struct kroute_nexthop n;
- RB_FOREACH(kn, knexthop_tree, &knt)
- if (kn->kroute == krn) {
-+ RB_FOREACH(kn, knexthop_tree, KT2KNT(kt))
-+ if (kn->kroute == krp) {
- bzero(&n, sizeof(n));
- memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop));
+- 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;
-+ switch (kn->nexthop.aid) {
-+ case AID_INET:
-+ kr = krp;
- n.valid = 1;
- n.connected = kr->r.flags & F_CONNECTED;
- if ((n.gateway.v4.s_addr =
- kr->r.nexthop.s_addr) != 0)
+- 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));
-+ n.gateway.aid = AID_INET;
-+ n.net.aid = AID_INET;
-+ n.net.v4.s_addr = kr->r.prefix.s_addr;
-+ n.netlen = kr->r.prefixlen;
- break;
+- break;
- case AF_INET6:
- kr6 = krn;
-+ case AID_INET6:
-+ kr6 = krp;
- n.valid = 1;
- n.connected = kr6->r.flags & F_CONNECTED;
- if (memcmp(&kr6->r.nexthop, &in6addr_any,
- sizeof(struct in6_addr)) != 0) {
+- 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;
-+ n.gateway.aid = AID_INET6;
- memcpy(&n.gateway.v6, &kr6->r.nexthop,
- sizeof(struct in6_addr));
- }
+- memcpy(&n.gateway.v6, &kr6->r.nexthop,
+- sizeof(struct in6_addr));
+- }
- memcpy(&n.kr.kr6, &kr6->r, sizeof(n.kr.kr6));
-+ 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);
-@@ -1579,7 +2206,7 @@ knexthop_track(void *krn)
+- 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 *
@@ -2071,7 +2132,7 @@ diff -u -p -r1.1.1.7 -r1.12
{
int i;
struct kroute_node *kr;
-@@ -1589,13 +2216,13 @@ kroute_match(in_addr_t key, int matchall
+@@ -1589,13 +2179,13 @@ kroute_match(in_addr_t key, int matchall
/* we will never match the default route */
for (i = 32; i > 0; i--)
@@ -2087,7 +2148,7 @@ diff -u -p -r1.1.1.7 -r1.12
if (matchall || bgpd_filternexthop(&kr->r, NULL) == 0)
return (kr);
-@@ -1603,7 +2230,7 @@ kroute_match(in_addr_t key, int matchall
+@@ -1603,7 +2193,7 @@ kroute_match(in_addr_t key, int matchall
}
struct kroute6_node *
@@ -2096,7 +2157,7 @@ diff -u -p -r1.1.1.7 -r1.12
{
int i;
struct kroute6_node *kr6;
-@@ -1612,13 +2239,13 @@ kroute6_match(struct in6_addr *key, int
+@@ -1612,13 +2202,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);
@@ -2112,7 +2173,7 @@ diff -u -p -r1.1.1.7 -r1.12
if (matchall || bgpd_filternexthop(NULL, &kr6->r) == 0)
return (kr6);
-@@ -1626,7 +2253,7 @@ kroute6_match(struct in6_addr *key, int
+@@ -1626,31 +2216,30 @@ kroute6_match(struct in6_addr *key, int
}
void
@@ -2121,15 +2182,25 @@ diff -u -p -r1.1.1.7 -r1.12
{
struct knexthop_node *s;
struct kroute_node *k;
-@@ -1640,17 +2267,17 @@ kroute_detach_nexthop(struct knexthop_no
- if (kn->kroute == NULL)
- return;
+ 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))
-+ for (s = RB_MIN(knexthop_tree, KT2KNT(kt)); s != NULL &&
-+ s->kroute != kn->kroute; s = RB_NEXT(knexthop_tree, KT2KNT(kt), s))
- ; /* nothing */
+- ; /* nothing */
++ RB_FOREACH(s, knexthop_tree, KT2KNT(kt))
++ if (s->kroute == kn->kroute && s != kn)
++ break;
if (s == NULL) {
- switch (kn->nexthop.af) {
@@ -2144,7 +2215,7 @@ diff -u -p -r1.1.1.7 -r1.12
k6 = kn->kroute;
k6->r.flags &= ~F_NEXTHOP;
break;
-@@ -1665,7 +2292,7 @@ kroute_detach_nexthop(struct knexthop_no
+@@ -1665,7 +2254,7 @@ kroute_detach_nexthop(struct knexthop_no
*/
int
@@ -2153,7 +2224,7 @@ diff -u -p -r1.1.1.7 -r1.12
{
struct kroute_node *kr;
struct kroute6_node *kr6;
-@@ -1675,11 +2302,11 @@ protect_lo(void)
+@@ -1675,11 +2264,11 @@ protect_lo(void)
log_warn("protect_lo");
return (-1);
}
@@ -2167,7 +2238,7 @@ diff -u -p -r1.1.1.7 -r1.12
free(kr); /* kernel route already there, no problem */
/* special protection for loopback */
-@@ -1689,9 +2316,9 @@ protect_lo(void)
+@@ -1689,9 +2278,9 @@ protect_lo(void)
}
memcpy(&kr6->r.prefix, &in6addr_loopback, sizeof(kr6->r.prefix));
kr6->r.prefixlen = 128;
@@ -2179,7 +2250,7 @@ diff -u -p -r1.1.1.7 -r1.12
free(kr6); /* kernel route already there, no problem */
return (0);
-@@ -1726,17 +2353,17 @@ mask2prefixlen(in_addr_t ina)
+@@ -1726,17 +2315,17 @@ mask2prefixlen(in_addr_t ina)
u_int8_t
mask2prefixlen6(struct sockaddr_in6 *sa_in6)
{
@@ -2202,7 +2273,7 @@ diff -u -p -r1.1.1.7 -r1.12
case 0xff:
l += 8;
break;
-@@ -1764,7 +2391,7 @@ mask2prefixlen6(struct sockaddr_in6 *sa_
+@@ -1764,7 +2353,7 @@ mask2prefixlen6(struct sockaddr_in6 *sa_
case 0x00:
return (l);
default:
@@ -2211,7 +2282,7 @@ diff -u -p -r1.1.1.7 -r1.12
}
}
-@@ -1788,7 +2415,7 @@ prefixlen2mask6(u_int8_t prefixlen)
+@@ -1788,7 +2377,7 @@ prefixlen2mask6(u_int8_t prefixlen)
}
#define ROUNDUP(a) \
@@ -2220,7 +2291,7 @@ diff -u -p -r1.1.1.7 -r1.12
void
get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
-@@ -1808,6 +2435,7 @@ get_rtaddrs(int addrs, struct sockaddr *
+@@ -1808,11 +2397,10 @@ get_rtaddrs(int addrs, struct sockaddr *
void
if_change(u_short ifindex, int flags, struct if_data *ifd)
{
@@ -2228,7 +2299,12 @@ diff -u -p -r1.1.1.7 -r1.12
struct kif_node *kif;
struct kif_kr *kkr;
struct kif_kr6 *kkr6;
-@@ -1833,13 +2461,18 @@ if_change(u_short ifindex, int flags, st
+- struct kroute_nexthop nh;
+- struct knexthop_node *n;
+ u_int8_t reachable;
+
+ if ((kif = kif_find(ifindex)) == NULL) {
+@@ -1833,28 +2421,18 @@ if_change(u_short ifindex, int flags, st
kif->k.nh_reachable = reachable;
@@ -2241,60 +2317,61 @@ diff -u -p -r1.1.1.7 -r1.12
kkr->kr->r.flags |= F_DOWN;
- RB_FOREACH(n, knexthop_tree, &knt)
-+ if (kt == NULL)
-+ continue;
-+
-+ RB_FOREACH(n, knexthop_tree, KT2KNT(kt))
- if (n->kroute == kkr->kr) {
- bzero(&nh, sizeof(nh));
- memcpy(&nh.nexthop, &n->nexthop,
-@@ -1849,10 +2482,11 @@ if_change(u_short ifindex, int flags, st
- nh.connected = 1;
- if ((nh.gateway.v4.s_addr =
- kkr->kr->r.nexthop.s_addr) != 0)
+- 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;
-+ nh.gateway.aid = AID_INET;
- }
+- }
- memcpy(&nh.kr.kr4, &kkr->kr->r,
- sizeof(nh.kr.kr4));
-+ nh.net.aid = AID_INET;
-+ nh.net.v4.s_addr = kkr->kr->r.prefix.s_addr;
-+ nh.netlen = kkr->kr->r.prefixlen;
- send_nexthop_update(&nh);
- }
+- send_nexthop_update(&nh);
+- }
++ if (kt == NULL)
++ continue;
++
++ knexthop_track(kt, kkr->kr);
}
-@@ -1862,7 +2496,9 @@ if_change(u_short ifindex, int flags, st
+ LIST_FOREACH(kkr6, &kif->kroute6_l, entry) {
+ if (reachable)
+@@ -1862,27 +2440,10 @@ if_change(u_short ifindex, int flags, st
else
kkr6->kr->r.flags |= F_DOWN;
- RB_FOREACH(n, knexthop_tree, &knt)
-+ if (kt == NULL)
-+ continue;
-+ RB_FOREACH(n, knexthop_tree, KT2KNT(kt))
- if (n->kroute == kkr6->kr) {
- bzero(&nh, sizeof(nh));
- memcpy(&nh.nexthop, &n->nexthop,
-@@ -1873,14 +2509,16 @@ if_change(u_short ifindex, int flags, st
- if (memcmp(&kkr6->kr->r.nexthop,
- &in6addr_any, sizeof(struct
- in6_addr))) {
+- 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;
-+ nh.gateway.aid = AID_INET6;
- memcpy(&nh.gateway.v6,
- &kkr6->kr->r.nexthop,
- sizeof(struct in6_addr));
- }
- }
+- memcpy(&nh.gateway.v6,
+- &kkr6->kr->r.nexthop,
+- sizeof(struct in6_addr));
+- }
+- }
- memcpy(&nh.kr.kr6, &kkr6->kr->r,
- sizeof(nh.kr.kr6));
-+ nh.net.aid = AID_INET6;
-+ memcpy(&nh.net.v6, &kkr6->kr->r.nexthop,
-+ sizeof(struct in6_addr));
-+ nh.netlen = kkr6->kr->r.prefixlen;
- send_nexthop_update(&nh);
- }
+- send_nexthop_update(&nh);
+- }
++ if (kt == NULL)
++ continue;
++
++ knexthop_track(kt, kkr6->kr);
}
-@@ -1917,25 +2555,38 @@ if_announce(void *msg)
+ }
+
+@@ -1917,25 +2478,38 @@ if_announce(void *msg)
*/
int
@@ -2337,7 +2414,7 @@ diff -u -p -r1.1.1.7 -r1.12
if (kroute->flags & F_BLACKHOLE)
hdr.rtm_flags |= RTF_BLACKHOLE;
if (kroute->flags & F_REJECT)
-@@ -1984,6 +2635,37 @@ send_rtmsg(int fd, int action, struct kr
+@@ -1984,6 +2558,37 @@ send_rtmsg(int fd, int action, struct kr
iov[iovcnt].iov_base = &mask;
iov[iovcnt++].iov_len = sizeof(mask);
@@ -2375,7 +2452,7 @@ diff -u -p -r1.1.1.7 -r1.12
if (kroute->labelid) {
bzero(&label, sizeof(label));
label.sr_len = sizeof(label);
-@@ -1996,11 +2678,11 @@ send_rtmsg(int fd, int action, struct kr
+@@ -1996,11 +2601,11 @@ send_rtmsg(int fd, int action, struct kr
iov[iovcnt].iov_base = &label;
iov[iovcnt++].iov_len = sizeof(label);
}
@@ -2389,7 +2466,7 @@ diff -u -p -r1.1.1.7 -r1.12
if (hdr.rtm_type == RTM_CHANGE) {
hdr.rtm_type = RTM_ADD;
goto retry;
-@@ -2009,27 +2691,18 @@ retry:
+@@ -2009,27 +2614,18 @@ retry:
inet_ntoa(kroute->prefix),
kroute->prefixlen);
return (0);
@@ -2421,7 +2498,7 @@ diff -u -p -r1.1.1.7 -r1.12
{
struct iovec iov[5];
struct rt_msghdr hdr;
-@@ -2037,17 +2710,23 @@ send_rt6msg(int fd, int action, struct k
+@@ -2037,17 +2633,23 @@ send_rt6msg(int fd, int action, struct k
struct sockaddr_in6 addr;
char pad[sizeof(long)];
} prefix, nexthop, mask;
@@ -2446,7 +2523,7 @@ diff -u -p -r1.1.1.7 -r1.12
if (kroute->flags & F_BLACKHOLE)
hdr.rtm_flags |= RTF_BLACKHOLE;
if (kroute->flags & F_REJECT)
-@@ -2100,6 +2779,7 @@ send_rt6msg(int fd, int action, struct k
+@@ -2100,6 +2702,7 @@ send_rt6msg(int fd, int action, struct k
iov[iovcnt].iov_base = &mask;
iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6));
@@ -2454,7 +2531,7 @@ diff -u -p -r1.1.1.7 -r1.12
if (kroute->labelid) {
bzero(&label, sizeof(label));
label.sr_len = sizeof(label);
-@@ -2112,11 +2792,11 @@ send_rt6msg(int fd, int action, struct k
+@@ -2112,11 +2715,11 @@ send_rt6msg(int fd, int action, struct k
iov[iovcnt].iov_base = &label;
iov[iovcnt++].iov_len = sizeof(label);
}
@@ -2468,7 +2545,7 @@ diff -u -p -r1.1.1.7 -r1.12
if (hdr.rtm_type == RTM_CHANGE) {
hdr.rtm_type = RTM_ADD;
goto retry;
-@@ -2125,31 +2805,26 @@ retry:
+@@ -2125,31 +2728,26 @@ retry:
log_in6addr(&kroute->prefix),
kroute->prefixlen);
return (0);
@@ -2509,7 +2586,7 @@ diff -u -p -r1.1.1.7 -r1.12
struct rt_msghdr *rtm;
struct sockaddr *sa, *gw, *rti_info[RTAX_MAX];
struct sockaddr_in *sa_in;
-@@ -2163,22 +2838,35 @@ fetchtable(u_int rtableid, int connected
+@@ -2163,22 +2761,35 @@ fetchtable(u_int rtableid, int connected
mib[3] = 0;
mib[4] = NET_RT_DUMP;
mib[5] = 0;
@@ -2555,7 +2632,7 @@ diff -u -p -r1.1.1.7 -r1.12
}
lim = buf + len;
-@@ -2186,7 +2874,11 @@ fetchtable(u_int rtableid, int connected
+@@ -2186,7 +2797,11 @@ fetchtable(u_int rtableid, int connected
rtm = (struct rt_msghdr *)next;
if (rtm->rtm_version != RTM_VERSION)
continue;
@@ -2567,7 +2644,7 @@ diff -u -p -r1.1.1.7 -r1.12
get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
if ((sa = rti_info[RTAX_DST]) == NULL)
-@@ -2205,7 +2897,11 @@ fetchtable(u_int rtableid, int connected
+@@ -2205,7 +2820,11 @@ fetchtable(u_int rtableid, int connected
}
kr->r.flags = F_KERNEL;
@@ -2579,7 +2656,7 @@ diff -u -p -r1.1.1.7 -r1.12
kr->r.ifindex = rtm->rtm_index;
kr->r.prefix.s_addr =
((struct sockaddr_in *)sa)->sin_addr.s_addr;
-@@ -2223,8 +2919,12 @@ fetchtable(u_int rtableid, int connected
+@@ -2223,8 +2842,12 @@ fetchtable(u_int rtableid, int connected
break;
kr->r.prefixlen =
mask2prefixlen(sa_in->sin_addr.s_addr);
@@ -2593,7 +2670,7 @@ diff -u -p -r1.1.1.7 -r1.12
else
kr->r.prefixlen =
prefixlen_classful(kr->r.prefix.s_addr);
-@@ -2238,7 +2938,11 @@ fetchtable(u_int rtableid, int connected
+@@ -2238,7 +2861,11 @@ fetchtable(u_int rtableid, int connected
}
kr6->r.flags = F_KERNEL;
@@ -2605,7 +2682,7 @@ diff -u -p -r1.1.1.7 -r1.12
kr6->r.ifindex = rtm->rtm_index;
memcpy(&kr6->r.prefix,
&((struct sockaddr_in6 *)sa)->sin6_addr,
-@@ -2257,8 +2961,12 @@ fetchtable(u_int rtableid, int connected
+@@ -2257,8 +2884,12 @@ fetchtable(u_int rtableid, int connected
if (sa_in6->sin6_len == 0)
break;
kr6->r.prefixlen = mask2prefixlen6(sa_in6);
@@ -2619,7 +2696,7 @@ diff -u -p -r1.1.1.7 -r1.12
else
fatalx("INET6 route without netmask");
break;
-@@ -2290,23 +2998,28 @@ fetchtable(u_int rtableid, int connected
+@@ -2290,23 +2921,28 @@ fetchtable(u_int rtableid, int connected
}
if (sa->sa_family == AF_INET) {
@@ -2660,7 +2737,7 @@ diff -u -p -r1.1.1.7 -r1.12
}
}
free(buf);
-@@ -2327,7 +3040,7 @@ fetchifs(int ifindex)
+@@ -2327,7 +2963,7 @@ fetchifs(int ifindex)
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
mib[2] = 0;
@@ -2669,7 +2746,7 @@ diff -u -p -r1.1.1.7 -r1.12
mib[4] = NET_RT_IFLIST;
mib[5] = ifindex;
-@@ -2396,7 +3109,7 @@ dispatch_rtmsg(void)
+@@ -2396,7 +3032,7 @@ dispatch_rtmsg(void)
struct rt_msghdr *rtm;
struct if_msghdr ifm;
struct sockaddr *sa, *rti_info[RTAX_MAX];
@@ -2678,7 +2755,7 @@ diff -u -p -r1.1.1.7 -r1.12
if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) {
log_warn("dispatch_rtmsg: read error");
-@@ -2418,7 +3131,11 @@ dispatch_rtmsg(void)
+@@ -2418,7 +3054,11 @@ dispatch_rtmsg(void)
case RTM_ADD:
case RTM_CHANGE:
case RTM_DELETE:
@@ -2690,7 +2767,7 @@ diff -u -p -r1.1.1.7 -r1.12
get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
if (rtm->rtm_pid == kr_state.pid) /* cause by us */
-@@ -2430,16 +3147,14 @@ dispatch_rtmsg(void)
+@@ -2430,16 +3070,14 @@ dispatch_rtmsg(void)
if (rtm->rtm_flags & RTF_LLINFO) /* arp cache */
continue;
@@ -2714,7 +2791,7 @@ diff -u -p -r1.1.1.7 -r1.12
return (-1);
break;
case RTM_IFINFO:
-@@ -2460,7 +3175,7 @@ dispatch_rtmsg(void)
+@@ -2460,7 +3098,7 @@ dispatch_rtmsg(void)
int
dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr *rti_info[RTAX_MAX],
@@ -2723,7 +2800,16 @@ diff -u -p -r1.1.1.7 -r1.12
{
struct sockaddr *sa;
struct sockaddr_in *sa_in;
-@@ -2494,31 +3209,44 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
+@@ -2468,7 +3106,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 +3132,44 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
mpath = 1;
#endif
@@ -2772,7 +2858,7 @@ diff -u -p -r1.1.1.7 -r1.12
else
fatalx("in6 net addr without netmask");
break;
-@@ -2537,10 +3265,10 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
+@@ -2537,10 +3188,10 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
}
if (rtm->rtm_type == RTM_DELETE) {
@@ -2786,7 +2872,7 @@ diff -u -p -r1.1.1.7 -r1.12
prefixlen, prio)) == NULL)
return (0);
if (!(kr->r.flags & F_KERNEL))
-@@ -2554,12 +3282,12 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
+@@ -2554,12 +3205,12 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
return (0);
}
@@ -2802,7 +2888,7 @@ diff -u -p -r1.1.1.7 -r1.12
prio)) == NULL)
return (0);
if (!(kr6->r.flags & F_KERNEL))
-@@ -2574,26 +3302,23 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
+@@ -2574,26 +3225,23 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
return (0);
}
@@ -2833,7 +2919,31 @@ diff -u -p -r1.1.1.7 -r1.12
prio)) != NULL) {
if (kr->r.flags & F_KERNEL) {
/* get the correct route */
-@@ -2619,16 +3344,16 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
+@@ -2605,30 +3253,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,
@@ -2847,13 +2957,14 @@ diff -u -p -r1.1.1.7 -r1.12
- &kr->r);
+ kt, &kr->r);
}
- if (kr->r.flags & F_NEXTHOP)
+- 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,12 +3376,13 @@ add4:
+@@ -2651,12 +3307,13 @@ add4:
kr->r.ifindex = ifindex;
kr->r.priority = prio;
@@ -2870,7 +2981,37 @@ diff -u -p -r1.1.1.7 -r1.12
if (kr6->r.flags & F_KERNEL) {
/* get the correct route */
if (mpath && rtm->rtm_type == RTM_CHANGE &&
-@@ -2685,16 +3411,16 @@ add4:
+@@ -2668,33 +3325,44 @@ add4:
+ } 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,
@@ -2884,13 +3025,14 @@ diff -u -p -r1.1.1.7 -r1.12
- &kr6->r);
+ kt, &kr6->r);
}
- if (kr6->r.flags & F_NEXTHOP)
+- 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",
-@@ -2720,7 +3446,7 @@ add6:
+@@ -2720,7 +3388,7 @@ add6:
kr6->r.ifindex = ifindex;
kr6->r.priority = prio;
diff --git a/net/openbgpd/files/patch-bgpd_log.c b/net/openbgpd/files/patch-bgpd_log.c
index ca58a9bcfa0c..6860c0f7f940 100644
--- a/net/openbgpd/files/patch-bgpd_log.c
+++ b/net/openbgpd/files/patch-bgpd_log.c
@@ -2,13 +2,13 @@ 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.7
-diff -u -p -r1.1.1.5 -r1.1.1.7
+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 12 Jun 2011 10:44:25 -0000 1.1.1.7
++++ 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.54 2010/11/18 12:51: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,15 +32,7 @@ diff -u -p -r1.1.1.5 -r1.1.1.7
if (asprintf(&p, "%s/%u", ip, peer->remote_masklen) == -1)
fatal(NULL);
} else {
-@@ -69,6 +71,7 @@ log_init(int n_debug)
- extern char *__progname;
-
- debug = n_debug;
-+ verbose = n_debug;
-
- if (!debug)
- openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
-@@ -77,6 +80,12 @@ log_init(int n_debug)
+@@ -77,6 +79,12 @@ log_init(int n_debug)
}
void
@@ -53,7 +45,7 @@ diff -u -p -r1.1.1.5 -r1.1.1.7
logit(int pri, const char *fmt, ...)
{
va_list ap;
-@@ -193,7 +202,7 @@ log_debug(const char *emsg, ...)
+@@ -193,7 +201,7 @@ log_debug(const char *emsg, ...)
{
va_list ap;
@@ -62,7 +54,7 @@ diff -u -p -r1.1.1.5 -r1.1.1.7
va_start(ap, emsg);
vlog(LOG_DEBUG, emsg, ap);
va_end(ap);
-@@ -250,7 +259,7 @@ log_statechange(struct peer *peer, enum
+@@ -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,
@@ -71,9 +63,19 @@ diff -u -p -r1.1.1.5 -r1.1.1.7
{
char *p;
const char *suberrname = NULL;
-@@ -287,23 +296,22 @@ log_notification(const struct peer *peer
+@@ -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);
@@ -103,7 +105,7 @@ diff -u -p -r1.1.1.5 -r1.1.1.7
}
free(p);
}
-@@ -318,6 +326,9 @@ log_conn_attempt(const struct peer *peer
+@@ -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 {
diff --git a/net/openbgpd/files/patch-bgpd_log.h b/net/openbgpd/files/patch-bgpd_log.h
new file mode 100644
index 000000000000..3d0d94de2a2e
--- /dev/null
+++ b/net/openbgpd/files/patch-bgpd_log.h
@@ -0,0 +1,39 @@
+Index: bgpd/log.h
+===================================================================
+RCS file: /home/cvs/private/hrs/openbgpd/bgpd/log.h,v
+retrieving revision 1.1.1.2
+retrieving revision 1.1.1.3
+diff -u -p -r1.1.1.2 -r1.1.1.3
+--- bgpd/log.h 9 Jul 2009 16:49:54 -0000 1.1.1.2
++++ bgpd/log.h 13 Oct 2012 18:22:43 -0000 1.1.1.3
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: log.h,v 1.11 2008/09/11 14:49:58 henning Exp $ */
++/* $OpenBSD: log.h,v 1.13 2012/06/10 11:16:08 claudio Exp $ */
+
+ /*
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+@@ -71,6 +71,13 @@ static const char * const suberr_open_na
+ "unsupported capability"
+ };
+
++static const char * const suberr_fsm_names[] = {
++ "unspecified error",
++ "received unexpected message in OpenSent",
++ "received unexpected message in OpenConfirm",
++ "received unexpected message in Established"
++};
++
+ static const char * const suberr_update_names[] = {
+ "none",
+ "attribute list error",
+@@ -109,7 +116,9 @@ static const char * const ctl_res_strerr
+ "no such neighbor",
+ "permission denied",
+ "neighbor does not have this capability",
+- "config file has errors, reload failed"
++ "config file has errors, reload failed",
++ "previous reload still running",
++ "out of memory"
+ };
+
+ static const char * const timernames[] = {
diff --git a/net/openbgpd/files/patch-bgpd_mrt.c b/net/openbgpd/files/patch-bgpd_mrt.c
index 4b5248a73d4e..2ff724a4714f 100644
--- a/net/openbgpd/files/patch-bgpd_mrt.c
+++ b/net/openbgpd/files/patch-bgpd_mrt.c
@@ -2,26 +2,36 @@ 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.9
-diff -u -p -r1.1.1.7 -r1.1.1.9
+retrieving revision 1.1.1.10
+diff -u -p -r1.1.1.7 -r1.1.1.10
--- bgpd/mrt.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/mrt.c 12 Jun 2011 10:44:25 -0000 1.1.1.9
++++ bgpd/mrt.c 13 Oct 2012 18:22:43 -0000 1.1.1.10
@@ -1,4 +1,4 @@
-/* $OpenBSD: mrt.c,v 1.63 2009/06/29 12:22:16 claudio Exp $ */
-+/* $OpenBSD: mrt.c,v 1.70 2010/09/02 14:03:21 sobrado Exp $ */
++/* $OpenBSD: mrt.c,v 1.71 2011/09/17 16:29:44 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
-@@ -32,20 +32,20 @@
+@@ -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 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);
@@ -34,44 +44,44 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
- if (buf_add((x), &t, sizeof(t)) == -1) { \
- log_warnx("mrt_dump1: buf_add error"); \
+ if (ibuf_add((x), &t, sizeof(t)) == -1) { \
-+ log_warnx("mrt_dump1: ibuf_add error"); \
++ log_warn("mrt_dump1: ibuf_add error"); \
goto fail; \
} \
} while (0)
-@@ -54,8 +54,8 @@ int mrt_open(struct mrt *, time_t);
+@@ -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_warnx("mrt_dump2: ibuf_add error"); \
++ log_warn("mrt_dump2: ibuf_add error"); \
goto fail; \
} \
} while (0)
-@@ -64,8 +64,8 @@ int mrt_open(struct mrt *, time_t);
+@@ -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_warnx("mrt_dump3: ibuf_add error"); \
++ log_warn("mrt_dump3: ibuf_add error"); \
goto fail; \
} \
} while (0)
-@@ -73,8 +73,8 @@ int mrt_open(struct mrt *, time_t);
+@@ -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_warnx("mrt_dump4: ibuf_add error"); \
++ log_warn("mrt_dump4: ibuf_add error"); \
goto fail; \
} \
} while (0)
-@@ -83,55 +83,63 @@ void
+@@ -83,55 +86,64 @@ void
mrt_dump_bgp_msg(struct mrt *mrt, void *pkg, u_int16_t pkglen,
struct peer *peer)
{
@@ -93,9 +103,10 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
return;
- if (buf_add(buf, pkg, pkglen) == -1) {
-+ if (ibuf_add(buf, pkg, pkglen) == -1) {
- log_warnx("mrt_dump_bgp_msg: buf_add error");
+- 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: buf_add error");
+ ibuf_free(buf);
return;
}
@@ -134,7 +145,8 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
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)
++mrt_attr_dump(struct ibuf *buf, struct rde_aspath *a, struct bgpd_addr *nexthop,
++ int v2)
{
struct attr *oa;
u_char *pdata;
@@ -143,15 +155,18 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
- u_int16_t plen;
- u_int8_t l;
+ u_int16_t plen, afi;
-+ u_int8_t l, mpattr[21];
++ u_int8_t l, safi;
/* origin */
if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ORIGIN,
-@@ -141,11 +149,14 @@ mrt_attr_dump(struct buf *buf, struct rd
+@@ -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);
+- 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);
@@ -164,21 +179,54 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
/* nexthop, already network byte order */
if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_NEXTHOP,
&nexthop->v4.s_addr, 4) == -1)
-@@ -173,12 +184,27 @@ mrt_attr_dump(struct buf *buf, struct rd
+@@ -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) {
-+ if (aid2afi(nexthop->aid, &afi, &mpattr[2]))
++ struct ibuf *nhbuf;
++
++ if ((nhbuf = ibuf_dynamic(0, UCHAR_MAX)) == NULL)
+ return (-1);
-+ afi = htons(afi);
-+ memcpy(mpattr, &afi, sizeof(afi));
-+ mpattr[3] = sizeof(struct in6_addr);
-+ memcpy(&mpattr[4], &nexthop->v6, sizeof(struct in6_addr));
-+ mpattr[20] = 0; /* Reserved must be 0 */
++ 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,
-+ mpattr, sizeof(mpattr)) == -1)
++ nhbuf->buf, ibuf_size(nhbuf)) == -1) {
++fail:
++ ibuf_free(nhbuf);
+ return (-1);
++ }
++ ibuf_free(nhbuf);
+ }
+
if (neednewpath) {
@@ -193,16 +241,16 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
free(pdata);
}
-@@ -189,14 +215,14 @@ int
+@@ -189,25 +244,23 @@ 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;
- void *bptr;
struct bgpd_addr addr, nexthop, *nh;
u_int16_t len;
- u_int8_t p_len;
+- u_int8_t p_len;
- sa_family_t af;
+ u_int8_t aid;
@@ -211,7 +259,9 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
log_warn("mrt_dump_entry_mp: buf_dynamic");
return (-1);
}
-@@ -205,9 +231,9 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
+
+- 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;
}
@@ -223,7 +273,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
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");
-@@ -219,25 +245,26 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
+@@ -219,25 +272,26 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
DUMP_SHORT(h2buf, /* ifindex */ 0);
/* XXX is this for peer self? */
@@ -247,7 +297,8 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
- 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_warnx("mrt_dump_entry_mp: buf_add error");
++ log_warn("mrt_dump_entry_mp: buf_add error");
goto fail;
}
break;
@@ -257,7 +308,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
goto fail;
}
-@@ -247,24 +274,24 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
+@@ -247,25 +301,25 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
if (p->aspath->nexthop == NULL) {
bzero(&nexthop, sizeof(struct bgpd_addr));
@@ -283,21 +334,27 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
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_warnx("mrt_dump_entry_mp: buf_add error");
++ log_warn("mrt_dump_entry_mp: buf_add error");
goto fail;
}
-@@ -275,7 +302,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
+ break;
+@@ -274,35 +328,30 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
+ goto fail;
}
- p_len = PREFIX_SIZE(p->prefix->prefixlen);
+- p_len = PREFIX_SIZE(p->prefix->prefixlen);
- if ((bptr = buf_reserve(h2buf, p_len)) == NULL) {
-+ if ((bptr = ibuf_reserve(h2buf, p_len)) == NULL) {
- log_warnx("mrt_dump_entry_mp: buf_reserve error");
+- 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;
}
-@@ -285,24 +312,24 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
- }
DUMP_SHORT(h2buf, len);
- len += buf_size(h2buf);
@@ -329,7 +386,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
return (-1);
}
-@@ -310,34 +337,37 @@ int
+@@ -310,34 +359,37 @@ int
mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum,
struct rde_peer *peer)
{
@@ -348,8 +405,9 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
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_warnx("mrt_dump_entry: buf_dynamic");
++ log_warn("mrt_dump_entry: buf_dynamic");
return (-1);
}
@@ -360,7 +418,8 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
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) == -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);
@@ -377,7 +436,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
return (-1);
}
-@@ -345,23 +375,44 @@ mrt_dump_entry(struct mrt *mrt, struct p
+@@ -345,23 +397,241 @@ mrt_dump_entry(struct mrt *mrt, struct p
DUMP_SHORT(hbuf, snum);
pt_getaddr(p->prefix, &addr);
@@ -388,7 +447,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
+ break;
+ case AID_INET6:
+ if (ibuf_add(hbuf, &addr.v6, sizeof(struct in6_addr)) == -1) {
-+ log_warnx("mrt_dump_entry: buf_add error");
++ log_warn("mrt_dump_entry: buf_add error");
+ goto fail;
+ }
+ break;
@@ -405,7 +464,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
+ case AID_INET6:
+ if (ibuf_add(hbuf, &peer->remote_addr.v6,
+ sizeof(struct in6_addr)) == -1) {
-+ log_warnx("mrt_dump_entry: buf_add error");
++ log_warn("mrt_dump_entry: buf_add error");
+ goto fail;
+ }
+ break;
@@ -425,10 +484,219 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
- 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: buf_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: buf_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: buf_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: buf_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: buf_add error");
++ goto fail;
++ }
++
++ off = ibuf_size(buf);
++ if (ibuf_reserve(buf, sizeof(nump)) == NULL) {
++ log_warn("mrt_dump_v2_hdr: buf_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: buf_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);
}
-@@ -387,7 +438,7 @@ mrt_dump_upcall(struct rib_entry *re, vo
+@@ -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
@@ -437,7 +705,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
{
struct mrt *mrtbuf = ptr;
-@@ -395,12 +446,12 @@ mrt_dump_done(void *ptr)
+@@ -395,14 +670,14 @@ mrt_dump_done(void *ptr)
}
int
@@ -450,9 +718,12 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
- 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_warnx("mrt_dump_hdr_se: buf_open error");
++ log_warn("mrt_dump_hdr_se: buf_open error");
return (-1);
-@@ -468,20 +519,20 @@ mrt_dump_hdr_se(struct buf ** bp, struct
+ }
+
+@@ -468,23 +743,23 @@ mrt_dump_hdr_se(struct buf ** bp, struct
case AF_INET6:
DUMP_SHORT(*bp, AFI_IPv6);
if (!swap)
@@ -460,14 +731,16 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
+ 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_warnx("mrt_dump_hdr_se: buf_add error");
++ log_warn("mrt_dump_hdr_se: buf_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_warnx("mrt_dump_hdr_se: buf_add error");
++ log_warn("mrt_dump_hdr_se: buf_add error");
goto fail;
}
if (swap)
@@ -475,8 +748,12 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
+ 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");
-@@ -493,17 +544,17 @@ mrt_dump_hdr_se(struct buf ** bp, struct
+- log_warnx("mrt_dump_hdr_se: buf_add error");
++ log_warn("mrt_dump_hdr_se: buf_add error");
+ goto fail;
+ }
+ break;
+@@ -493,20 +768,20 @@ mrt_dump_hdr_se(struct buf ** bp, struct
return (0);
fail:
@@ -496,8 +773,12 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
+ 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");
-@@ -517,7 +568,15 @@ mrt_dump_hdr_rde(struct buf **bp, u_int1
+- log_warnx("mrt_dump_hdr_rde: buf_dynamic error");
++ log_warn("mrt_dump_hdr_rde: buf_dynamic error");
+ return (-1);
+ }
+
+@@ -517,19 +792,28 @@ mrt_dump_hdr_rde(struct buf **bp, u_int1
switch (type) {
case MSG_TABLE_DUMP:
@@ -513,8 +794,9 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
+ DUMP_LONG(*bp, len);
break;
case MSG_PROTOCOL_BGP4MP:
++ case MSG_TABLE_DUMP_V2:
DUMP_LONG(*bp, len);
-@@ -525,11 +584,11 @@ mrt_dump_hdr_rde(struct buf **bp, u_int1
+ break;
default:
log_warnx("mrt_dump_hdr_rde: unsupported type");
goto fail;
@@ -528,7 +810,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
return (-1);
}
-@@ -538,21 +597,22 @@ mrt_write(struct mrt *mrt)
+@@ -538,21 +822,22 @@ mrt_write(struct mrt *mrt)
{
int r;
@@ -554,3 +836,24 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
}
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
index 7bf1857d39eb..0c9d835f5b78 100644
--- a/net/openbgpd/files/patch-bgpd_mrt.h
+++ b/net/openbgpd/files/patch-bgpd_mrt.h
@@ -2,13 +2,13 @@ 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.8
-diff -u -p -r1.1.1.6 -r1.1.1.8
+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 12 Jun 2011 10:44:25 -0000 1.1.1.8
++++ 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.27 2010/06/04 10:13:00 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>
@@ -26,7 +26,34 @@ diff -u -p -r1.1.1.6 -r1.1.1.8
* http://www.quagga.net/docs/docs-multi/Packet-Binary-Dump-Format.html
*/
-@@ -75,8 +73,10 @@ enum MRT_BGP4MP_TYPES {
+@@ -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) */
@@ -38,29 +65,223 @@ diff -u -p -r1.1.1.6 -r1.1.1.8
};
/* size of the BGP4MP headers without payload */
-@@ -184,6 +184,7 @@ enum MRT_BGP4MP_TYPES {
+@@ -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
-@@ -235,7 +236,7 @@ enum MRT_BGP_TYPES {
+@@ -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.
-+ * State are defined in RFC 1771/4271.
++ * States are defined in RFC 1771/4271.
*/
/*
-@@ -303,7 +304,7 @@ void mrt_dump_state(struct mrt *, u_in
- struct peer *);
- void mrt_clear_seq(void);
- void mrt_dump_upcall(struct rib_entry *, void *);
+@@ -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_done(void *);
- void mrt_write(struct mrt *);
- void mrt_clean(struct mrt *);
- void mrt_init(struct imsgbuf *, struct imsgbuf *);
+-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
new file mode 100644
index 000000000000..bf6cfbd067a8
--- /dev/null
+++ b/net/openbgpd/files/patch-bgpd_name2id.c
@@ -0,0 +1,14 @@
+Index: bgpd/name2id.c
+===================================================================
+RCS file: /home/cvs/private/hrs/openbgpd/bgpd/name2id.c,v
+retrieving revision 1.1.1.2
+retrieving revision 1.1.1.3
+diff -u -p -r1.1.1.2 -r1.1.1.3
+--- bgpd/name2id.c 9 Jul 2009 16:49:54 -0000 1.1.1.2
++++ bgpd/name2id.c 13 Oct 2012 18:22:43 -0000 1.1.1.3
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: name2id.c,v 1.9 2009/06/04 04:46:42 claudio Exp $ */
++/* $OpenBSD: name2id.c,v 1.8 2009/05/17 12:25:15 claudio Exp $ */
+
+ /*
+ * Copyright (c) 2004, 2005 Henning Brauer <henning@openbsd.org>
diff --git a/net/openbgpd/files/patch-bgpd_parse.y b/net/openbgpd/files/patch-bgpd_parse.y
index 64e9081f287d..76bc093b8ed3 100644
--- a/net/openbgpd/files/patch-bgpd_parse.y
+++ b/net/openbgpd/files/patch-bgpd_parse.y
@@ -2,12 +2,13 @@ Index: bgpd/parse.y
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/parse.y,v
retrieving revision 1.1.1.8
-diff -u -p -r1.1.1.8 parse.y
+retrieving revision 1.11
+diff -u -p -r1.1.1.8 -r1.11
--- bgpd/parse.y 14 Feb 2010 20:19:57 -0000 1.1.1.8
-+++ bgpd/parse.y 3 Jul 2011 04:43:32 -0000
++++ bgpd/parse.y 13 Oct 2012 18:50:07 -0000 1.11
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.231 2009/06/06 01:10:29 claudio Exp $ */
-+/* $OpenBSD: parse.y,v 1.250 2010/03/31 18:53:23 claudio Exp $ */
++/* $OpenBSD: parse.y,v 1.263 2012/09/12 05:56:22 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -23,7 +24,17 @@ diff -u -p -r1.1.1.8 parse.y
#include <ctype.h>
#include <err.h>
#include <unistd.h>
-@@ -74,10 +77,12 @@ char *symget(const char *);
+@@ -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;
@@ -37,7 +48,7 @@ diff -u -p -r1.1.1.8 parse.y
static struct filter_head *filter_l;
static struct filter_head *peerfilter_l;
static struct filter_head *groupfilter_l;
-@@ -105,7 +110,7 @@ struct filter_match_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;
@@ -46,7 +57,7 @@ diff -u -p -r1.1.1.8 parse.y
} fmopts;
struct peer *alloc_peer(void);
-@@ -113,8 +118,8 @@ struct peer *new_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 *);
@@ -57,7 +68,7 @@ diff -u -p -r1.1.1.8 parse.y
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 +128,14 @@ int neighbor_consistent(struct peer *)
+@@ -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 *);
@@ -75,7 +86,7 @@ diff -u -p -r1.1.1.8 parse.y
typedef struct {
union {
-@@ -159,29 +166,33 @@ typedef struct {
+@@ -159,29 +169,33 @@ typedef struct {
%}
%token AS ROUTERID HOLDTIME YMIN LISTEN ON FIBUPDATE RTABLE
@@ -117,7 +128,7 @@ diff -u -p -r1.1.1.8 parse.y
%type <v.string> string filter_rib
%type <v.addr> address
%type <v.prefix> prefix addrspec
-@@ -204,6 +215,7 @@ grammar : /* empty */
+@@ -204,6 +218,7 @@ grammar : /* empty */
| grammar include '\n'
| grammar conf_main '\n'
| grammar varset '\n'
@@ -125,7 +136,7 @@ diff -u -p -r1.1.1.8 parse.y
| grammar neighbor '\n'
| grammar group '\n'
| grammar filterrule '\n'
-@@ -211,8 +223,12 @@ grammar : /* empty */
+@@ -211,8 +226,12 @@ grammar : /* empty */
;
asnumber : NUMBER {
@@ -140,7 +151,7 @@ diff -u -p -r1.1.1.8 parse.y
YYERROR;
}
}
-@@ -274,6 +290,8 @@ yesno : STRING {
+@@ -274,6 +293,8 @@ yesno : STRING {
else if (!strcmp($1, "no"))
$$ = 0;
else {
@@ -149,7 +160,7 @@ diff -u -p -r1.1.1.8 parse.y
free($1);
YYERROR;
}
-@@ -318,7 +336,7 @@ conf_main : AS as4number {
+@@ -318,7 +339,7 @@ conf_main : AS as4number {
conf->short_as = $3;
}
| ROUTERID address {
@@ -158,7 +169,7 @@ diff -u -p -r1.1.1.8 parse.y
yyerror("router-id must be an IPv4 address");
YYERROR;
}
-@@ -342,42 +360,25 @@ conf_main : AS as4number {
+@@ -342,42 +363,25 @@ conf_main : AS as4number {
}
| LISTEN ON address {
struct listen_addr *la;
@@ -209,7 +220,7 @@ diff -u -p -r1.1.1.8 parse.y
}
| ROUTECOLL yesno {
if ($2 == 1)
-@@ -386,7 +387,7 @@ conf_main : AS as4number {
+@@ -386,7 +390,7 @@ conf_main : AS as4number {
conf->flags &= ~BGPD_FLAG_NO_EVALUATE;
}
| RDE RIB STRING {
@@ -218,7 +229,7 @@ diff -u -p -r1.1.1.8 parse.y
free($3);
YYERROR;
}
-@@ -395,9 +396,27 @@ conf_main : AS as4number {
+@@ -395,9 +399,27 @@ conf_main : AS as4number {
| RDE RIB STRING yesno EVALUATE {
if ($4) {
free($3);
@@ -247,7 +258,7 @@ diff -u -p -r1.1.1.8 parse.y
free($3);
YYERROR;
}
-@@ -418,59 +437,7 @@ conf_main : AS as4number {
+@@ -418,59 +440,7 @@ conf_main : AS as4number {
}
free($2);
}
@@ -308,7 +319,25 @@ diff -u -p -r1.1.1.8 parse.y
| DUMP STRING STRING optnumber {
int action;
-@@ -575,11 +542,20 @@ conf_main : AS as4number {
+@@ -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 {
@@ -332,7 +361,7 @@ diff -u -p -r1.1.1.8 parse.y
}
| CONNECTRETRY NUMBER {
if ($2 > USHRT_MAX || $2 < 1) {
-@@ -588,6 +564,15 @@ conf_main : AS as4number {
+@@ -588,6 +571,15 @@ conf_main : AS as4number {
}
conf->connectretry = $2;
}
@@ -348,7 +377,7 @@ diff -u -p -r1.1.1.8 parse.y
;
mrtdump : DUMP STRING inout STRING optnumber {
-@@ -620,10 +605,47 @@ mrtdump : DUMP STRING inout STRING optn
+@@ -620,10 +612,47 @@ mrtdump : DUMP STRING inout STRING optn
}
;
@@ -396,7 +425,7 @@ diff -u -p -r1.1.1.8 parse.y
address : STRING {
u_int8_t len;
-@@ -635,11 +657,11 @@ address : STRING {
+@@ -635,11 +664,11 @@ address : STRING {
}
free($1);
@@ -411,7 +440,7 @@ diff -u -p -r1.1.1.8 parse.y
YYERROR;
}
}
-@@ -653,7 +675,7 @@ prefix : STRING '/' NUMBER {
+@@ -653,7 +682,7 @@ prefix : STRING '/' NUMBER {
free($1);
YYERROR;
}
@@ -420,7 +449,7 @@ diff -u -p -r1.1.1.8 parse.y
fatal(NULL);
free($1);
-@@ -672,7 +694,7 @@ prefix : STRING '/' NUMBER {
+@@ -672,7 +701,7 @@ prefix : STRING '/' NUMBER {
yyerror("bad prefix %lld/%lld", $1, $3);
YYERROR;
}
@@ -429,7 +458,7 @@ diff -u -p -r1.1.1.8 parse.y
fatal(NULL);
if (!host(s, &$$.prefix, &$$.len)) {
-@@ -686,7 +708,7 @@ prefix : STRING '/' NUMBER {
+@@ -686,7 +715,7 @@ prefix : STRING '/' NUMBER {
addrspec : address {
memcpy(&$$.prefix, &$1, sizeof(struct bgpd_addr));
@@ -438,7 +467,7 @@ diff -u -p -r1.1.1.8 parse.y
$$.len = 32;
else
$$.len = 128;
-@@ -705,14 +727,150 @@ optnumber : /* empty */ { $$ = 0; }
+@@ -705,14 +734,150 @@ optnumber : /* empty */ { $$ = 0; }
| NUMBER
;
@@ -591,7 +620,7 @@ diff -u -p -r1.1.1.8 parse.y
if (get_id(curpeer)) {
yyerror("get_id failed");
YYERROR;
-@@ -802,6 +960,17 @@ peeropts : REMOTEAS as4number {
+@@ -802,6 +967,17 @@ peeropts : REMOTEAS as4number {
}
free($2);
}
@@ -609,7 +638,7 @@ diff -u -p -r1.1.1.8 parse.y
| LOCALADDR address {
memcpy(&curpeer->conf.local_addr, &$2,
sizeof(curpeer->conf.local_addr));
-@@ -852,13 +1021,17 @@ peeropts : REMOTEAS as4number {
+@@ -852,13 +1028,17 @@ peeropts : REMOTEAS as4number {
curpeer->conf.min_holdtime = $3;
}
| ANNOUNCE family STRING {
@@ -632,7 +661,7 @@ diff -u -p -r1.1.1.8 parse.y
yyerror("unknown/unsupported SAFI \"%s\"",
$3);
free($3);
-@@ -866,25 +1039,31 @@ peeropts : REMOTEAS as4number {
+@@ -866,25 +1046,31 @@ peeropts : REMOTEAS as4number {
}
free($3);
@@ -658,7 +687,7 @@ diff -u -p -r1.1.1.8 parse.y
+ curpeer->conf.capabilities.refresh = $3;
+ }
+ | ANNOUNCE RESTART yesno {
-+ curpeer->conf.capabilities.restart = $3;
++ curpeer->conf.capabilities.grestart.restart = $3;
+ }
+ | ANNOUNCE AS4BYTE yesno {
+ curpeer->conf.capabilities.as4byte = $3;
@@ -674,7 +703,7 @@ diff -u -p -r1.1.1.8 parse.y
curpeer->conf.announce_type = ANNOUNCE_NONE;
else if (!strcmp($2, "all"))
curpeer->conf.announce_type = ANNOUNCE_ALL;
-@@ -1083,7 +1262,7 @@ peeropts : REMOTEAS as4number {
+@@ -1083,7 +1269,7 @@ peeropts : REMOTEAS as4number {
curpeer->conf.reflector_client = 1;
}
| REFLECTOR address {
@@ -683,7 +712,7 @@ diff -u -p -r1.1.1.8 parse.y
yyerror("route reflector cluster-id must be "
"an IPv4 address");
YYERROR;
-@@ -1157,6 +1336,10 @@ family : IPV4 { $$ = AFI_IPv4; }
+@@ -1157,6 +1343,10 @@ family : IPV4 { $$ = AFI_IPv4; }
| IPV6 { $$ = AFI_IPv6; }
;
@@ -694,7 +723,7 @@ diff -u -p -r1.1.1.8 parse.y
espah : ESP { $$ = 1; }
| AH { $$ = 0; }
;
-@@ -1336,12 +1519,12 @@ filter_prefix_l : filter_prefix { $$
+@@ -1336,12 +1526,12 @@ filter_prefix_l : filter_prefix { $$
;
filter_prefix : prefix {
@@ -709,7 +738,7 @@ diff -u -p -r1.1.1.8 parse.y
if (($$ = calloc(1, sizeof(struct filter_prefix_l))) ==
NULL)
fatal(NULL);
-@@ -1410,6 +1593,12 @@ filter_as : as4number {
+@@ -1410,6 +1600,12 @@ filter_as : as4number {
fatal(NULL);
$$->a.as = $1;
}
@@ -722,7 +751,7 @@ diff -u -p -r1.1.1.8 parse.y
;
filter_match_h : /* empty */ {
-@@ -1437,18 +1626,18 @@ filter_elm : filter_prefix_h {
+@@ -1437,18 +1633,18 @@ filter_elm : filter_prefix_h {
fmopts.prefix_l = $1;
}
| PREFIXLEN prefixlenop {
@@ -744,7 +773,7 @@ diff -u -p -r1.1.1.8 parse.y
}
| filter_as_h {
if (fmopts.as_l != NULL) {
-@@ -1457,32 +1646,73 @@ filter_elm : filter_prefix_h {
+@@ -1457,32 +1653,73 @@ filter_elm : filter_prefix_h {
}
fmopts.as_l = $1;
}
@@ -781,11 +810,11 @@ diff -u -p -r1.1.1.8 parse.y
- if (parsecommunity($2, &fmopts.m.community.as,
- &fmopts.m.community.type) == -1) {
+ if (parsecommunity(&fmopts.m.community, $2) == -1) {
- free($2);
- YYERROR;
- }
- free($2);
- }
++ free($2);
++ YYERROR;
++ }
++ free($2);
++ }
+ | EXTCOMMUNITY STRING STRING {
+ if (fmopts.m.ext_community.flags &
+ EXT_COMMUNITY_FLAG_VALID) {
@@ -797,13 +826,13 @@ diff -u -p -r1.1.1.8 parse.y
+
+ if (parseextcommunity(&fmopts.m.ext_community,
+ $2, $3) == -1) {
-+ free($2);
+ free($2);
+ free($3);
-+ YYERROR;
-+ }
-+ free($2);
+ YYERROR;
+ }
+ free($2);
+ free($3);
-+ }
+ }
| IPV4 {
- if (fmopts.af) {
+ if (fmopts.aid) {
@@ -824,7 +853,25 @@ diff -u -p -r1.1.1.8 parse.y
}
;
-@@ -1782,8 +2012,7 @@ filter_set_opt : LOCALPREF NUMBER {
+@@ -1588,7 +1825,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 +1860,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 +2019,7 @@ filter_set_opt : LOCALPREF NUMBER {
else
$$->type = ACTION_SET_COMMUNITY;
@@ -834,7 +881,7 @@ diff -u -p -r1.1.1.8 parse.y
free($3);
free($$);
YYERROR;
-@@ -1796,40 +2025,62 @@ filter_set_opt : LOCALPREF NUMBER {
+@@ -1796,40 +2032,62 @@ filter_set_opt : LOCALPREF NUMBER {
free($$);
YYERROR;
}
@@ -917,7 +964,7 @@ diff -u -p -r1.1.1.8 parse.y
;
%%
-@@ -1873,6 +2124,7 @@ lookup(char *s)
+@@ -1873,6 +2131,7 @@ lookup(char *s)
{ "allow", ALLOW},
{ "announce", ANNOUNCE},
{ "any", ANY},
@@ -925,7 +972,7 @@ diff -u -p -r1.1.1.8 parse.y
{ "blackhole", BLACKHOLE},
{ "capabilities", CAPABILITIES},
{ "community", COMMUNITY},
-@@ -1889,16 +2141,22 @@ lookup(char *s)
+@@ -1889,16 +2148,22 @@ lookup(char *s)
{ "enforce", ENFORCE},
{ "esp", ESP},
{ "evaluate", EVALUATE},
@@ -948,7 +995,7 @@ diff -u -p -r1.1.1.8 parse.y
{ "ipsec", IPSEC},
{ "key", KEY},
{ "listen", LISTEN},
-@@ -1906,6 +2164,8 @@ lookup(char *s)
+@@ -1906,6 +2171,8 @@ lookup(char *s)
{ "localpref", LOCALPREF},
{ "log", LOG},
{ "match", MATCH},
@@ -957,7 +1004,7 @@ diff -u -p -r1.1.1.8 parse.y
{ "max-prefix", MAXPREFIX},
{ "md5sig", MD5SIG},
{ "med", MED},
-@@ -1918,6 +2178,7 @@ lookup(char *s)
+@@ -1918,6 +2185,7 @@ lookup(char *s)
{ "nexthop", NEXTHOP},
{ "no-modify", NOMODIFY},
{ "on", ON},
@@ -965,7 +1012,7 @@ diff -u -p -r1.1.1.8 parse.y
{ "out", OUT},
{ "passive", PASSIVE},
{ "password", PASSWORD},
-@@ -1929,10 +2190,14 @@ lookup(char *s)
+@@ -1929,10 +2197,14 @@ lookup(char *s)
{ "prepend-self", PREPEND_SELF},
{ "qualify", QUALIFY},
{ "quick", QUICK},
@@ -980,7 +1027,7 @@ diff -u -p -r1.1.1.8 parse.y
{ "rib", RIB},
{ "route-collector", ROUTECOLL},
{ "route-reflector", REFLECTOR},
-@@ -1941,6 +2206,7 @@ lookup(char *s)
+@@ -1941,6 +2213,7 @@ lookup(char *s)
{ "rtlabel", RTLABEL},
{ "self", SELF},
{ "set", SET},
@@ -988,7 +1035,7 @@ diff -u -p -r1.1.1.8 parse.y
{ "softreconfig", SOFTRECONFIG},
{ "source-as", SOURCEAS},
{ "spi", SPI},
-@@ -2117,9 +2383,10 @@ top:
+@@ -2117,9 +2390,10 @@ top:
return (0);
if (next == quotec || c == ' ' || c == '\t')
c = next;
@@ -1001,7 +1048,7 @@ diff -u -p -r1.1.1.8 parse.y
lungetc(next);
} else if (c == quotec) {
*p = '\0';
-@@ -2135,6 +2402,26 @@ top:
+@@ -2135,6 +2409,26 @@ top:
if (yylval.v.string == NULL)
fatal("yylex: strdup");
return (STRING);
@@ -1028,7 +1075,7 @@ diff -u -p -r1.1.1.8 parse.y
}
#define allowed_to_end_number(x) \
-@@ -2274,18 +2561,21 @@ popfile(void)
+@@ -2274,18 +2568,21 @@ popfile(void)
int
parse_config(char *filename, struct bgpd_config *xconf,
struct mrt_head *xmconf, struct peer **xpeers, struct network_head *nc,
@@ -1051,7 +1098,7 @@ diff -u -p -r1.1.1.8 parse.y
if ((file = pushfile(filename, 1)) == NULL) {
free(conf);
-@@ -2316,13 +2606,15 @@ parse_config(char *filename, struct bgpd
+@@ -2316,13 +2613,15 @@ parse_config(char *filename, struct bgpd
id = 1;
/* network list is always empty in the parent */
@@ -1070,7 +1117,7 @@ diff -u -p -r1.1.1.8 parse.y
yyparse();
errors = file->errors;
-@@ -2344,6 +2636,9 @@ parse_config(char *filename, struct bgpd
+@@ -2344,6 +2643,9 @@ parse_config(char *filename, struct bgpd
if (errors) {
/* XXX more leaks in this case */
@@ -1080,7 +1127,7 @@ diff -u -p -r1.1.1.8 parse.y
while ((la = TAILQ_FIRST(listen_addrs)) != NULL) {
TAILQ_REMOVE(listen_addrs, la, entry);
free(la);
-@@ -2357,23 +2652,44 @@ parse_config(char *filename, struct bgpd
+@@ -2357,23 +2659,44 @@ parse_config(char *filename, struct bgpd
while ((n = TAILQ_FIRST(netconf)) != NULL) {
TAILQ_REMOVE(netconf, n, entry);
@@ -1125,7 +1172,7 @@ diff -u -p -r1.1.1.8 parse.y
} else {
errors += merge_config(xconf, conf, peer_l, listen_addrs);
errors += mrt_mergeconfig(xmconf, mrtconf);
-@@ -2505,27 +2821,27 @@ getcommunity(char *s)
+@@ -2505,27 +2828,27 @@ getcommunity(char *s)
}
int
@@ -1163,7 +1210,7 @@ diff -u -p -r1.1.1.8 parse.y
return (0);
}
-@@ -2537,23 +2853,176 @@ parsecommunity(char *s, int *as, int *ty
+@@ -2537,23 +2860,176 @@ parsecommunity(char *s, int *as, int *ty
if ((i = getcommunity(s)) == COMMUNITY_ERROR)
return (-1);
@@ -1343,7 +1390,7 @@ diff -u -p -r1.1.1.8 parse.y
if ((p = calloc(1, sizeof(struct peer))) == NULL)
fatal("new_peer");
-@@ -2564,11 +3033,11 @@ alloc_peer(void)
+@@ -2564,11 +3040,11 @@ alloc_peer(void)
p->conf.distance = 1;
p->conf.announce_type = ANNOUNCE_UNDEF;
p->conf.announce_capa = 1;
@@ -1352,13 +1399,14 @@ diff -u -p -r1.1.1.8 parse.y
+ 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.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 +3061,9 @@ new_peer(void)
+@@ -2592,6 +3068,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");
@@ -1368,7 +1416,7 @@ diff -u -p -r1.1.1.8 parse.y
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 +3146,52 @@ add_mrtconfig(enum mrt_type type, char *
+@@ -2674,39 +3153,52 @@ add_mrtconfig(enum mrt_type type, char *
}
int
@@ -1433,7 +1481,7 @@ diff -u -p -r1.1.1.8 parse.y
}
int
-@@ -2715,7 +3200,7 @@ get_id(struct peer *newpeer)
+@@ -2715,7 +3207,7 @@ get_id(struct peer *newpeer)
struct peer *p;
for (p = peer_l_old; p != NULL; p = p->next)
@@ -1442,7 +1490,7 @@ diff -u -p -r1.1.1.8 parse.y
if (!memcmp(&p->conf.remote_addr,
&newpeer->conf.remote_addr,
sizeof(p->conf.remote_addr))) {
-@@ -2856,9 +3341,11 @@ str2key(char *s, char *dest, size_t max_
+@@ -2856,9 +3348,11 @@ str2key(char *s, char *dest, size_t max_
int
neighbor_consistent(struct peer *p)
{
@@ -1456,7 +1504,7 @@ diff -u -p -r1.1.1.8 parse.y
yyerror("local-address and neighbor address "
"must be of the same address family");
return (-1);
-@@ -2869,7 +3356,7 @@ neighbor_consistent(struct peer *p)
+@@ -2869,7 +3363,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) &&
@@ -1465,7 +1513,7 @@ diff -u -p -r1.1.1.8 parse.y
yyerror("neighbors with any form of IPsec configured "
"need local-address to be specified");
return (-1);
-@@ -2889,10 +3376,6 @@ neighbor_consistent(struct peer *p)
+@@ -2889,18 +3383,14 @@ neighbor_consistent(struct peer *p)
return (-1);
}
@@ -1476,7 +1524,19 @@ diff -u -p -r1.1.1.8 parse.y
/* set default values if they where undefined */
p->conf.ebgp = (p->conf.remote_as != conf->as);
if (p->conf.announce_type == ANNOUNCE_UNDEF)
-@@ -2909,6 +3392,11 @@ neighbor_consistent(struct peer *p)
+- 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 +3399,11 @@ neighbor_consistent(struct peer *p)
return (-1);
}
@@ -1488,7 +1548,7 @@ diff -u -p -r1.1.1.8 parse.y
return (0);
}
-@@ -2927,6 +3415,11 @@ merge_filterset(struct filter_set_head *
+@@ -2927,6 +3422,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");
@@ -1500,7 +1560,7 @@ diff -u -p -r1.1.1.8 parse.y
else
yyerror("redefining set parameter %s",
filterset_name(s->type));
-@@ -2953,9 +3446,18 @@ merge_filterset(struct filter_set_head *
+@@ -2953,9 +3453,18 @@ merge_filterset(struct filter_set_head *
return (0);
}
break;
@@ -1521,7 +1581,7 @@ diff -u -p -r1.1.1.8 parse.y
TAILQ_INSERT_BEFORE(t, s, entry);
return (0);
}
-@@ -2985,22 +3487,6 @@ copy_filterset(struct filter_set_head *s
+@@ -2985,22 +3494,6 @@ copy_filterset(struct filter_set_head *s
}
}
diff --git a/net/openbgpd/files/patch-bgpd_pfkey.c b/net/openbgpd/files/patch-bgpd_pfkey.c
index f8e6845f1661..7ad7548a3e5a 100644
--- a/net/openbgpd/files/patch-bgpd_pfkey.c
+++ b/net/openbgpd/files/patch-bgpd_pfkey.c
@@ -2,13 +2,13 @@ Index: bgpd/pfkey.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/pfkey.c,v
retrieving revision 1.1.1.6
-retrieving revision 1.1.1.8
-diff -u -p -r1.1.1.6 -r1.1.1.8
+retrieving revision 1.1.1.9
+diff -u -p -r1.1.1.6 -r1.1.1.9
--- bgpd/pfkey.c 14 Feb 2010 20:19:57 -0000 1.1.1.6
-+++ bgpd/pfkey.c 12 Jun 2011 10:44:25 -0000 1.1.1.8
++++ bgpd/pfkey.c 13 Oct 2012 18:22:44 -0000 1.1.1.9
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkey.c,v 1.37 2009/04/21 15:25:52 henning Exp $ */
-+/* $OpenBSD: pfkey.c,v 1.41 2010/12/09 13:50:41 claudio Exp $ */
++/* $OpenBSD: pfkey.c,v 1.40 2009/12/14 17:38:18 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
diff --git a/net/openbgpd/files/patch-bgpd_pftable.c b/net/openbgpd/files/patch-bgpd_pftable.c
index a9f2092dd156..ee6a1ea2750c 100644
--- a/net/openbgpd/files/patch-bgpd_pftable.c
+++ b/net/openbgpd/files/patch-bgpd_pftable.c
@@ -2,16 +2,10 @@ 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.6
-diff -u -p -r1.1.1.5 -r1.1.1.6
+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 14 Feb 2010 20:27:06 -0000 1.1.1.6
-@@ -1,4 +1,4 @@
--/* $OpenBSD: pftable.c,v 1.5 2005/07/01 09:19:24 claudio Exp $ */
-+/* $OpenBSD: pftable.c,v 1.6 2009/12/01 14:28:05 claudio Exp $ */
-
- /*
- * Copyright (c) 2004 Damien Miller <djm@openbsd.org>
++++ 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));
diff --git a/net/openbgpd/files/patch-bgpd_printconf.c b/net/openbgpd/files/patch-bgpd_printconf.c
index 82fb337ccb7b..ecc7dfdc4aaf 100644
--- a/net/openbgpd/files/patch-bgpd_printconf.c
+++ b/net/openbgpd/files/patch-bgpd_printconf.c
@@ -2,13 +2,13 @@ Index: bgpd/printconf.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/printconf.c,v
retrieving revision 1.1.1.7
-retrieving revision 1.8
-diff -u -p -r1.1.1.7 -r1.8
+retrieving revision 1.9
+diff -u -p -r1.1.1.7 -r1.9
--- bgpd/printconf.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/printconf.c 2 Jul 2011 16:06:38 -0000 1.8
++++ bgpd/printconf.c 13 Oct 2012 18:36:00 -0000 1.9
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.70 2009/06/06 01:10:29 claudio Exp $ */
-+/* $OpenBSD: printconf.c,v 1.79 2010/03/05 15:25:00 claudio Exp $ */
++/* $OpenBSD: printconf.c,v 1.87 2012/09/12 05:56:22 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -263,8 +263,8 @@ diff -u -p -r1.1.1.7 -r1.8
printf("%s\tannounce capabilities no\n", c);
+ if (p->capabilities.refresh == 0)
+ printf("%s\tannounce refresh no\n", c);
-+ if (p->capabilities.restart == 1)
-+ printf("%s\tannounce restart yes\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)
@@ -356,16 +356,34 @@ diff -u -p -r1.1.1.7 -r1.8
print_set(&r->set);
-@@ -547,7 +645,7 @@ print_mrt(u_int32_t pid, u_int32_t gid,
+@@ -513,6 +611,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,13 +641,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("%s %s %d\n", mrt_type(m->type),
+- MRT2MC(m)->name,
- MRT2MC(m)->ReopenTimerInterval);
-+ (int)MRT2MC(m)->ReopenTimerInterval);
++ printf(" %d\n", MRT2MC(m)->ReopenTimerInterval);
}
}
-@@ -612,26 +710,34 @@ peer_compare(const void *aa, const void
+@@ -612,26 +711,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,
diff --git a/net/openbgpd/files/patch-bgpd_rde.c b/net/openbgpd/files/patch-bgpd_rde.c
index a62bcf26fdc7..62634c6aa5c1 100644
--- a/net/openbgpd/files/patch-bgpd_rde.c
+++ b/net/openbgpd/files/patch-bgpd_rde.c
@@ -2,16 +2,17 @@ Index: bgpd/rde.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde.c,v
retrieving revision 1.1.1.8
-diff -u -p -r1.1.1.8 rde.c
+retrieving revision 1.11
+diff -u -p -r1.1.1.8 -r1.11
--- bgpd/rde.c 14 Feb 2010 20:19:57 -0000 1.1.1.8
-+++ bgpd/rde.c 3 Jul 2011 04:43:59 -0000
++++ bgpd/rde.c 13 Oct 2012 18:36:00 -0000 1.11
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.264 2009/06/29 12:22:16 claudio Exp $ */
-+/* $OpenBSD: rde.c,v 1.290 2010/03/30 15:43:30 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,6 +18,8 @@
+@@ -18,10 +18,11 @@
#include <sys/types.h>
#include <sys/socket.h>
@@ -20,9 +21,15 @@ diff -u -p -r1.1.1.8 rde.c
#include <errno.h>
#include <ifaddrs.h>
-@@ -51,12 +53,16 @@ void rde_update_withdraw(struct rde_pe
+-#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 *);
@@ -56,12 +63,15 @@ diff -u -p -r1.1.1.8 rde.c
void peer_init(u_int32_t);
void peer_shutdown(void);
-@@ -91,10 +101,9 @@ struct rde_peer *peer_add(u_int32_t, str
+@@ -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);
@@ -69,7 +79,7 @@ diff -u -p -r1.1.1.8 rde.c
void network_add(struct network_config *, int);
void network_delete(struct network_config *, int);
void network_dump_upcall(struct rib_entry *, void *);
-@@ -108,6 +117,7 @@ time_t reloadtime;
+@@ -108,6 +120,7 @@ time_t reloadtime;
struct rde_peer_head peerlist;
struct rde_peer *peerself;
struct filter_head *rules_l, *newrules;
@@ -77,7 +87,7 @@ diff -u -p -r1.1.1.8 rde.c
struct imsgbuf *ibuf_se;
struct imsgbuf *ibuf_se_ctl;
struct imsgbuf *ibuf_main;
-@@ -120,11 +130,12 @@ struct rde_dump_ctx {
+@@ -120,11 +133,12 @@ struct rde_dump_ctx {
};
struct rde_mrt_ctx {
@@ -93,7 +103,7 @@ diff -u -p -r1.1.1.8 rde.c
u_int rde_mrt_cnt;
void
-@@ -144,24 +155,18 @@ u_int32_t attrhashsize = 512;
+@@ -144,24 +158,17 @@ u_int32_t attrhashsize = 512;
u_int32_t nexthophashsize = 64;
pid_t
@@ -104,7 +114,6 @@ diff -u -p -r1.1.1.8 rde.c
+rde_main(int pipe_m2r[2], int pipe_s2r[2], int pipe_m2s[2], int pipe_s2rctl[2],
+ int debug)
{
-+ struct rlimit rl;
pid_t pid;
struct passwd *pw;
- struct peer *p;
@@ -123,7 +132,7 @@ diff -u -p -r1.1.1.8 rde.c
switch (pid = fork()) {
case -1:
-@@ -172,8 +177,6 @@ rde_main(struct bgpd_config *config, str
+@@ -172,8 +179,6 @@ rde_main(struct bgpd_config *config, str
return (pid);
}
@@ -132,20 +141,7 @@ diff -u -p -r1.1.1.8 rde.c
if ((pw = getpwnam(BGPD_USER)) == NULL)
fatal("getpwnam");
-@@ -185,6 +188,12 @@ rde_main(struct bgpd_config *config, str
- setproctitle("route decision engine");
- bgpd_process = PROC_RDE;
-
-+ if (getrlimit(RLIMIT_DATA, &rl) == -1)
-+ fatal("getrlimit");
-+ rl.rlim_cur = rl.rlim_max;
-+ if (setrlimit(RLIMIT_DATA, &rl) == -1)
-+ fatal("setrlimit");
-+
- 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))
-@@ -194,6 +203,8 @@ rde_main(struct bgpd_config *config, str
+@@ -194,6 +199,8 @@ rde_main(struct bgpd_config *config, str
signal(SIGINT, rde_sighdlr);
signal(SIGPIPE, SIG_IGN);
signal(SIGHUP, SIG_IGN);
@@ -154,7 +150,7 @@ diff -u -p -r1.1.1.8 rde.c
close(pipe_s2r[0]);
close(pipe_s2rctl[0]);
-@@ -210,50 +221,25 @@ rde_main(struct bgpd_config *config, str
+@@ -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]);
@@ -215,7 +211,7 @@ diff -u -p -r1.1.1.8 rde.c
while (rde_quit == 0) {
if (pfd_elms < PFD_PIPE_COUNT + rde_mrt_cnt) {
if ((newp = realloc(pfd, sizeof(struct pollfd) *
-@@ -287,11 +273,18 @@ rde_main(struct bgpd_config *config, str
+@@ -287,11 +269,18 @@ rde_main(struct bgpd_config *config, str
timeout = 0;
i = PFD_PIPE_COUNT;
@@ -237,7 +233,7 @@ diff -u -p -r1.1.1.8 rde.c
}
}
-@@ -325,24 +318,17 @@ rde_main(struct bgpd_config *config, str
+@@ -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);
@@ -269,7 +265,7 @@ diff -u -p -r1.1.1.8 rde.c
if (ibuf_se_ctl->w.queued <= 0)
rib_dump_runner();
}
-@@ -351,11 +337,12 @@ rde_main(struct bgpd_config *config, str
+@@ -351,11 +333,12 @@ rde_main(struct bgpd_config *config, str
if (debug)
rde_shutdown();
@@ -287,26 +283,73 @@ diff -u -p -r1.1.1.8 rde.c
}
msgbuf_clear(&ibuf_se->w);
-@@ -378,13 +365,14 @@ rde_dispatch_imsg_session(struct imsgbuf
+@@ -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 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");
-@@ -423,12 +411,14 @@ rde_dispatch_imsg_session(struct imsgbuf
+@@ -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)) {
@@ -322,7 +365,55 @@ diff -u -p -r1.1.1.8 rde.c
break;
case IMSG_NETWORK_ADD:
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
-@@ -446,13 +436,13 @@ rde_dispatch_imsg_session(struct imsgbuf
+@@ -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;
@@ -339,7 +430,29 @@ diff -u -p -r1.1.1.8 rde.c
if (netconf_s.prefixlen > 128)
goto badnet;
network_add(&netconf_s, 0);
-@@ -544,6 +534,11 @@ badnet:
+ 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;
@@ -351,7 +464,7 @@ diff -u -p -r1.1.1.8 rde.c
default:
break;
}
-@@ -554,14 +549,17 @@ badnet:
+@@ -554,14 +639,17 @@ badnet:
void
rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
{
@@ -370,7 +483,7 @@ diff -u -p -r1.1.1.8 rde.c
u_int16_t rid;
if ((n = imsg_read(ibuf)) == -1)
-@@ -576,20 +574,12 @@ rde_dispatch_imsg_parent(struct imsgbuf
+@@ -576,20 +664,12 @@ rde_dispatch_imsg_parent(struct imsgbuf
break;
switch (imsg.hdr.type) {
@@ -396,7 +509,7 @@ diff -u -p -r1.1.1.8 rde.c
memcpy(&netconf_p, imsg.data, sizeof(netconf_p));
TAILQ_INIT(&netconf_p.attrset);
parent_set = &netconf_p.attrset;
-@@ -608,6 +598,26 @@ rde_dispatch_imsg_parent(struct imsgbuf
+@@ -608,6 +688,26 @@ rde_dispatch_imsg_parent(struct imsgbuf
TAILQ_INIT(&netconf_p.attrset);
network_delete(&netconf_p, 1);
break;
@@ -423,7 +536,7 @@ diff -u -p -r1.1.1.8 rde.c
case IMSG_RECONF_RIB:
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
sizeof(struct rde_rib))
-@@ -615,9 +625,26 @@ rde_dispatch_imsg_parent(struct imsgbuf
+@@ -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)
@@ -453,7 +566,7 @@ diff -u -p -r1.1.1.8 rde.c
break;
case IMSG_RECONF_FILTER:
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
-@@ -631,12 +658,42 @@ rde_dispatch_imsg_parent(struct imsgbuf
+@@ -631,12 +748,42 @@ rde_dispatch_imsg_parent(struct imsgbuf
parent_set = &r->set;
TAILQ_INSERT_TAIL(newrules, r, entry);
break;
@@ -497,7 +610,7 @@ diff -u -p -r1.1.1.8 rde.c
"mode ignored");
if (conf->flags & BGPD_FLAG_NO_EVALUATE)
nconf->flags |= BGPD_FLAG_NO_EVALUATE;
-@@ -644,10 +701,27 @@ rde_dispatch_imsg_parent(struct imsgbuf
+@@ -644,10 +791,27 @@ rde_dispatch_imsg_parent(struct imsgbuf
nconf->flags &= ~BGPD_FLAG_NO_EVALUATE;
}
memcpy(conf, nconf, sizeof(struct bgpd_config));
@@ -526,7 +639,7 @@ diff -u -p -r1.1.1.8 rde.c
/* check if filter changed */
LIST_FOREACH(peer, &peerlist, peer_l) {
-@@ -655,30 +729,59 @@ rde_dispatch_imsg_parent(struct imsgbuf
+@@ -655,30 +819,59 @@ rde_dispatch_imsg_parent(struct imsgbuf
continue;
peer->reconf_out = 0;
peer->reconf_in = 0;
@@ -558,9 +671,7 @@ diff -u -p -r1.1.1.8 rde.c
+ 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)
@@ -569,7 +680,9 @@ diff -u -p -r1.1.1.8 rde.c
+ rib_dump(&ribs[0],
+ rde_softreconfig_load, &ribs[rid],
+ AID_UNSPEC);
-+ }
+ }
+- /* XXX this needs rework anyway */
+- /* sync local-RIB first */
+ /* sync local-RIBs first */
if (reconf_in)
rib_dump(&ribs[0], rde_softreconfig_in, NULL,
@@ -597,7 +710,7 @@ diff -u -p -r1.1.1.8 rde.c
}
while ((r = TAILQ_FIRST(rules_l)) != NULL) {
-@@ -688,16 +791,16 @@ rde_dispatch_imsg_parent(struct imsgbuf
+@@ -688,16 +881,18 @@ rde_dispatch_imsg_parent(struct imsgbuf
}
free(rules_l);
rules_l = newrules;
@@ -607,6 +720,8 @@ diff -u -p -r1.1.1.8 rde.c
- }
+
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);
@@ -618,7 +733,17 @@ diff -u -p -r1.1.1.8 rde.c
if (parent_set == NULL) {
log_warnx("rde_dispatch_imsg_parent: "
"IMSG_FILTER_SET unexpected");
-@@ -744,6 +847,8 @@ rde_dispatch_imsg_parent(struct imsgbuf
+@@ -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)
{
@@ -627,7 +752,7 @@ diff -u -p -r1.1.1.8 rde.c
struct rde_peer *peer;
struct rde_aspath *asp = NULL;
u_char *p, *mpp = NULL;
-@@ -752,9 +857,8 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -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;
@@ -639,7 +764,7 @@ diff -u -p -r1.1.1.8 rde.c
peer = peer_get(imsg->hdr.peerid);
if (peer == NULL) /* unknown peer, cannot happen */
-@@ -810,26 +914,21 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -810,26 +1007,21 @@ rde_update_dispatch(struct imsg *imsg)
goto done;
}
@@ -676,7 +801,7 @@ diff -u -p -r1.1.1.8 rde.c
rde_reflector(peer, asp);
}
-@@ -860,9 +959,9 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -860,9 +1052,9 @@ rde_update_dispatch(struct imsg *imsg)
p += pos;
len -= pos;
@@ -689,7 +814,18 @@ diff -u -p -r1.1.1.8 rde.c
rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR,
NULL, 0);
goto done;
-@@ -892,15 +991,25 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -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--;
@@ -719,12 +855,17 @@ diff -u -p -r1.1.1.8 rde.c
+ 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 +1035,32 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -926,6 +1137,32 @@ rde_update_dispatch(struct imsg *imsg)
rde_update_withdraw(peer, &prefix, prefixlen);
}
break;
@@ -757,7 +898,7 @@ diff -u -p -r1.1.1.8 rde.c
default:
/* silently ignore unsupported multiprotocol AF */
break;
-@@ -963,9 +1098,9 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -963,9 +1200,9 @@ rde_update_dispatch(struct imsg *imsg)
p += pos;
nlri_len -= pos;
@@ -770,7 +911,7 @@ diff -u -p -r1.1.1.8 rde.c
rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR,
NULL, 0);
goto done;
-@@ -995,6 +1130,22 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -995,6 +1232,22 @@ rde_update_dispatch(struct imsg *imsg)
safi = *mpp++;
mplen--;
@@ -793,7 +934,7 @@ diff -u -p -r1.1.1.8 rde.c
/*
* this works because asp is not linked.
* But first unlock the previously locked nexthop.
-@@ -1004,8 +1155,8 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -1004,8 +1257,8 @@ rde_update_dispatch(struct imsg *imsg)
(void)nexthop_delete(asp->nexthop);
asp->nexthop = NULL;
}
@@ -804,7 +945,7 @@ diff -u -p -r1.1.1.8 rde.c
rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR,
mpa.reach, mpa.reach_len);
goto done;
-@@ -1013,16 +1164,8 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -1013,16 +1266,8 @@ rde_update_dispatch(struct imsg *imsg)
mpp += pos;
mplen -= pos;
@@ -823,7 +964,7 @@ diff -u -p -r1.1.1.8 rde.c
while (mplen > 0) {
if ((pos = rde_update_get_prefix6(mpp, mplen,
&prefix, &prefixlen)) == -1) {
-@@ -1058,6 +1201,42 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -1058,6 +1303,42 @@ rde_update_dispatch(struct imsg *imsg)
}
break;
@@ -866,7 +1007,7 @@ diff -u -p -r1.1.1.8 rde.c
default:
/* silently ignore unsupported multiprotocol AF */
break;
-@@ -1085,7 +1264,8 @@ rde_update_update(struct rde_peer *peer,
+@@ -1085,7 +1366,8 @@ rde_update_update(struct rde_peer *peer,
struct bgpd_addr *prefix, u_int8_t prefixlen)
{
struct rde_aspath *fasp;
@@ -876,7 +1017,7 @@ diff -u -p -r1.1.1.8 rde.c
u_int16_t i;
peer->prefix_rcvd_update++;
-@@ -1095,18 +1275,24 @@ rde_update_update(struct rde_peer *peer,
+@@ -1095,18 +1377,24 @@ rde_update_update(struct rde_peer *peer,
for (i = 1; i < rib_size; i++) {
/* input filter */
@@ -908,7 +1049,7 @@ diff -u -p -r1.1.1.8 rde.c
/* free modified aspath */
if (fasp != asp)
path_put(fasp);
-@@ -1114,6 +1300,8 @@ done:
+@@ -1114,6 +1402,8 @@ done:
if (r)
peer->prefix_cnt++;
@@ -917,7 +1058,16 @@ diff -u -p -r1.1.1.8 rde.c
}
void
-@@ -1161,6 +1349,7 @@ rde_attr_parse(u_char *p, u_int16_t len,
+@@ -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;
@@ -925,7 +1075,7 @@ diff -u -p -r1.1.1.8 rde.c
u_int16_t attr_len, nlen;
u_int16_t plen = 0;
u_int8_t flags;
-@@ -1195,6 +1384,7 @@ bad_len:
+@@ -1195,6 +1486,7 @@ bad_len:
switch (type) {
case ATTR_UNDEF:
/* ignore and drop path attributes with a type code of 0 */
@@ -933,7 +1083,7 @@ diff -u -p -r1.1.1.8 rde.c
break;
case ATTR_ORIGIN:
if (attr_len != 1)
-@@ -1220,7 +1410,17 @@ bad_flags:
+@@ -1220,7 +1512,17 @@ bad_flags:
case ATTR_ASPATH:
if (!CHECK_FLAGS(flags, ATTR_WELL_KNOWN, 0))
goto bad_flags;
@@ -952,7 +1102,7 @@ diff -u -p -r1.1.1.8 rde.c
rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH,
NULL, 0);
return (-1);
-@@ -1248,7 +1448,7 @@ bad_flags:
+@@ -1248,7 +1550,7 @@ bad_flags:
a->flags |= F_ATTR_NEXTHOP;
bzero(&nexthop, sizeof(nexthop));
@@ -961,7 +1111,7 @@ diff -u -p -r1.1.1.8 rde.c
UPD_READ(&nexthop.v4.s_addr, p, plen, 4);
/*
* Check if the nexthop is a valid IP address. We consider
-@@ -1305,9 +1505,21 @@ bad_flags:
+@@ -1305,9 +1607,21 @@ bad_flags:
goto optattr;
case ATTR_AGGREGATOR:
if ((!rde_as4byte(peer) && attr_len != 6) ||
@@ -986,7 +1136,7 @@ diff -u -p -r1.1.1.8 rde.c
goto bad_flags;
if (!rde_as4byte(peer)) {
/* need to inflate aggregator AS to 4-byte */
-@@ -1323,8 +1535,35 @@ bad_flags:
+@@ -1323,8 +1637,35 @@ bad_flags:
/* 4-byte ready server take the default route */
goto optattr;
case ATTR_COMMUNITIES:
@@ -1024,7 +1174,7 @@ diff -u -p -r1.1.1.8 rde.c
if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE,
ATTR_PARTIAL))
goto bad_flags;
-@@ -1336,7 +1575,7 @@ bad_flags:
+@@ -1336,7 +1677,7 @@ bad_flags:
goto bad_flags;
goto optattr;
case ATTR_CLUSTER_LIST:
@@ -1033,7 +1183,7 @@ diff -u -p -r1.1.1.8 rde.c
goto bad_len;
if (!CHECK_FLAGS(flags, ATTR_OPTIONAL, 0))
goto bad_flags;
-@@ -1370,8 +1609,15 @@ bad_flags:
+@@ -1370,8 +1711,15 @@ bad_flags:
plen += attr_len;
break;
case ATTR_AS4_AGGREGATOR:
@@ -1051,7 +1201,7 @@ diff -u -p -r1.1.1.8 rde.c
if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE,
ATTR_PARTIAL))
goto bad_flags;
-@@ -1381,17 +1627,28 @@ bad_flags:
+@@ -1381,19 +1729,30 @@ bad_flags:
if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE,
ATTR_PARTIAL))
goto bad_flags;
@@ -1074,6 +1224,8 @@ diff -u -p -r1.1.1.8 rde.c
*/
- a->flags |= F_ATTR_LOOP;
- goto optattr;
+- }
+- a->flags |= F_ATTR_AS4BYTE_NEW;
+ if (flags & ATTR_PARTIAL || err == AS_ERR_SOFT) {
+ a->flags |= F_ATTR_PARSE_ERR;
+ log_peer_warnx(&peer->conf, "bad AS4_PATH, "
@@ -1084,10 +1236,55 @@ diff -u -p -r1.1.1.8 rde.c
+ NULL, 0);
+ return (-1);
+ }
- }
- a->flags |= F_ATTR_AS4BYTE_NEW;
++ }
++ a->flags |= F_ATTR_AS4BYTE_NEW;
goto optattr;
-@@ -1440,8 +1697,8 @@ rde_attr_missing(struct rde_aspath *a, i
+ default:
+ if ((flags & ATTR_OPTIONAL) == 0) {
+@@ -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
@@ -1098,7 +1295,7 @@ diff -u -p -r1.1.1.8 rde.c
{
struct bgpd_addr nexthop;
u_int8_t totlen, nhlen;
-@@ -1457,8 +1714,9 @@ rde_get_mp_nexthop(u_char *data, u_int16
+@@ -1457,8 +1852,9 @@ rde_get_mp_nexthop(u_char *data, u_int16
return (-1);
bzero(&nexthop, sizeof(nexthop));
@@ -1110,7 +1307,7 @@ diff -u -p -r1.1.1.8 rde.c
/*
* RFC2545 describes that there may be a link-local
* address carried in nexthop. Yikes!
-@@ -1471,72 +1729,143 @@ rde_get_mp_nexthop(u_char *data, u_int16
+@@ -1471,72 +1867,143 @@ rde_get_mp_nexthop(u_char *data, u_int16
log_warnx("bad multiprotocol nexthop, bad size");
return (-1);
}
@@ -1137,7 +1334,7 @@ diff -u -p -r1.1.1.8 rde.c
- * 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 the number got.
++ * 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
@@ -1293,7 +1490,7 @@ diff -u -p -r1.1.1.8 rde.c
if (len < 1)
return (-1);
-@@ -1546,25 +1875,50 @@ rde_update_get_prefix6(u_char *p, u_int1
+@@ -1546,25 +2013,50 @@ rde_update_get_prefix6(u_char *p, u_int1
plen = 1;
bzero(prefix, sizeof(struct bgpd_addr));
@@ -1355,7 +1552,7 @@ diff -u -p -r1.1.1.8 rde.c
if ((wbuf = imsg_create(ibuf_se, IMSG_UPDATE_ERR, peer->conf.id, 0,
size + sizeof(error) + sizeof(suberr))) == NULL)
-@@ -1616,16 +1970,30 @@ rde_as4byte_fixup(struct rde_peer *peer,
+@@ -1616,16 +2108,30 @@ rde_as4byte_fixup(struct rde_peer *peer,
struct attr *nasp, *naggr, *oaggr;
u_int32_t as;
@@ -1388,7 +1585,7 @@ diff -u -p -r1.1.1.8 rde.c
return;
}
/* OLD session using 2-byte ASNs */
-@@ -1669,6 +2037,10 @@ rde_reflector(struct rde_peer *peer, str
+@@ -1669,6 +2175,10 @@ rde_reflector(struct rde_peer *peer, str
u_int16_t len;
u_int32_t id;
@@ -1399,7 +1596,21 @@ diff -u -p -r1.1.1.8 rde.c
/* 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) {
-@@ -1724,7 +2096,7 @@ void
+@@ -1677,10 +2187,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 +2234,17 @@ void
rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags)
{
struct ctl_show_rib rib;
@@ -1407,8 +1618,20 @@ diff -u -p -r1.1.1.8 rde.c
+ struct ibuf *wbuf;
struct attr *a;
void *bp;
++ time_t staletime;
u_int8_t l;
-@@ -1748,23 +2120,23 @@ rde_dump_rib_as(struct prefix *p, struct
+
+ 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 +2258,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));
@@ -1423,9 +1646,10 @@ diff -u -p -r1.1.1.8 rde.c
rib.flags = 0;
if (p->rib->active == p)
- rib.flags |= F_RIB_ACTIVE;
-+ rib.flags |= F_PREF_ACTIVE;
- if (asp->peer->conf.ebgp == 0)
+- 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;
@@ -1436,10 +1660,13 @@ diff -u -p -r1.1.1.8 rde.c
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 +2156,13 @@ rde_dump_rib_as(struct prefix *p, struct
+@@ -1784,13 +2297,13 @@ rde_dump_rib_as(struct prefix *p, struct
IMSG_CTL_SHOW_RIB_ATTR, 0, pid,
attr_optlen(a))) == NULL)
return;
@@ -1456,7 +1683,7 @@ diff -u -p -r1.1.1.8 rde.c
return;
}
imsg_close(ibuf_se_ctl, wbuf);
-@@ -1828,15 +2200,15 @@ rde_dump_filter(struct prefix *p, struct
+@@ -1828,17 +2341,20 @@ rde_dump_filter(struct prefix *p, struct
{
struct rde_peer *peer;
@@ -1466,16 +1693,22 @@ diff -u -p -r1.1.1.8 rde.c
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, req->as.type, req->as.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);
-@@ -1872,7 +2244,7 @@ rde_dump_prefix_upcall(struct rib_entry
+ } else if (req->flags & F_CTL_ADJ_OUT) {
+ if (p->rib->active != p)
+@@ -1872,7 +2388,7 @@ rde_dump_prefix_upcall(struct rib_entry
pt = re->prefix;
pt_getaddr(pt, &addr);
@@ -1484,7 +1717,7 @@ diff -u -p -r1.1.1.8 rde.c
return;
if (ctx->req.prefixlen > pt->prefixlen)
return;
-@@ -1889,6 +2261,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req
+@@ -1889,6 +2405,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req
struct rib_entry *re;
u_int error;
u_int16_t id;
@@ -1492,7 +1725,7 @@ diff -u -p -r1.1.1.8 rde.c
if ((ctx = calloc(1, sizeof(*ctx))) == NULL) {
log_warn("rde_dump_ctx_new");
-@@ -1902,6 +2275,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req
+@@ -1902,6 +2419,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));
@@ -1500,7 +1733,7 @@ diff -u -p -r1.1.1.8 rde.c
return;
}
-@@ -1924,7 +2298,18 @@ rde_dump_ctx_new(struct ctl_show_rib_req
+@@ -1924,7 +2442,18 @@ rde_dump_ctx_new(struct ctl_show_rib_req
ctx->ribctx.ctx_upcall = rde_dump_prefix_upcall;
break;
}
@@ -1520,7 +1753,7 @@ diff -u -p -r1.1.1.8 rde.c
re = rib_lookup(&ribs[id], &req->prefix);
else
re = rib_get(&ribs[id], &req->prefix, req->prefixlen);
-@@ -1937,7 +2322,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req
+@@ -1937,7 +2466,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req
}
ctx->ribctx.ctx_done = rde_dump_done;
ctx->ribctx.ctx_arg = ctx;
@@ -1529,7 +1762,14 @@ diff -u -p -r1.1.1.8 rde.c
rib_dump_r(&ctx->ribctx);
}
-@@ -1974,10 +2359,10 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t
+@@ -1971,13 +2500,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;
@@ -1543,7 +1783,7 @@ diff -u -p -r1.1.1.8 rde.c
rde_mrt_cnt++;
rib_dump_r(&ctx->ribctx);
}
-@@ -1985,13 +2370,25 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t
+@@ -1985,13 +2518,25 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t
/*
* kroute specific functions
*/
@@ -1572,7 +1812,7 @@ diff -u -p -r1.1.1.8 rde.c
enum imsg_type type;
/*
-@@ -2011,43 +2408,45 @@ rde_send_kroute(struct prefix *new, stru
+@@ -2011,43 +2556,43 @@ rde_send_kroute(struct prefix *new, stru
}
pt_getaddr(p->prefix, &addr);
@@ -1613,8 +1853,6 @@ diff -u -p -r1.1.1.8 rde.c
+ break;
+
+ SIMPLEQ_FOREACH(rd, rdomains_l, entry) {
-+ if (addr.vpn4.rd != rd->rd)
-+ continue;
+ if (!rde_rdomain_import(p->aspath, rd))
+ continue;
+ /* must send exit_nexthop so that correct MPLS tunnel
@@ -1654,7 +1892,7 @@ diff -u -p -r1.1.1.8 rde.c
fatal("imsg_compose error");
break;
}
-@@ -2098,7 +2497,6 @@ rde_send_pftable_commit(void)
+@@ -2098,7 +2643,6 @@ rde_send_pftable_commit(void)
void
rde_send_nexthop(struct bgpd_addr *next, int valid)
{
@@ -1662,7 +1900,7 @@ diff -u -p -r1.1.1.8 rde.c
int type;
if (valid)
-@@ -2106,8 +2504,6 @@ rde_send_nexthop(struct bgpd_addr *next,
+@@ -2106,8 +2650,6 @@ rde_send_nexthop(struct bgpd_addr *next,
else
type = IMSG_NEXTHOP_REMOVE;
@@ -1671,7 +1909,7 @@ diff -u -p -r1.1.1.8 rde.c
if (imsg_compose(ibuf_main, type, 0, 0, -1, next,
sizeof(struct bgpd_addr)) == -1)
fatal("imsg_compose error");
-@@ -2201,6 +2597,10 @@ rde_softreconfig_in(struct rib_entry *re
+@@ -2201,6 +2743,10 @@ rde_softreconfig_in(struct rib_entry *re
continue;
for (i = 1; i < rib_size; i++) {
@@ -1682,7 +1920,7 @@ diff -u -p -r1.1.1.8 rde.c
/* check if prefix changed */
oa = rde_filter(i, &oasp, rules_l, peer, asp, &addr,
pt->prefixlen, peer, DIR_IN);
-@@ -2228,7 +2628,7 @@ rde_softreconfig_in(struct rib_entry *re
+@@ -2228,7 +2774,7 @@ rde_softreconfig_in(struct rib_entry *re
if (path_compare(nasp, oasp) == 0)
goto done;
/* send update */
@@ -1691,7 +1929,7 @@ diff -u -p -r1.1.1.8 rde.c
pt->prefixlen);
}
-@@ -2241,6 +2641,104 @@ done:
+@@ -2241,6 +2787,104 @@ done:
}
}
@@ -1796,7 +2034,7 @@ diff -u -p -r1.1.1.8 rde.c
/*
* update specific functions
*/
-@@ -2252,7 +2750,7 @@ rde_up_dump_upcall(struct rib_entry *re,
+@@ -2252,7 +2896,7 @@ rde_up_dump_upcall(struct rib_entry *re,
struct rde_peer *peer = ptr;
if (re->ribid != peer->ribid)
@@ -1805,7 +2043,7 @@ diff -u -p -r1.1.1.8 rde.c
if (re->active == NULL)
return;
up_generate_updates(rules_l, peer, re->active, NULL);
-@@ -2265,7 +2763,7 @@ rde_generate_updates(u_int16_t ribid, st
+@@ -2265,7 +2909,7 @@ rde_generate_updates(u_int16_t ribid, st
/*
* If old is != NULL we know it was active and should be removed.
@@ -1814,7 +2052,7 @@ diff -u -p -r1.1.1.8 rde.c
* generate an update.
*/
if (old == NULL && new == NULL)
-@@ -2286,7 +2784,7 @@ void
+@@ -2286,7 +2930,7 @@ void
rde_update_queue_runner(void)
{
struct rde_peer *peer;
@@ -1823,7 +2061,7 @@ diff -u -p -r1.1.1.8 rde.c
u_int16_t len, wd_len, wpos;
len = sizeof(queue_buf) - MSGSIZE_HEADER;
-@@ -2300,7 +2798,7 @@ rde_update_queue_runner(void)
+@@ -2300,7 +2944,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,
@@ -1832,7 +2070,7 @@ diff -u -p -r1.1.1.8 rde.c
wd_len = r;
/* write withdraws length filed */
wd_len = htons(wd_len);
-@@ -2310,31 +2808,49 @@ rde_update_queue_runner(void)
+@@ -2310,31 +2954,49 @@ rde_update_queue_runner(void)
/* now bgp path attributes */
r = up_dump_attrnlri(queue_buf + wpos, len - wpos,
peer);
@@ -1892,7 +2130,7 @@ diff -u -p -r1.1.1.8 rde.c
u_int16_t len;
/* first withdraws ... */
-@@ -2346,7 +2862,7 @@ rde_update6_queue_runner(void)
+@@ -2346,7 +3008,7 @@ rde_update6_queue_runner(void)
if (peer->state != PEER_UP)
continue;
len = sizeof(queue_buf) - MSGSIZE_HEADER;
@@ -1901,7 +2139,7 @@ diff -u -p -r1.1.1.8 rde.c
if (b == NULL)
continue;
-@@ -2369,10 +2885,18 @@ rde_update6_queue_runner(void)
+@@ -2369,10 +3031,18 @@ rde_update6_queue_runner(void)
if (peer->state != PEER_UP)
continue;
len = sizeof(queue_buf) - MSGSIZE_HEADER;
@@ -1911,10 +2149,10 @@ diff -u -p -r1.1.1.8 rde.c
+ r = up_dump_mp_reach(queue_buf, &len, peer, aid);
+ switch (r) {
+ case -2:
-+ continue;
+ continue;
+ case -1:
+ peer_send_eor(peer, aid);
- continue;
++ continue;
+ default:
+ b = queue_buf + r;
+ break;
@@ -1923,7 +2161,7 @@ diff -u -p -r1.1.1.8 rde.c
/* finally send message to SE */
if (imsg_compose(ibuf_se, IMSG_UPDATE, peer->conf.id,
0, -1, b, len) == -1)
-@@ -2411,7 +2935,7 @@ rde_decisionflags(void)
+@@ -2411,7 +3081,7 @@ rde_decisionflags(void)
int
rde_as4byte(struct rde_peer *peer)
{
@@ -1932,7 +2170,7 @@ diff -u -p -r1.1.1.8 rde.c
}
/*
-@@ -2429,7 +2953,6 @@ void
+@@ -2429,7 +3099,6 @@ void
peer_init(u_int32_t hashsize)
{
struct peer_config pc;
@@ -1940,7 +2178,7 @@ diff -u -p -r1.1.1.8 rde.c
u_int32_t hs, i;
for (hs = 1; hs < hashsize; hs <<= 1)
-@@ -2445,17 +2968,13 @@ peer_init(u_int32_t hashsize)
+@@ -2445,17 +3114,13 @@ peer_init(u_int32_t hashsize)
peertable.peer_hashmask = hs - 1;
bzero(&pc, sizeof(pc));
@@ -1959,7 +2197,7 @@ diff -u -p -r1.1.1.8 rde.c
}
void
-@@ -2534,14 +3053,10 @@ peer_localaddrs(struct rde_peer *peer, s
+@@ -2534,14 +3199,10 @@ peer_localaddrs(struct rde_peer *peer, s
if (ifa->ifa_addr->sa_family ==
match->ifa_addr->sa_family)
ifa = match;
@@ -1975,7 +2213,7 @@ diff -u -p -r1.1.1.8 rde.c
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 +3074,7 @@ peer_localaddrs(struct rde_peer *peer, s
+@@ -2559,13 +3220,7 @@ peer_localaddrs(struct rde_peer *peer, s
&((struct sockaddr_in6 *)ifa->
ifa_addr)->sin6_addr))
continue;
@@ -1990,7 +2228,7 @@ diff -u -p -r1.1.1.8 rde.c
break;
}
}
-@@ -2577,6 +3086,7 @@ void
+@@ -2577,23 +3232,22 @@ void
peer_up(u_int32_t id, struct session_up *sup)
{
struct rde_peer *peer;
@@ -1998,7 +2236,16 @@ diff -u -p -r1.1.1.8 rde.c
peer = peer_get(id);
if (peer == NULL) {
-@@ -2590,10 +3100,7 @@ peer_up(u_int32_t id, struct session_up
+- 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));
@@ -2010,7 +2257,7 @@ diff -u -p -r1.1.1.8 rde.c
peer_localaddrs(peer, &sup->local_addr);
-@@ -2607,7 +3114,10 @@ peer_up(u_int32_t id, struct session_up
+@@ -2607,7 +3261,10 @@ peer_up(u_int32_t id, struct session_up
*/
return;
@@ -2022,19 +2269,43 @@ diff -u -p -r1.1.1.8 rde.c
}
void
-@@ -2642,42 +3152,32 @@ peer_down(u_int32_t id)
+@@ -2641,43 +3298,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_dump(u_int32_t id, u_int8_t aid)
++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_dump: unknown peer id %d", id);
++ log_warnx("peer_stale: unknown peer id %d", id);
return;
}
@@ -2054,32 +2325,65 @@ diff -u -p -r1.1.1.8 rde.c
- 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);
-+ 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.restart)
-+ up_generate_marker(peer, aid);
++ /* 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 */
-+/* End-of-RIB marker, RFC 4724 */
void
-peer_send_eor(struct rde_peer *peer, u_int16_t afi, u_int16_t safi)
-+peer_send_eor(struct rde_peer *peer, u_int8_t aid)
++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 +3188,9 @@ peer_send_eor(struct rde_peer *peer, u_i
+@@ -2688,6 +3392,9 @@ peer_send_eor(struct rde_peer *peer, u_i
u_int16_t i;
u_char buf[10];
@@ -2089,7 +2393,7 @@ diff -u -p -r1.1.1.8 rde.c
i = 0; /* v4 withdrawn len */
bcopy(&i, &buf[0], sizeof(i));
i = htons(6); /* path attr len */
-@@ -2709,25 +3212,43 @@ peer_send_eor(struct rde_peer *peer, u_i
+@@ -2709,39 +3416,61 @@ peer_send_eor(struct rde_peer *peer, u_i
* network announcement stuff
*/
void
@@ -2115,6 +2419,12 @@ diff -u -p -r1.1.1.8 rde.c
+ 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)
@@ -2144,13 +2454,19 @@ diff -u -p -r1.1.1.8 rde.c
+ }
+ }
+
- asp = path_get();
- asp->aspath = aspath_get(NULL, 0);
- asp->origin = ORIGIN_IGP;
-@@ -2737,7 +3258,9 @@ network_add(struct network_config *nc, i
++ 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)
@@ -2158,7 +2474,11 @@ diff -u -p -r1.1.1.8 rde.c
for (i = 1; i < rib_size; i++)
path_update(&ribs[i], peerself, asp, &nc->prefix,
nc->prefixlen);
-@@ -2749,12 +3272,41 @@ network_add(struct network_config *nc, i
+-
+ path_put(asp);
+ filterset_free(&nc->attrset);
+ }
+@@ -2749,12 +3478,41 @@ network_add(struct network_config *nc, i
void
network_delete(struct network_config *nc, int flagstatic)
{
@@ -2202,7 +2522,7 @@ diff -u -p -r1.1.1.8 rde.c
for (i = rib_size - 1; i > 0; i--)
prefix_remove(&ribs[i], peerself, &nc->prefix, nc->prefixlen,
flags);
-@@ -2764,38 +3316,31 @@ void
+@@ -2764,38 +3522,31 @@ void
network_dump_upcall(struct rib_entry *re, void *ptr)
{
struct prefix *p;
@@ -2260,7 +2580,7 @@ diff -u -p -r1.1.1.8 rde.c
}
}
-@@ -2841,10 +3386,10 @@ sa_cmp(struct bgpd_addr *a, struct socka
+@@ -2841,10 +3592,10 @@ sa_cmp(struct bgpd_addr *a, struct socka
struct sockaddr_in *in_b;
struct sockaddr_in6 *in6_b;
diff --git a/net/openbgpd/files/patch-bgpd_rde.h b/net/openbgpd/files/patch-bgpd_rde.h
index 22b372178ee9..717422949486 100644
--- a/net/openbgpd/files/patch-bgpd_rde.h
+++ b/net/openbgpd/files/patch-bgpd_rde.h
@@ -2,17 +2,17 @@ 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.11
-diff -u -p -r1.1.1.8 -r1.1.1.11
+retrieving revision 1.1.1.12
+diff -u -p -r1.1.1.8 -r1.1.1.12
--- bgpd/rde.h 14 Feb 2010 20:19:57 -0000 1.1.1.8
-+++ bgpd/rde.h 12 Jun 2011 10:44:25 -0000 1.1.1.11
++++ bgpd/rde.h 13 Oct 2012 18:22:46 -0000 1.1.1.12
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.120 2009/06/06 01:10:29 claudio Exp $ */
-+/* $OpenBSD: rde.h,v 1.138 2010/11/18 12:18:31 claudio Exp $ */
++/* $OpenBSD: rde.h,v 1.143 2012/08/12 14:24:56 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
-@@ -56,12 +56,9 @@ struct rde_peer {
+@@ -56,16 +56,16 @@ struct rde_peer {
struct bgpd_addr local_v6_addr;
struct uptree_prefix up_prefix;
struct uptree_attr up_attrs;
@@ -25,11 +25,21 @@ diff -u -p -r1.1.1.8 -r1.1.1.11
+ 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;
-@@ -77,10 +74,13 @@ struct rde_peer {
+ 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 */
@@ -42,15 +52,26 @@ diff -u -p -r1.1.1.8 -r1.1.1.11
#define ASPATH_HEADER_SIZE (sizeof(struct aspath) - sizeof(u_char))
LIST_HEAD(aspath_list, aspath);
-@@ -163,6 +163,7 @@ LIST_HEAD(prefix_head, prefix);
+@@ -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 +221,14 @@ struct nexthop {
+@@ -220,14 +229,14 @@ struct nexthop {
/* generic entry without address specific part */
struct pt_entry {
RB_ENTRY(pt_entry) pt_e;
@@ -67,7 +88,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.11
u_int8_t prefixlen;
u_int16_t refcnt;
struct in_addr prefix4;
-@@ -235,12 +236,25 @@ struct pt_entry4 {
+@@ -235,12 +244,25 @@ struct pt_entry4 {
struct pt_entry6 {
RB_ENTRY(pt_entry) pt_e;
@@ -94,7 +115,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.11
struct rib_context {
LIST_ENTRY(rib_context) entry;
struct rib_entry *ctx_re;
-@@ -250,7 +264,7 @@ struct rib_context {
+@@ -250,7 +272,7 @@ struct rib_context {
void (*ctx_wait)(void *);
void *ctx_arg;
unsigned int ctx_count;
@@ -103,7 +124,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.11
};
struct rib_entry {
-@@ -262,23 +276,15 @@ struct rib_entry {
+@@ -262,23 +284,15 @@ struct rib_entry {
u_int16_t flags;
};
@@ -129,16 +150,23 @@ diff -u -p -r1.1.1.8 -r1.1.1.11
#define RIB_FAILED 0xffff
struct prefix {
-@@ -293,7 +299,7 @@ extern struct rde_memstats rdemem;
+@@ -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 +315,7 @@ int rde_as4byte(struct rde_peer *);
+@@ -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);
@@ -147,7 +175,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.11
u_int16_t);
void attr_init(u_int32_t);
void attr_shutdown(void);
-@@ -327,6 +333,7 @@ int aspath_verify(void *, u_int16_t, i
+@@ -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
@@ -155,10 +183,11 @@ diff -u -p -r1.1.1.8 -r1.1.1.11
void aspath_init(u_int32_t);
void aspath_shutdown(void);
struct aspath *aspath_get(void *, u_int16_t);
-@@ -342,21 +349,30 @@ int aspath_loopfree(struct aspath *, u
+@@ -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 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);
@@ -172,6 +201,42 @@ diff -u -p -r1.1.1.8 -r1.1.1.11
+ 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;
@@ -189,7 +254,32 @@ diff -u -p -r1.1.1.8 -r1.1.1.11
void rib_dump_r(struct rib_context *);
void rib_dump_runner(void);
int rib_dump_pending(void);
-@@ -395,7 +411,7 @@ void prefix_network_clean(struct rde_p
+@@ -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 *,
@@ -198,7 +288,17 @@ diff -u -p -r1.1.1.8 -r1.1.1.11
void nexthop_link(struct rde_aspath *);
void nexthop_unlink(struct rde_aspath *);
int nexthop_delete(struct nexthop *);
-@@ -415,12 +431,15 @@ int up_generate(struct rde_peer *, str
+@@ -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 *,
@@ -210,20 +310,47 @@ diff -u -p -r1.1.1.8 -r1.1.1.11
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);
- /* rde_prefix.c */
- #define pt_empty(pt) ((pt)->refcnt == 0)
-@@ -452,8 +471,7 @@ enum filter_actions rde_filter(u_int16_t
- 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);
-+ u_int8_t, struct rde_peer *, struct rde_peer *);
- int rde_filter_equal(struct filter_head *, struct filter_head *,
- struct rde_peer *, enum directions);
-
+ #endif /* __RDE_H__ */
diff --git a/net/openbgpd/files/patch-bgpd_rde_attr.c b/net/openbgpd/files/patch-bgpd_rde_attr.c
index eccdc1e36c27..2c0192abe5da 100644
--- a/net/openbgpd/files/patch-bgpd_rde_attr.c
+++ b/net/openbgpd/files/patch-bgpd_rde_attr.c
@@ -2,13 +2,13 @@ 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.6
-diff -u -p -r1.1.1.6 -r1.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 2 Jul 2011 16:06:38 -0000 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.83 2010/03/29 09:24:07 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>
@@ -35,7 +35,21 @@ diff -u -p -r1.1.1.6 -r1.6
#include "bgpd.h"
#include "rde.h"
-@@ -63,7 +71,7 @@ attr_write(void *p, u_int16_t p_len, u_i
+@@ -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
@@ -44,7 +58,17 @@ diff -u -p -r1.1.1.6 -r1.6
u_int16_t data_len)
{
u_char hdr[4];
-@@ -80,9 +88,9 @@ attr_writebuf(struct buf *buf, u_int8_t
+
++ 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;
@@ -69,7 +93,23 @@ diff -u -p -r1.1.1.6 -r1.6
}
/* add attribute to the table but first bump refcnt */
-@@ -405,6 +416,7 @@ aspath_verify(void *data, u_int16_t len,
+@@ -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;
@@ -77,7 +117,7 @@ diff -u -p -r1.1.1.6 -r1.6
if (len & 1)
/* odd length aspath are invalid */
-@@ -419,7 +431,15 @@ aspath_verify(void *data, u_int16_t len,
+@@ -419,7 +433,15 @@ aspath_verify(void *data, u_int16_t len,
seg_type = seg[0];
seg_len = seg[1];
@@ -94,7 +134,7 @@ diff -u -p -r1.1.1.6 -r1.6
return (AS_ERR_TYPE);
seg_size = 2 + as_size * seg_len;
-@@ -431,7 +451,7 @@ aspath_verify(void *data, u_int16_t len,
+@@ -431,7 +453,7 @@ aspath_verify(void *data, u_int16_t len,
/* empty aspath segments are not allowed */
return (AS_ERR_BAD);
}
@@ -103,38 +143,90 @@ diff -u -p -r1.1.1.6 -r1.6
}
void
-@@ -972,14 +992,62 @@ aspath_match(struct aspath *a, enum as_s
+@@ -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
--community_match(void *data, u_int16_t len, int as, int type)
+-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 *p = data;
-- u_int16_t eas, etype;
-+ u_int8_t *seg;
+ 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;
-+
+ 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);
-+ }
+ return (1);
+ else
+ return (0);
+ }
-- len >>= 2; /* divide by four */
+- 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;
+ 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;
-- for (; len > 0; len--) {
-+ for (i = 0; i < seg_len; i++) {
+- 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) {
@@ -143,35 +235,40 @@ diff -u -p -r1.1.1.6 -r1.6
+ } else
+ count = 1;
+ lastas = as;
-+ }
-+ }
-+ return (0);
-+}
-+
+ }
+ }
+ return (0);
+ }
+
+/*
+ * Functions handling communities and extended communities.
+ */
+
+int community_ext_matchone(struct filter_extcommunity *, u_int16_t, u_int64_t);
+
-+int
+ 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 +1068,6 @@ community_set(struct rde_aspath *asp, in
+@@ -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;
@@ -179,7 +276,7 @@ diff -u -p -r1.1.1.6 -r1.6
attr = attr_optget(asp, ATTR_COMMUNITIES);
if (attr != NULL) {
-@@ -1017,7 +1084,7 @@ community_set(struct rde_aspath *asp, in
+@@ -1017,7 +1019,7 @@ community_set(struct rde_aspath *asp, in
p += 4;
}
@@ -188,7 +285,7 @@ diff -u -p -r1.1.1.6 -r1.6
/* overflow */
return (0);
-@@ -1032,11 +1099,10 @@ community_set(struct rde_aspath *asp, in
+@@ -1032,11 +1034,10 @@ community_set(struct rde_aspath *asp, in
if (attr != NULL) {
memcpy(p + 4, attr->data, attr->len);
f = attr->flags;
@@ -201,7 +298,7 @@ diff -u -p -r1.1.1.6 -r1.6
free(p);
return (1);
-@@ -1049,7 +1115,7 @@ community_delete(struct rde_aspath *asp,
+@@ -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;
@@ -210,7 +307,7 @@ diff -u -p -r1.1.1.6 -r1.6
attr = attr_optget(asp, ATTR_COMMUNITIES);
if (attr == NULL)
-@@ -1100,10 +1166,250 @@ community_delete(struct rde_aspath *asp,
+@@ -1100,10 +1101,250 @@ community_delete(struct rde_aspath *asp,
}
f = attr->flags;
@@ -219,9 +316,9 @@ diff -u -p -r1.1.1.6 -r1.6
attr_free(asp, attr);
- attr_optadd(asp, f, t, n, len);
+ attr_optadd(asp, f, ATTR_COMMUNITIES, n, len);
-+ free(n);
-+}
-+
+ free(n);
+ }
+
+int
+community_ext_match(struct rde_aspath *asp, struct filter_extcommunity *c,
+ u_int16_t neighas)
@@ -343,9 +440,9 @@ diff -u -p -r1.1.1.6 -r1.6
+
+ attr_free(asp, attr);
+ attr_optadd(asp, f, ATTR_EXT_COMMUNITIES, n, len);
- free(n);
- }
-
++ free(n);
++}
++
+int
+community_ext_conv(struct filter_extcommunity *c, u_int16_t neighas,
+ u_int64_t *community)
diff --git a/net/openbgpd/files/patch-bgpd_rde_decide.c b/net/openbgpd/files/patch-bgpd_rde_decide.c
index 3ed963b194dc..c9d27af5dbef 100644
--- a/net/openbgpd/files/patch-bgpd_rde_decide.c
+++ b/net/openbgpd/files/patch-bgpd_rde_decide.c
@@ -2,16 +2,27 @@ Index: bgpd/rde_decide.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_decide.c,v
retrieving revision 1.1.1.6
-diff -u -p -r1.1.1.6 rde_decide.c
+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 3 Jul 2011 04:44:36 -0000
++++ 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.59 2009/08/06 08:53:11 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>
-@@ -118,6 +118,12 @@ prefix_cmp(struct prefix *p1, struct pre
+@@ -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;
@@ -24,7 +35,76 @@ diff -u -p -r1.1.1.6 rde_decide.c
/* only loop free pathes are eligible */
if (asp1->flags & F_ATTR_LOOP)
return (-1);
-@@ -204,7 +210,7 @@ prefix_cmp(struct prefix *p1, struct pre
+@@ -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");
@@ -33,7 +113,7 @@ diff -u -p -r1.1.1.6 rde_decide.c
}
/*
-@@ -245,7 +251,7 @@ prefix_evaluate(struct prefix *p, struct
+@@ -245,7 +271,7 @@ prefix_evaluate(struct prefix *p, struct
}
xp = LIST_FIRST(&re->prefix_h);
@@ -42,7 +122,7 @@ diff -u -p -r1.1.1.6 rde_decide.c
(xp->aspath->nexthop != NULL &&
xp->aspath->nexthop->state != NEXTHOP_REACH))
/* xp is ineligible */
-@@ -263,7 +269,7 @@ prefix_evaluate(struct prefix *p, struct
+@@ -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)
diff --git a/net/openbgpd/files/patch-bgpd_rde_filter.c b/net/openbgpd/files/patch-bgpd_rde_filter.c
index b4fe8982b949..c08eff6a5a18 100644
--- a/net/openbgpd/files/patch-bgpd_rde_filter.c
+++ b/net/openbgpd/files/patch-bgpd_rde_filter.c
@@ -2,10 +2,10 @@ 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.7
-diff -u -p -r1.1.1.7 -r1.7
+retrieving revision 1.8
+diff -u -p -r1.1.1.7 -r1.8
--- bgpd/rde_filter.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/rde_filter.c 2 Jul 2011 16:06:38 -0000 1.7
++++ bgpd/rde_filter.c 13 Oct 2012 18:36:00 -0000 1.8
@@ -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.62 2010/03/05 15:25:00 claudio Exp $ */
@@ -71,7 +71,7 @@ diff -u -p -r1.1.1.7 -r1.7
}
}
}
-@@ -251,11 +269,21 @@ int
+@@ -251,11 +269,22 @@ int
rde_filter_match(struct filter_rule *f, struct rde_aspath *asp,
struct bgpd_addr *prefix, u_int8_t plen, struct rde_peer *peer)
{
@@ -87,7 +87,8 @@ diff -u -p -r1.1.1.7 -r1.7
+ pas = peer->conf.remote_as;
+ else
+ pas = f->match.as.as;
-+ if (aspath_match(asp->aspath, f->match.as.type, pas) == 0)
++ if (aspath_match(asp->aspath->data, asp->aspath->len,
++ f->match.as.type, pas) == 0)
+ return (0);
+ }
+
@@ -97,7 +98,7 @@ diff -u -p -r1.1.1.7 -r1.7
return (0);
if (asp != NULL && f->match.community.as != COMMUNITY_UNSET) {
-@@ -263,10 +291,10 @@ rde_filter_match(struct filter_rule *f,
+@@ -263,10 +292,10 @@ rde_filter_match(struct filter_rule *f,
case COMMUNITY_ERROR:
fatalx("rde_apply_set bad community string");
case COMMUNITY_NEIGHBOR_AS:
@@ -110,7 +111,7 @@ diff -u -p -r1.1.1.7 -r1.7
break;
}
-@@ -281,12 +309,17 @@ rde_filter_match(struct filter_rule *f,
+@@ -281,12 +310,17 @@ rde_filter_match(struct filter_rule *f,
break;
}
@@ -131,7 +132,7 @@ diff -u -p -r1.1.1.7 -r1.7
/* don't use IPv4 rules for IPv6 and vice versa */
return (0);
-@@ -322,7 +355,7 @@ rde_filter_match(struct filter_rule *f,
+@@ -322,7 +356,7 @@ rde_filter_match(struct filter_rule *f,
} else if (f->match.prefixlen.op != OP_NONE) {
/* only prefixlen without a prefix */
@@ -140,7 +141,7 @@ diff -u -p -r1.1.1.7 -r1.7
/* don't use IPv4 rules for IPv6 and vice versa */
return (0);
-@@ -356,19 +389,6 @@ rde_filter_match(struct filter_rule *f,
+@@ -356,19 +390,6 @@ rde_filter_match(struct filter_rule *f,
}
int
@@ -160,7 +161,7 @@ diff -u -p -r1.1.1.7 -r1.7
rde_filter_equal(struct filter_head *a, struct filter_head *b,
struct rde_peer *peer, enum directions dir)
{
-@@ -476,6 +496,12 @@ filterset_cmp(struct filter_set *a, stru
+@@ -476,6 +497,12 @@ filterset_cmp(struct filter_set *a, stru
return (a->action.community.type - b->action.community.type);
}
@@ -173,7 +174,7 @@ diff -u -p -r1.1.1.7 -r1.7
if (a->type == ACTION_SET_NEXTHOP && b->type == ACTION_SET_NEXTHOP) {
/*
* This is the only interesting case, all others are considered
-@@ -483,13 +509,29 @@ filterset_cmp(struct filter_set *a, stru
+@@ -483,13 +510,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.
*/
@@ -204,7 +205,7 @@ diff -u -p -r1.1.1.7 -r1.7
int
filterset_equal(struct filter_set_head *ah, struct filter_set_head *bh)
{
-@@ -574,6 +616,19 @@ filterset_equal(struct filter_set_head *
+@@ -574,6 +617,19 @@ filterset_equal(struct filter_set_head *
if (strcmp(as, bs) == 0)
continue;
break;
@@ -224,7 +225,7 @@ diff -u -p -r1.1.1.7 -r1.7
}
/* compare failed */
return (0);
-@@ -616,7 +671,14 @@ filterset_name(enum action_types type)
+@@ -616,7 +672,14 @@ filterset_name(enum action_types type)
case ACTION_RTLABEL:
case ACTION_RTLABEL_ID:
return ("rtlabel");
diff --git a/net/openbgpd/files/patch-bgpd_rde_prefix.c b/net/openbgpd/files/patch-bgpd_rde_prefix.c
index a2612312ffcc..daea5cf62272 100644
--- a/net/openbgpd/files/patch-bgpd_rde_prefix.c
+++ b/net/openbgpd/files/patch-bgpd_rde_prefix.c
@@ -2,13 +2,13 @@ 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.5
-diff -u -p -r1.1.1.6 -r1.5
+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 10 Apr 2010 12:16:23 -0000 1.5
++++ 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.32 2010/03/26 15:41:04 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>
diff --git a/net/openbgpd/files/patch-bgpd_rde_rib.c b/net/openbgpd/files/patch-bgpd_rde_rib.c
index 22d6f0ee0a48..2fe781c69c4b 100644
--- a/net/openbgpd/files/patch-bgpd_rde_rib.c
+++ b/net/openbgpd/files/patch-bgpd_rde_rib.c
@@ -2,12 +2,13 @@ Index: bgpd/rde_rib.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_rib.c,v
retrieving revision 1.1.1.7
-diff -u -p -r1.1.1.7 rde_rib.c
+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 3 Jul 2011 04:45:31 -0000
++++ 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.125 2010/04/07 09:44:11 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>
@@ -122,68 +123,102 @@ diff -u -p -r1.1.1.7 rde_rib.c
re = RB_NEXT(rib_tree, unused, re);
/* free the previously locked rib element if empty */
-@@ -632,11 +639,11 @@ prefix_compare(const struct bgpd_addr *a
- int i;
- u_int8_t m;
+@@ -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);
-+ if (a->aid != b->aid)
-+ return (a->aid - b->aid);
-
+-
- switch (a->af) {
- case AF_INET:
-+ switch (a->aid) {
-+ case AID_INET:
- if (prefixlen > 32)
- fatalx("prefix_cmp: bad IPv4 prefixlen");
- mask = htonl(prefixlen2mask(prefixlen));
-@@ -645,7 +652,7 @@ prefix_compare(const struct bgpd_addr *a
- if (aa != ba)
- return (aa - ba);
- return (0);
+- 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:
-+ case AID_INET6:
- if (prefixlen > 128)
- fatalx("prefix_cmp: bad IPv6 prefixlen");
- for (i = 0; i < prefixlen / 8; i++)
-@@ -660,6 +667,24 @@ prefix_compare(const struct bgpd_addr *a
- (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");
- }
-@@ -806,16 +831,33 @@ prefix_write(u_char *buf, int len, struc
+- 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)
-- return (-1);
+ switch (prefix->aid) {
+ case AID_INET:
+ case AID_INET6:
+ totlen = PREFIX_SIZE(plen);
-
-- totlen = PREFIX_SIZE(plen);
++
+ if (totlen > len)
+ return (-1);
+ *buf++ = plen;
@@ -193,8 +228,7 @@ diff -u -p -r1.1.1.7 rde_rib.c
+ totlen = PREFIX_SIZE(plen) + sizeof(prefix->vpn4.rd) +
+ prefix->vpn4.labellen;
+ plen += (sizeof(prefix->vpn4.rd) + prefix->vpn4.labellen) * 8;
-
-- if (totlen > len)
++
+ if (totlen > len)
+ return (-1);
+ *buf++ = plen;
@@ -206,14 +240,41 @@ diff -u -p -r1.1.1.7 rde_rib.c
+ 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 +903,7 @@ prefix_updateall(struct rde_aspath *asp,
+@@ -861,7 +898,7 @@ prefix_updateall(struct rde_aspath *asp,
*/
if ((p->rib->flags & F_RIB_NOFIB) == 0 &&
p == p->rib->active)
@@ -222,7 +283,16 @@ diff -u -p -r1.1.1.7 rde_rib.c
continue;
}
-@@ -885,16 +927,12 @@ prefix_updateall(struct rde_aspath *asp,
+@@ -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)
{
@@ -239,7 +309,7 @@ diff -u -p -r1.1.1.7 rde_rib.c
if (path_empty(asp))
path_destroy(asp);
}
-@@ -907,7 +945,6 @@ prefix_network_clean(struct rde_peer *pe
+@@ -907,21 +940,16 @@ prefix_network_clean(struct rde_peer *pe
{
struct rde_aspath *asp, *xasp;
struct prefix *p, *xp;
@@ -247,7 +317,9 @@ diff -u -p -r1.1.1.7 rde_rib.c
for (asp = LIST_FIRST(&peer->path_h); asp != NULL; asp = xasp) {
xasp = LIST_NEXT(asp, peer_l);
-@@ -916,12 +953,8 @@ prefix_network_clean(struct rde_peer *pe
+- 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) {
@@ -260,7 +332,7 @@ diff -u -p -r1.1.1.7 rde_rib.c
}
}
if (path_empty(asp))
-@@ -954,11 +987,11 @@ prefix_link(struct prefix *pref, struct
+@@ -954,11 +982,11 @@ prefix_link(struct prefix *pref, struct
static void
prefix_unlink(struct prefix *pref)
{
@@ -277,7 +349,7 @@ diff -u -p -r1.1.1.7 rde_rib.c
LIST_REMOVE(pref, path_l);
PREFIX_COUNT(pref->aspath, -1);
-@@ -966,6 +999,8 @@ prefix_unlink(struct prefix *pref)
+@@ -966,6 +994,8 @@ prefix_unlink(struct prefix *pref)
pt_unref(pref->prefix);
if (pt_empty(pref->prefix))
pt_remove(pref->prefix);
@@ -286,7 +358,7 @@ diff -u -p -r1.1.1.7 rde_rib.c
/* destroy all references to other objects */
pref->aspath = NULL;
-@@ -973,8 +1008,8 @@ prefix_unlink(struct prefix *pref)
+@@ -973,8 +1003,8 @@ prefix_unlink(struct prefix *pref)
pref->rib = NULL;
/*
@@ -297,7 +369,7 @@ diff -u -p -r1.1.1.7 rde_rib.c
*/
}
-@@ -1070,10 +1105,6 @@ nexthop_update(struct kroute_nexthop *ms
+@@ -1070,10 +1100,6 @@ nexthop_update(struct kroute_nexthop *ms
return;
}
@@ -308,7 +380,7 @@ diff -u -p -r1.1.1.7 rde_rib.c
oldstate = nh->state;
if (msg->valid)
nh->state = NEXTHOP_REACH;
-@@ -1088,21 +1119,13 @@ nexthop_update(struct kroute_nexthop *ms
+@@ -1088,21 +1114,13 @@ nexthop_update(struct kroute_nexthop *ms
memcpy(&nh->true_nexthop, &msg->gateway,
sizeof(nh->true_nexthop));
@@ -337,7 +409,7 @@ diff -u -p -r1.1.1.7 rde_rib.c
if (rde_noevaluate())
/*
-@@ -1118,7 +1141,7 @@ nexthop_update(struct kroute_nexthop *ms
+@@ -1118,35 +1136,38 @@ nexthop_update(struct kroute_nexthop *ms
void
nexthop_modify(struct rde_aspath *asp, struct bgpd_addr *nexthop,
@@ -346,16 +418,58 @@ diff -u -p -r1.1.1.7 rde_rib.c
{
struct nexthop *nh;
-@@ -1138,7 +1161,7 @@ nexthop_modify(struct rde_aspath *asp, s
- asp->flags |= F_NEXTHOP_SELF;
+- 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)
-+ if (aid != nexthop->aid)
- return;
+- 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);
+ }
- nh = nexthop_get(nexthop);
-@@ -1233,17 +1256,17 @@ nexthop_compare(struct nexthop *na, stru
+ void
+@@ -1233,17 +1254,17 @@ nexthop_compare(struct nexthop *na, stru
a = &na->exit_nexthop;
b = &nb->exit_nexthop;
@@ -378,7 +492,7 @@ diff -u -p -r1.1.1.7 rde_rib.c
return (memcmp(&a->v6, &b->v6, sizeof(struct in6_addr)));
default:
fatalx("nexthop_cmp: unknown af");
-@@ -1269,14 +1292,14 @@ nexthop_hash(struct bgpd_addr *nexthop)
+@@ -1269,14 +1290,14 @@ nexthop_hash(struct bgpd_addr *nexthop)
{
u_int32_t h = 0;
diff --git a/net/openbgpd/files/patch-bgpd_rde_update.c b/net/openbgpd/files/patch-bgpd_rde_update.c
index cbffb73387e5..ccd9601dcd3d 100644
--- a/net/openbgpd/files/patch-bgpd_rde_update.c
+++ b/net/openbgpd/files/patch-bgpd_rde_update.c
@@ -2,9 +2,10 @@ Index: bgpd/rde_update.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_update.c,v
retrieving revision 1.1.1.7
-diff -u -p -r1.1.1.7 rde_update.c
+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 3 Jul 2011 04:45:50 -0000
++++ 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 $ */
@@ -143,7 +144,7 @@ diff -u -p -r1.1.1.7 rde_update.c
/* 1. search for attr */
if (a != NULL && (na = RB_FIND(uptree_attr, &peer->up_attrs, a)) ==
-@@ -270,21 +291,14 @@ up_test_update(struct rde_peer *peer, st
+@@ -270,23 +291,16 @@ up_test_update(struct rde_peer *peer, st
/* Do not send routes back to sender */
return (0);
@@ -167,8 +168,11 @@ diff -u -p -r1.1.1.7 rde_update.c
+ 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 == 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
}
@@ -414,13 +418,41 @@ diff -u -p -r1.1.1.7 rde_update.c
* 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 ||
+- 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 */
diff --git a/net/openbgpd/files/patch-bgpd_session.c b/net/openbgpd/files/patch-bgpd_session.c
index bfbef718ac84..97648857e8f7 100644
--- a/net/openbgpd/files/patch-bgpd_session.c
+++ b/net/openbgpd/files/patch-bgpd_session.c
@@ -2,26 +2,40 @@ Index: bgpd/session.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/session.c,v
retrieving revision 1.1.1.8
-retrieving revision 1.9
-diff -u -p -r1.1.1.8 -r1.9
+retrieving revision 1.12
+diff -u -p -r1.1.1.8 -r1.12
--- bgpd/session.c 14 Feb 2010 20:19:57 -0000 1.1.1.8
-+++ bgpd/session.c 3 Jul 2011 11:18:26 -0000 1.9
++++ bgpd/session.c 13 Oct 2012 19:10:00 -0000 1.12
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.293 2009/06/07 05:56:24 eric Exp $ */
-+/* $OpenBSD: session.c,v 1.304 2010/01/05 08:49:57 claudio Exp $ */
++/* $OpenBSD: session.c,v 1.324 2012/09/12 05:56:22 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
-@@ -21,6 +21,8 @@
+@@ -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>
-@@ -50,7 +52,12 @@
+ #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
@@ -35,7 +49,7 @@ diff -u -p -r1.1.1.8 -r1.9
void session_sighdlr(int);
int setup_listeners(u_int *);
-@@ -65,9 +72,8 @@ void session_accept(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 *);
@@ -44,19 +58,24 @@ diff -u -p -r1.1.1.8 -r1.9
-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,7 +81,7 @@ void session_keepalive(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 *);
-@@ -83,22 +89,22 @@ int parse_update(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 *);
@@ -88,7 +107,54 @@ diff -u -p -r1.1.1.8 -r1.9
int csock = -1, rcsock = -1;
u_int peer_cnt;
struct imsgbuf *ibuf_rde;
-@@ -175,12 +181,11 @@ setup_listeners(u_int *la_cnt)
+@@ -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_LOCAL, SOCK_STREAM, 0);
++ 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
@@ -100,12 +166,11 @@ diff -u -p -r1.1.1.8 -r1.9
+ int pipe_s2rctl[2])
{
- int nfds, timeout;
-+ struct rlimit rl;
+ 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 +194,13 @@ session_main(struct bgpd_config *config,
+@@ -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;
@@ -126,7 +191,7 @@ diff -u -p -r1.1.1.8 -r1.9
switch (pid = fork()) {
case -1:
fatal("cannot fork");
-@@ -211,13 +210,6 @@ session_main(struct bgpd_config *config,
+@@ -211,13 +234,6 @@ session_main(struct bgpd_config *config,
return (pid);
}
@@ -140,18 +205,13 @@ diff -u -p -r1.1.1.8 -r1.9
if ((pw = getpwnam(BGPD_USER)) == NULL)
fatal(NULL);
-@@ -229,28 +221,31 @@ session_main(struct bgpd_config *config,
+@@ -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");
-+ if (getrlimit(RLIMIT_NOFILE, &rl) == -1)
-+ fatal("getrlimit");
-+ rl.rlim_cur = rl.rlim_max;
-+ if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
-+ fatal("setrlimit");
-+
+ pfkeysock = pfkey_init(&sysdep);
if (setgroups(1, &pw->pw_gid) ||
@@ -179,7 +239,7 @@ diff -u -p -r1.1.1.8 -r1.9
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 +253,21 @@ session_main(struct bgpd_config *config,
+@@ -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]);
@@ -226,7 +286,7 @@ diff -u -p -r1.1.1.8 -r1.9
while (session_quit == 0) {
/* check for peers to be initialized or deleted */
-@@ -308,8 +287,9 @@ session_main(struct bgpd_config *config,
+@@ -308,8 +304,9 @@ session_main(struct bgpd_config *config,
/* reinit due? */
if (p->conf.reconf_action == RECONF_REINIT) {
@@ -238,7 +298,7 @@ diff -u -p -r1.1.1.8 -r1.9
}
/* deletion due? */
-@@ -317,7 +297,7 @@ session_main(struct bgpd_config *config,
+@@ -317,7 +314,7 @@ session_main(struct bgpd_config *config,
if (p->demoted)
session_demote(p, -1);
p->conf.demote_group[0] = 0;
@@ -247,7 +307,7 @@ diff -u -p -r1.1.1.8 -r1.9
log_peer_warnx(&p->conf, "removed");
if (last != NULL)
last->next = next;
-@@ -346,9 +326,17 @@ session_main(struct bgpd_config *config,
+@@ -346,9 +343,17 @@ session_main(struct bgpd_config *config,
}
mrt_cnt = 0;
@@ -266,7 +326,7 @@ diff -u -p -r1.1.1.8 -r1.9
if (mrt_cnt > mrt_l_elms) {
if ((newp = realloc(mrt_l, sizeof(struct mrt *) *
-@@ -394,14 +382,19 @@ session_main(struct bgpd_config *config,
+@@ -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
@@ -274,11 +334,20 @@ diff -u -p -r1.1.1.8 -r1.9
+ * 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;
+- 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;
@@ -287,8 +356,60 @@ diff -u -p -r1.1.1.8 -r1.9
+#endif
i = PFD_LISTENERS_START;
TAILQ_FOREACH(la, conf->listen_addrs, entry) {
- pfd[i].fd = la->fd;
-@@ -534,6 +527,14 @@ session_main(struct bgpd_config *config,
+- 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);
}
@@ -303,7 +424,18 @@ diff -u -p -r1.1.1.8 -r1.9
for (j = PFD_LISTENERS_START; nfds > 0 && j < idx_listeners;
j++)
if (pfd[j].revents & POLLIN) {
-@@ -557,7 +558,7 @@ session_main(struct bgpd_config *config,
+@@ -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;
@@ -312,7 +444,7 @@ diff -u -p -r1.1.1.8 -r1.9
pfkey_remove(p);
free(p);
}
-@@ -643,10 +644,9 @@ bgp_fsm(struct peer *peer, enum session_
+@@ -643,10 +689,9 @@ bgp_fsm(struct peer *peer, enum session_
timer_stop(peer, Timer_IdleHold);
/* allocate read buffer */
@@ -324,7 +456,7 @@ diff -u -p -r1.1.1.8 -r1.9
/* init write buffer */
msgbuf_init(&peer->wbuf);
-@@ -746,7 +746,6 @@ bgp_fsm(struct peer *peer, enum session_
+@@ -746,7 +791,6 @@ bgp_fsm(struct peer *peer, enum session_
/* ignore */
break;
case EVNT_STOP:
@@ -332,7 +464,7 @@ diff -u -p -r1.1.1.8 -r1.9
change_state(peer, STATE_IDLE, event);
break;
case EVNT_CON_CLOSED:
-@@ -780,7 +779,8 @@ bgp_fsm(struct peer *peer, enum session_
+@@ -780,7 +824,8 @@ bgp_fsm(struct peer *peer, enum session_
change_state(peer, STATE_IDLE, event);
break;
default:
@@ -342,7 +474,7 @@ diff -u -p -r1.1.1.8 -r1.9
change_state(peer, STATE_IDLE, event);
break;
}
-@@ -791,7 +791,6 @@ bgp_fsm(struct peer *peer, enum session_
+@@ -791,7 +836,6 @@ bgp_fsm(struct peer *peer, enum session_
/* ignore */
break;
case EVNT_STOP:
@@ -350,7 +482,7 @@ diff -u -p -r1.1.1.8 -r1.9
change_state(peer, STATE_IDLE, event);
break;
case EVNT_CON_CLOSED:
-@@ -815,7 +814,8 @@ bgp_fsm(struct peer *peer, enum session_
+@@ -815,7 +859,8 @@ bgp_fsm(struct peer *peer, enum session_
change_state(peer, STATE_IDLE, event);
break;
default:
@@ -360,7 +492,7 @@ diff -u -p -r1.1.1.8 -r1.9
change_state(peer, STATE_IDLE, event);
break;
}
-@@ -826,7 +826,6 @@ bgp_fsm(struct peer *peer, enum session_
+@@ -826,7 +871,6 @@ bgp_fsm(struct peer *peer, enum session_
/* ignore */
break;
case EVNT_STOP:
@@ -368,7 +500,7 @@ diff -u -p -r1.1.1.8 -r1.9
change_state(peer, STATE_IDLE, event);
break;
case EVNT_CON_CLOSED:
-@@ -856,7 +855,8 @@ bgp_fsm(struct peer *peer, enum session_
+@@ -856,7 +900,8 @@ bgp_fsm(struct peer *peer, enum session_
change_state(peer, STATE_IDLE, event);
break;
default:
@@ -378,7 +510,20 @@ diff -u -p -r1.1.1.8 -r1.9
change_state(peer, STATE_IDLE, event);
break;
}
-@@ -923,6 +923,7 @@ change_state(struct peer *peer, enum ses
+@@ -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);
@@ -386,7 +531,88 @@ diff -u -p -r1.1.1.8 -r1.9
timer_stop(peer, Timer_IdleHoldReset);
session_close_connection(peer);
msgbuf_clear(&peer->wbuf);
-@@ -1069,7 +1070,7 @@ session_connect(struct peer *peer)
+ 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);
@@ -395,7 +621,7 @@ diff -u -p -r1.1.1.8 -r1.9
IPPROTO_TCP)) == -1) {
log_peer_warn(&peer->conf, "session_connect socket");
bgp_fsm(peer, EVNT_CON_OPENFAIL);
-@@ -1100,8 +1101,7 @@ session_connect(struct peer *peer)
+@@ -1100,8 +1182,7 @@ session_connect(struct peer *peer)
peer->wbuf.fd = peer->fd;
/* if update source is set we need to bind() */
@@ -405,7 +631,7 @@ diff -u -p -r1.1.1.8 -r1.9
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 +1139,50 @@ session_setup_socket(struct peer *p)
+@@ -1139,42 +1220,50 @@ session_setup_socket(struct peer *p)
int nodelay = 1;
int bsize;
@@ -486,7 +712,7 @@ diff -u -p -r1.1.1.8 -r1.9
}
/* set TCP_NODELAY */
-@@ -1185,14 +1193,6 @@ session_setup_socket(struct peer *p)
+@@ -1185,24 +1274,18 @@ session_setup_socket(struct peer *p)
return (-1);
}
@@ -501,7 +727,23 @@ diff -u -p -r1.1.1.8 -r1.9
/* 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 */
-@@ -1244,40 +1244,32 @@ session_tcp_established(struct peer *pee
+ 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)
{
@@ -516,11 +758,9 @@ diff -u -p -r1.1.1.8 -r1.9
int
-session_capa_add(struct peer *p, struct buf *opb, u_int8_t capa_code,
- u_int8_t capa_len, u_int8_t *optparamlen)
-+session_capa_add(struct ibuf *opb, u_int8_t capa_code, u_int8_t capa_len)
- {
+-{
- u_int8_t op_type, op_len, tot_len, errs = 0;
-+ int 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;
@@ -529,6 +769,10 @@ diff -u -p -r1.1.1.8 -r1.9
- 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);
@@ -545,17 +789,41 @@ diff -u -p -r1.1.1.8 -r1.9
+ 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(buf, &afi, sizeof(afi));
-+ errs += ibuf_add(buf, &pad, sizeof(pad));
-+ errs += ibuf_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 +1279,22 @@ session_newmsg(enum msg_type msgtype, u_
+@@ -1287,23 +1386,22 @@ session_newmsg(enum msg_type msgtype, u_
{
struct bgp_msg *msg;
struct msg_header hdr;
@@ -587,7 +855,7 @@ diff -u -p -r1.1.1.8 -r1.9
return (NULL);
}
-@@ -1329,7 +1320,7 @@ session_sendmsg(struct bgp_msg *msg, str
+@@ -1329,7 +1427,7 @@ session_sendmsg(struct bgp_msg *msg, str
mrt_dump_bgp_msg(mrt, msg->buf->buf, msg->len, p);
}
@@ -596,7 +864,7 @@ diff -u -p -r1.1.1.8 -r1.9
free(msg);
return (0);
}
-@@ -1338,40 +1329,38 @@ void
+@@ -1338,40 +1436,70 @@ void
session_open(struct peer *p)
{
struct bgp_msg *buf;
@@ -608,6 +876,7 @@ diff -u -p -r1.1.1.8 -r1.9
- 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) {
@@ -630,6 +899,7 @@ diff -u -p -r1.1.1.8 -r1.9
+ 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 */
@@ -637,21 +907,56 @@ diff -u -p -r1.1.1.8 -r1.9
- 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];
-
+- /* 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 */
+- c[0] = 0x80; /* we're always restarting */
- errs += session_capa_add(p, opb, CAPA_RESTART, 2, &optparamlen);
- errs += buf_add(opb, &c, 2);
-+ c[1] = 0;
-+ errs += session_capa_add(opb, CAPA_RESTART, 2);
-+ errs += ibuf_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 +1368,17 @@ session_open(struct peer *p)
+@@ -1379,13 +1507,17 @@ session_open(struct peer *p)
u_int32_t nas;
nas = htonl(conf->as);
@@ -672,7 +977,7 @@ diff -u -p -r1.1.1.8 -r1.9
bgp_fsm(p, EVNT_CON_FATAL);
return;
}
-@@ -1399,19 +1392,24 @@ session_open(struct peer *p)
+@@ -1399,19 +1531,24 @@ session_open(struct peer *p)
msg.bgpid = conf->bgpid; /* is already in network byte order */
msg.optparamlen = optparamlen;
@@ -708,7 +1013,7 @@ diff -u -p -r1.1.1.8 -r1.9
free(buf);
bgp_fsm(p, EVNT_CON_FATAL);
return;
-@@ -1459,8 +1457,8 @@ session_update(u_int32_t peerid, void *d
+@@ -1459,8 +1596,8 @@ session_update(u_int32_t peerid, void *d
return;
}
@@ -719,7 +1024,7 @@ diff -u -p -r1.1.1.8 -r1.9
free(buf);
bgp_fsm(p, EVNT_CON_FATAL);
return;
-@@ -1480,29 +1478,27 @@ session_notification(struct peer *p, u_i
+@@ -1480,29 +1617,27 @@ session_notification(struct peer *p, u_i
void *data, ssize_t datalen)
{
struct bgp_msg *buf;
@@ -757,7 +1062,7 @@ diff -u -p -r1.1.1.8 -r1.9
free(buf);
bgp_fsm(p, EVNT_CON_FATAL);
return;
-@@ -1521,23 +1517,29 @@ session_notification(struct peer *p, u_i
+@@ -1521,23 +1656,29 @@ session_notification(struct peer *p, u_i
int
session_neighbor_rrefresh(struct peer *p)
{
@@ -793,7 +1098,7 @@ diff -u -p -r1.1.1.8 -r1.9
if ((buf = session_newmsg(RREFRESH, MSGSIZE_RREFRESH)) == NULL) {
bgp_fsm(p, EVNT_CON_FATAL);
-@@ -1545,12 +1547,12 @@ session_rrefresh(struct peer *p, u_int16
+@@ -1545,12 +1686,12 @@ session_rrefresh(struct peer *p, u_int16
}
afi = htons(afi);
@@ -811,7 +1116,229 @@ diff -u -p -r1.1.1.8 -r1.9
free(buf);
bgp_fsm(p, EVNT_CON_FATAL);
return;
-@@ -1853,12 +1855,6 @@ parse_open(struct peer *peer)
+@@ -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;
++int
++session_process_msg(struct peer *p)
++{
++ ssize_t rpos, av, left;
++ int processed = 0;
++ u_int16_t msglen;
++ u_int8_t msgtype;
+
+- 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);
++ rpos = 0;
++ av = p->rbuf->wpos;
+
+- if (rpos < av) {
+- left = av - rpos;
+- memcpy(&p->rbuf->buf, p->rbuf->buf + rpos, left);
+- p->rbuf->wpos = left;
+- } else
+- p->rbuf->wpos = 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;
+
+- return (1);
++ 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);
@@ -824,7 +1351,7 @@ diff -u -p -r1.1.1.8 -r1.9
memcpy(&oholdtime, p, sizeof(oholdtime));
p += sizeof(oholdtime);
-@@ -1966,6 +1962,15 @@ parse_open(struct peer *peer)
+@@ -1966,6 +2174,15 @@ parse_open(struct peer *peer)
}
}
@@ -840,13 +1367,13 @@ diff -u -p -r1.1.1.8 -r1.9
if (peer->conf.remote_as != as) {
log_peer_warnx(&peer->conf, "peer sent wrong AS %s",
log_as(as));
-@@ -1974,6 +1979,14 @@ parse_open(struct peer *peer)
+@@ -1974,6 +2191,14 @@ parse_open(struct peer *peer)
return (-1);
}
+ if (capa_neg_calc(peer) == -1) {
+ log_peer_warnx(&peer->conf,
-+ "capabilitiy negotiation calculation failed");
++ "capability negotiation calculation failed");
+ session_notification(peer, ERR_OPEN, 0, NULL, 0);
+ change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN);
+ return (-1);
@@ -855,7 +1382,7 @@ diff -u -p -r1.1.1.8 -r1.9
return (0);
}
-@@ -2008,24 +2021,35 @@ int
+@@ -2008,24 +2233,35 @@ int
parse_refresh(struct peer *peer)
{
u_char *p;
@@ -897,7 +1424,7 @@ diff -u -p -r1.1.1.8 -r1.9
return (-1);
return (0);
-@@ -2035,11 +2059,12 @@ int
+@@ -2035,11 +2271,12 @@ int
parse_notification(struct peer *peer)
{
u_char *p;
@@ -911,7 +1438,7 @@ diff -u -p -r1.1.1.8 -r1.9
/* just log */
p = peer->rbuf->rptr;
-@@ -2059,7 +2084,7 @@ parse_notification(struct peer *peer)
+@@ -2059,7 +2296,7 @@ parse_notification(struct peer *peer)
p += sizeof(subcode);
datalen -= sizeof(subcode);
@@ -920,7 +1447,7 @@ diff -u -p -r1.1.1.8 -r1.9
peer->errcnt++;
if (errcode == ERR_OPEN && subcode == ERR_OPEN_CAPA) {
-@@ -2094,8 +2119,8 @@ parse_notification(struct peer *peer)
+@@ -2094,8 +2331,8 @@ parse_notification(struct peer *peer)
datalen -= capa_len;
switch (capa_code) {
case CAPA_MP:
@@ -931,7 +1458,16 @@ diff -u -p -r1.1.1.8 -r1.9
log_peer_warnx(&peer->conf,
"disabling multiprotocol capability");
break;
-@@ -2139,13 +2164,14 @@ parse_notification(struct peer *peer)
+@@ -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,13 +2376,17 @@ parse_notification(struct peer *peer)
int
parse_capabilities(struct peer *peer, u_char *d, u_int16_t dlen, u_int32_t *as)
{
@@ -939,18 +1475,21 @@ diff -u -p -r1.1.1.8 -r1.9
+ 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) {
-@@ -2182,29 +2208,16 @@ parse_capabilities(struct peer *peer, u_
+@@ -2182,36 +2423,65 @@ parse_capabilities(struct peer *peer, u_
"expect len 4, len is %u", capa_len);
return (-1);
}
@@ -988,7 +1527,58 @@ diff -u -p -r1.1.1.8 -r1.9
break;
case CAPA_REFRESH:
peer->capa.peer.refresh = 1;
-@@ -2232,6 +2245,37 @@ parse_capabilities(struct peer *peer, u_
+ 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,
++ "parse_capabilities: "
++ "expect len 2 + x*4, len is %u", capa_len);
++ return (-1);
++ }
++
++ 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,
++ "graceful restart timeout is zero");
++ return (-1);
++ }
++
++ 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,
++ "parse_capabilities: restart: AFI "
++ "%u, safi %u unknown", afi, safi);
++ return (-1);
++ }
++ 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) {
+@@ -2232,6 +2502,66 @@ parse_capabilities(struct peer *peer, u_
return (0);
}
@@ -1014,11 +1604,40 @@ diff -u -p -r1.1.1.8 -r1.9
+ } else
+ p->capa.neg.mp[i] = 0;
+ }
-+ /* if no MP capability present for default IPv4 unicast mode */
++ /* if no MP capability present default to IPv4 unicast mode */
+ if (!hasmp)
+ p->capa.neg.mp[AID_INET] = 1;
+
-+ p->capa.neg.restart = p->capa.peer.restart;
++ /*
++ * 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);
+}
@@ -1026,16 +1645,18 @@ diff -u -p -r1.1.1.8 -r1.9
void
session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
{
-@@ -2244,7 +2288,7 @@ session_dispatch_imsg(struct imsgbuf *ib
+@@ -2244,8 +2574,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 errcode, subcode;
++ u_int8_t aid, errcode, subcode;
if ((n = imsg_read(ibuf)) == -1)
-@@ -2332,15 +2376,42 @@ session_dispatch_imsg(struct imsgbuf *ib
+ fatal("session_dispatch_imsg: imsg_read error");
+@@ -2332,15 +2662,42 @@ session_dispatch_imsg(struct imsgbuf *ib
}
break;
@@ -1079,7 +1700,27 @@ diff -u -p -r1.1.1.8 -r1.9
/* add new peers */
for (p = npeers; p != NULL; p = next) {
-@@ -2408,7 +2479,8 @@ session_dispatch_imsg(struct imsgbuf *ib
+@@ -2388,6 +2745,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 +2756,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 +2765,8 @@ session_dispatch_imsg(struct imsgbuf *ib
bgp_fsm(p, EVNT_START);
} else if (!depend_ok && p->depend_ok) {
p->depend_ok = depend_ok;
@@ -1089,7 +1730,7 @@ diff -u -p -r1.1.1.8 -r1.9
}
}
break;
-@@ -2456,10 +2528,10 @@ session_dispatch_imsg(struct imsgbuf *ib
+@@ -2456,10 +2814,10 @@ session_dispatch_imsg(struct imsgbuf *ib
}
break;
case IMSG_CTL_KROUTE:
@@ -1101,7 +1742,7 @@ diff -u -p -r1.1.1.8 -r1.9
if (idx != PFD_PIPE_MAIN)
fatalx("ctl kroute request not from parent");
control_imsg_relay(&imsg);
-@@ -2469,7 +2541,6 @@ session_dispatch_imsg(struct imsgbuf *ib
+@@ -2469,7 +2827,6 @@ session_dispatch_imsg(struct imsgbuf *ib
case IMSG_CTL_SHOW_RIB_ATTR:
case IMSG_CTL_SHOW_RIB_MEM:
case IMSG_CTL_SHOW_NETWORK:
@@ -1109,7 +1750,48 @@ diff -u -p -r1.1.1.8 -r1.9
case IMSG_CTL_SHOW_NEIGHBOR:
if (idx != PFD_PIPE_ROUTE_CTL)
fatalx("ctl rib request not from RDE");
-@@ -2612,29 +2683,23 @@ getpeerbydesc(const char *descr)
+@@ -2531,6 +2888,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 +3003,23 @@ getpeerbydesc(const char *descr)
struct peer *
getpeerbyip(struct sockaddr *ip)
{
@@ -1146,7 +1828,7 @@ diff -u -p -r1.1.1.8 -r1.9
if (loose == NULL || loose->conf.remote_masklen <
p->conf.remote_masklen)
loose = p;
-@@ -2653,21 +2718,19 @@ getpeerbyip(struct sockaddr *ip)
+@@ -2653,21 +3038,19 @@ getpeerbyip(struct sockaddr *ip)
break;
}
}
@@ -1175,7 +1857,7 @@ diff -u -p -r1.1.1.8 -r1.9
newpeer->rbuf = NULL;
init_peer(newpeer);
bgp_fsm(newpeer, EVNT_START);
-@@ -2680,40 +2743,24 @@ getpeerbyip(struct sockaddr *ip)
+@@ -2680,40 +3063,24 @@ getpeerbyip(struct sockaddr *ip)
}
int
@@ -1227,7 +1909,7 @@ diff -u -p -r1.1.1.8 -r1.9
return (0);
}
-@@ -2733,6 +2780,7 @@ getpeerbyid(u_int32_t peerid)
+@@ -2733,6 +3100,7 @@ getpeerbyid(u_int32_t peerid)
void
session_down(struct peer *peer)
{
@@ -1235,9 +1917,17 @@ diff -u -p -r1.1.1.8 -r1.9
peer->stats.last_updown = time(NULL);
if (imsg_compose(ibuf_rde, IMSG_SESSION_DOWN, peer->conf.id, 0, -1,
NULL, 0) == -1)
-@@ -2748,35 +2796,12 @@ session_up(struct peer *p)
- &p->conf, sizeof(p->conf)) == -1)
- fatalx("imsg_compose error");
+@@ -2744,39 +3112,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:
@@ -1274,7 +1964,7 @@ diff -u -p -r1.1.1.8 -r1.9
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 +2809,10 @@ session_up(struct peer *p)
+@@ -2784,9 +3130,10 @@ session_up(struct peer *p)
}
int
@@ -1287,7 +1977,7 @@ diff -u -p -r1.1.1.8 -r1.9
}
int
-@@ -2795,34 +2821,6 @@ imsg_compose_rde(int type, pid_t pid, vo
+@@ -2795,34 +3142,6 @@ imsg_compose_rde(int type, pid_t pid, vo
return (imsg_compose(ibuf_rde, type, 0, pid, -1, data, datalen));
}
@@ -1322,7 +2012,7 @@ diff -u -p -r1.1.1.8 -r1.9
void
session_demote(struct peer *p, int level)
{
-@@ -2837,3 +2835,19 @@ session_demote(struct peer *p, int level
+@@ -2837,3 +3156,19 @@ session_demote(struct peer *p, int level
p->demoted += level;
}
diff --git a/net/openbgpd/files/patch-bgpd_session.h b/net/openbgpd/files/patch-bgpd_session.h
index 4eb8dbce5f6b..6ffbd79abd1f 100644
--- a/net/openbgpd/files/patch-bgpd_session.h
+++ b/net/openbgpd/files/patch-bgpd_session.h
@@ -2,13 +2,13 @@ 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.9
-diff -u -p -r1.1.1.7 -r1.1.1.9
+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 12 Jun 2011 10:44:25 -0000 1.1.1.9
++++ 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.111 2010/12/09 13:50:41 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>
@@ -35,7 +35,26 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
enum msg_type type;
u_int16_t len;
};
-@@ -189,6 +196,7 @@ struct peer {
+@@ -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;
@@ -43,7 +62,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
} capa;
struct {
struct bgpd_addr local_addr;
-@@ -201,7 +209,7 @@ struct peer {
+@@ -201,7 +212,7 @@ struct peer {
struct sockaddr_storage sa_remote;
struct peer_timer_head timers;
struct msgbuf wbuf;
@@ -52,76 +71,118 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
struct peer *next;
int fd;
int lasterr;
-@@ -217,7 +225,7 @@ struct peer {
+@@ -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;
-@@ -226,38 +234,36 @@ struct ctl_timer {
+ time_t val;
+ };
- /* session.c */
- void session_socket_blockmode(int, enum blockmodes);
+-/* 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]);
-+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 *);
+-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_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);
-
- /* 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,
+-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);
-+ u_char *, u_int16_t, const char *);
- void log_conn_attempt(const struct peer *, struct sockaddr *);
-
- /* parse.y */
- int parse_config(char *, struct bgpd_config *, struct mrt_head *,
+-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 *);
-+ struct peer **, struct network_head *, struct filter_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);
/* config.c */
int merge_config(struct bgpd_config *, struct bgpd_config *,
struct peer *, struct listen_addrs *);
void prepare_listeners(struct bgpd_config *);
-+int get_mpe_label(struct rdomain *);
-
- /* rde.c */
+-
+-/* 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);
-+pid_t rde_main(int[2], int[2], int[2], int[2], int);
++int get_mpe_label(struct rdomain *);
/* control.c */
int control_init(int, char *);
-@@ -267,6 +273,7 @@ int control_dispatch_msg(struct pollfd *
+@@ -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,7 +281,7 @@ 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);
+-/* 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
index 1bace94e1998..1238897b94fa 100644
--- a/net/openbgpd/files/patch-bgpd_timer.c
+++ b/net/openbgpd/files/patch-bgpd_timer.c
@@ -2,17 +2,26 @@ 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.3
-diff -u -p -r1.1.1.2 -r1.1.1.3
+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 12 Jun 2011 10:44:25 -0000 1.1.1.3
++++ 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>
-@@ -43,7 +43,7 @@ timer_get(struct peer *p, enum Timer tim
+@@ -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)
diff --git a/net/openbgpd/files/patch-bgpd_util.c b/net/openbgpd/files/patch-bgpd_util.c
index 213c90a2276e..54e74ec9805f 100644
--- a/net/openbgpd/files/patch-bgpd_util.c
+++ b/net/openbgpd/files/patch-bgpd_util.c
@@ -2,10 +2,10 @@ Index: bgpd/util.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/util.c,v
retrieving revision 1.1.1.6
-retrieving revision 1.6
-diff -u -p -r1.1.1.6 -r1.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 2 Jul 2011 16:06:38 -0000 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 $ */
@@ -43,14 +43,14 @@ diff -u -p -r1.1.1.6 -r1.6
+ if (inet_ntop(aid2af(addr->aid), &addr->ba, buf,
+ sizeof(buf)) == NULL)
+ return ("?");
-+ return (buf);
+ 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 (buf);
+ }
+ return ("???");
}
@@ -187,7 +187,142 @@ diff -u -p -r1.1.1.6 -r1.6
}
/* ensure that we have a valid C-string especially for empty as path */
if (size > 0)
-@@ -276,3 +376,115 @@ inet6applymask(struct in6_addr *dest, co
+@@ -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];
}
diff --git a/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h b/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h
index 312906fefe60..3855a8dd3f95 100644
--- a/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h
+++ b/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h
@@ -3,10 +3,10 @@ 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 3 Jul 2011 04:46:38 -0000 1.6
-@@ -0,0 +1,87 @@
++++ 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.6 2011/07/03 04:46:38 hrs Exp $
++ * $hrs: openbgpd/openbsd-compat/openbsd-compat.h,v 1.8 2012/10/13 18:50:10 hrs Exp $
+ */
+
+#ifndef _OPENBSD_COMPAT_H
@@ -16,7 +16,11 @@ diff -N openbsd-compat/openbsd-compat.h
+
+/* 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;