FreeBSD Bugzilla – Attachment 204136 Details for
Bug 213445
net/openbgpd: Update to 6.5p0
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
patch
obgp.diff (text/plain), 730.96 KB, created by
Kurt Jaeger
on 2019-05-01 07:29:36 UTC
(
hide
)
Description:
patch
Filename:
MIME Type:
Creator:
Kurt Jaeger
Created:
2019-05-01 07:29:36 UTC
Size:
730.96 KB
patch
obsolete
>Index: Makefile >=================================================================== >--- Makefile (revision 500577) >+++ Makefile (working copy) >@@ -1,12 +1,9 @@ > # $FreeBSD$ > > PORTNAME= openbgpd >-PORTVERSION= 5.2.20121209 >-PORTREVISION= 3 >+PORTVERSION= 6.5p0 > CATEGORIES= net > MASTER_SITES= OPENBSD/OpenBGPD >-DISTNAME= ${PORTNAME}-4.6 >-DIST_SUBDIR= ${PORTNAME} > > MAINTAINER= hrs@FreeBSD.org > COMMENT= Free implementation of the Border Gateway Protocol, Version 4 >@@ -16,12 +13,10 @@ > > CONFLICTS= zebra-[0-9]* quagga-[0-9]* > >-USES= tar:tgz uidfix >+USES= autoreconf libtool uidfix > USE_RC_SUBR= ${PORTNAME} >+GNU_CONFIGURE= yes > >-NO_WRKSUBDIR= yes >-PLIST_FILES= sbin/bgpctl sbin/bgpd man/man5/bgpd.conf.5.gz \ >- man/man8/bgpctl.8.gz man/man8/bgpd.8.gz > SUB_FILES= pkg-message > USERS= _bgpd > GROUPS= _bgpd >@@ -31,10 +26,4 @@ > IPV6LLPEER_DESC=Support nexthop using IPv6 link-local address > IPV6LLPEER_MAKE_ARGS= -DIPV6_LINKLOCAL_PEER > >-post-patch: >- @${REINPLACE_CMD} -e "s|%%PREFIX%%|${PREFIX}|g" \ >- ${WRKSRC}/bgpd/bgpd.8 \ >- ${WRKSRC}/bgpd/bgpd.conf.5 \ >- ${WRKSRC}/bgpctl/bgpctl.8 >- > .include <bsd.port.mk> >Index: distinfo >=================================================================== >--- distinfo (revision 500577) >+++ distinfo (working copy) >@@ -1,2 +1,3 @@ >-SHA256 (openbgpd/openbgpd-4.6.tgz) = d9a0a3542e5ec744889ca12871f01aa1d86f12844e093010f37d0601796e15cf >-SIZE (openbgpd/openbgpd-4.6.tgz) = 168197 >+TIMESTAMP = 1556692508 >+SHA256 (openbgpd-6.5p0.tar.gz) = 20c1a40bafcbbea60c4ecc6dd2e87fcba6847bfad62739b705a3806b6b442a56 >+SIZE (openbgpd-6.5p0.tar.gz) = 677691 >Index: files/patch-Makefile >=================================================================== >--- files/patch-Makefile (revision 500577) >+++ files/patch-Makefile (nonexistent) >@@ -1,12 +0,0 @@ >-Index: Makefile >-=================================================================== >-RCS file: Makefile >-diff -N Makefile >---- /dev/null 1 Jan 1970 00:00:00 -0000 >-+++ Makefile 30 Jun 2009 07:07:55 -0000 1.2 >-@@ -0,0 +1,5 @@ >-+# $hrs: openbgpd/Makefile,v 1.2 2009/06/30 07:07:55 hrs Exp $ >-+ >-+SUBDIR= bgpd bgpctl >-+ >-+.include <bsd.subdir.mk> > >Property changes on: files/patch-Makefile >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-Makefile.am >=================================================================== >--- files/patch-Makefile.am (nonexistent) >+++ files/patch-Makefile.am (working copy) >@@ -0,0 +1,20 @@ >+--- Makefile.am.orig 2019-05-01 09:22:14.978244000 +0200 >++++ Makefile.am 2019-05-01 09:23:45.851314000 +0200 >+@@ -19,13 +19,14 @@ >+ EXTRA_DIST = README.md VERSION bgpd.conf >+ >+ install-data-hook: >+- @if [ ! -d "$(DESTDIR)$(localstatedir)/run" ]; then \ >++ if [ ! -d "$(DESTDIR)$(localstatedir)/run" ]; then \ >+ $(INSTALL) -m 755 -d "$(DESTDIR)$(localstatedir)/run"; \ >+ fi >+- @if [ ! -d "$(DESTDIR)$(sysconfdir)" ]; then \ >++ if [ ! -d "$(DESTDIR)$(sysconfdir)" ]; then \ >+ $(INSTALL) -m 755 -d "$(DESTDIR)$(sysconfdir)"; \ >+ fi >+- @if [ ! -f "$(DESTDIR)$(sysconfdir)/bgpd.conf" ]; then \ >++ $(INSTALL) -m 644 "$(srcdir)/bgpd.conf" "$(DESTDIR)$(sysconfdir)/bgpd.conf.sample"; \ >++ if [ ! -f "$(DESTDIR)$(sysconfdir)/bgpd.conf" ]; then \ >+ $(INSTALL) -m 644 "$(srcdir)/bgpd.conf" "$(DESTDIR)$(sysconfdir)/bgpd.conf"; \ >+ else \ >+ echo; \ > >Property changes on: files/patch-Makefile.am >___________________________________________________________________ >Added: fbsd:nokeywords >## -0,0 +1 ## >+yes >\ No newline at end of property >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Added: svn:mime-type >## -0,0 +1 ## >+text/plain >\ No newline at end of property >Index: files/patch-Makefile.inc >=================================================================== >--- files/patch-Makefile.inc (revision 500577) >+++ files/patch-Makefile.inc (nonexistent) >@@ -1,12 +0,0 @@ >-Index: Makefile.inc >-=================================================================== >-RCS file: Makefile.inc >-diff -N Makefile.inc >---- /dev/null 1 Jan 1970 00:00:00 -0000 >-+++ Makefile.inc 16 May 2014 01:06:14 -0000 1.5 >-@@ -0,0 +1,5 @@ >-+# $hrs: openbgpd/Makefile.inc,v 1.5 2014/05/16 01:06:14 hrs Exp $ >-+ >-+PREFIX?= /usr/local >-+BINDIR?= ${PREFIX}/sbin >-+MANDIR?= ${PREFIX}/man/man > >Property changes on: files/patch-Makefile.inc >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpctl_Makefile >=================================================================== >--- files/patch-bgpctl_Makefile (revision 500577) >+++ files/patch-bgpctl_Makefile (nonexistent) >@@ -1,31 +0,0 @@ >-Index: bgpctl/Makefile >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/Makefile,v >-retrieving revision 1.1.1.1 >-retrieving revision 1.4 >-diff -u -p -r1.1.1.1 -r1.4 >---- bgpctl/Makefile 30 Jun 2009 05:46:15 -0000 1.1.1.1 >-+++ bgpctl/Makefile 13 Oct 2012 18:35:56 -0000 1.4 >-@@ -1,17 +1,18 @@ >- # $OpenBSD: Makefile,v 1.10 2007/12/20 17:08:48 henning Exp $ >- >--.PATH: ${.CURDIR}/../bgpd >-+.PATH: ${.CURDIR}/../bgpd ${.CURDIR}/../openbsd-compat >- >- PROG= bgpctl >--SRCS= bgpctl.c parser.c buffer.c imsg.c util.c timer.c >-+SRCS= bgpctl.c parser.c util.c timer.c >- SRCS+= irrfilter.c whois.c irr_asset.c irr_prefix.c irr_output.c >--SRCS+= irr_parser.c >-+SRCS+= irr_parser.c mrtparser.c >-+SRCS+= fmt_scaled.c imsg.c imsg-buffer.c >- CFLAGS+= -Wall >- CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes >- CFLAGS+= -Wmissing-declarations >- CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual >- CFLAGS+= -Wsign-compare >--CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../bgpd >-+CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../bgpd -I${.CURDIR}/../openbsd-compat >- MAN= bgpctl.8 >- LDADD= -lutil >- DPADD+= ${LIBUTIL} > >Property changes on: files/patch-bgpctl_Makefile >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpctl_bgpctl.8 >=================================================================== >--- files/patch-bgpctl_bgpctl.8 (revision 500577) >+++ files/patch-bgpctl_bgpctl.8 (nonexistent) >@@ -1,287 +0,0 @@ >-Index: bgpctl/bgpctl.8 >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/bgpctl.8,v >-retrieving revision 1.1.1.6 >-retrieving revision 1.6 >-diff -u -p -r1.1.1.6 -r1.6 >---- bgpctl/bgpctl.8 14 Feb 2010 20:20:13 -0000 1.1.1.6 >-+++ bgpctl/bgpctl.8 13 Oct 2012 18:35:56 -0000 1.6 >-@@ -1,4 +1,4 @@ >--.\" $OpenBSD: bgpctl.8,v 1.49 2009/06/06 06:11:17 claudio Exp $ >-+.\" $OpenBSD: bgpctl.8,v 1.59 2012/05/27 20:49:42 jmc Exp $ >- .\" >- .\" Copyright (c) 2003 Henning Brauer <henning@openbsd.org> >- .\" >-@@ -14,7 +14,7 @@ >- .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF >- .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >- .\" >--.Dd $Mdocdate: June 6 2009 $ >-+.Dd $Mdocdate: May 27 2012 $ >- .Dt BGPCTL 8 >- .Os >- .Sh NAME >-@@ -32,8 +32,7 @@ The >- program controls the >- .Xr bgpd 8 >- daemon. >--Commands to switch between displays may be abbreviated to the >--minimum unambiguous prefix; for example, >-+Commands may be abbreviated to the minimum unambiguous prefix; for example, >- .Cm s s >- for >- .Cm show summary . >-@@ -53,11 +52,19 @@ to communicate with >- .Pp >- The commands are as follows: >- .Bl -tag -width xxxxxx >--.It Cm fib couple >--Insert the learned routes into the Forwarding Information Base >-+.It Xo >-+.Cm fib >-+.Op Cm table Ar number >-+.Cm couple >-+.Xc >-+Insert the learned routes into the specified Forwarding Information Base >- a.k.a. the kernel routing table. >--.It Cm fib decouple >--Remove the learned routes from the Forwarding Information Base >-+.It Xo >-+.Cm fib >-+.Op Cm table Ar number >-+.Cm decouple >-+.Xc >-+Remove the learned routes from the specified Forwarding Information Base >- a.k.a. the kernel routing table. >- .It Xo >- .Cm irrfilter >-@@ -79,7 +86,15 @@ The options are as follows: >- Use >- .Ar directory >- to write the filter files to. >-+.It Fl 4 >-+Fetch only IPv4 prefixes from the registry. >-+.It Fl 6 >-+Fetch only IPv6 prefixes from the registry. >- .El >-+.It Cm log brief >-+Disable verbose debug logging. >-+.It Cm log verbose >-+Enable verbose debug logging. >- .It Cm neighbor Ar peer Cm up >- Take the BGP session to the specified neighbor up. >- .Ar peer >-@@ -98,12 +113,21 @@ Note that the neighbor is not obliged to >- all, even if it announced the route refresh capability. >- .Ar peer >- may be the neighbor's address or description. >--.It Cm network add Ar prefix >-+.It Cm network add Ar prefix Op Ar arguments >- Add the specified prefix to the list of announced networks. >-+It is possible to set various path attributes with additional >-+.Ar arguments . >- .It Cm network delete Ar prefix >- Remove the specified prefix from the list of announced networks. >- .It Cm network flush >- Remove all dynamically added prefixes from the list of announced networks. >-+.It Cm network mrt file Ar file filter >-+Import networks from an MRT table dump for debugging purposes. >-+.Ar filter >-+can be specified similarly to the >-+.Ar show mrt >-+command. >-+Only networks matching the filter will be imported. >- .It Cm network show Ar family >- Show all announced networks. >- .Ar family , >-@@ -122,7 +146,7 @@ view of the Forwarding Information Base. >- can be an IP address, in which case the route to this address is shown, >- or a flag: >- .Pp >--.Bl -tag -width connected -compact >-+.Bl -tag -width tableXnumber -compact >- .It Cm connected >- Show only connected routes. >- .It Cm static >-@@ -133,9 +157,81 @@ Show only routes originating from >- itself. >- .It Cm nexthop >- Show only routes required to reach a BGP nexthop. >-+.It Cm inet >-+Show only IPv4 routes. >-+.It Cm inet6 >-+Show only IPv6 routes. >-+.It Cm table Ar number >-+Show the routing table with ID >-+.Ar number >-+instead of the default routing table with ID 0. >- .El >- .It Cm show interfaces >- Show the interface states. >-+.It Xo >-+.Cm show mrt >-+.Op Ar options >-+.Ar filter >-+.Xc >-+Show routes from an MRT table dump file. >-+.Ar filter >-+can be an IP address, a CIDR prefix, an AS filter, a combination or nothing: >-+.Pp >-+.Bl -tag -width "address/len all" -compact >-+.It Ar address >-+Show best matching route for address. >-+.It Ar address Ns Li / Ns Ar len >-+Show RIB entry for this CIDR prefix. >-+.It Xo >-+.Ar address Ns Li / Ns Ar len >-+.Cm all >-+.Xc >-+Show all entries in the specified range. >-+.\".It Ar address/len Cm longer-prefixes >-+.It Cm as Ar as >-+Show all entries with >-+.Ar as >-+anywhere in the AS path. >-+.It Cm empty-as >-+Show all entries that are internal routes with no AS's in the AS path. >-+.It Cm neighbor Ar ip >-+Show only entries from the specified peer. >-+.It Cm peer-as Ar as >-+Show all entries with >-+.Ar as >-+as leftmost AS. >-+.It Cm source-as Ar as >-+Show all entries with >-+.Ar as >-+as rightmost AS. >-+.It Cm transit-as Ar as >-+Show all entries with >-+.Ar as >-+anywhere but rightmost. >-+.El >-+.Pp >-+Additionally, the following >-+.Ar options >-+are defined: >-+.Pp >-+.Bl -tag -width "file name" -compact >-+.It Cm detail >-+Show more detailed output for matching routes. >-+.It Ar family >-+Limit the output to the given address family. >-+.It Cm file Ar name >-+Read the MRT dump from file >-+.Ar name >-+instead of using stdin. >-+.El >-+.Pp >-+Multiple options and filters can be used at the same time. >-+.It Cm show summary >-+Show a list of all neighbors, including information about the session state >-+and message counters. >-+.It Cm show summary terse >-+Show a list of all neighbors, including information about the session state, >-+in a terse format. >- .It Cm show neighbor Ar peer modifier >- Show detailed information about the neighbor identified by >- .Ar peer , >-@@ -183,33 +279,33 @@ Show all entries in the specified range. >- Show all entries with >- .Ar as >- anywhere in the AS path. >--.It Cm source-as Ar as >--Show all entries with >--.Ar as >--as rightmost AS. >--.It Cm transit-as Ar as >--Show all entries with >--.Ar as >--anywhere but rightmost. >--.It Cm peer-as Ar as >--Show all entries with >--.Ar as >--as leftmost AS. >--.It Cm empty-as >--Show all entries that are internal routes with no AS's in the AS path. >- .It Cm community Ar community >- Show all entries with community >- .Ar community . >-+.It Cm empty-as >-+Show all entries that are internal routes with no AS's in the AS path. >-+.It Cm memory >-+Show RIB memory statistics. >- .It Cm neighbor Ar peer >- Show only entries from the specified peer. >--.It Cm table Ar rib >--Show only entries from the specified RIB table. >-+.It Cm peer-as Ar as >-+Show all entries with >-+.Ar as >-+as leftmost AS. >-+.It Cm source-as Ar as >-+Show all entries with >-+.Ar as >-+as rightmost AS. >- .It Cm summary >- This is the same as the >- .Ic show summary >- command. >--.It Cm memory >--Show RIB memory statistics. >-+.It Cm table Ar rib >-+Show only entries from the specified RIB table. >-+.It Cm transit-as Ar as >-+Show all entries with >-+.Ar as >-+anywhere but rightmost. >- .El >- .Pp >- Additionally, the following >-@@ -217,8 +313,10 @@ Additionally, the following >- are defined: >- .Pp >- .Bl -tag -width "detail" -compact >-+.It Cm selected >-+Show only selected routes. >- .It Cm detail >--Show more detailed output for matched routes. >-+Show more detailed output for matching routes. >- .It Ar family >- Limit the output to the given address family. >- .It Cm in >-@@ -243,10 +341,12 @@ and message counters. >- .It Cm show summary terse >- Show a list of all neighbors, including information about the session state, >- in a terse format. >-+.It Cm show tables >-+Show a list of all currently loaded fib routing tables. >- .El >- .Sh FILES >- .Bl -tag -width "/var/run/bgpd.sockXXX" -compact >--.It Pa /etc/bgpd.conf >-+.It Pa %%PREFIX%%/etc/bgpd.conf >- default >- .Xr bgpd 8 >- configuration file >-@@ -260,10 +360,19 @@ control socket >- .Xr bgpd 8 , >- .Xr bgplg 8 , >- .Xr bgplgsh 8 >-+.Sh STANDARDS >- .Rs >--.%R RFC 2622 >--.%T "Routing Policy Specification Language (RPSL)" >-+.%A C. Alaettinoglu >-+.%A C. Villamizar >-+.%A E. Gerich >-+.%A D. Kessens >-+.%A D. Meyer >-+.%A T. Bates >-+.%A D. Karrenberg >-+.%A M. Terpstra >- .%D June 1999 >-+.%R RFC 2622 >-+.%T Routing Policy Specification Language (RPSL) >- .Re >- .Sh HISTORY >- The > >Property changes on: files/patch-bgpctl_bgpctl.8 >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpctl_bgpctl.c >=================================================================== >--- files/patch-bgpctl_bgpctl.c (revision 500577) >+++ files/patch-bgpctl_bgpctl.c (nonexistent) >@@ -1,1529 +0,0 @@ >-Index: bgpctl/bgpctl.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/bgpctl.c,v >-retrieving revision 1.1.1.7 >-retrieving revision 1.10 >-diff -u -p -r1.1.1.7 -r1.10 >---- bgpctl/bgpctl.c 14 Feb 2010 20:20:14 -0000 1.1.1.7 >-+++ bgpctl/bgpctl.c 8 Dec 2012 20:17:55 -0000 1.10 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: bgpctl.c,v 1.142 2009/06/06 06:33:15 eric Exp $ */ >-+/* $OpenBSD: bgpctl.c,v 1.167 2012/11/15 19:55:08 sthen Exp $ */ >- >- /* >- * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> >-@@ -16,11 +16,19 @@ >- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >- */ >- >-+#if defined(__FreeBSD__) /* compat */ >-+#include "openbsd-compat.h" >-+#endif /* defined(__FreeBSD__) */ >-+ >- #include <sys/types.h> >- #include <sys/socket.h> >- #include <sys/un.h> >- #include <net/if.h> >-+#if defined(__FreeBSD__) /* net/if_media.h */ >-+#include "if_media.h" >-+#else >- #include <net/if_media.h> >-+#endif /* defined(__FreeBSD__) */ >- #include <net/if_types.h> >- >- #include <err.h> >-@@ -29,7 +37,11 @@ >- #include <stdlib.h> >- #include <string.h> >- #include <unistd.h> >-+#if defined(__FreeBSD__) /* util.h */ >-+#include "util.h" >-+#else >- #include <util.h> >-+#endif /* defined(__FreeBSD__) */ >- >- #include "bgpd.h" >- #include "session.h" >-@@ -37,6 +49,11 @@ >- #include "log.h" >- #include "parser.h" >- #include "irrfilter.h" >-+#include "mrtparser.h" >-+ >-+#if defined(__FreeBSD__) /* FreeBSD has no LINK_STATE_IS_UP macro. */ >-+#define LINK_STATE_IS_UP(_s) ((_s) >= LINK_STATE_UP) >-+#endif /* defined(__FreeBSD__) */ >- >- enum neighbor_views { >- NV_DEFAULT, >-@@ -50,12 +67,14 @@ int show_summary_msg(struct imsg *, in >- int show_summary_terse_msg(struct imsg *, int); >- int show_neighbor_terse(struct imsg *); >- int show_neighbor_msg(struct imsg *, enum neighbor_views); >--void print_neighbor_capa_mp_safi(u_int8_t); >-+void print_neighbor_capa_mp(struct peer *); >-+void print_neighbor_capa_restart(struct peer *); >- void print_neighbor_msgstats(struct peer *); >- void print_timer(const char *, time_t); >- static char *fmt_timeframe(time_t t); >- static char *fmt_timeframe_core(time_t t); >- void show_fib_head(void); >-+void show_fib_tables_head(void); >- void show_network_head(void); >- void show_fib_flags(u_int16_t); >- int show_fib_msg(struct imsg *); >-@@ -65,7 +84,7 @@ void show_interface_head(void); >- int ift2ifm(int); >- const char * get_media_descr(int); >- const char * get_linkstate(int, int); >--void print_baudrate(u_int64_t); >-+const char * get_baudrate(u_int64_t, char *); >- int show_interface_msg(struct imsg *); >- void show_rib_summary_head(void); >- void print_prefix(struct bgpd_addr *, u_int8_t, u_int8_t); >-@@ -73,16 +92,25 @@ const char * print_origin(u_int8_t, int >- void print_flags(u_int8_t, int); >- int show_rib_summary_msg(struct imsg *); >- int show_rib_detail_msg(struct imsg *, int); >-+void show_rib_brief(struct ctl_show_rib *, u_char *); >-+void show_rib_detail(struct ctl_show_rib *, u_char *, int); >-+void show_attr(void *, u_int16_t); >- void show_community(u_char *, u_int16_t); >--const char *get_ext_subtype(u_int8_t); >- void show_ext_community(u_char *, u_int16_t); >- char *fmt_mem(int64_t); >- int show_rib_memory_msg(struct imsg *); >- void send_filterset(struct imsgbuf *, struct filter_set_head *); >- static const char *get_errstr(u_int8_t, u_int8_t); >- int show_result(struct imsg *); >-+void show_mrt_dump(struct mrt_rib *, struct mrt_peer *, void *); >-+void network_mrt_dump(struct mrt_rib *, struct mrt_peer *, void *); >-+void show_mrt_state(struct mrt_bgp_state *, void *); >-+void show_mrt_msg(struct mrt_bgp_msg *, void *); >-+void mrt_to_bgpd_addr(union mrt_addr *, struct bgpd_addr *); >- >- struct imsgbuf *ibuf; >-+struct mrt_parser show_mrt = { show_mrt_dump, show_mrt_state, show_mrt_msg }; >-+struct mrt_parser net_mrt = { network_mrt_dump, NULL, NULL }; >- >- __dead void >- usage(void) >-@@ -98,7 +126,7 @@ int >- main(int argc, char *argv[]) >- { >- struct sockaddr_un sun; >-- int fd, n, done, ch, nodescr = 0; >-+ int fd, n, done, ch, nodescr = 0, verbose = 0; >- struct imsg imsg; >- struct network_config net; >- struct parse_result *res; >-@@ -128,8 +156,11 @@ main(int argc, char *argv[]) >- if ((res = parse(argc, argv)) == NULL) >- exit(1); >- >-- if (res->action == IRRFILTER) >-+ if (res->action == IRRFILTER) { >-+ if (!(res->flags & (F_IPV4|F_IPV6))) >-+ res->flags |= (F_IPV4|F_IPV6); >- irr_main(res->as.as, res->flags, res->irr_outdir); >-+ } >- >- memcpy(&neighbor.addr, &res->peeraddr, sizeof(neighbor.addr)); >- strlcpy(neighbor.descr, res->peerdesc, sizeof(neighbor.descr)); >-@@ -154,7 +185,7 @@ main(int argc, char *argv[]) >- case NONE: >- case IRRFILTER: >- usage(); >-- /* not reached */ >-+ /* NOTREACHED */ >- case SHOW: >- case SHOW_SUMMARY: >- imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1, NULL, 0); >-@@ -164,24 +195,32 @@ main(int argc, char *argv[]) >- imsg_compose(ibuf, IMSG_CTL_SHOW_TERSE, 0, 0, -1, NULL, 0); >- break; >- case SHOW_FIB: >-- if (!res->addr.af) { >-- struct buf *msg; >-- >-- if ((msg = imsg_create(ibuf, IMSG_CTL_KROUTE, 0, 0, >-- sizeof(res->flags) + sizeof(res->af))) == NULL) >-+ if (!res->addr.aid) { >-+ struct ibuf *msg; >-+ sa_family_t af; >-+ >-+ af = aid2af(res->aid); >-+ if ((msg = imsg_create(ibuf, IMSG_CTL_KROUTE, >-+ res->rtableid, 0, sizeof(res->flags) + >-+ sizeof(af))) == NULL) >- errx(1, "imsg_create failure"); >- if (imsg_add(msg, &res->flags, sizeof(res->flags)) == >- -1 || >-- imsg_add(msg, &res->af, sizeof(res->af)) == -1) >-+ imsg_add(msg, &af, sizeof(af)) == -1) >- errx(1, "imsg_add failure"); >- imsg_close(ibuf, msg); >- } else >-- imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1, >-- &res->addr, sizeof(res->addr)); >-+ imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, res->rtableid, >-+ 0, -1, &res->addr, sizeof(res->addr)); >- show_fib_head(); >- break; >-+ case SHOW_FIB_TABLES: >-+ imsg_compose(ibuf, IMSG_CTL_SHOW_FIB_TABLES, 0, 0, -1, NULL, 0); >-+ show_fib_tables_head(); >-+ break; >- case SHOW_NEXTHOP: >-- imsg_compose(ibuf, IMSG_CTL_SHOW_NEXTHOP, 0, 0, -1, NULL, 0); >-+ imsg_compose(ibuf, IMSG_CTL_SHOW_NEXTHOP, res->rtableid, 0, -1, >-+ NULL, 0); >- show_nexthop_head(); >- break; >- case SHOW_INTERFACE: >-@@ -192,7 +231,7 @@ main(int argc, char *argv[]) >- case SHOW_NEIGHBOR_TIMERS: >- case SHOW_NEIGHBOR_TERSE: >- neighbor.show_timers = (res->action == SHOW_NEIGHBOR_TIMERS); >-- if (res->peeraddr.af || res->peerdesc[0]) >-+ if (res->peeraddr.aid || res->peerdesc[0]) >- imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1, >- &neighbor, sizeof(neighbor)); >- else >-@@ -206,7 +245,7 @@ main(int argc, char *argv[]) >- memcpy(&ribreq.as, &res->as, sizeof(res->as)); >- type = IMSG_CTL_SHOW_RIB_AS; >- } >-- if (res->addr.af) { >-+ if (res->addr.aid) { >- memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr)); >- ribreq.prefixlen = res->prefixlen; >- type = IMSG_CTL_SHOW_RIB_PREFIX; >-@@ -217,15 +256,35 @@ main(int argc, char *argv[]) >- sizeof(res->community)); >- type = IMSG_CTL_SHOW_RIB_COMMUNITY; >- } >-- memcpy(&ribreq.neighbor, &neighbor, >-- sizeof(ribreq.neighbor)); >-+ memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor)); >- strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib)); >-- ribreq.af = res->af; >-+ ribreq.aid = res->aid; >- ribreq.flags = res->flags; >- imsg_compose(ibuf, type, 0, 0, -1, &ribreq, sizeof(ribreq)); >- if (!(res->flags & F_CTL_DETAIL)) >- show_rib_summary_head(); >- break; >-+ case SHOW_MRT: >-+ close(fd); >-+ bzero(&ribreq, sizeof(ribreq)); >-+ if (res->as.type != AS_NONE) >-+ memcpy(&ribreq.as, &res->as, sizeof(res->as)); >-+ if (res->addr.aid) { >-+ memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr)); >-+ ribreq.prefixlen = res->prefixlen; >-+ } >-+ if (res->community.as != COMMUNITY_UNSET && >-+ res->community.type != COMMUNITY_UNSET) >-+ memcpy(&ribreq.community, &res->community, >-+ sizeof(res->community)); >-+ memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor)); >-+ ribreq.aid = res->aid; >-+ ribreq.flags = res->flags; >-+ show_mrt.arg = &ribreq; >-+ if (!(res->flags & F_CTL_DETAIL)) >-+ show_rib_summary_head(); >-+ mrt_parse(res->mrtfd, &show_mrt, 1); >-+ exit(0); >- case SHOW_RIB_MEM: >- imsg_compose(ibuf, IMSG_CTL_SHOW_RIB_MEM, 0, 0, -1, NULL, 0); >- break; >-@@ -237,12 +296,14 @@ main(int argc, char *argv[]) >- errx(1, "action==FIB"); >- break; >- case FIB_COUPLE: >-- imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0); >-+ imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, res->rtableid, 0, -1, >-+ NULL, 0); >- printf("couple request sent.\n"); >- done = 1; >- break; >- case FIB_DECOUPLE: >-- imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0); >-+ imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, res->rtableid, 0, -1, >-+ NULL, 0); >- printf("decouple request sent.\n"); >- done = 1; >- break; >-@@ -290,12 +351,40 @@ main(int argc, char *argv[]) >- break; >- case NETWORK_SHOW: >- bzero(&ribreq, sizeof(ribreq)); >-- ribreq.af = res->af; >-+ ribreq.aid = res->aid; >- strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib)); >- imsg_compose(ibuf, IMSG_CTL_SHOW_NETWORK, 0, 0, -1, >- &ribreq, sizeof(ribreq)); >- show_network_head(); >- break; >-+ case NETWORK_MRT: >-+ bzero(&ribreq, sizeof(ribreq)); >-+ if (res->as.type != AS_NONE) >-+ memcpy(&ribreq.as, &res->as, sizeof(res->as)); >-+ if (res->addr.aid) { >-+ memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr)); >-+ ribreq.prefixlen = res->prefixlen; >-+ } >-+ if (res->community.as != COMMUNITY_UNSET && >-+ res->community.type != COMMUNITY_UNSET) >-+ memcpy(&ribreq.community, &res->community, >-+ sizeof(res->community)); >-+ memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor)); >-+ ribreq.aid = res->aid; >-+ ribreq.flags = res->flags; >-+ net_mrt.arg = &ribreq; >-+ mrt_parse(res->mrtfd, &net_mrt, 1); >-+ done = 1; >-+ break; >-+ case LOG_VERBOSE: >-+ verbose = 1; >-+ /* FALLTHROUGH */ >-+ case LOG_BRIEF: >-+ imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1, >-+ &verbose, sizeof(verbose)); >-+ printf("logging request sent.\n"); >-+ done = 1; >-+ break; >- } >- >- while (ibuf->w.queued) >-@@ -304,13 +393,13 @@ main(int argc, char *argv[]) >- >- while (!done) { >- if ((n = imsg_read(ibuf)) == -1) >-- errx(1, "imsg_read error"); >-+ err(1, "imsg_read error"); >- if (n == 0) >- errx(1, "pipe closed"); >- >- while (!done) { >- if ((n = imsg_get(ibuf, &imsg)) == -1) >-- errx(1, "imsg_get error"); >-+ err(1, "imsg_get error"); >- if (n == 0) >- break; >- >-@@ -329,6 +418,8 @@ main(int argc, char *argv[]) >- done = show_summary_terse_msg(&imsg, nodescr); >- break; >- case SHOW_FIB: >-+ case SHOW_FIB_TABLES: >-+ case NETWORK_SHOW: >- done = show_fib_msg(&imsg); >- break; >- case SHOW_NEXTHOP: >-@@ -356,9 +447,6 @@ main(int argc, char *argv[]) >- case SHOW_RIB_MEM: >- done = show_rib_memory_msg(&imsg); >- break; >-- case NETWORK_SHOW: >-- done = show_fib_msg(&imsg); >-- break; >- case NEIGHBOR: >- case NEIGHBOR_UP: >- case NEIGHBOR_DOWN: >-@@ -373,6 +461,10 @@ main(int argc, char *argv[]) >- case NETWORK_REMOVE: >- case NETWORK_FLUSH: >- case IRRFILTER: >-+ case LOG_VERBOSE: >-+ case LOG_BRIEF: >-+ case SHOW_MRT: >-+ case NETWORK_MRT: >- break; >- } >- imsg_free(&imsg); >-@@ -398,8 +490,8 @@ fmt_peer(const char *descr, const struct >- } >- >- ip = log_addr(remote_addr); >-- if (masklen != -1 && ((remote_addr->af == AF_INET && masklen != 32) || >-- (remote_addr->af == AF_INET6 && masklen != 128))) { >-+ if (masklen != -1 && ((remote_addr->aid == AID_INET && masklen != 32) || >-+ (remote_addr->aid == AID_INET6 && masklen != 128))) { >- if (asprintf(&p, "%s/%u", ip, masklen) == -1) >- err(1, NULL); >- } else { >-@@ -430,7 +522,7 @@ show_summary_msg(struct imsg *imsg, int >- p->conf.remote_masklen, nodescr); >- if (strlen(s) >= 20) >- s[20] = 0; >-- printf("%-20s %8s %10llu %10llu %5u %-8s ", >-+ printf("%-20s %8s %10" PRIu64 " %10" PRIu64 " %5u %-8s ", >- s, log_as(p->conf.remote_as), >- p->stats.msg_rcvd_open + p->stats.msg_rcvd_notification + >- p->stats.msg_rcvd_update + p->stats.msg_rcvd_keepalive + >-@@ -492,8 +584,8 @@ show_neighbor_terse(struct imsg *imsg) >- switch (imsg->hdr.type) { >- case IMSG_CTL_SHOW_NEIGHBOR: >- p = imsg->data; >-- printf("%llu %llu %llu %llu %llu %llu %llu " >-- "%llu %llu %llu %u %u %llu %llu %llu %llu\n", >-+ printf("%" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " " >-+ "%" PRIu64 " %" PRIu64 " %" PRIu64 " %u %u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", >- p->stats.msg_sent_open, p->stats.msg_rcvd_open, >- p->stats.msg_sent_notification, >- p->stats.msg_rcvd_notification, >-@@ -521,13 +613,15 @@ show_neighbor_msg(struct imsg *imsg, enu >- struct ctl_timer *t; >- struct in_addr ina; >- char buf[NI_MAXHOST], pbuf[NI_MAXSERV], *s; >-+ int hascapamp = 0; >-+ u_int8_t i; >- >- switch (imsg->hdr.type) { >- case IMSG_CTL_SHOW_NEIGHBOR: >- p = imsg->data; >-- if ((p->conf.remote_addr.af == AF_INET && >-+ if ((p->conf.remote_addr.aid == AID_INET && >- p->conf.remote_masklen != 32) || >-- (p->conf.remote_addr.af == AF_INET6 && >-+ (p->conf.remote_addr.aid == AID_INET6 && >- p->conf.remote_masklen != 128)) { >- if (asprintf(&s, "%s/%u", >- log_addr(&p->conf.remote_addr), >-@@ -549,9 +643,20 @@ show_neighbor_msg(struct imsg *imsg, enu >- printf(", Template"); >- if (p->conf.cloned) >- printf(", Cloned"); >-+ if (p->conf.passive) >-+ printf(", Passive"); >-+ if (p->conf.ebgp && p->conf.distance > 1) >-+ printf(", Multihop (%u)", (int)p->conf.distance); >- printf("\n"); >- if (p->conf.descr[0]) >- printf(" Description: %s\n", p->conf.descr); >-+ if (p->conf.max_prefix) { >-+ printf(" Max-prefix: %u", p->conf.max_prefix); >-+ if (p->conf.max_prefix_restart) >-+ printf(" (restart %u)", >-+ p->conf.max_prefix_restart); >-+ printf("\n"); >-+ } >- printf(" BGP version 4, remote router-id %s\n", >- inet_ntoa(ina)); >- printf(" BGP state = %s", statenames[p->state]); >-@@ -563,22 +668,24 @@ show_neighbor_msg(struct imsg *imsg, enu >- printf(" Last read %s, holdtime %us, keepalive interval %us\n", >- fmt_timeframe(p->stats.last_read), >- p->holdtime, p->holdtime/3); >-- if (p->capa.peer.mp_v4 || p->capa.peer.mp_v6 || >-- p->capa.peer.refresh || p->capa.peer.restart || >-- p->capa.peer.as4byte) { >-+ for (i = 0; i < AID_MAX; i++) >-+ if (p->capa.peer.mp[i]) >-+ hascapamp = 1; >-+ if (hascapamp || p->capa.peer.refresh || >-+ p->capa.peer.grestart.restart || p->capa.peer.as4byte) { >- printf(" Neighbor capabilities:\n"); >-- if (p->capa.peer.mp_v4) { >-- printf(" Multiprotocol extensions: IPv4"); >-- print_neighbor_capa_mp_safi(p->capa.peer.mp_v4); >-- } >-- if (p->capa.peer.mp_v6) { >-- printf(" Multiprotocol extensions: IPv6"); >-- print_neighbor_capa_mp_safi(p->capa.peer.mp_v6); >-+ if (hascapamp) { >-+ printf(" Multiprotocol extensions: "); >-+ print_neighbor_capa_mp(p); >-+ printf("\n"); >- } >- if (p->capa.peer.refresh) >- printf(" Route Refresh\n"); >-- if (p->capa.peer.restart) >-- printf(" Graceful Restart\n"); >-+ if (p->capa.peer.grestart.restart) { >-+ printf(" Graceful Restart"); >-+ print_neighbor_capa_restart(p); >-+ printf("\n"); >-+ } >- if (p->capa.peer.as4byte) >- printf(" 4-byte AS numbers\n"); >- } >-@@ -633,20 +740,38 @@ show_neighbor_msg(struct imsg *imsg, enu >- } >- >- void >--print_neighbor_capa_mp_safi(u_int8_t safi) >-+print_neighbor_capa_mp(struct peer *p) >- { >-- switch (safi) { >-- case SAFI_UNICAST: >-- printf(" Unicast"); >-- break; >-- case SAFI_MULTICAST: >-- printf(" Multicast"); >-- break; >-- default: >-- printf(" unknown (%u)", safi); >-- break; >-- } >-- printf("\n"); >-+ int comma; >-+ u_int8_t i; >-+ >-+ for (i = 0, comma = 0; i < AID_MAX; i++) >-+ if (p->capa.peer.mp[i]) { >-+ printf("%s%s", comma ? ", " : "", aid2str(i)); >-+ comma = 1; >-+ } >-+} >-+ >-+void >-+print_neighbor_capa_restart(struct peer *p) >-+{ >-+ int comma; >-+ u_int8_t i; >-+ >-+ if (p->capa.peer.grestart.timeout) >-+ printf(": Timeout: %d, ", p->capa.peer.grestart.timeout); >-+ for (i = 0, comma = 0; i < AID_MAX; i++) >-+ if (p->capa.peer.grestart.flags[i] & CAPA_GR_PRESENT) { >-+ if (!comma && >-+ p->capa.peer.grestart.flags[i] & CAPA_GR_RESTART) >-+ printf("restarted, "); >-+ if (comma) >-+ printf(", "); >-+ printf("%s", aid2str(i)); >-+ if (p->capa.peer.grestart.flags[i] & CAPA_GR_FORWARD) >-+ printf(" (preserved)"); >-+ comma = 1; >-+ } >- } >- >- void >-@@ -654,17 +779,17 @@ print_neighbor_msgstats(struct peer *p) >- { >- printf(" Message statistics:\n"); >- printf(" %-15s %-10s %-10s\n", "", "Sent", "Received"); >-- printf(" %-15s %10llu %10llu\n", "Opens", >-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Opens", >- p->stats.msg_sent_open, p->stats.msg_rcvd_open); >-- printf(" %-15s %10llu %10llu\n", "Notifications", >-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Notifications", >- p->stats.msg_sent_notification, p->stats.msg_rcvd_notification); >-- printf(" %-15s %10llu %10llu\n", "Updates", >-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Updates", >- p->stats.msg_sent_update, p->stats.msg_rcvd_update); >-- printf(" %-15s %10llu %10llu\n", "Keepalives", >-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Keepalives", >- p->stats.msg_sent_keepalive, p->stats.msg_rcvd_keepalive); >-- printf(" %-15s %10llu %10llu\n", "Route Refresh", >-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Route Refresh", >- p->stats.msg_sent_rrefresh, p->stats.msg_rcvd_rrefresh); >-- printf(" %-15s %10llu %10llu\n\n", "Total", >-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n\n", "Total", >- p->stats.msg_sent_open + p->stats.msg_sent_notification + >- p->stats.msg_sent_update + p->stats.msg_sent_keepalive + >- p->stats.msg_sent_rrefresh, >-@@ -673,14 +798,16 @@ print_neighbor_msgstats(struct peer *p) >- p->stats.msg_rcvd_rrefresh); >- printf(" Update statistics:\n"); >- printf(" %-15s %-10s %-10s\n", "", "Sent", "Received"); >-- printf(" %-15s %10llu %10llu\n", "Updates", >-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Updates", >- p->stats.prefix_sent_update, p->stats.prefix_rcvd_update); >-- printf(" %-15s %10llu %10llu\n", "Withdraws", >-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Withdraws", >- p->stats.prefix_sent_withdraw, p->stats.prefix_rcvd_withdraw); >-+ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "End-of-Rib", >-+ p->stats.prefix_sent_eor, p->stats.prefix_rcvd_eor); >- } >- >- void >--print_timer(const char *name, timer_t d) >-+print_timer(const char *name, time_t d) >- { >- printf(" %-20s ", name); >- >-@@ -745,6 +872,12 @@ show_fib_head(void) >- } >- >- void >-+show_fib_tables_head(void) >-+{ >-+ printf("%-5s %-20s %-8s\n", "Table", "Description", "State"); >-+} >-+ >-+void >- show_network_head(void) >- { >- printf("flags: S = Static\n"); >-@@ -788,56 +921,44 @@ show_fib_flags(u_int16_t flags) >- int >- show_fib_msg(struct imsg *imsg) >- { >-- struct kroute *k; >-- struct kroute6 *k6; >-+ struct kroute_full *kf; >-+ struct ktable *kt; >- char *p; >- >- switch (imsg->hdr.type) { >- case IMSG_CTL_KROUTE: >- case IMSG_CTL_SHOW_NETWORK: >-- if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute)) >-+ if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(*kf)) >- errx(1, "wrong imsg len"); >-- k = imsg->data; >-+ kf = imsg->data; >- >-- show_fib_flags(k->flags); >-+ show_fib_flags(kf->flags); >- >-- if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), k->prefixlen) == >-- -1) >-+ if (asprintf(&p, "%s/%u", log_addr(&kf->prefix), >-+ kf->prefixlen) == -1) >- err(1, NULL); >-- printf("%4i %-20s ", k->priority, p); >-+ printf("%4i %-20s ", kf->priority, p); >- free(p); >- >-- if (k->nexthop.s_addr) >-- printf("%s", inet_ntoa(k->nexthop)); >-- else if (k->flags & F_CONNECTED) >-- printf("link#%u", k->ifindex); >-+ if (kf->flags & F_CONNECTED) >-+ printf("link#%u", kf->ifindex); >-+ else >-+ printf("%s", log_addr(&kf->nexthop)); >- printf("\n"); >- >- break; >-- case IMSG_CTL_KROUTE6: >-- case IMSG_CTL_SHOW_NETWORK6: >-- if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute6)) >-+ case IMSG_CTL_SHOW_FIB_TABLES: >-+ if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(*kt)) >- errx(1, "wrong imsg len"); >-- k6 = imsg->data; >-- >-- show_fib_flags(k6->flags); >-+ kt = imsg->data; >- >-- if (asprintf(&p, "%s/%u", log_in6addr(&k6->prefix), >-- k6->prefixlen) == -1) >-- err(1, NULL); >-- printf("%4i %-20s ", k6->priority, p); >-- free(p); >-- >-- if (!IN6_IS_ADDR_UNSPECIFIED(&k6->nexthop)) >-- printf("%s", log_in6addr(&k6->nexthop)); >-- else if (k6->flags & F_CONNECTED) >-- printf("link#%u", k6->ifindex); >-- printf("\n"); >-+ printf("%5i %-20s %-8s%s\n", kt->rtableid, kt->descr, >-+ kt->fib_sync ? "coupled" : "decoupled", >-+ kt->fib_sync != kt->fib_conf ? "*" : ""); >- >- break; >- case IMSG_CTL_END: >- return (1); >-- break; >- default: >- break; >- } >-@@ -848,35 +969,70 @@ show_fib_msg(struct imsg *imsg) >- void >- show_nexthop_head(void) >- { >-- printf("%-20s %-10s\n", "Nexthop", "State"); >-+ printf("Flags: * = nexthop valid\n"); >-+ printf("\n %-15s %-19s%-4s %-15s %-20s\n", "Nexthop", "Route", >-+ "Prio", "Gateway", "Iface"); >- } >- >- int >- show_nexthop_msg(struct imsg *imsg) >- { >- struct ctl_show_nexthop *p; >-- int ifms_type; >-+ struct kroute *k; >-+ struct kroute6 *k6; >-+ char *s; >- >- switch (imsg->hdr.type) { >- case IMSG_CTL_SHOW_NEXTHOP: >- p = imsg->data; >-- printf("%-20s %-10s", log_addr(&p->addr), >-- p->valid ? "valid" : "invalid"); >-+ printf("%s %-15s ", p->valid ? "*" : " ", log_addr(&p->addr)); >-+ if (!p->krvalid) { >-+ printf("\n"); >-+ return (0); >-+ } >-+ switch (p->addr.aid) { >-+ case AID_INET: >-+ k = &p->kr.kr4; >-+ if (asprintf(&s, "%s/%u", inet_ntoa(k->prefix), >-+ k->prefixlen) == -1) >-+ err(1, NULL); >-+ printf("%-20s", s); >-+ free(s); >-+ printf("%3i %-15s ", k->priority, >-+ k->flags & F_CONNECTED ? "connected" : >-+ inet_ntoa(k->nexthop)); >-+ break; >-+ case AID_INET6: >-+ k6 = &p->kr.kr6; >-+ if (asprintf(&s, "%s/%u", log_in6addr(&k6->prefix), >-+ k6->prefixlen) == -1) >-+ err(1, NULL); >-+ printf("%-20s", s); >-+ free(s); >-+ printf("%3i %-15s ", k6->priority, >-+ k6->flags & F_CONNECTED ? "connected" : >-+ log_in6addr(&k6->nexthop)); >-+ break; >-+ default: >-+ printf("unknown address family\n"); >-+ return (0); >-+ } >- if (p->kif.ifname[0]) { >-- printf("%-8s", p->kif.ifname); >-- if (p->kif.flags & IFF_UP) { >-- printf("UP"); >-- ifms_type = ift2ifm(p->kif.media_type); >-- if (ifms_type != 0) >-- printf(", %s, %s", >-- get_media_descr(ifms_type), >-- get_linkstate(ifms_type, >-- p->kif.link_state)); >-- if (p->kif.baudrate) { >-- printf(", "); >-- print_baudrate(p->kif.baudrate); >-- } >-- } >-+ char *s1; >-+ if (p->kif.baudrate) { >-+ if (asprintf(&s1, ", %s", >-+ get_baudrate(p->kif.baudrate, >-+ "bps")) == -1) >-+ err(1, NULL); >-+ } else if (asprintf(&s1, ", %s", get_linkstate( >-+ p->kif.media_type, p->kif.link_state)) == -1) >-+ err(1, NULL); >-+ if (asprintf(&s, "%s (%s%s)", p->kif.ifname, >-+ p->kif.flags & IFF_UP ? "UP" : "DOWN", s1) == -1) >-+ err(1, NULL); >-+ printf("%-15s", s); >-+ free(s1); >-+ free(s); >- } >- printf("\n"); >- break; >-@@ -898,9 +1054,8 @@ show_interface_head(void) >- "Link state"); >- } >- >--const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST; >--const struct ifmedia_status_description >-- ifm_status_descriptions[] = IFM_STATUS_DESCRIPTIONS; >-+const struct if_status_description >-+ if_status_descriptions[] = LINK_STATE_DESCRIPTIONS; >- const struct ifmedia_description >- ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; >- >-@@ -936,36 +1091,36 @@ get_media_descr(int media_type) >- const char * >- get_linkstate(int media_type, int link_state) >- { >-- const struct ifmedia_status_description *p; >-- int i; >-- >-- if (link_state == LINK_STATE_UNKNOWN) >-- return ("unknown"); >-- >-- for (i = 0; ifm_status_valid_list[i] != 0; i++) >-- for (p = ifm_status_descriptions; p->ifms_valid != 0; p++) { >-- if (p->ifms_type != media_type || >-- p->ifms_valid != ifm_status_valid_list[i]) >-- continue; >-- if (LINK_STATE_IS_UP(link_state)) >-- return (p->ifms_string[1]); >-- return (p->ifms_string[0]); >-- } >-+ const struct if_status_description *p; >-+ static char buf[8]; >- >-- return ("unknown link state"); >-+ for (p = if_status_descriptions; p->ifs_string != NULL; p++) { >-+ if (LINK_STATE_DESC_MATCH(p, media_type, link_state)) >-+ return (p->ifs_string); >-+ } >-+ snprintf(buf, sizeof(buf), "[#%d]", link_state); >-+ return (buf); >- } >- >--void >--print_baudrate(u_int64_t baudrate) >-+const char * >-+get_baudrate(u_int64_t baudrate, char *unit) >- { >-+ static char bbuf[16]; >-+ >- if (baudrate > IF_Gbps(1)) >-- printf("%llu GBit/s", baudrate / IF_Gbps(1)); >-+ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " G%s", >-+ baudrate / IF_Gbps(1), unit); >- else if (baudrate > IF_Mbps(1)) >-- printf("%llu MBit/s", baudrate / IF_Mbps(1)); >-+ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " M%s", >-+ baudrate / IF_Mbps(1), unit); >- else if (baudrate > IF_Kbps(1)) >-- printf("%llu KBit/s", baudrate / IF_Kbps(1)); >-+ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " K%s", >-+ baudrate / IF_Kbps(1), unit); >- else >-- printf("%llu Bit/s", baudrate); >-+ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " %s", >-+ baudrate, unit); >-+ >-+ return (bbuf); >- } >- >- int >-@@ -982,17 +1137,12 @@ show_interface_msg(struct imsg *imsg) >- printf("%-15s", k->flags & IFF_UP ? "UP" : ""); >- >- if ((ifms_type = ift2ifm(k->media_type)) != 0) >-- printf("%s, %s", get_media_descr(ifms_type), >-- get_linkstate(ifms_type, k->link_state)); >-- else if (k->link_state == LINK_STATE_UNKNOWN) >-- printf("unknown"); >-- else >-- printf("link state %u", k->link_state); >-+ printf("%s, ", get_media_descr(ifms_type)); >- >-- if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) { >-- printf(", "); >-- print_baudrate(k->baudrate); >-- } >-+ printf("%s", get_linkstate(k->media_type, k->link_state)); >-+ >-+ if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) >-+ printf(", %s", get_baudrate(k->baudrate, "Bit/s")); >- printf("\n"); >- break; >- case IMSG_CTL_END: >-@@ -1008,10 +1158,10 @@ show_interface_msg(struct imsg *imsg) >- void >- show_rib_summary_head(void) >- { >-- printf( >-- "flags: * = Valid, > = Selected, I = via IBGP, A = Announced\n"); >-+ printf("flags: * = Valid, > = Selected, I = via IBGP, A = Announced, " >-+ "S = Stale\n"); >- printf("origin: i = IGP, e = EGP, ? = Incomplete\n\n"); >-- printf("%-5s %-20s%-15s %5s %5s %s\n", "flags", "destination", >-+ printf("%-5s %-20s %-15s %5s %5s %s\n", "flags", "destination", >- "gateway", "lpref", "med", "aspath origin"); >- } >- >-@@ -1049,26 +1199,30 @@ print_flags(u_int8_t flags, int sum) >- char *p = flagstr; >- >- if (sum) { >-- if (flags & F_RIB_ANNOUNCE) >-+ if (flags & F_PREF_ANNOUNCE) >- *p++ = 'A'; >-- if (flags & F_RIB_INTERNAL) >-+ if (flags & F_PREF_INTERNAL) >- *p++ = 'I'; >-- if (flags & F_RIB_ELIGIBLE) >-+ if (flags & F_PREF_STALE) >-+ *p++ = 'S'; >-+ if (flags & F_PREF_ELIGIBLE) >- *p++ = '*'; >-- if (flags & F_RIB_ACTIVE) >-+ if (flags & F_PREF_ACTIVE) >- *p++ = '>'; >- *p = '\0'; >- printf("%-5s ", flagstr); >- } else { >-- if (flags & F_RIB_INTERNAL) >-+ if (flags & F_PREF_INTERNAL) >- printf("internal"); >- else >- printf("external"); >-- if (flags & F_RIB_ELIGIBLE) >-+ if (flags & F_PREF_STALE) >-+ printf(", stale"); >-+ if (flags & F_PREF_ELIGIBLE) >- printf(", valid"); >-- if (flags & F_RIB_ACTIVE) >-+ if (flags & F_PREF_ACTIVE) >- printf(", best"); >-- if (flags & F_RIB_ANNOUNCE) >-+ if (flags & F_PREF_ANNOUNCE) >- printf(", announced"); >- } >- } >-@@ -1077,27 +1231,14 @@ int >- show_rib_summary_msg(struct imsg *imsg) >- { >- struct ctl_show_rib rib; >-- char *aspath; >- u_char *asdata; >- >- switch (imsg->hdr.type) { >- case IMSG_CTL_SHOW_RIB: >- memcpy(&rib, imsg->data, sizeof(rib)); >-- >-- print_prefix(&rib.prefix, rib.prefixlen, rib.flags); >-- printf("%-15s ", log_addr(&rib.exit_nexthop)); >-- >-- printf(" %5u %5u ", rib.local_pref, rib.med); >-- >- asdata = imsg->data; >- asdata += sizeof(struct ctl_show_rib); >-- if (aspath_asprint(&aspath, asdata, rib.aspath_len) == -1) >-- err(1, NULL); >-- if (strlen(aspath) > 0) >-- printf("%s ", aspath); >-- free(aspath); >-- >-- printf("%s\n", print_origin(rib.origin, 1)); >-+ show_rib_brief(&rib, asdata); >- break; >- case IMSG_CTL_END: >- return (1); >-@@ -1112,108 +1253,21 @@ int >- show_rib_detail_msg(struct imsg *imsg, int nodescr) >- { >- struct ctl_show_rib rib; >-- struct in_addr id; >-- char *aspath, *s; >-- u_char *data; >-- u_int32_t as; >-- u_int16_t ilen, alen, ioff; >-- u_int8_t flags, type; >-- time_t now; >-+ u_char *asdata; >-+ u_int16_t ilen; >- >- switch (imsg->hdr.type) { >- case IMSG_CTL_SHOW_RIB: >- memcpy(&rib, imsg->data, sizeof(rib)); >-- >-- printf("\nBGP routing table entry for %s/%u\n", >-- log_addr(&rib.prefix), rib.prefixlen); >-- >-- data = imsg->data; >-- data += sizeof(struct ctl_show_rib); >-- if (aspath_asprint(&aspath, data, rib.aspath_len) == -1) >-- err(1, NULL); >-- if (strlen(aspath) > 0) >-- printf(" %s\n", aspath); >-- free(aspath); >-- >-- s = fmt_peer(rib.descr, &rib.remote_addr, -1, nodescr); >-- printf(" Nexthop %s ", log_addr(&rib.exit_nexthop)); >-- printf("(via %s) from %s (", log_addr(&rib.true_nexthop), s); >-- free(s); >-- id.s_addr = htonl(rib.remote_id); >-- printf("%s)\n", inet_ntoa(id)); >-- >-- printf(" Origin %s, metric %u, localpref %u, ", >-- print_origin(rib.origin, 0), rib.med, rib.local_pref); >-- print_flags(rib.flags, 0); >-- >-- now = time(NULL); >-- if (now > rib.lastchange) >-- now -= rib.lastchange; >-- else >-- now = 0; >-- >-- printf("\n Last update: %s ago\n", >-- fmt_timeframe_core(now)); >-+ asdata = imsg->data; >-+ asdata += sizeof(struct ctl_show_rib); >-+ show_rib_detail(&rib, asdata, nodescr); >- break; >- case IMSG_CTL_SHOW_RIB_ATTR: >- ilen = imsg->hdr.len - IMSG_HEADER_SIZE; >- if (ilen < 3) >- errx(1, "bad IMSG_CTL_SHOW_RIB_ATTR received"); >-- data = imsg->data; >-- flags = data[0]; >-- type = data[1]; >-- >-- /* get the attribute length */ >-- if (flags & ATTR_EXTLEN) { >-- if (ilen < 4) >-- errx(1, "bad IMSG_CTL_SHOW_RIB_ATTR received"); >-- memcpy(&alen, data+2, sizeof(u_int16_t)); >-- alen = ntohs(alen); >-- data += 4; >-- ilen -= 4; >-- } else { >-- alen = data[2]; >-- data += 3; >-- ilen -= 3; >-- } >-- /* bad imsg len how can that happen!? */ >-- if (alen != ilen) >-- errx(1, "bad IMSG_CTL_SHOW_RIB_ATTR received"); >-- >-- switch (type) { >-- case ATTR_COMMUNITIES: >-- printf(" Communities: "); >-- show_community(data, alen); >-- printf("\n"); >-- break; >-- case ATTR_AGGREGATOR: >-- memcpy(&as, data, sizeof(as)); >-- memcpy(&id, data + sizeof(as), sizeof(id)); >-- printf(" Aggregator: %s [%s]\n", >-- log_as(htonl(as)), inet_ntoa(id)); >-- break; >-- case ATTR_ORIGINATOR_ID: >-- memcpy(&id, data, sizeof(id)); >-- printf(" Originator Id: %s\n", inet_ntoa(id)); >-- break; >-- case ATTR_CLUSTER_LIST: >-- printf(" Cluster ID List:"); >-- for (ioff = 0; ioff + sizeof(id) <= ilen; >-- ioff += sizeof(id)) { >-- memcpy(&id, data + ioff, sizeof(id)); >-- printf(" %s", inet_ntoa(id)); >-- } >-- printf("\n"); >-- break; >-- case ATTR_EXT_COMMUNITIES: >-- printf(" Ext. communities: "); >-- show_ext_community(data, alen); >-- printf("\n"); >-- break; >-- default: >-- /* ignore unknown attributes */ >-- break; >-- } >-+ show_attr(imsg->data, ilen); >- break; >- case IMSG_CTL_END: >- printf("\n"); >-@@ -1225,67 +1279,128 @@ show_rib_detail_msg(struct imsg *imsg, i >- return (0); >- } >- >--char * >--fmt_mem(int64_t num) >-+void >-+show_rib_brief(struct ctl_show_rib *r, u_char *asdata) >- { >-- static char buf[16]; >-+ char *aspath; >- >-- if (fmt_scaled(num, buf) == -1) >-- snprintf(buf, sizeof(buf), "%lldB", (long long)num); >-+ print_prefix(&r->prefix, r->prefixlen, r->flags); >-+ printf(" %-15s ", log_addr(&r->exit_nexthop)); >-+ printf(" %5u %5u ", r->local_pref, r->med); >- >-- return (buf); >-+ if (aspath_asprint(&aspath, asdata, r->aspath_len) == -1) >-+ err(1, NULL); >-+ if (strlen(aspath) > 0) >-+ printf("%s ", aspath); >-+ free(aspath); >-+ >-+ printf("%s\n", print_origin(r->origin, 1)); >- } >- >--int >--show_rib_memory_msg(struct imsg *imsg) >-+void >-+show_rib_detail(struct ctl_show_rib *r, u_char *asdata, int nodescr) >- { >-- struct rde_memstats stats; >-+ struct in_addr id; >-+ char *aspath, *s; >-+ time_t now; >- >-- switch (imsg->hdr.type) { >-- case IMSG_CTL_SHOW_RIB_MEM: >-- memcpy(&stats, imsg->data, sizeof(stats)); >-- printf("RDE memory statistics\n"); >-- printf("%10lld IPv4 network entries using %s of memory\n", >-- (long long)stats.pt4_cnt, fmt_mem(stats.pt4_cnt * >-- sizeof(struct pt_entry4))); >-- if (stats.pt6_cnt != 0) >-- printf("%10lld IPv6 network entries using " >-- "%s of memory\n", (long long)stats.pt6_cnt, >-- fmt_mem(stats.pt6_cnt * sizeof(struct pt_entry6))); >-- printf("%10lld rib entries using %s of memory\n", >-- (long long)stats.rib_cnt, fmt_mem(stats.rib_cnt * >-- sizeof(struct rib_entry))); >-- printf("%10lld prefix entries using %s of memory\n", >-- (long long)stats.prefix_cnt, fmt_mem(stats.prefix_cnt * >-- sizeof(struct prefix))); >-- printf("%10lld BGP path attribute entries using %s of memory\n", >-- (long long)stats.path_cnt, fmt_mem(stats.path_cnt * >-- sizeof(struct rde_aspath))); >-- printf("%10lld BGP AS-PATH attribute entries using " >-- "%s of memory,\n\t and holding %lld references\n", >-- (long long)stats.aspath_cnt, fmt_mem(stats.aspath_size), >-- (long long)stats.aspath_refs); >-- printf("%10lld BGP attributes entries using %s of memory\n", >-- (long long)stats.attr_cnt, fmt_mem(stats.attr_cnt * >-- sizeof(struct attr))); >-- printf("\t and holding %lld references\n", >-- (long long)stats.attr_refs); >-- printf("%10lld BGP attributes using %s of memory\n", >-- (long long)stats.attr_dcnt, fmt_mem(stats.attr_data)); >-- printf("RIB using %s of memory\n", fmt_mem( >-- stats.pt4_cnt * sizeof(struct pt_entry4) + >-- stats.pt6_cnt * sizeof(struct pt_entry6) + >-- stats.prefix_cnt * sizeof(struct prefix) + >-- stats.rib_cnt * sizeof(struct rib_entry) + >-- stats.path_cnt * sizeof(struct rde_aspath) + >-- stats.aspath_size + stats.attr_cnt * sizeof(struct attr) + >-- stats.attr_data)); >-+ printf("\nBGP routing table entry for %s/%u\n", >-+ log_addr(&r->prefix), r->prefixlen); >-+ >-+ if (aspath_asprint(&aspath, asdata, r->aspath_len) == -1) >-+ err(1, NULL); >-+ if (strlen(aspath) > 0) >-+ printf(" %s\n", aspath); >-+ free(aspath); >-+ >-+ s = fmt_peer(r->descr, &r->remote_addr, -1, nodescr); >-+ printf(" Nexthop %s ", log_addr(&r->exit_nexthop)); >-+ printf("(via %s) from %s (", log_addr(&r->true_nexthop), s); >-+ free(s); >-+ id.s_addr = htonl(r->remote_id); >-+ printf("%s)\n", inet_ntoa(id)); >-+ >-+ printf(" Origin %s, metric %u, localpref %u, weight %u, ", >-+ print_origin(r->origin, 0), r->med, r->local_pref, r->weight); >-+ print_flags(r->flags, 0); >-+ >-+ now = time(NULL); >-+ if (now > r->lastchange) >-+ now -= r->lastchange; >-+ else >-+ now = 0; >-+ >-+ printf("\n Last update: %s ago\n", fmt_timeframe_core(now)); >-+} >-+ >-+void >-+show_attr(void *b, u_int16_t len) >-+{ >-+ char *data = b; >-+ struct in_addr id; >-+ u_int32_t as; >-+ u_int16_t alen, ioff; >-+ u_int8_t flags, type; >-+ >-+ data = b; >-+ if (len < 3) >-+ errx(1, "show_attr: too short bgp attr"); >-+ >-+ flags = data[0]; >-+ type = data[1]; >-+ >-+ /* get the attribute length */ >-+ if (flags & ATTR_EXTLEN) { >-+ if (len < 4) >-+ errx(1, "show_attr: too short bgp attr"); >-+ memcpy(&alen, data+2, sizeof(u_int16_t)); >-+ alen = ntohs(alen); >-+ data += 4; >-+ len -= 4; >-+ } else { >-+ alen = data[2]; >-+ data += 3; >-+ len -= 3; >-+ } >-+ >-+ /* bad imsg len how can that happen!? */ >-+ if (alen > len) >-+ errx(1, "show_attr: bad length"); >-+ >-+ switch (type) { >-+ case ATTR_COMMUNITIES: >-+ printf(" Communities: "); >-+ show_community(data, alen); >-+ printf("\n"); >-+ break; >-+ case ATTR_AGGREGATOR: >-+ memcpy(&as, data, sizeof(as)); >-+ memcpy(&id, data + sizeof(as), sizeof(id)); >-+ printf(" Aggregator: %s [%s]\n", >-+ log_as(ntohl(as)), inet_ntoa(id)); >-+ break; >-+ case ATTR_ORIGINATOR_ID: >-+ memcpy(&id, data, sizeof(id)); >-+ printf(" Originator Id: %s\n", inet_ntoa(id)); >-+ break; >-+ case ATTR_CLUSTER_LIST: >-+ printf(" Cluster ID List:"); >-+ for (ioff = 0; ioff + sizeof(id) <= alen; >-+ ioff += sizeof(id)) { >-+ memcpy(&id, data + ioff, sizeof(id)); >-+ printf(" %s", inet_ntoa(id)); >-+ } >-+ printf("\n"); >-+ break; >-+ case ATTR_EXT_COMMUNITIES: >-+ printf(" Ext. communities: "); >-+ show_ext_community(data, alen); >-+ printf("\n"); >- break; >- default: >-+ /* ignore unknown attributes */ >- break; >- } >-- >-- return (1); >- } >- >- void >-@@ -1328,30 +1443,6 @@ show_community(u_char *data, u_int16_t l >- } >- } >- >--const char * >--get_ext_subtype(u_int8_t type) >--{ >-- static char etype[6]; >-- >-- switch (type) { >-- case EXT_COMMUNITY_ROUTE_TGT: >-- return "rt"; /* route target */ >-- case EXT_CUMMUNITY_ROUTE_ORIG: >-- return "soo"; /* source of origin */ >-- case EXT_COMMUNITY_OSPF_DOM_ID: >-- return "odi"; /* ospf domain id */ >-- case EXT_COMMUNITY_OSPF_RTR_TYPE: >-- return "ort"; /* ospf route type */ >-- case EXT_COMMUNITY_OSPF_RTR_ID: >-- return "ori"; /* ospf router id */ >-- case EXT_COMMUNITY_BGP_COLLECT: >-- return "bdc"; /* bgp data collection */ >-- default: >-- snprintf(etype, sizeof(etype), "[%i]", (int)type); >-- return etype; >-- } >--} >-- >- void >- show_ext_community(u_char *data, u_int16_t len) >- { >-@@ -1372,34 +1463,101 @@ show_ext_community(u_char *data, u_int16 >- case EXT_COMMUNITY_TWO_AS: >- memcpy(&as2, data + i + 2, sizeof(as2)); >- memcpy(&u32, data + i + 4, sizeof(u32)); >-- printf("%s %hu:%u", get_ext_subtype(subtype), as2, u32); >-+ printf("%s %s:%u", log_ext_subtype(subtype), >-+ log_as(ntohs(as2)), ntohl(u32)); >- break; >- case EXT_COMMUNITY_IPV4: >- memcpy(&ip, data + i + 2, sizeof(ip)); >- memcpy(&u16, data + i + 6, sizeof(u16)); >-- printf("%s %s:%hu", get_ext_subtype(subtype), >-- inet_ntoa(ip), u16); >-+ printf("%s %s:%hu", log_ext_subtype(subtype), >-+ inet_ntoa(ip), ntohs(u16)); >- break; >- case EXT_COMMUNITY_FOUR_AS: >- memcpy(&as4, data + i + 2, sizeof(as4)); >- memcpy(&u16, data + i + 6, sizeof(u16)); >-- printf("%s %s:%hu", get_ext_subtype(subtype), >-- log_as(as4), u16); >-+ printf("%s %s:%hu", log_ext_subtype(subtype), >-+ log_as(ntohl(as4)), ntohs(u16)); >- break; >- case EXT_COMMUNITY_OPAQUE: >- memcpy(&ext, data + i, sizeof(ext)); >- ext = betoh64(ext) & 0xffffffffffffLL; >-- printf("%s 0x%llx", get_ext_subtype(subtype), ext); >-+ printf("%s 0x%" PRIx64, log_ext_subtype(subtype), ext); >- break; >- default: >- memcpy(&ext, data + i, sizeof(ext)); >-- printf("0x%llx", betoh64(ext)); >-+ printf("0x%" PRIx64, betoh64(ext)); >- } >- if (i + 8 < len) >- printf(", "); >- } >- } >- >-+char * >-+fmt_mem(int64_t num) >-+{ >-+ static char buf[16]; >-+ >-+ if (fmt_scaled(num, buf) == -1) >-+ snprintf(buf, sizeof(buf), "%lldB", (long long)num); >-+ >-+ return (buf); >-+} >-+ >-+size_t pt_sizes[AID_MAX] = AID_PTSIZE; >-+ >-+int >-+show_rib_memory_msg(struct imsg *imsg) >-+{ >-+ struct rde_memstats stats; >-+ size_t pts = 0; >-+ int i; >-+ >-+ switch (imsg->hdr.type) { >-+ case IMSG_CTL_SHOW_RIB_MEM: >-+ memcpy(&stats, imsg->data, sizeof(stats)); >-+ printf("RDE memory statistics\n"); >-+ for (i = 0; i < AID_MAX; i++) { >-+ if (stats.pt_cnt[i] == 0) >-+ continue; >-+ pts += stats.pt_cnt[i] * pt_sizes[i]; >-+ printf("%10lld %s network entries using %s of memory\n", >-+ (long long)stats.pt_cnt[i], aid_vals[i].name, >-+ fmt_mem(stats.pt_cnt[i] * pt_sizes[i])); >-+ } >-+ printf("%10lld rib entries using %s of memory\n", >-+ (long long)stats.rib_cnt, fmt_mem(stats.rib_cnt * >-+ sizeof(struct rib_entry))); >-+ printf("%10lld prefix entries using %s of memory\n", >-+ (long long)stats.prefix_cnt, fmt_mem(stats.prefix_cnt * >-+ sizeof(struct prefix))); >-+ printf("%10lld BGP path attribute entries using %s of memory\n", >-+ (long long)stats.path_cnt, fmt_mem(stats.path_cnt * >-+ sizeof(struct rde_aspath))); >-+ printf("%10lld BGP AS-PATH attribute entries using " >-+ "%s of memory,\n\t and holding %lld references\n", >-+ (long long)stats.aspath_cnt, fmt_mem(stats.aspath_size), >-+ (long long)stats.aspath_refs); >-+ printf("%10lld BGP attributes entries using %s of memory\n", >-+ (long long)stats.attr_cnt, fmt_mem(stats.attr_cnt * >-+ sizeof(struct attr))); >-+ printf("\t and holding %lld references\n", >-+ (long long)stats.attr_refs); >-+ printf("%10lld BGP attributes using %s of memory\n", >-+ (long long)stats.attr_dcnt, fmt_mem(stats.attr_data)); >-+ printf("RIB using %s of memory\n", fmt_mem(pts + >-+ stats.prefix_cnt * sizeof(struct prefix) + >-+ stats.rib_cnt * sizeof(struct rib_entry) + >-+ stats.path_cnt * sizeof(struct rde_aspath) + >-+ stats.aspath_size + stats.attr_cnt * sizeof(struct attr) + >-+ stats.attr_data)); >-+ break; >-+ default: >-+ break; >-+ } >-+ >-+ return (1); >-+} >-+ >- void >- send_filterset(struct imsgbuf *i, struct filter_set_head *set) >- { >-@@ -1469,6 +1627,183 @@ show_result(struct imsg *imsg) >- return (1); >- } >- >-+void >-+show_mrt_dump(struct mrt_rib *mr, struct mrt_peer *mp, void *arg) >-+{ >-+ struct ctl_show_rib ctl; >-+ struct ctl_show_rib_request *req = arg; >-+ struct mrt_rib_entry *mre; >-+ u_int16_t i, j; >-+ >-+ for (i = 0; i < mr->nentries; i++) { >-+ mre = &mr->entries[i]; >-+ bzero(&ctl, sizeof(ctl)); >-+ mrt_to_bgpd_addr(&mr->prefix, &ctl.prefix); >-+ ctl.prefixlen = mr->prefixlen; >-+ ctl.lastchange = mre->originated; >-+ mrt_to_bgpd_addr(&mre->nexthop, &ctl.true_nexthop); >-+ mrt_to_bgpd_addr(&mre->nexthop, &ctl.exit_nexthop); >-+ ctl.origin = mre->origin; >-+ ctl.local_pref = mre->local_pref; >-+ ctl.med = mre->med; >-+ /* weight is not part of the mrt dump so it can't be set */ >-+ ctl.aspath_len = mre->aspath_len; >-+ >-+ if (mre->peer_idx < mp->npeers) { >-+ mrt_to_bgpd_addr(&mp->peers[mre->peer_idx].addr, >-+ &ctl.remote_addr); >-+ ctl.remote_id = mp->peers[mre->peer_idx].bgp_id; >-+ } >-+ >-+ /* filter by neighbor */ >-+ if (req->neighbor.addr.aid != AID_UNSPEC && >-+ memcmp(&req->neighbor.addr, &ctl.remote_addr, >-+ sizeof(ctl.remote_addr)) != 0) >-+ continue; >-+ /* filter by AF */ >-+ if (req->aid && req->aid != ctl.prefix.aid) >-+ return; >-+ /* filter by prefix */ >-+ if (req->prefix.aid != AID_UNSPEC) { >-+ if (!prefix_compare(&req->prefix, &ctl.prefix, >-+ req->prefixlen)) { >-+ if (req->flags & F_LONGER) { >-+ if (req->prefixlen > ctl.prefixlen) >-+ return; >-+ } else if (req->prefixlen != ctl.prefixlen) >-+ return; >-+ } else >-+ return; >-+ } >-+ /* filter by AS */ >-+ if (req->as.type != AS_NONE && >-+ !aspath_match(mre->aspath, mre->aspath_len, >-+ req->as.type, req->as.as)) >-+ continue; >-+ >-+ if (req->flags & F_CTL_DETAIL) { >-+ show_rib_detail(&ctl, mre->aspath, 1); >-+ for (j = 0; j < mre->nattrs; j++) >-+ show_attr(mre->attrs[j].attr, >-+ mre->attrs[j].attr_len); >-+ } else >-+ show_rib_brief(&ctl, mre->aspath); >-+ } >-+} >-+ >-+void >-+network_mrt_dump(struct mrt_rib *mr, struct mrt_peer *mp, void *arg) >-+{ >-+ struct ctl_show_rib ctl; >-+ struct network_config net; >-+ struct ctl_show_rib_request *req = arg; >-+ struct mrt_rib_entry *mre; >-+ struct ibuf *msg; >-+ u_int16_t i, j; >-+ >-+ for (i = 0; i < mr->nentries; i++) { >-+ mre = &mr->entries[i]; >-+ bzero(&ctl, sizeof(ctl)); >-+ mrt_to_bgpd_addr(&mr->prefix, &ctl.prefix); >-+ ctl.prefixlen = mr->prefixlen; >-+ ctl.lastchange = mre->originated; >-+ mrt_to_bgpd_addr(&mre->nexthop, &ctl.true_nexthop); >-+ mrt_to_bgpd_addr(&mre->nexthop, &ctl.exit_nexthop); >-+ ctl.origin = mre->origin; >-+ ctl.local_pref = mre->local_pref; >-+ ctl.med = mre->med; >-+ ctl.aspath_len = mre->aspath_len; >-+ >-+ if (mre->peer_idx < mp->npeers) { >-+ mrt_to_bgpd_addr(&mp->peers[mre->peer_idx].addr, >-+ &ctl.remote_addr); >-+ ctl.remote_id = mp->peers[mre->peer_idx].bgp_id; >-+ } >-+ >-+ /* filter by neighbor */ >-+ if (req->neighbor.addr.aid != AID_UNSPEC && >-+ memcmp(&req->neighbor.addr, &ctl.remote_addr, >-+ sizeof(ctl.remote_addr)) != 0) >-+ continue; >-+ /* filter by AF */ >-+ if (req->aid && req->aid != ctl.prefix.aid) >-+ return; >-+ /* filter by prefix */ >-+ if (req->prefix.aid != AID_UNSPEC) { >-+ if (!prefix_compare(&req->prefix, &ctl.prefix, >-+ req->prefixlen)) { >-+ if (req->flags & F_LONGER) { >-+ if (req->prefixlen > ctl.prefixlen) >-+ return; >-+ } else if (req->prefixlen != ctl.prefixlen) >-+ return; >-+ } else >-+ return; >-+ } >-+ /* filter by AS */ >-+ if (req->as.type != AS_NONE && >-+ !aspath_match(mre->aspath, mre->aspath_len, >-+ req->as.type, req->as.as)) >-+ continue; >-+ >-+ bzero(&net, sizeof(net)); >-+ memcpy(&net.prefix, &ctl.prefix, sizeof(net.prefix)); >-+ net.prefixlen = ctl.prefixlen; >-+ net.type = NETWORK_MRTCLONE; >-+ /* XXX rtableid */ >-+ >-+ imsg_compose(ibuf, IMSG_NETWORK_ADD, 0, 0, -1, >-+ &net, sizeof(net)); >-+ if ((msg = imsg_create(ibuf, IMSG_NETWORK_ASPATH, >-+ 0, 0, sizeof(ctl) + mre->aspath_len)) == NULL) >-+ errx(1, "imsg_create failure"); >-+ if (imsg_add(msg, &ctl, sizeof(ctl)) == -1 || >-+ imsg_add(msg, mre->aspath, mre->aspath_len) == -1) >-+ errx(1, "imsg_add failure"); >-+ imsg_close(ibuf, msg); >-+ for (j = 0; j < mre->nattrs; j++) >-+ imsg_compose(ibuf, IMSG_NETWORK_ATTR, 0, 0, -1, >-+ mre->attrs[j].attr, mre->attrs[j].attr_len); >-+ imsg_compose(ibuf, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0); >-+ >-+ while (ibuf->w.queued) { >-+ if (msgbuf_write(&ibuf->w) < 0) >-+ err(1, "write error"); >-+ } >-+ } >-+} >-+ >-+void >-+show_mrt_state(struct mrt_bgp_state *ms, void *arg) >-+{ >-+ printf("show_mrt_state\n"); >-+} >-+ >-+void >-+show_mrt_msg(struct mrt_bgp_msg *mm, void *arg) >-+{ >-+ printf("show_mrt_msg\n"); >-+} >-+ >-+void >-+mrt_to_bgpd_addr(union mrt_addr *ma, struct bgpd_addr *ba) >-+{ >-+ switch (ma->sa.sa_family) { >-+ case AF_INET: >-+ case AF_INET6: >-+ sa2addr(&ma->sa, ba); >-+ break; >-+ case AF_VPNv4: >-+ bzero(ba, sizeof(*ba)); >-+ ba->aid = AID_VPN_IPv4; >-+ ba->vpn4.rd = ma->svpn4.sv_rd; >-+ ba->vpn4.addr.s_addr = ma->svpn4.sv_addr.s_addr; >-+ memcpy(ba->vpn4.labelstack, ma->svpn4.sv_label, >-+ sizeof(ba->vpn4.labelstack)); >-+ break; >-+ } >-+} >-+ >- /* following functions are necessary for imsg framework */ >- void >- log_warnx(const char *emsg, ...) >-@@ -1495,3 +1830,9 @@ fatal(const char *emsg) >- { >- err(1, emsg); >- } >-+ >-+void >-+fatalx(const char *emsg) >-+{ >-+ errx(1, emsg); >-+} > >Property changes on: files/patch-bgpctl_bgpctl.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpctl_irr_asset.c >=================================================================== >--- files/patch-bgpctl_irr_asset.c (revision 500577) >+++ files/patch-bgpctl_irr_asset.c (nonexistent) >@@ -1,14 +0,0 @@ >-Index: bgpctl/irr_asset.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_asset.c,v >-retrieving revision 1.1.1.2 >-retrieving revision 1.1.1.3 >-diff -u -p -r1.1.1.2 -r1.1.1.3 >---- bgpctl/irr_asset.c 9 Jul 2009 16:49:55 -0000 1.1.1.2 >-+++ bgpctl/irr_asset.c 13 Oct 2012 18:22:52 -0000 1.1.1.3 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: irr_asset.c,v 1.8 2009/04/14 21:10:54 jj Exp $ */ >-+/* $OpenBSD: irr_asset.c,v 1.7 2007/03/31 12:46:55 henning Exp $ */ >- >- /* >- * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> > >Property changes on: files/patch-bgpctl_irr_asset.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpctl_irr_output.c >=================================================================== >--- files/patch-bgpctl_irr_output.c (revision 500577) >+++ files/patch-bgpctl_irr_output.c (nonexistent) >@@ -1,14 +0,0 @@ >-Index: bgpctl/irr_output.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_output.c,v >-retrieving revision 1.1.1.1 >-retrieving revision 1.1.1.2 >-diff -u -p -r1.1.1.1 -r1.1.1.2 >---- bgpctl/irr_output.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 >-+++ bgpctl/irr_output.c 13 Oct 2012 18:22:52 -0000 1.1.1.2 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: irr_output.c,v 1.13 2007/03/05 17:28:21 henning Exp $ */ >-+/* $OpenBSD: irr_output.c,v 1.12 2007/03/05 15:02:05 henning Exp $ */ >- >- /* >- * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> > >Property changes on: files/patch-bgpctl_irr_output.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpctl_irr_parser.c >=================================================================== >--- files/patch-bgpctl_irr_parser.c (revision 500577) >+++ files/patch-bgpctl_irr_parser.c (nonexistent) >@@ -1,48 +0,0 @@ >-Index: bgpctl/irr_parser.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_parser.c,v >-retrieving revision 1.1.1.5 >-retrieving revision 1.5 >-diff -u -p -r1.1.1.5 -r1.5 >---- bgpctl/irr_parser.c 14 Feb 2010 20:20:14 -0000 1.1.1.5 >-+++ bgpctl/irr_parser.c 13 Oct 2012 18:35:56 -0000 1.5 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: irr_parser.c,v 1.8 2007/03/05 22:34:08 henning Exp $ */ >-+/* $OpenBSD: irr_parser.c,v 1.9 2009/09/08 15:40:25 claudio Exp $ */ >- >- /* >- * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> >-@@ -81,6 +81,7 @@ parse_response(FILE *f, enum qtype qtype >- return (-1); >- break; >- case QTYPE_ROUTE: >-+ case QTYPE_ROUTE6: >- if ((n = parse_route(key, val)) == -1) >- return (-1); >- break; >-@@ -281,7 +282,7 @@ parse_policy(char *key, char *val) >- !isdigit(tok[2])) >- errx(1, "peering spec \"%s\": format " >- "error, AS expected", tok); >-- pi->peer_as = strtonum(tok + 2, 1, USHRT_MAX, >-+ pi->peer_as = strtonum(tok + 2, 1, UINT_MAX, >- &errstr); >- if (errstr) >- errx(1, "peering spec \"%s\": format " >-@@ -407,11 +408,13 @@ parse_asset(char *key, char *val) >- int >- parse_route(char *key, char *val) >- { >-- if (strcmp(key, "route")) /* ignore everything else */ >-+ if (strcmp(key, "route") && strcmp(key, "route6")) >-+ /* ignore everything else */ >- return (0); >- >-- /* route is single-value, but seen trailing , in the wild */ >-- if (strlen(val) > 0 && val[strlen(val) - 1] == ',') >-+ /* route is single-value, but seen trailing , and \r in the wild */ >-+ if (strlen(val) > 0 && (val[strlen(val) - 1] == ',' || >-+ val[strlen(val) - 1] == '\r')) >- val[strlen(val) - 1] = '\0'; >- >- return (prefixset_addmember(val)); > >Property changes on: files/patch-bgpctl_irr_parser.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpctl_irr_prefix.c >=================================================================== >--- files/patch-bgpctl_irr_prefix.c (revision 500577) >+++ files/patch-bgpctl_irr_prefix.c (nonexistent) >@@ -1,157 +0,0 @@ >-Index: bgpctl/irr_prefix.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_prefix.c,v >-retrieving revision 1.1.1.5 >-retrieving revision 1.1.1.8 >-diff -u -p -r1.1.1.5 -r1.1.1.8 >---- bgpctl/irr_prefix.c 14 Feb 2010 20:20:14 -0000 1.1.1.5 >-+++ bgpctl/irr_prefix.c 13 Oct 2012 18:22:52 -0000 1.1.1.8 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: irr_prefix.c,v 1.15 2007/05/27 18:54:25 henning Exp $ */ >-+/* $OpenBSD: irr_prefix.c,v 1.17 2009/09/08 16:11:36 sthen Exp $ */ >- >- /* >- * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> >-@@ -29,6 +29,7 @@ >- #include <arpa/inet.h> >- >- #include "irrfilter.h" >-+#include "bgpd.h" >- >- void prefixset_aggregate(struct prefix_set *); >- int prefix_aggregate(struct irr_prefix *, const struct irr_prefix *); >-@@ -63,7 +64,11 @@ prefixset_get(char *as) >- fflush(stdout); >- } >- curpfxs = pfxs; >-- if (whois(as, QTYPE_ROUTE) == -1) >-+ if ((irrflags & F_IPV4) && whois(as, QTYPE_ROUTE) == -1) >-+ errx(1, "whois error, prefixset_get %s", as); >-+ if ((irrflags & F_IPV6) && whois(as, QTYPE_ROUTE6) == -1) >-+ errx(1, "whois error, prefixset_get %s", as); >-+ if (whois(as, QTYPE_ROUTE6) == -1) >- errx(1, "whois error, prefixset_get %s", as); >- curpfxs = NULL; >- if (irrverbose >= 3) >-@@ -80,9 +85,11 @@ prefixset_addmember(char *s) >- void *p; >- u_int i; >- struct irr_prefix *pfx; >-- int len; >-+ int len, ret; >-+ char *slash; >-+ const char *errstr; >- >-- if (strchr(s, '/') == NULL) { >-+ if ((slash = strchr(s, '/')) == NULL) { >- fprintf(stderr, "%s: prefix %s does not have the len " >- "specified, ignoring\n", curpfxs->as, s); >- return (0); >-@@ -92,17 +99,26 @@ prefixset_addmember(char *s) >- err(1, "prefixset_addmember calloc"); >- >- if ((len = inet_net_pton(AF_INET, s, &pfx->addr.in, >-- sizeof(pfx->addr.in))) == -1) { >-- if (errno == ENOENT) { >-- fprintf(stderr, "%s: prefix \"%s\": parse error\n", >-+ sizeof(pfx->addr.in))) != -1) { >-+ pfx->af = AF_INET; >-+ } else { >-+ len = strtonum(slash + 1, 0, 128, &errstr); >-+ if (errstr) >-+ errx(1, "prefixset_addmember %s prefix %s: prefixlen " >-+ "is %s", curpfxs->as, s, errstr); >-+ *slash = '\0'; >-+ >-+ if ((ret = inet_pton(AF_INET6, s, &pfx->addr.in6)) == -1) >-+ err(1, "prefixset_addmember %s prefix \"%s\"", >- curpfxs->as, s); >-+ else if (ret == 0) { >-+ fprintf(stderr, "prefixset_addmember %s prefix \"%s\": " >-+ "No matching address family found", curpfxs->as, s); >-+ free(pfx); >- return (0); >-- } else >-- err(1, "prefixset_addmember %s inet_net_pton \"%s\"", >-- curpfxs->as, s); >-+ } >-+ pfx->af = AF_INET6; >- } >-- >-- pfx->af = AF_INET; >- pfx->len = pfx->maxlen = len; >- >- /* yes, there are dupes... e. g. from multiple sources */ >-@@ -175,24 +191,47 @@ prefixset_aggregate(struct prefix_set *p >- int >- prefix_aggregate(struct irr_prefix *a, const struct irr_prefix *b) >- { >-- in_addr_t mask; >-+ in_addr_t mask; >-+ struct in6_addr ma; >-+ struct in6_addr mb; >- >- if (a->len == 0) >- return (1); >- >-- mask = htonl(0xffffffff << (32 - a->len)); >-+ if (a->af != b->af) >-+ /* We cannot aggregate addresses of different families. */ >-+ return (0); >- >-- if ((a->addr.in.s_addr & mask) == (b->addr.in.s_addr & mask)) >-- return (1); >-+ if (a->af == AF_INET) { >-+ mask = htonl(prefixlen2mask(a->len)); >-+ if ((a->addr.in.s_addr & mask) == (b->addr.in.s_addr & mask)) >-+ return (1); >-+ } else if (a->af == AF_INET6) { >-+ inet6applymask(&ma, &a->addr.in6, a->len); >-+ inet6applymask(&mb, &b->addr.in6, a->len); >-+ if (IN6_ARE_ADDR_EQUAL(&ma, &mb)) >-+ return (1); >-+ } >- >-- /* see wether we can fold them in one */ >-+ /* see whether we can fold them in one */ >- if (a->len == b->len && a->len > 1) { >-- mask = htonl(0xffffffff << (32 - (a->len - 1))); >-- if ((a->addr.in.s_addr & mask) == >-- (b->addr.in.s_addr & mask)) { >-- a->len--; >-- a->addr.in.s_addr &= mask; >-- return (1); >-+ if (a->af == AF_INET) { >-+ mask = htonl(prefixlen2mask(a->len - 1)); >-+ if ((a->addr.in.s_addr & mask) == >-+ (b->addr.in.s_addr & mask)) { >-+ a->len--; >-+ a->addr.in.s_addr &= mask; >-+ return (1); >-+ } >-+ } else if (a->af == AF_INET6) { >-+ inet6applymask(&ma, &a->addr.in6, a->len - 1); >-+ inet6applymask(&mb, &b->addr.in6, a->len - 1); >-+ >-+ if (IN6_ARE_ADDR_EQUAL(&ma, &mb)) { >-+ a->len--; >-+ memcpy(&a->addr.in6, &ma, sizeof(ma)); >-+ return (1); >-+ } >- } >- } >- >-@@ -219,6 +258,13 @@ irr_prefix_cmp(const void *a, const void >- if (ntohl(pa->addr.in.s_addr) > >- ntohl(pb->addr.in.s_addr)) >- return (1); >-+ } else if (pa->af == AF_INET6) { >-+ for (r = 0; r < 16; r++) { >-+ if (pa->addr.in6.s6_addr[r] < pb->addr.in6.s6_addr[r]) >-+ return (-1); >-+ if (pa->addr.in6.s6_addr[r] > pb->addr.in6.s6_addr[r]) >-+ return (1); >-+ } >- } else >- errx(1, "irr_prefix_cmp unknown af %u", pa->af); >- > >Property changes on: files/patch-bgpctl_irr_prefix.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpctl_irrfilter.c >=================================================================== >--- files/patch-bgpctl_irrfilter.c (revision 500577) >+++ files/patch-bgpctl_irrfilter.c (nonexistent) >@@ -1,24 +0,0 @@ >-Index: bgpctl/irrfilter.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irrfilter.c,v >-retrieving revision 1.1.1.1 >-retrieving revision 1.3 >-diff -u -p -r1.1.1.1 -r1.3 >---- bgpctl/irrfilter.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 >-+++ bgpctl/irrfilter.c 13 Oct 2012 18:35:56 -0000 1.3 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: irrfilter.c,v 1.4 2007/05/28 23:31:53 henning Exp $ */ >-+/* $OpenBSD: irrfilter.c,v 1.3 2007/03/06 16:45:34 henning Exp $ */ >- >- /* >- * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> >-@@ -15,6 +15,9 @@ >- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT >- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >- */ >-+#if defined(__FreeBSD__) /* compat */ >-+#include "openbsd-compat.h" >-+#endif /* defined(__FreeBSD__) */ >- >- #include <sys/types.h> >- #include <sys/param.h> > >Property changes on: files/patch-bgpctl_irrfilter.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpctl_irrfilter.h >=================================================================== >--- files/patch-bgpctl_irrfilter.h (revision 500577) >+++ files/patch-bgpctl_irrfilter.h (nonexistent) >@@ -1,59 +0,0 @@ >-Index: bgpctl/irrfilter.h >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irrfilter.h,v >-retrieving revision 1.1.1.5 >-retrieving revision 1.4 >-diff -u -p -r1.1.1.5 -r1.4 >---- bgpctl/irrfilter.h 14 Feb 2010 20:20:14 -0000 1.1.1.5 >-+++ bgpctl/irrfilter.h 13 Oct 2012 18:35:56 -0000 1.4 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: irrfilter.h,v 1.7 2007/03/06 16:45:34 henning Exp $ */ >-+/* $OpenBSD: irrfilter.h,v 1.8 2009/09/08 15:40:25 claudio Exp $ */ >- >- /* >- * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> >-@@ -16,11 +16,17 @@ >- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >- */ >- >-+#if defined(__FreeBSD__) /* compat */ >-+#include "openbsd-compat.h" >-+#endif /* defined(__FreeBSD__) */ >-+ >- #include <sys/queue.h> >- #include <sys/tree.h> >- #include <netinet/in.h> >- >- #define F_IMPORTONLY 0x01 /* skip export: items */ >-+#define F_IPV4 0x02 /* use IPv4 items */ >-+#define F_IPV6 0x04 /* use IPv6 items */ >- >- int irrflags; >- int irrverbose; >-@@ -37,7 +43,7 @@ struct policy_item { >- char *action; >- char *filter; >- enum pdir dir; >-- u_int16_t peer_as; >-+ u_int32_t peer_as; >- }; >- >- TAILQ_HEAD(policy_head, policy_item); >-@@ -55,7 +61,8 @@ enum qtype { >- QTYPE_NONE, >- QTYPE_OWNAS, >- QTYPE_ASSET, >-- QTYPE_ROUTE >-+ QTYPE_ROUTE, >-+ QTYPE_ROUTE6 >- }; >- >- struct as_set { >-@@ -72,6 +79,7 @@ struct as_set { >- struct irr_prefix { >- union { >- struct in_addr in; >-+ struct in6_addr in6; >- } addr; >- sa_family_t af; >- u_int8_t len; > >Property changes on: files/patch-bgpctl_irrfilter.h >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpctl_mrtparser.c >=================================================================== >--- files/patch-bgpctl_mrtparser.c (revision 500577) >+++ files/patch-bgpctl_mrtparser.c (nonexistent) >@@ -1,977 +0,0 @@ >-Index: bgpctl/mrtparser.c >-=================================================================== >-RCS file: bgpctl/mrtparser.c >-diff -N bgpctl/mrtparser.c >---- /dev/null 1 Jan 1970 00:00:00 -0000 >-+++ bgpctl/mrtparser.c 13 Oct 2012 18:22:53 -0000 1.1.1.1 >-@@ -0,0 +1,970 @@ >-+/* $OpenBSD: mrtparser.c,v 1.2 2012/03/06 07:52:32 claudio Exp $ */ >-+/* >-+ * Copyright (c) 2011 Claudio Jeker <claudio@openbsd.org> >-+ * >-+ * Permission to use, copy, modify, and distribute this software for any >-+ * purpose with or without fee is hereby granted, provided that the above >-+ * copyright notice and this permission notice appear in all copies. >-+ * >-+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES >-+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF >-+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR >-+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES >-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN >-+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF >-+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >-+ */ >-+#include <sys/types.h> >-+#include <sys/socket.h> >-+#include <netinet/in.h> >-+#include <err.h> >-+#include <errno.h> >-+#include <limits.h> >-+#include <stdlib.h> >-+#include <stdio.h> >-+#include <string.h> >-+#include <unistd.h> >-+ >-+#include "mrt.h" >-+#include "mrtparser.h" >-+ >-+void *mrt_read_msg(int, struct mrt_hdr *); >-+size_t mrt_read_buf(int, void *, size_t); >-+ >-+struct mrt_peer *mrt_parse_v2_peer(struct mrt_hdr *, void *); >-+struct mrt_rib *mrt_parse_v2_rib(struct mrt_hdr *, void *); >-+int mrt_parse_dump(struct mrt_hdr *, void *, struct mrt_peer **, >-+ struct mrt_rib **); >-+int mrt_parse_dump_mp(struct mrt_hdr *, void *, struct mrt_peer **, >-+ struct mrt_rib **); >-+int mrt_extract_attr(struct mrt_rib_entry *, u_char *, int, sa_family_t, >-+ int); >-+ >-+void mrt_free_peers(struct mrt_peer *); >-+void mrt_free_rib(struct mrt_rib *); >-+void mrt_free_bgp_state(struct mrt_bgp_state *); >-+void mrt_free_bgp_msg(struct mrt_bgp_msg *); >-+ >-+u_char *mrt_aspath_inflate(void *, u_int16_t, u_int16_t *); >-+int mrt_extract_addr(void *, u_int, union mrt_addr *, sa_family_t); >-+ >-+void * >-+mrt_read_msg(int fd, struct mrt_hdr *hdr) >-+{ >-+ void *buf; >-+ >-+ bzero(hdr, sizeof(*hdr)); >-+ if (mrt_read_buf(fd, hdr, sizeof(*hdr)) != sizeof(*hdr)) >-+ return (NULL); >-+ >-+ if ((buf = malloc(ntohl(hdr->length))) == NULL) >-+ err(1, "malloc(%d)", hdr->length); >-+ >-+ if (mrt_read_buf(fd, buf, ntohl(hdr->length)) != ntohl(hdr->length)) { >-+ free(buf); >-+ return (NULL); >-+ } >-+ return (buf); >-+} >-+ >-+size_t >-+mrt_read_buf(int fd, void *buf, size_t len) >-+{ >-+ char *b = buf; >-+ ssize_t n; >-+ >-+ while (len > 0) { >-+ if ((n = read(fd, b, len)) == -1) { >-+ if (errno == EINTR) >-+ continue; >-+ err(1, "read"); >-+ } >-+ if (n == 0) >-+ break; >-+ b += n; >-+ len -= n; >-+ } >-+ >-+ return (b - (char *)buf); >-+} >-+ >-+void >-+mrt_parse(int fd, struct mrt_parser *p, int verbose) >-+{ >-+ struct mrt_hdr h; >-+ struct mrt_peer *pctx = NULL; >-+ struct mrt_rib *r; >-+ void *msg; >-+ >-+ while ((msg = mrt_read_msg(fd, &h))) { >-+ switch (ntohs(h.type)) { >-+ case MSG_NULL: >-+ case MSG_START: >-+ case MSG_DIE: >-+ case MSG_I_AM_DEAD: >-+ case MSG_PEER_DOWN: >-+ case MSG_PROTOCOL_BGP: >-+ case MSG_PROTOCOL_IDRP: >-+ case MSG_PROTOCOL_BGP4PLUS: >-+ case MSG_PROTOCOL_BGP4PLUS1: >-+ if (verbose) >-+ printf("deprecated MRT type %d\n", >-+ ntohs(h.type)); >-+ break; >-+ case MSG_PROTOCOL_RIP: >-+ case MSG_PROTOCOL_RIPNG: >-+ case MSG_PROTOCOL_OSPF: >-+ case MSG_PROTOCOL_ISIS_ET: >-+ case MSG_PROTOCOL_ISIS: >-+ case MSG_PROTOCOL_OSPFV3_ET: >-+ case MSG_PROTOCOL_OSPFV3: >-+ if (verbose) >-+ printf("unsuported MRT type %d\n", >-+ ntohs(h.type)); >-+ break; >-+ case MSG_TABLE_DUMP: >-+ switch (ntohs(h.subtype)) { >-+ case MRT_DUMP_AFI_IP: >-+ case MRT_DUMP_AFI_IPv6: >-+ if (p->dump == NULL) >-+ break; >-+ if (mrt_parse_dump(&h, msg, &pctx, &r) == 0) { >-+ p->dump(r, pctx, p->arg); >-+ mrt_free_rib(r); >-+ } >-+ break; >-+ default: >-+ if (verbose) >-+ printf("unknown AFI %d in table dump\n", >-+ ntohs(h.subtype)); >-+ break; >-+ } >-+ break; >-+ case MSG_TABLE_DUMP_V2: >-+ switch (ntohs(h.subtype)) { >-+ case MRT_DUMP_V2_PEER_INDEX_TABLE: >-+ if (p->dump == NULL) >-+ break; >-+ if (pctx) >-+ mrt_free_peers(pctx); >-+ pctx = mrt_parse_v2_peer(&h, msg); >-+ break; >-+ case MRT_DUMP_V2_RIB_IPV4_UNICAST: >-+ case MRT_DUMP_V2_RIB_IPV4_MULTICAST: >-+ case MRT_DUMP_V2_RIB_IPV6_UNICAST: >-+ case MRT_DUMP_V2_RIB_IPV6_MULTICAST: >-+ case MRT_DUMP_V2_RIB_GENERIC: >-+ if (p->dump == NULL) >-+ break; >-+ r = mrt_parse_v2_rib(&h, msg); >-+ if (r) { >-+ p->dump(r, pctx, p->arg); >-+ mrt_free_rib(r); >-+ } >-+ break; >-+ default: >-+ if (verbose) >-+ printf("unhandled BGP4MP subtype %d\n", >-+ ntohs(h.subtype)); >-+ break; >-+ } >-+ break; >-+ case MSG_PROTOCOL_BGP4MP_ET: >-+ /* currently just ignore the microsec field */ >-+ msg = (char *)msg + sizeof(u_int32_t); >-+ h.length -= sizeof(u_int32_t); >-+ /* FALLTHROUGH */ >-+ case MSG_PROTOCOL_BGP4MP: >-+ switch (ntohs(h.subtype)) { >-+ case BGP4MP_STATE_CHANGE: >-+ case BGP4MP_STATE_CHANGE_AS4: >-+ /* XXX p->state(s, p->arg); */ >-+ errx(1, "BGP4MP subtype not yet implemented"); >-+ break; >-+ case BGP4MP_MESSAGE: >-+ case BGP4MP_MESSAGE_AS4: >-+ case BGP4MP_MESSAGE_LOCAL: >-+ case BGP4MP_MESSAGE_AS4_LOCAL: >-+ /* XXX p->message(m, p->arg); */ >-+ errx(1, "BGP4MP subtype not yet implemented"); >-+ break; >-+ case BGP4MP_ENTRY: >-+ if (p->dump == NULL) >-+ break; >-+ if (mrt_parse_dump_mp(&h, msg, &pctx, &r) == >-+ 0) { >-+ p->dump(r, pctx, p->arg); >-+ mrt_free_rib(r); >-+ } >-+ break; >-+ default: >-+ if (verbose) >-+ printf("unhandled BGP4MP subtype %d\n", >-+ ntohs(h.subtype)); >-+ break; >-+ } >-+ break; >-+ default: >-+ if (verbose) >-+ printf("unknown MRT type %d\n", ntohs(h.type)); >-+ break; >-+ } >-+ free(msg); >-+ } >-+ if (pctx) >-+ mrt_free_peers(pctx); >-+} >-+ >-+struct mrt_peer * >-+mrt_parse_v2_peer(struct mrt_hdr *hdr, void *msg) >-+{ >-+ struct mrt_peer_entry *peers; >-+ struct mrt_peer *p; >-+ u_int8_t *b = msg; >-+ u_int32_t bid, as4; >-+ u_int16_t cnt, i, as2; >-+ u_int len = ntohl(hdr->length); >-+ >-+ if (len < 8) /* min msg size */ >-+ return NULL; >-+ >-+ p = calloc(1, sizeof(struct mrt_peer)); >-+ if (p == NULL) >-+ err(1, "calloc"); >-+ >-+ /* collector bgp id */ >-+ memcpy(&bid, b, sizeof(bid)); >-+ b += sizeof(bid); >-+ len -= sizeof(bid); >-+ p->bgp_id = ntohl(bid); >-+ >-+ /* view name length */ >-+ memcpy(&cnt, b, sizeof(cnt)); >-+ b += sizeof(cnt); >-+ len -= sizeof(cnt); >-+ cnt = ntohs(cnt); >-+ >-+ /* view name */ >-+ if (cnt > len) >-+ goto fail; >-+ if (cnt != 0) { >-+ if ((p->view = malloc(cnt + 1)) == NULL) >-+ err(1, "malloc"); >-+ memcpy(p->view, b, cnt); >-+ p->view[cnt] = 0; >-+ } else >-+ if ((p->view = strdup("")) == NULL) >-+ err(1, "strdup"); >-+ b += cnt; >-+ len -= cnt; >-+ >-+ /* peer_count */ >-+ if (len < sizeof(cnt)) >-+ goto fail; >-+ memcpy(&cnt, b, sizeof(cnt)); >-+ b += sizeof(cnt); >-+ len -= sizeof(cnt); >-+ cnt = ntohs(cnt); >-+ >-+ /* peer entries */ >-+ if ((peers = calloc(cnt, sizeof(struct mrt_peer_entry))) == NULL) >-+ err(1, "calloc"); >-+ for (i = 0; i < cnt; i++) { >-+ u_int8_t type; >-+ >-+ if (len < sizeof(u_int8_t) + sizeof(u_int32_t)) >-+ goto fail; >-+ type = *b++; >-+ len -= 1; >-+ memcpy(&bid, b, sizeof(bid)); >-+ b += sizeof(bid); >-+ len -= sizeof(bid); >-+ peers[i].bgp_id = ntohl(bid); >-+ >-+ if (type & MRT_DUMP_V2_PEER_BIT_I) { >-+ if (mrt_extract_addr(b, len, &peers[i].addr, >-+ AF_INET6) == -1) >-+ goto fail; >-+ b += sizeof(struct in6_addr); >-+ len -= sizeof(struct in6_addr); >-+ } else { >-+ if (mrt_extract_addr(b, len, &peers[i].addr, >-+ AF_INET) == -1) >-+ goto fail; >-+ b += sizeof(struct in_addr); >-+ len -= sizeof(struct in_addr); >-+ } >-+ >-+ if (type & MRT_DUMP_V2_PEER_BIT_A) { >-+ memcpy(&as4, b, sizeof(as4)); >-+ b += sizeof(as4); >-+ len -= sizeof(as4); >-+ as4 = ntohl(as4); >-+ } else { >-+ memcpy(&as2, b, sizeof(as2)); >-+ b += sizeof(as2); >-+ len -= sizeof(as2); >-+ as4 = ntohs(as2); >-+ } >-+ peers[i].asnum = as4; >-+ } >-+ p->peers = peers; >-+ p->npeers = cnt; >-+ return (p); >-+fail: >-+ mrt_free_peers(p); >-+ return (NULL); >-+} >-+ >-+struct mrt_rib * >-+mrt_parse_v2_rib(struct mrt_hdr *hdr, void *msg) >-+{ >-+ struct mrt_rib_entry *entries; >-+ struct mrt_rib *r; >-+ u_int8_t *b = msg; >-+ u_int len = ntohl(hdr->length); >-+ u_int32_t snum; >-+ u_int16_t cnt, i; >-+ u_int8_t plen; >-+ >-+ if (len < sizeof(snum) + 1) >-+ return NULL; >-+ >-+ r = calloc(1, sizeof(struct mrt_rib)); >-+ if (r == NULL) >-+ err(1, "calloc"); >-+ >-+ /* seq_num */ >-+ memcpy(&snum, b, sizeof(snum)); >-+ b += sizeof(snum); >-+ len -= sizeof(snum); >-+ r->seqnum = ntohl(snum); >-+ >-+ switch (ntohs(hdr->subtype)) { >-+ case MRT_DUMP_V2_RIB_IPV4_UNICAST: >-+ case MRT_DUMP_V2_RIB_IPV4_MULTICAST: >-+ plen = *b++; >-+ len -= 1; >-+ if (len < MRT_PREFIX_LEN(plen)) >-+ goto fail; >-+ r->prefix.sin.sin_family = AF_INET; >-+ r->prefix.sin.sin_len = sizeof(struct sockaddr_in); >-+ memcpy(&r->prefix.sin.sin_addr, b, MRT_PREFIX_LEN(plen)); >-+ b += MRT_PREFIX_LEN(plen); >-+ len -= MRT_PREFIX_LEN(plen); >-+ r->prefixlen = plen; >-+ break; >-+ case MRT_DUMP_V2_RIB_IPV6_UNICAST: >-+ case MRT_DUMP_V2_RIB_IPV6_MULTICAST: >-+ plen = *b++; >-+ len -= 1; >-+ if (len < MRT_PREFIX_LEN(plen)) >-+ goto fail; >-+ r->prefix.sin6.sin6_family = AF_INET6; >-+ r->prefix.sin6.sin6_len = sizeof(struct sockaddr_in6); >-+ memcpy(&r->prefix.sin6.sin6_addr, b, MRT_PREFIX_LEN(plen)); >-+ b += MRT_PREFIX_LEN(plen); >-+ len -= MRT_PREFIX_LEN(plen); >-+ r->prefixlen = plen; >-+ break; >-+ case MRT_DUMP_V2_RIB_GENERIC: >-+ /* XXX unhandled */ >-+ errx(1, "MRT_DUMP_V2_RIB_GENERIC subtype not yet implemented"); >-+ goto fail; >-+ } >-+ >-+ /* entries count */ >-+ if (len < sizeof(cnt)) >-+ goto fail; >-+ memcpy(&cnt, b, sizeof(cnt)); >-+ b += sizeof(cnt); >-+ len -= sizeof(cnt); >-+ cnt = ntohs(cnt); >-+ r->nentries = cnt; >-+ >-+ /* entries */ >-+ if ((entries = calloc(cnt, sizeof(struct mrt_rib_entry))) == NULL) >-+ err(1, "calloc"); >-+ for (i = 0; i < cnt; i++) { >-+ u_int32_t otm; >-+ u_int16_t pix, alen; >-+ if (len < 2 * sizeof(u_int16_t) + sizeof(u_int32_t)) >-+ goto fail; >-+ /* peer index */ >-+ memcpy(&pix, b, sizeof(pix)); >-+ b += sizeof(pix); >-+ len -= sizeof(pix); >-+ entries[i].peer_idx = ntohs(pix); >-+ >-+ /* originated */ >-+ memcpy(&otm, b, sizeof(otm)); >-+ b += sizeof(otm); >-+ len -= sizeof(otm); >-+ entries[i].originated = ntohl(otm); >-+ >-+ /* attr_len */ >-+ memcpy(&alen, b, sizeof(alen)); >-+ b += sizeof(alen); >-+ len -= sizeof(alen); >-+ alen = ntohs(alen); >-+ >-+ /* attr */ >-+ if (len < alen) >-+ goto fail; >-+ if (mrt_extract_attr(&entries[i], b, alen, >-+ r->prefix.sa.sa_family, 1) == -1) >-+ goto fail; >-+ b += alen; >-+ len -= alen; >-+ } >-+ r->entries = entries; >-+ return (r); >-+fail: >-+ mrt_free_rib(r); >-+ return (NULL); >-+} >-+ >-+int >-+mrt_parse_dump(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp, >-+ struct mrt_rib **rp) >-+{ >-+ struct mrt_peer *p; >-+ struct mrt_rib *r; >-+ struct mrt_rib_entry *re; >-+ u_int8_t *b = msg; >-+ u_int len = ntohl(hdr->length); >-+ u_int16_t asnum, alen; >-+ >-+ if (*pp == NULL) { >-+ *pp = calloc(1, sizeof(struct mrt_peer)); >-+ if (*pp == NULL) >-+ err(1, "calloc"); >-+ (*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry)); >-+ if ((*pp)->peers == NULL) >-+ err(1, "calloc"); >-+ (*pp)->npeers = 1; >-+ } >-+ p = *pp; >-+ >-+ *rp = r = calloc(1, sizeof(struct mrt_rib)); >-+ if (r == NULL) >-+ err(1, "calloc"); >-+ re = calloc(1, sizeof(struct mrt_rib_entry)); >-+ if (re == NULL) >-+ err(1, "calloc"); >-+ r->nentries = 1; >-+ r->entries = re; >-+ >-+ if (len < 2 * sizeof(u_int16_t)) >-+ goto fail; >-+ /* view */ >-+ b += sizeof(u_int16_t); >-+ len -= sizeof(u_int16_t); >-+ /* seqnum */ >-+ memcpy(&r->seqnum, b, sizeof(u_int16_t)); >-+ b += sizeof(u_int16_t); >-+ len -= sizeof(u_int16_t); >-+ r->seqnum = ntohs(r->seqnum); >-+ >-+ switch (ntohs(hdr->subtype)) { >-+ case MRT_DUMP_AFI_IP: >-+ if (mrt_extract_addr(b, len, &r->prefix, AF_INET) == -1) >-+ goto fail; >-+ b += sizeof(struct in_addr); >-+ len -= sizeof(struct in_addr); >-+ break; >-+ case MRT_DUMP_AFI_IPv6: >-+ if (mrt_extract_addr(b, len, &r->prefix, AF_INET6) == -1) >-+ goto fail; >-+ b += sizeof(struct in6_addr); >-+ len -= sizeof(struct in6_addr); >-+ break; >-+ } >-+ if (len < 2 * sizeof(u_int32_t) + 2 * sizeof(u_int16_t) + 2) >-+ goto fail; >-+ r->prefixlen = *b++; >-+ len -= 1; >-+ /* status */ >-+ b += 1; >-+ len -= 1; >-+ /* originated */ >-+ memcpy(&re->originated, b, sizeof(u_int32_t)); >-+ b += sizeof(u_int32_t); >-+ len -= sizeof(u_int32_t); >-+ re->originated = ntohl(re->originated); >-+ /* peer ip */ >-+ switch (ntohs(hdr->subtype)) { >-+ case MRT_DUMP_AFI_IP: >-+ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET) == -1) >-+ goto fail; >-+ b += sizeof(struct in_addr); >-+ len -= sizeof(struct in_addr); >-+ break; >-+ case MRT_DUMP_AFI_IPv6: >-+ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET6) == -1) >-+ goto fail; >-+ b += sizeof(struct in6_addr); >-+ len -= sizeof(struct in6_addr); >-+ break; >-+ } >-+ memcpy(&asnum, b, sizeof(asnum)); >-+ b += sizeof(asnum); >-+ len -= sizeof(asnum); >-+ p->peers->asnum = ntohs(asnum); >-+ >-+ memcpy(&alen, b, sizeof(alen)); >-+ b += sizeof(alen); >-+ len -= sizeof(alen); >-+ alen = ntohs(alen); >-+ >-+ /* attr */ >-+ if (len < alen) >-+ goto fail; >-+ if (mrt_extract_attr(re, b, alen, r->prefix.sa.sa_family, 0) == -1) >-+ goto fail; >-+ b += alen; >-+ len -= alen; >-+ >-+ return (0); >-+fail: >-+ mrt_free_rib(r); >-+ return (-1); >-+} >-+ >-+int >-+mrt_parse_dump_mp(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp, >-+ struct mrt_rib **rp) >-+{ >-+ struct mrt_peer *p; >-+ struct mrt_rib *r; >-+ struct mrt_rib_entry *re; >-+ u_int8_t *b = msg; >-+ u_int len = ntohl(hdr->length); >-+ u_int16_t asnum, alen, afi; >-+ u_int8_t safi, nhlen; >-+ sa_family_t af; >-+ >-+ if (*pp == NULL) { >-+ *pp = calloc(1, sizeof(struct mrt_peer)); >-+ if (*pp == NULL) >-+ err(1, "calloc"); >-+ (*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry)); >-+ if ((*pp)->peers == NULL) >-+ err(1, "calloc"); >-+ (*pp)->npeers = 1; >-+ } >-+ p = *pp; >-+ >-+ *rp = r = calloc(1, sizeof(struct mrt_rib)); >-+ if (r == NULL) >-+ err(1, "calloc"); >-+ re = calloc(1, sizeof(struct mrt_rib_entry)); >-+ if (re == NULL) >-+ err(1, "calloc"); >-+ r->nentries = 1; >-+ r->entries = re; >-+ >-+ if (len < 4 * sizeof(u_int16_t)) >-+ goto fail; >-+ /* source AS */ >-+ b += sizeof(u_int16_t); >-+ len -= sizeof(u_int16_t); >-+ /* dest AS */ >-+ memcpy(&asnum, b, sizeof(asnum)); >-+ b += sizeof(asnum); >-+ len -= sizeof(asnum); >-+ p->peers->asnum = ntohs(asnum); >-+ /* iface index */ >-+ b += sizeof(u_int16_t); >-+ len -= sizeof(u_int16_t); >-+ /* afi */ >-+ memcpy(&afi, b, sizeof(afi)); >-+ b += sizeof(afi); >-+ len -= sizeof(afi); >-+ afi = ntohs(afi); >-+ >-+ /* source + dest ip */ >-+ switch (afi) { >-+ case MRT_DUMP_AFI_IP: >-+ if (len < 2 * sizeof(struct in_addr)) >-+ goto fail; >-+ /* source IP */ >-+ b += sizeof(struct in_addr); >-+ len -= sizeof(struct in_addr); >-+ /* dest IP */ >-+ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET) == -1) >-+ goto fail; >-+ b += sizeof(struct in_addr); >-+ len -= sizeof(struct in_addr); >-+ break; >-+ case MRT_DUMP_AFI_IPv6: >-+ if (len < 2 * sizeof(struct in6_addr)) >-+ goto fail; >-+ /* source IP */ >-+ b += sizeof(struct in6_addr); >-+ len -= sizeof(struct in6_addr); >-+ /* dest IP */ >-+ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET6) == -1) >-+ goto fail; >-+ b += sizeof(struct in6_addr); >-+ len -= sizeof(struct in6_addr); >-+ break; >-+ } >-+ >-+ if (len < 2 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t)) >-+ goto fail; >-+ /* view + status */ >-+ b += 2 * sizeof(u_int16_t); >-+ len -= 2 * sizeof(u_int16_t); >-+ /* originated */ >-+ memcpy(&re->originated, b, sizeof(u_int32_t)); >-+ b += sizeof(u_int32_t); >-+ len -= sizeof(u_int32_t); >-+ re->originated = ntohl(re->originated); >-+ >-+ /* afi */ >-+ memcpy(&afi, b, sizeof(afi)); >-+ b += sizeof(afi); >-+ len -= sizeof(afi); >-+ afi = ntohs(afi); >-+ >-+ /* safi */ >-+ safi = *b++; >-+ len -= 1; >-+ >-+ switch (afi) { >-+ case MRT_DUMP_AFI_IP: >-+ if (safi == 1 || safi == 2) { >-+ af = AF_INET; >-+ break; >-+ } else if (safi == 128) { >-+ af = AF_VPNv4; >-+ break; >-+ } >-+ goto fail; >-+ case MRT_DUMP_AFI_IPv6: >-+ if (safi != 1 && safi != 2) >-+ goto fail; >-+ af = AF_INET6; >-+ break; >-+ default: >-+ goto fail; >-+ } >-+ >-+ /* nhlen */ >-+ nhlen = *b++; >-+ len -= 1; >-+ >-+ /* nexthop */ >-+ if (mrt_extract_addr(b, len, &re->nexthop, af) == -1) >-+ goto fail; >-+ if (len < nhlen) >-+ goto fail; >-+ b += nhlen; >-+ len -= nhlen; >-+ >-+ if (len < 1) >-+ goto fail; >-+ r->prefixlen = *b++; >-+ len -= 1; >-+ >-+ /* prefix */ >-+ switch (af) { >-+ case AF_INET: >-+ if (len < MRT_PREFIX_LEN(r->prefixlen)) >-+ goto fail; >-+ r->prefix.sin.sin_family = AF_INET; >-+ r->prefix.sin.sin_len = sizeof(struct sockaddr_in); >-+ memcpy(&r->prefix.sin.sin_addr, b, >-+ MRT_PREFIX_LEN(r->prefixlen)); >-+ b += MRT_PREFIX_LEN(r->prefixlen); >-+ len -= MRT_PREFIX_LEN(r->prefixlen); >-+ break; >-+ case AF_INET6: >-+ if (len < MRT_PREFIX_LEN(r->prefixlen)) >-+ goto fail; >-+ r->prefix.sin6.sin6_family = AF_INET6; >-+ r->prefix.sin6.sin6_len = sizeof(struct sockaddr_in6); >-+ memcpy(&r->prefix.sin6.sin6_addr, b, >-+ MRT_PREFIX_LEN(r->prefixlen)); >-+ b += MRT_PREFIX_LEN(r->prefixlen); >-+ len -= MRT_PREFIX_LEN(r->prefixlen); >-+ break; >-+ case AF_VPNv4: >-+ if (len < MRT_PREFIX_LEN(r->prefixlen)) >-+ goto fail; >-+ errx(1, "AF_VPNv4 handling not yet implemented"); >-+ goto fail; >-+ } >-+ >-+ memcpy(&alen, b, sizeof(alen)); >-+ b += sizeof(alen); >-+ len -= sizeof(alen); >-+ alen = ntohs(alen); >-+ >-+ /* attr */ >-+ if (len < alen) >-+ goto fail; >-+ if (mrt_extract_attr(re, b, alen, r->prefix.sa.sa_family, 0) == -1) >-+ goto fail; >-+ b += alen; >-+ len -= alen; >-+ >-+ return (0); >-+fail: >-+ mrt_free_rib(r); >-+ return (-1); >-+} >-+ >-+int >-+mrt_extract_attr(struct mrt_rib_entry *re, u_char *a, int alen, sa_family_t af, >-+ int as4) >-+{ >-+ struct mrt_attr *ap; >-+ u_int32_t tmp; >-+ u_int16_t attr_len; >-+ u_int8_t type, flags, *attr; >-+ >-+ do { >-+ if (alen < 3) >-+ return (-1); >-+ attr = a; >-+ flags = *a++; >-+ alen -= 1; >-+ type = *a++; >-+ alen -= 1; >-+ >-+ if (flags & MRT_ATTR_EXTLEN) { >-+ if (alen < 2) >-+ return (-1); >-+ memcpy(&attr_len, a, sizeof(attr_len)); >-+ attr_len = ntohs(attr_len); >-+ a += sizeof(attr_len); >-+ alen -= sizeof(attr_len); >-+ } else { >-+ attr_len = *a++; >-+ alen -= 1; >-+ } >-+ switch (type) { >-+ case MRT_ATTR_ORIGIN: >-+ if (attr_len != 1) >-+ return (-1); >-+ re->origin = *a; >-+ break; >-+ case MRT_ATTR_ASPATH: >-+ if (as4) { >-+ re->aspath_len = attr_len; >-+ if ((re->aspath = malloc(attr_len)) == NULL) >-+ err(1, "malloc"); >-+ memcpy(re->aspath, a, attr_len); >-+ } else { >-+ re->aspath = mrt_aspath_inflate(a, attr_len, >-+ &re->aspath_len); >-+ if (re->aspath == NULL) >-+ return (-1); >-+ } >-+ break; >-+ case MRT_ATTR_NEXTHOP: >-+ if (attr_len != 4) >-+ return (-1); >-+ if (af != AF_INET) >-+ break; >-+ memcpy(&tmp, a, sizeof(tmp)); >-+ re->nexthop.sin.sin_len = sizeof(struct sockaddr_in); >-+ re->nexthop.sin.sin_family = AF_INET; >-+ re->nexthop.sin.sin_addr.s_addr = tmp; >-+ break; >-+ case MRT_ATTR_MED: >-+ if (attr_len != 4) >-+ return (-1); >-+ memcpy(&tmp, a, sizeof(tmp)); >-+ re->med = ntohl(tmp); >-+ break; >-+ case MRT_ATTR_LOCALPREF: >-+ if (attr_len != 4) >-+ return (-1); >-+ memcpy(&tmp, a, sizeof(tmp)); >-+ re->local_pref = ntohl(tmp); >-+ break; >-+ case MRT_ATTR_MP_REACH_NLRI: >-+ /* >-+ * XXX horrible hack: >-+ * Once again IETF and the real world differ in the >-+ * implementation. In short the abbreviated MP_NLRI >-+ * hack in the standard is not used in real life. >-+ * Detect the two cases by looking at the first byte >-+ * of the payload (either the nexthop addr length (RFC) >-+ * or the high byte of the AFI (old form)). If the >-+ * first byte matches the expected nexthop length it >-+ * is expected to be the RFC 6396 encoding. >-+ */ >-+ if (*a != attr_len - 1) { >-+ a += 3; >-+ alen -= 3; >-+ attr_len -= 3; >-+ } >-+ switch (af) { >-+ case AF_INET6: >-+ if (attr_len < sizeof(struct in6_addr) + 1) >-+ return (-1); >-+ re->nexthop.sin6.sin6_len = >-+ sizeof(struct sockaddr_in6); >-+ re->nexthop.sin6.sin6_family = AF_INET6; >-+ memcpy(&re->nexthop.sin6.sin6_addr, a + 1, >-+ sizeof(struct in6_addr)); >-+ break; >-+ case AF_VPNv4: >-+ if (attr_len < sizeof(u_int64_t) + >-+ sizeof(struct in_addr)) >-+ return (-1); >-+ re->nexthop.svpn4.sv_len = >-+ sizeof(struct sockaddr_vpn4); >-+ re->nexthop.svpn4.sv_family = AF_VPNv4; >-+ memcpy(&tmp, a + 1 + sizeof(u_int64_t), >-+ sizeof(tmp)); >-+ re->nexthop.svpn4.sv_addr.s_addr = tmp; >-+ break; >-+ } >-+ break; >-+ case MRT_ATTR_AS4PATH: >-+ if (!as4) { >-+ if (re->aspath) >-+ free(re->aspath); >-+ re->aspath_len = attr_len; >-+ if ((re->aspath = malloc(attr_len)) == NULL) >-+ err(1, "malloc"); >-+ memcpy(re->aspath, a, attr_len); >-+ break; >-+ } >-+ /* FALLTHROUGH */ >-+ default: >-+ re->nattrs++; >-+ if (re->nattrs >= UCHAR_MAX) >-+ err(1, "too many attributes"); >-+ ap = realloc(re->attrs, >-+ re->nattrs * sizeof(struct mrt_attr)); >-+ if (ap == NULL) >-+ err(1, "realloc"); >-+ re->attrs = ap; >-+ ap = re->attrs + re->nattrs - 1; >-+ ap->attr_len = a + attr_len - attr; >-+ if ((ap->attr = malloc(ap->attr_len)) == NULL) >-+ err(1, "malloc"); >-+ memcpy(ap->attr, attr, ap->attr_len); >-+ break; >-+ } >-+ a += attr_len; >-+ alen -= attr_len; >-+ } while (alen > 0); >-+ >-+ return (0); >-+} >-+ >-+void >-+mrt_free_peers(struct mrt_peer *p) >-+{ >-+ free(p->peers); >-+ free(p->view); >-+ free(p); >-+} >-+ >-+void >-+mrt_free_rib(struct mrt_rib *r) >-+{ >-+ u_int16_t i, j; >-+ >-+ for (i = 0; i < r->nentries && r->entries; i++) { >-+ for (j = 0; j < r->entries[i].nattrs; j++) >-+ free(r->entries[i].attrs[j].attr); >-+ free(r->entries[i].attrs); >-+ free(r->entries[i].aspath); >-+ } >-+ >-+ free(r->entries); >-+ free(r); >-+} >-+ >-+void >-+mrt_free_bgp_state(struct mrt_bgp_state *s) >-+{ >-+ free(s); >-+} >-+ >-+void >-+mrt_free_bgp_msg(struct mrt_bgp_msg *m) >-+{ >-+ free(m->msg); >-+ free(m); >-+} >-+ >-+u_char * >-+mrt_aspath_inflate(void *data, u_int16_t len, u_int16_t *newlen) >-+{ >-+ u_int8_t *seg, *nseg, *ndata; >-+ u_int16_t seg_size, olen, nlen; >-+ u_int8_t seg_len; >-+ >-+ /* first calculate the length of the aspath */ >-+ seg = data; >-+ nlen = 0; >-+ for (olen = len; olen > 0; olen -= seg_size, seg += seg_size) { >-+ seg_len = seg[1]; >-+ seg_size = 2 + sizeof(u_int16_t) * seg_len; >-+ nlen += 2 + sizeof(u_int32_t) * seg_len; >-+ >-+ if (seg_size > olen) >-+ return NULL; >-+ } >-+ >-+ *newlen = nlen; >-+ if ((ndata = malloc(nlen)) == NULL) >-+ err(1, "malloc"); >-+ >-+ /* then copy the aspath */ >-+ seg = data; >-+ for (nseg = ndata; nseg < ndata + nlen; ) { >-+ *nseg++ = *seg++; >-+ *nseg++ = seg_len = *seg++; >-+ for (; seg_len > 0; seg_len--) { >-+ *nseg++ = 0; >-+ *nseg++ = 0; >-+ *nseg++ = *seg++; >-+ *nseg++ = *seg++; >-+ } >-+ } >-+ >-+ return (ndata); >-+} >-+ >-+int >-+mrt_extract_addr(void *msg, u_int len, union mrt_addr *addr, sa_family_t af) >-+{ >-+ u_int8_t *b = msg; >-+ >-+ switch (af) { >-+ case AF_INET: >-+ if (len < sizeof(struct in_addr)) >-+ return (-1); >-+ addr->sin.sin_family = AF_INET; >-+ addr->sin.sin_len = sizeof(struct sockaddr_in); >-+ memcpy(&addr->sin.sin_addr, b, sizeof(struct in_addr)); >-+ return sizeof(struct in_addr); >-+ case AF_INET6: >-+ if (len < sizeof(struct in6_addr)) >-+ return (-1); >-+ addr->sin6.sin6_family = AF_INET6; >-+ addr->sin6.sin6_len = sizeof(struct sockaddr_in6); >-+ memcpy(&addr->sin6.sin6_addr, b, sizeof(struct in6_addr)); >-+ return sizeof(struct in6_addr); >-+ case AF_VPNv4: >-+ if (len < sizeof(u_int64_t) + sizeof(struct in_addr)) >-+ return (-1); >-+ addr->svpn4.sv_len = sizeof(struct sockaddr_vpn4); >-+ addr->svpn4.sv_family = AF_VPNv4; >-+ memcpy(&addr->svpn4.sv_addr, b + sizeof(u_int64_t), >-+ sizeof(struct in_addr)); >-+ return (sizeof(u_int64_t) + sizeof(struct in_addr)); >-+ default: >-+ return (-1); >-+ } >-+} > >Property changes on: files/patch-bgpctl_mrtparser.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpctl_mrtparser.h >=================================================================== >--- files/patch-bgpctl_mrtparser.h (revision 500577) >+++ files/patch-bgpctl_mrtparser.h (nonexistent) >@@ -1,122 +0,0 @@ >-Index: bgpctl/mrtparser.h >-=================================================================== >-RCS file: bgpctl/mrtparser.h >-diff -N bgpctl/mrtparser.h >---- /dev/null 1 Jan 1970 00:00:00 -0000 >-+++ bgpctl/mrtparser.h 13 Oct 2012 18:22:53 -0000 1.1.1.1 >-@@ -0,0 +1,115 @@ >-+/* $OpenBSD$ */ >-+/* >-+ * Copyright (c) 2011 Claudio Jeker <claudio@openbsd.org> >-+ * >-+ * Permission to use, copy, modify, and distribute this software for any >-+ * purpose with or without fee is hereby granted, provided that the above >-+ * copyright notice and this permission notice appear in all copies. >-+ * >-+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES >-+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF >-+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR >-+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES >-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN >-+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF >-+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >-+ */ >-+ >-+struct sockaddr_vpn4 { >-+ u_int8_t sv_len; >-+ sa_family_t sv_family; >-+ u_int8_t sv_labellen; >-+ u_int8_t sv_pad; >-+ struct in_addr sv_addr; >-+ u_int64_t sv_rd; >-+ u_int8_t sv_label[21]; >-+ u_int8_t sv_pad2[3]; >-+}; >-+ >-+#define AF_VPNv4 250 /* XXX high enough to not cause issues */ >-+ >-+union mrt_addr { >-+ struct sockaddr_in6 sin6; >-+ struct sockaddr_in sin; >-+ struct sockaddr_vpn4 svpn4; >-+ struct sockaddr sa; >-+}; >-+ >-+/* data structures for the MSG_TABLE_DUMP_V2 format */ >-+struct mrt_peer_entry { >-+ union mrt_addr addr; >-+ u_int32_t bgp_id; >-+ u_int32_t asnum; >-+}; >-+ >-+struct mrt_peer { >-+ char *view; >-+ struct mrt_peer_entry *peers; >-+ u_int32_t bgp_id; >-+ u_int16_t npeers; >-+}; >-+ >-+struct mrt_attr { >-+ void *attr; >-+ size_t attr_len; >-+}; >-+ >-+struct mrt_rib_entry { >-+ void *aspath; >-+ struct mrt_attr *attrs; >-+ union mrt_addr nexthop; >-+ time_t originated; >-+ u_int32_t local_pref; >-+ u_int32_t med; >-+ u_int16_t peer_idx; >-+ u_int16_t aspath_len; >-+ u_int16_t nattrs; >-+ u_int8_t origin; >-+}; >-+ >-+struct mrt_rib { >-+ struct mrt_rib_entry *entries; >-+ union mrt_addr prefix; >-+ u_int32_t seqnum; >-+ u_int16_t nentries; >-+ u_int8_t prefixlen; >-+}; >-+ >-+/* data structures for the BGP4MP MESSAGE and STATE types */ >-+struct mrt_bgp_state { >-+ union mrt_addr src; >-+ union mrt_addr dst; >-+ u_int32_t src_as; >-+ u_int32_t dst_as; >-+ u_int16_t old_state; >-+ u_int16_t new_state; >-+}; >-+ >-+struct mrt_bgp_msg { >-+ union mrt_addr src; >-+ union mrt_addr dst; >-+ u_int32_t src_as; >-+ u_int32_t dst_as; >-+ u_int16_t msg_len; >-+ void *msg; >-+}; >-+ >-+#define MRT_ATTR_ORIGIN 1 >-+#define MRT_ATTR_ASPATH 2 >-+#define MRT_ATTR_NEXTHOP 3 >-+#define MRT_ATTR_MED 4 >-+#define MRT_ATTR_LOCALPREF 5 >-+#define MRT_ATTR_MP_REACH_NLRI 14 >-+#define MRT_ATTR_AS4PATH 17 >-+#define MRT_ATTR_EXTLEN 0x10 >-+ >-+#define MRT_PREFIX_LEN(x) ((((u_int)x) + 7) / 8) >-+ >-+struct mrt_parser { >-+ void (*dump)(struct mrt_rib *, struct mrt_peer *, void *); >-+ void (*state)(struct mrt_bgp_state *, void *); >-+ void (*message)(struct mrt_bgp_msg *, void *); >-+ void *arg; >-+}; >-+ >-+void mrt_parse(int, struct mrt_parser *, int); > >Property changes on: files/patch-bgpctl_mrtparser.h >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpctl_parser.c >=================================================================== >--- files/patch-bgpctl_parser.c (revision 500577) >+++ files/patch-bgpctl_parser.c (nonexistent) >@@ -1,400 +0,0 @@ >-Index: bgpctl/parser.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/parser.c,v >-retrieving revision 1.1.1.6 >-retrieving revision 1.7 >-diff -u -p -r1.1.1.6 -r1.7 >---- bgpctl/parser.c 14 Feb 2010 20:20:14 -0000 1.1.1.6 >-+++ bgpctl/parser.c 13 Oct 2012 18:35:56 -0000 1.7 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: parser.c,v 1.54 2009/06/12 16:44:02 claudio Exp $ */ >-+/* $OpenBSD: parser.c,v 1.64 2012/03/27 18:24:11 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-@@ -16,11 +16,16 @@ >- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >- */ >- >-+#if defined(__FreeBSD__) /* compat */ >-+#include "openbsd-compat.h" >-+#endif /* defined(__FreeBSD__) */ >-+ >- #include <sys/types.h> >- #include <sys/socket.h> >- >- #include <err.h> >- #include <errno.h> >-+#include <fcntl.h> >- #include <limits.h> >- #include <netdb.h> >- #include <stdio.h> >-@@ -52,7 +57,9 @@ enum token_type { >- PREPSELF, >- WEIGHT, >- FAMILY, >-- GETOPT >-+ GETOPT, >-+ RTABLE, >-+ FILENAME >- }; >- >- enum getopts { >-@@ -72,14 +79,18 @@ static const struct token t_show[]; >- static const struct token t_show_summary[]; >- static const struct token t_show_fib[]; >- static const struct token t_show_rib[]; >-+static const struct token t_show_mrt[]; >-+static const struct token t_show_mrt_file[]; >- static const struct token t_show_rib_neigh[]; >-+static const struct token t_show_mrt_neigh[]; >- static const struct token t_show_rib_rib[]; >- static const struct token t_show_neighbor[]; >- static const struct token t_show_neighbor_modifiers[]; >- static const struct token t_fib[]; >- static const struct token t_neighbor[]; >- static const struct token t_neighbor_modifiers[]; >--static const struct token t_show_as[]; >-+static const struct token t_show_rib_as[]; >-+static const struct token t_show_mrt_as[]; >- static const struct token t_show_prefix[]; >- static const struct token t_show_ip[]; >- static const struct token t_show_community[]; >-@@ -97,6 +108,9 @@ static const struct token t_prepself[]; >- static const struct token t_weight[]; >- static const struct token t_irrfilter[]; >- static const struct token t_irrfilter_opts[]; >-+static const struct token t_log[]; >-+static const struct token t_fib_table[]; >-+static const struct token t_show_fib_table[]; >- >- static const struct token t_main[] = { >- { KEYWORD, "reload", RELOAD, NULL}, >-@@ -105,6 +119,7 @@ static const struct token t_main[] = { >- { KEYWORD, "neighbor", NEIGHBOR, t_neighbor}, >- { KEYWORD, "network", NONE, t_network}, >- { KEYWORD, "irrfilter", IRRFILTER, t_irrfilter}, >-+ { KEYWORD, "log", NONE, t_log}, >- { ENDTOKEN, "", NONE, NULL} >- }; >- >-@@ -116,8 +131,10 @@ static const struct token t_show[] = { >- { KEYWORD, "network", NETWORK_SHOW, t_network_show}, >- { KEYWORD, "nexthop", SHOW_NEXTHOP, NULL}, >- { KEYWORD, "rib", SHOW_RIB, t_show_rib}, >-+ { KEYWORD, "tables", SHOW_FIB_TABLES, NULL}, >- { KEYWORD, "ip", NONE, t_show_ip}, >- { KEYWORD, "summary", SHOW_SUMMARY, t_show_summary}, >-+ { KEYWORD, "mrt", SHOW_MRT, t_show_mrt}, >- { ENDTOKEN, "", NONE, NULL} >- }; >- >-@@ -128,24 +145,26 @@ static const struct token t_show_summary >- }; >- >- static const struct token t_show_fib[] = { >-- { NOTOKEN, "", NONE, NULL}, >-- { FLAG, "connected", F_CONNECTED, t_show_fib}, >-- { FLAG, "static", F_STATIC, t_show_fib}, >-- { FLAG, "bgp", F_BGPD_INSERTED, t_show_fib}, >-- { FLAG, "nexthop", F_NEXTHOP, t_show_fib}, >-- { FAMILY, "", NONE, t_show_fib}, >-- { ADDRESS, "", NONE, NULL}, >-- { ENDTOKEN, "", NONE, NULL} >-+ { NOTOKEN, "", NONE, NULL}, >-+ { FLAG, "connected", F_CONNECTED, t_show_fib}, >-+ { FLAG, "static", F_STATIC, t_show_fib}, >-+ { FLAG, "bgp", F_BGPD_INSERTED, t_show_fib}, >-+ { FLAG, "nexthop", F_NEXTHOP, t_show_fib}, >-+ { KEYWORD, "table", NONE, t_show_fib_table}, >-+ { FAMILY, "", NONE, t_show_fib}, >-+ { ADDRESS, "", NONE, NULL}, >-+ { ENDTOKEN, "", NONE, NULL} >- }; >- >- static const struct token t_show_rib[] = { >- { NOTOKEN, "", NONE, NULL}, >-- { ASTYPE, "as", AS_ALL, t_show_as}, >-- { ASTYPE, "source-as", AS_SOURCE, t_show_as}, >-- { ASTYPE, "transit-as", AS_TRANSIT, t_show_as}, >-- { ASTYPE, "peer-as", AS_PEER, t_show_as}, >-+ { ASTYPE, "as", AS_ALL, t_show_rib_as}, >-+ { ASTYPE, "source-as", AS_SOURCE, t_show_rib_as}, >-+ { ASTYPE, "transit-as", AS_TRANSIT, t_show_rib_as}, >-+ { ASTYPE, "peer-as", AS_PEER, t_show_rib_as}, >- { ASTYPE, "empty-as", AS_EMPTY, t_show_rib}, >- { KEYWORD, "community", NONE, t_show_community}, >-+ { FLAG, "selected", F_CTL_ACTIVE, t_show_rib}, >- { FLAG, "detail", F_CTL_DETAIL, t_show_rib}, >- { FLAG, "in", F_CTL_ADJ_IN, t_show_rib}, >- { FLAG, "out", F_CTL_ADJ_OUT, t_show_rib}, >-@@ -158,12 +177,38 @@ static const struct token t_show_rib[] = >- { ENDTOKEN, "", NONE, NULL} >- }; >- >-+ >-+static const struct token t_show_mrt[] = { >-+ { NOTOKEN, "", NONE, NULL}, >-+ { ASTYPE, "as", AS_ALL, t_show_mrt_as}, >-+ { ASTYPE, "source-as", AS_SOURCE, t_show_mrt_as}, >-+ { ASTYPE, "transit-as", AS_TRANSIT, t_show_mrt_as}, >-+ { ASTYPE, "peer-as", AS_PEER, t_show_mrt_as}, >-+ { ASTYPE, "empty-as", AS_EMPTY, t_show_mrt}, >-+ { FLAG, "detail", F_CTL_DETAIL, t_show_mrt}, >-+ { KEYWORD, "neighbor", NONE, t_show_mrt_neigh}, >-+ { KEYWORD, "file", NONE, t_show_mrt_file}, >-+ { FAMILY, "", NONE, t_show_mrt}, >-+ { PREFIX, "", NONE, t_show_prefix}, >-+ { ENDTOKEN, "", NONE, NULL} >-+}; >-+ >-+static const struct token t_show_mrt_file[] = { >-+ { FILENAME, "", NONE, t_show_mrt}, >-+ { ENDTOKEN, "", NONE, NULL} >-+}; >-+ >- static const struct token t_show_rib_neigh[] = { >- { PEERADDRESS, "", NONE, t_show_rib}, >- { PEERDESC, "", NONE, t_show_rib}, >- { ENDTOKEN, "", NONE, NULL} >- }; >- >-+static const struct token t_show_mrt_neigh[] = { >-+ { PEERADDRESS, "", NONE, t_show_mrt}, >-+ { ENDTOKEN, "", NONE, NULL} >-+}; >-+ >- static const struct token t_show_rib_rib[] = { >- { RIBNAME, "", NONE, t_show_rib}, >- { ENDTOKEN, "", NONE, NULL} >-@@ -187,6 +232,7 @@ static const struct token t_show_neighbo >- static const struct token t_fib[] = { >- { KEYWORD, "couple", FIB_COUPLE, NULL}, >- { KEYWORD, "decouple", FIB_DECOUPLE, NULL}, >-+ { KEYWORD, "table", NONE, t_fib_table}, >- { ENDTOKEN, "", NONE, NULL} >- }; >- >-@@ -204,11 +250,16 @@ static const struct token t_neighbor_mod >- { ENDTOKEN, "", NONE, NULL} >- }; >- >--static const struct token t_show_as[] = { >-+static const struct token t_show_rib_as[] = { >- { ASNUM, "", NONE, t_show_rib}, >- { ENDTOKEN, "", NONE, NULL} >- }; >- >-+static const struct token t_show_mrt_as[] = { >-+ { ASNUM, "", NONE, t_show_mrt}, >-+ { ENDTOKEN, "", NONE, NULL} >-+}; >-+ >- static const struct token t_show_prefix[] = { >- { NOTOKEN, "", NONE, NULL}, >- { FLAG, "all", F_LONGER, NULL}, >-@@ -231,6 +282,7 @@ static const struct token t_network[] = >- { KEYWORD, "delete", NETWORK_REMOVE, t_prefix}, >- { KEYWORD, "flush", NETWORK_FLUSH, NULL}, >- { KEYWORD, "show", NETWORK_SHOW, t_network_show}, >-+ { KEYWORD, "mrt", NETWORK_MRT, t_show_mrt}, >- { ENDTOKEN, "", NONE, NULL} >- }; >- >-@@ -311,6 +363,22 @@ static const struct token t_irrfilter_op >- { ENDTOKEN, "", NONE, NULL} >- }; >- >-+static const struct token t_log[] = { >-+ { KEYWORD, "verbose", LOG_VERBOSE, NULL}, >-+ { KEYWORD, "brief", LOG_BRIEF, NULL}, >-+ { ENDTOKEN, "", NONE, NULL} >-+}; >-+ >-+static const struct token t_fib_table[] = { >-+ { RTABLE, "", NONE, t_fib}, >-+ { ENDTOKEN, "", NONE, NULL} >-+}; >-+ >-+static const struct token t_show_fib_table[] = { >-+ { RTABLE, "", NONE, t_show_fib}, >-+ { ENDTOKEN, "", NONE, NULL} >-+}; >-+ >- static struct parse_result res; >- >- const struct token *match_token(int *argc, char **argv[], >-@@ -404,15 +472,22 @@ match_token(int *argc, char **argv[], co >- case FAMILY: >- if (word == NULL) >- break; >-- if (!strcmp(word, "inet") || !strcmp(word, "IPv4")) { >-+ if (!strcmp(word, "inet") || >-+ !strcasecmp(word, "IPv4")) { >- match++; >- t = &table[i]; >-- res.af = AF_INET; >-+ res.aid = AID_INET; >- } >-- if (!strcmp(word, "inet6") || !strcmp(word, "IPv6")) { >-+ if (!strcmp(word, "inet6") || >-+ !strcasecmp(word, "IPv6")) { >- match++; >- t = &table[i]; >-- res.af = AF_INET6; >-+ res.aid = AID_INET6; >-+ } >-+ if (!strcasecmp(word, "VPNv4")) { >-+ match++; >-+ t = &table[i]; >-+ res.aid = AID_VPN_IPv4; >- } >- break; >- case ADDRESS: >-@@ -485,6 +560,7 @@ match_token(int *argc, char **argv[], co >- case PREPNBR: >- case PREPSELF: >- case WEIGHT: >-+ case RTABLE: >- if (word != NULL && strlen(word) > 0 && >- parse_number(word, &res, table[i].type)) { >- match++; >-@@ -518,6 +594,23 @@ match_token(int *argc, char **argv[], co >- t = &table[i]; >- } >- break; >-+ case FILENAME: >-+ if (word != NULL && strlen(word) > 0) { >-+ if ((res.mrtfd = open(word, O_RDONLY)) == -1) { >-+ /* >-+ * ignore error if path has no / and >-+ * does not exist. In hope to print >-+ * usage. >-+ */ >-+ if (errno == ENOENT && >-+ !strchr(word, '/')) >-+ break; >-+ err(1, "mrt open(%s)", word); >-+ } >-+ match++; >-+ t = &table[i]; >-+ } >-+ break; >- case ENDTOKEN: >- break; >- } >-@@ -577,6 +670,9 @@ show_valid_args(const struct token table >- case WEIGHT: >- fprintf(stderr, " <number>\n"); >- break; >-+ case RTABLE: >-+ fprintf(stderr, " <rtableid>\n"); >-+ break; >- case NEXTHOP: >- fprintf(stderr, " <address>\n"); >- break; >-@@ -584,11 +680,14 @@ show_valid_args(const struct token table >- fprintf(stderr, " <pftable>\n"); >- break; >- case FAMILY: >-- fprintf(stderr, " [ inet | inet6 | IPv4 | IPv6 ]\n"); >-+ fprintf(stderr, " [ inet | inet6 | IPv4 | IPv6 | VPNv4 ]\n"); >- break; >- case GETOPT: >- fprintf(stderr, " <options>\n"); >- break; >-+ case FILENAME: >-+ fprintf(stderr, " <filename>\n"); >-+ break; >- case ENDTOKEN: >- break; >- } >-@@ -608,7 +707,7 @@ parse_addr(const char *word, struct bgpd >- bzero(&ina, sizeof(ina)); >- >- if (inet_net_pton(AF_INET, word, &ina, sizeof(ina)) != -1) { >-- addr->af = AF_INET; >-+ addr->aid = AID_INET; >- addr->v4 = ina; >- return (1); >- } >-@@ -618,13 +717,7 @@ parse_addr(const char *word, struct bgpd >- hints.ai_socktype = SOCK_DGRAM; /*dummy*/ >- hints.ai_flags = AI_NUMERICHOST; >- if (getaddrinfo(word, "0", &hints, &r) == 0) { >-- addr->af = AF_INET6; >-- memcpy(&addr->v6, >-- &((struct sockaddr_in6 *)r->ai_addr)->sin6_addr, >-- sizeof(addr->v6)); >-- addr->scope_id = >-- ((struct sockaddr_in6 *)r->ai_addr)->sin6_scope_id; >-- >-+ sa2addr(r->ai_addr, addr); >- freeaddrinfo(r); >- return (1); >- } >-@@ -647,7 +740,7 @@ parse_prefix(const char *word, struct bg >- if ((p = strrchr(word, '/')) != NULL) { >- mask = strtonum(p + 1, 0, 128, &errstr); >- if (errstr) >-- errx(1, "invalid netmask: %s", errstr); >-+ errx(1, "netmask %s", errstr); >- >- if ((ps = malloc(strlen(word) - strlen(p) + 1)) == NULL) >- err(1, "parse_prefix: malloc"); >-@@ -663,15 +756,15 @@ parse_prefix(const char *word, struct bg >- if (parse_addr(word, addr) == 0) >- return (0); >- >-- switch (addr->af) { >-- case AF_INET: >-+ switch (addr->aid) { >-+ case AID_INET: >- if (mask == -1) >- mask = 32; >- if (mask > 32) >- errx(1, "invalid netmask: too large"); >- addr->v4.s_addr = addr->v4.s_addr & htonl(prefixlen2mask(mask)); >- break; >-- case AF_INET6: >-+ case AID_INET6: >- if (mask == -1) >- mask = 128; >- inet6applymask(&addr->v6, &addr->v6, mask); >-@@ -706,7 +799,7 @@ parse_asnum(const char *word, u_int32_t >- if (errstr) >- errx(1, "AS number is %s: %s", errstr, word); >- } else { >-- uval = strtonum(word, 0, ASNUM_MAX - 1, &errstr); >-+ uval = strtonum(word, 0, UINT_MAX, &errstr); >- if (errstr) >- errx(1, "AS number is %s: %s", errstr, word); >- } >-@@ -730,6 +823,11 @@ parse_number(const char *word, struct pa >- errx(1, "number is %s: %s", errstr, word); >- >- /* number was parseable */ >-+ if (type == RTABLE) { >-+ r->rtableid = uval; >-+ return (1); >-+ } >-+ >- if ((fs = calloc(1, sizeof(struct filter_set))) == NULL) >- err(1, NULL); >- switch (type) { >-@@ -882,8 +980,14 @@ bgpctl_getopt(int *argc, char **argv[], >- int ch; >- >- optind = optreset = 1; >-- while ((ch = getopt((*argc) + 1, (*argv) - 1, "o:")) != -1) { >-+ while ((ch = getopt((*argc) + 1, (*argv) - 1, "46o:")) != -1) { >- switch (ch) { >-+ case '4': >-+ res.flags = (res.flags | F_IPV4) & ~F_IPV6; >-+ break; >-+ case '6': >-+ res.flags = (res.flags | F_IPV6) & ~F_IPV4; >-+ break; >- case 'o': >- res.irr_outdir = optarg; >- break; > >Property changes on: files/patch-bgpctl_parser.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpctl_parser.h >=================================================================== >--- files/patch-bgpctl_parser.h (revision 500577) >+++ files/patch-bgpctl_parser.h (nonexistent) >@@ -1,55 +0,0 @@ >-Index: bgpctl/parser.h >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/parser.h,v >-retrieving revision 1.1.1.6 >-retrieving revision 1.1.1.9 >-diff -u -p -r1.1.1.6 -r1.1.1.9 >---- bgpctl/parser.h 14 Feb 2010 20:20:14 -0000 1.1.1.6 >-+++ bgpctl/parser.h 13 Oct 2012 18:22:53 -0000 1.1.1.9 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: parser.h,v 1.19 2009/06/06 06:05:41 claudio Exp $ */ >-+/* $OpenBSD: parser.h,v 1.23 2011/09/21 10:37:51 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-@@ -29,7 +29,9 @@ enum actions { >- SHOW_NEIGHBOR_TIMERS, >- SHOW_NEIGHBOR_TERSE, >- SHOW_FIB, >-+ SHOW_FIB_TABLES, >- SHOW_RIB, >-+ SHOW_MRT, >- SHOW_RIB_MEM, >- SHOW_NEXTHOP, >- SHOW_INTERFACE, >-@@ -37,6 +39,8 @@ enum actions { >- FIB, >- FIB_COUPLE, >- FIB_DECOUPLE, >-+ LOG_VERBOSE, >-+ LOG_BRIEF, >- NEIGHBOR, >- NEIGHBOR_UP, >- NEIGHBOR_DOWN, >-@@ -46,6 +50,7 @@ enum actions { >- NETWORK_REMOVE, >- NETWORK_FLUSH, >- NETWORK_SHOW, >-+ NETWORK_MRT, >- IRRFILTER >- }; >- >-@@ -59,9 +64,11 @@ struct parse_result { >- char rib[PEER_DESCR_LEN]; >- char *irr_outdir; >- int flags; >-- enum actions action; >-+ u_int rtableid; >-+ enum actions action; >- u_int8_t prefixlen; >-- sa_family_t af; >-+ u_int8_t aid; >-+ int mrtfd; >- }; >- >- __dead void usage(void); > >Property changes on: files/patch-bgpctl_parser.h >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpctl_whois.c >=================================================================== >--- files/patch-bgpctl_whois.c (revision 500577) >+++ files/patch-bgpctl_whois.c (nonexistent) >@@ -1,18 +0,0 @@ >-Index: bgpctl/whois.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/whois.c,v >-retrieving revision 1.1.1.5 >-retrieving revision 1.1.1.7 >-diff -u -p -r1.1.1.5 -r1.1.1.7 >---- bgpctl/whois.c 14 Feb 2010 20:20:14 -0000 1.1.1.5 >-+++ bgpctl/whois.c 13 Oct 2012 18:22:54 -0000 1.1.1.7 >-@@ -68,7 +68,8 @@ char *qtype_opts[] = { >- "", >- "-T aut-num", >- "-K -T as-set", >-- "-K -T route -i origin" >-+ "-K -T route -i origin", >-+ "-K -T route6 -i origin" >- }; >- >- char *server = "whois.radb.net"; > >Property changes on: files/patch-bgpctl_whois.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_Makefile >=================================================================== >--- files/patch-bgpd_Makefile (revision 500577) >+++ files/patch-bgpd_Makefile (nonexistent) >@@ -1,30 +0,0 @@ >---- bgpd/Makefile.orig 2013-02-21 19:20:05.000000000 +0000 >-+++ bgpd/Makefile 2013-02-21 19:20:54.000000000 +0000 >-@@ -1,15 +1,25 @@ >- # $OpenBSD: Makefile,v 1.28 2009/06/25 14:14:54 deraadt Exp $ >- >-+.PATH: ${.CURDIR}/.. ${.CURDIR}/../openbsd-compat >-+ >-+CONFFILE?= ${PREFIX}/etc/bgpd.conf >-+ >- PROG= bgpd >--SRCS= bgpd.c buffer.c session.c log.c parse.y config.c imsg.c \ >-+SRCS= bgpd.c session.c log.c parse.y config.c \ >- rde.c rde_rib.c rde_decide.c rde_prefix.c mrt.c kroute.c \ >- control.c pfkey.c rde_update.c rde_attr.c printconf.c \ >-- rde_filter.c pftable.c name2id.c util.c carp.c timer.c >-+ rde_filter.c pftable.c name2id.c util.c carp.c timer.c \ >-+ imsg.c imsg-buffer.c >- CFLAGS+= -Wall -I${.CURDIR} >-+CFLAGS+= -I${.CURDIR}/../openbsd-compat >- CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes >- CFLAGS+= -Wmissing-declarations >- CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual >- CFLAGS+= -Wsign-compare >-+CFLAGS+= -DCONFFILE=\"${CONFFILE}\" >-+.if defined(IPV6_LINKLOCAL_PEER) >-+CFLAGS+= -DIPV6_LINKLOCAL_PEER >-+.endif >- YFLAGS= >- MAN= bgpd.8 bgpd.conf.5 >- > >Property changes on: files/patch-bgpd_Makefile >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_bgpd.8 >=================================================================== >--- files/patch-bgpd_bgpd.8 (revision 500577) >+++ files/patch-bgpd_bgpd.8 (nonexistent) >@@ -1,348 +0,0 @@ >-Index: bgpd/bgpd.8 >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.8,v >-retrieving revision 1.1.1.8 >-retrieving revision 1.10 >-diff -u -p -r1.1.1.8 -r1.10 >---- bgpd/bgpd.8 14 Feb 2010 20:19:57 -0000 1.1.1.8 >-+++ bgpd/bgpd.8 13 Oct 2012 18:36:00 -0000 1.10 >-@@ -1,4 +1,4 @@ >--.\" $OpenBSD: bgpd.8,v 1.28 2009/01/13 23:01:36 sthen Exp $ >-+.\" $OpenBSD: bgpd.8,v 1.45 2012/08/24 20:13:03 jmc Exp $ >- .\" >- .\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >- .\" >-@@ -14,7 +14,7 @@ >- .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF >- .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >- .\" >--.Dd $Mdocdate: January 13 2009 $ >-+.Dd $Mdocdate: August 24 2012 $ >- .Dt BGPD 8 >- .Os >- .Sh NAME >-@@ -24,12 +24,8 @@ >- .Nm bgpd >- .Bk -words >- .Op Fl cdnv >--.Oo Xo >--.Fl D Ar macro Ns = Ns Ar value Oc >--.Xc >-+.Op Fl D Ar macro Ns = Ns Ar value >- .Op Fl f Ar file >--.Op Fl r Ar path >--.Op Fl s Ar path >- .Ek >- .Sh DESCRIPTION >- .Nm >-@@ -42,15 +38,106 @@ concerning >- with other BGP systems. >- .Nm >- uses the Border Gateway Protocol, Version 4, >--as described in RFC 1771. >--Please refer to that document for more information about BGP. >-+as described in RFC 4271. >-+.Pp >-+BGP is an exterior gateway protocol using a multiple step decision process >-+to find the best path. >-+Advanced filtering can be used to influence the route >-+decision for traffic engineering. >-+The session engine of >-+.Nm >-+is responsible for maintaining the TCP session with each neighbor. >-+Updates are passed to the Route Decision Engine (RDE) where the paths >-+are filtered and used to compute a Routing Information Base (RIB). >-+The parent process is responsible for keeping the RIB in sync with >-+the kernel routing table. >-+.Pp >-+The route decision process selects the best path by evaluating all paths to >-+the same destination. >-+The decision process continues to the next step if paths have equal attributes. >-+Paths that are less preferred are taken out of consideration until there is >-+only one path left. >-+.Bl -enum -width 42 -offset bula >-+.It >-+All paths with errors or loops are not eligible. >-+.It >-+Paths with an unreachable nexthop are not eligible. >-+After this step all remaining paths are valid. >-+.It >-+The path with the highest >-+.Em LOCAL_PREF >-+is selected. >-+.It >-+The path with the shortest >-+.Em AS path >-+attribute is selected. >-+.It >-+The >-+.Em ORIGIN >-+attribute is compared. >-+The order is IGP before EGP before incomplete origins. >-+.It >-+The path with the lowest >-+.Em MULTI_EXIT_DISC >-+metric is selected. >-+Normally, this value is only considered when choosing between multiple >-+routes sent by the same neighbouring AS. >-+However, if >-+.Dq Li rde med compare always >-+is set in the configuration, the metric is compared for routes sent by any AS. >-+.It >-+Comparison of the BGP session type. >-+Paths learned over an external (EBGP) session are preferred over those >-+learned via an internal (IBGP) session. >-+.It >-+The path with the lowest local >-+.Em weight >-+is selected. >-+.It >-+If >-+.Dq Li rde route-age evaluate >-+is set then the oldest path is selected. >-+.It >-+The path coming from the neighbor with the lowest >-+.Em BGP ID >-+wins. >-+If the >-+.Em ORIGINATOR_ID >-+attribute is present that value will be used in the comparison instead. >-+.It >-+The path with the shortest >-+.Em CLUSTER_LIST >-+attribute is selected. >-+If it is not present then a length of 0 is used in the comparison. >-+.It >-+The path coming from the peer with the lowest IP address is selected. >-+IPv4 sessions will be preferred over IPv6 ones. >-+.It >-+In case of locally announced prefixes >-+.Nm >-+will prefer statically set prefixes over dynamically inserted ones. >-+.El >-+.Pp >-+Attributes set by filters can be used to tip the decision process to prefer >-+particular paths over others. >-+This can be achieved by changing the >-+.Em localpref , >-+.Em med , >-+or >-+.Em weight >-+attributes. >-+AS path prepending or changing the >-+.Em med >-+or >-+.Em origin >-+attribute can be used to influencing the routing behaviour on remote systems. >- .Pp >- .Nm >- is usually started at boot time, and can be enabled by >- setting the following in >--.Pa /etc/rc.conf.local : >-+.Pa /etc/rc.conf : >- .Pp >--.Dl bgpd_flags=\&"\&" >-+.Dl openbgpd_enable=\&"YES\&" >- .Pp >- See >- .Xr rc 8 >-@@ -117,25 +204,16 @@ Use >- .Ar file >- as the configuration file, >- instead of the default >--.Pa /etc/bgpd.conf . >-+.Pa %%PREFIX%%/etc/bgpd.conf . >- .It Fl n >- Configtest mode. >- Only check the configuration file for validity. >--.It Fl r Ar path >--Open a second, restricted, control socket that >--.Xr bgpctl 8 >--can use. >--Only >--.Em show >--requests are allowed on this socket. >--.It Fl s Ar path >--Use an alternate location for the default control socket. >- .It Fl v >- Produce more verbose output. >- .El >- .Sh FILES >- .Bl -tag -width "/var/run/bgpd.sockXXX" -compact >--.It Pa /etc/bgpd.conf >-+.It Pa %%PREFIX%%/etc/bgpd.conf >- default >- .Nm >- configuration file >-@@ -149,55 +227,144 @@ control socket >- .Xr bgpctl 8 , >- .Xr bgplg 8 , >- .Xr bgplgsh 8 >-+.Sh STANDARDS >- .Rs >--.%R RFC 1771 >--.%T "A Border Gateway Protocol 4 (BGP-4)" >--.%D March 1995 >--.Re >--.Rs >--.%R RFC 1997 >--.%T "BGP Communities Attribute" >-+.%A R. Chandra >-+.%A P. Traina >-+.%A "T. Li" >- .%D August 1996 >-+.%R RFC 1997 >-+.%T BGP Communities Attribute >- .Re >-+.Pp >- .Rs >--.%R RFC 2385 >--.%T "Protection of BGP Sessions via the TCP MD5 Signature Option" >-+.%A A. Heffernan >- .%D August 1998 >-+.%R RFC 2385 >-+.%T Protection of BGP Sessions via the TCP MD5 Signature Option >- .Re >-+.Pp >- .Rs >--.%R RFC 2796 >--.%T "BGP Route Reflection - An Alternative to Full Mesh IBGP" >--.%D April 2000 >-+.%A P. Marques >-+.%A F. Dupont >-+.%D March 1999 >-+.%R RFC 2545 >-+.%T Use of BGP-4 Multiprotocol Extensions for IPv6 Inter-Domain Routing >- .Re >-+.Pp >- .Rs >--.%R RFC 2918 >--.%T "Route Refresh Capability for BGP-4" >-+.%A E. Chen >- .%D September 2000 >-+.%R RFC 2918 >-+.%T Route Refresh Capability for BGP-4 >- .Re >-+.Pp >- .Rs >--.%R RFC 3392 >--.%T "Capabilities Advertisement with BGP-4" >--.%D January 1999 >-+.%A G. Huston >-+.%D April 2004 >-+.%R RFC 3765 >-+.%T NOPEER Community for Border Gateway Protocol (BGP) Route Scope Control >- .Re >-+.Pp >- .Rs >--.%R RFC 3682 >--.%T "The Generalized TTL Security Mechanism (GTSM)" >--.%D February 2004 >-+.%A Y. Rekhter >-+.%A "T. Li" >-+.%A S. Hares >-+.%D January 2006 >-+.%R RFC 4271 >-+.%T A Border Gateway Protocol 4 (BGP-4) >- .Re >-+.Pp >- .Rs >--.%R RFC 3765 >--.%T "NOPEER Community for Border Gateway Protocol" >--.%D April 2004 >-+.%A S. Sangli >-+.%A D. Tappan >-+.%A Y. Rekhter >-+.%D February 2006 >-+.%R RFC 4360 >-+.%T BGP Extended Communities Attribute >- .Re >-+.Pp >- .Rs >--.%R RFC 4760 >--.%T "Multiprotocol Extensions for BGP-4" >-+.%A E. Rosen >-+.%A Y. Rekhter >-+.%D February 2006 >-+.%R RFC 4364 >-+.%T BGP/MPLS IP Virtual Private Networks (VPNs) >-+.Re >-+.Pp >-+.Rs >-+.%A T. Bates >-+.%A E. Chen >-+.%A R. Chandra >-+.%D April 2006 >-+.%R RFC 4456 >-+.%T "BGP Route Reflection: An Alternative to Full Mesh Internal BGP (IBGP)" >-+.Re >-+.Pp >-+.Rs >-+.%A E. Chen >-+.%A V. Gillet >-+.%D April 2006 >-+.%R RFC 4486 >-+.%T Subcodes for BGP Cease Notification Message >-+.Re >-+.Pp >-+.Rs >-+.%A T. Bates >-+.%A R. Chandra >-+.%A D. Katz >-+.%A Y. Rekhter >- .%D January 2007 >-+.%R RFC 4760 >-+.%T Multiprotocol Extensions for BGP-4 >- .Re >-+.Pp >- .Rs >--.%R RFC 4893 >--.%T "BGP Support for Four-octet AS Number Space" >-+.%A Q. Vohra >-+.%A E. Chen >- .%D May 2007 >-+.%R RFC 4893 >-+.%T BGP Support for Four-octet AS Number Space >-+.Re >-+.Pp >-+.Rs >-+.%A V. Gill >-+.%A J. Heasley >-+.%A D. Meyer >-+.%A P. Savola >-+.%A C. Pignatoro >-+.%D October 2007 >-+.%R RFC 5082 >-+.%T The Generalized TTL Security Mechanism (GTSM) >-+.Re >-+.Pp >-+.Rs >-+.%A J. Scudder >-+.%A R. Chandra >-+.%D February 2009 >-+.%R RFC 5492 >-+.%T Capabilities Advertisement with BGP-4 >-+.Re >-+.Pp >-+.Rs >-+.%D April 2009 >-+.%R draft-ietf-idr-optional-transitive-00 >-+.%T Error Handling for Optional Transitive BGP Attributes >-+.Re >-+.Pp >-+.Rs >-+.%D August 2011 >-+.%R draft-ietf-grow-mrt-17 >-+.%T MRT routing information export format >-+.Re >-+.Pp >-+.Rs >-+.%A J. Dong >-+.%A M. Chen >-+.%A A. Suryanarayana >-+.%D May 2012 >-+.%R RFC 6608 >-+.%T Subcodes for BGP Finite State Machine Error >- .Re >- .Sh HISTORY >- The > >Property changes on: files/patch-bgpd_bgpd.8 >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_bgpd.c >=================================================================== >--- files/patch-bgpd_bgpd.c (revision 500577) >+++ files/patch-bgpd_bgpd.c (nonexistent) >@@ -1,693 +0,0 @@ >-Index: bgpd/bgpd.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.c,v >-retrieving revision 1.1.1.7 >-retrieving revision 1.1.1.12 >-diff -u -p -r1.1.1.7 -r1.1.1.12 >---- bgpd/bgpd.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 >-+++ bgpd/bgpd.c 8 Dec 2012 10:37:08 -0000 1.1.1.12 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: bgpd.c,v 1.148 2009/06/07 00:30:23 claudio Exp $ */ >-+/* $OpenBSD: bgpd.c,v 1.169 2012/09/18 09:45:51 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-@@ -32,8 +32,8 @@ >- #include <string.h> >- #include <unistd.h> >- >--#include "mrt.h" >- #include "bgpd.h" >-+#include "mrt.h" >- #include "session.h" >- >- void sighdlr(int); >-@@ -42,23 +42,23 @@ int main(int, char *[]); >- int check_child(pid_t, const char *); >- int send_filterset(struct imsgbuf *, struct filter_set_head *); >- int reconfigure(char *, struct bgpd_config *, struct mrt_head *, >-- struct peer **, struct filter_head *); >-+ struct peer **); >- int dispatch_imsg(struct imsgbuf *, int); >-+int control_setup(struct bgpd_config *); >- >- int rfd = -1; >--int cflags = 0; >--struct filter_set_head *connectset; >--struct filter_set_head *connectset6; >--struct filter_set_head *staticset; >--struct filter_set_head *staticset6; >--volatile sig_atomic_t mrtdump = 0; >--volatile sig_atomic_t quit = 0; >--volatile sig_atomic_t sigchld = 0; >--volatile sig_atomic_t reconfig = 0; >--pid_t reconfpid = 0; >-+int cflags; >-+volatile sig_atomic_t mrtdump; >-+volatile sig_atomic_t quit; >-+volatile sig_atomic_t sigchld; >-+volatile sig_atomic_t reconfig; >-+pid_t reconfpid; >-+int reconfpending; >- struct imsgbuf *ibuf_se; >- struct imsgbuf *ibuf_rde; >- struct rib_names ribnames = SIMPLEQ_HEAD_INITIALIZER(ribnames); >-+char *cname; >-+char *rcname; >- >- void >- sighdlr(int sig) >-@@ -86,8 +86,8 @@ usage(void) >- { >- extern char *__progname; >- >-- fprintf(stderr, "usage: %s [-cdnv] ", __progname); >-- fprintf(stderr, "[-D macro=value] [-f file] [-r path] [-s path]\n"); >-+ fprintf(stderr, "usage: %s [-cdnv] [-D macro=value] [-f file]\n", >-+ __progname); >- exit(1); >- } >- >-@@ -101,15 +101,10 @@ int >- main(int argc, char *argv[]) >- { >- struct bgpd_config conf; >-- struct peer *peer_l, *p; >- struct mrt_head mrt_l; >-- struct network_head net_l; >-- struct filter_head *rules_l; >-- struct network *net; >-- struct filter_rule *r; >-+ struct peer *peer_l, *p; >- struct mrt *m; >- struct listen_addr *la; >-- struct rde_rib *rr; >- struct pollfd pfd[POLL_MAX]; >- pid_t io_pid = 0, rde_pid = 0, pid; >- char *conffile; >-@@ -124,18 +119,13 @@ main(int argc, char *argv[]) >- bgpd_process = PROC_MAIN; >- >- log_init(1); /* log to stderr until daemonized */ >-- >-- if ((rules_l = calloc(1, sizeof(struct filter_head))) == NULL) >-- err(1, NULL); >-+ log_verbose(1); >- >- bzero(&conf, sizeof(conf)); >- LIST_INIT(&mrt_l); >-- TAILQ_INIT(&net_l); >-- TAILQ_INIT(rules_l); >- peer_l = NULL; >-- conf.csock = SOCKET_NAME; >- >-- while ((ch = getopt(argc, argv, "cdD:f:nr:s:v")) != -1) { >-+ while ((ch = getopt(argc, argv, "cdD:f:nv")) != -1) { >- switch (ch) { >- case 'c': >- conf.opts |= BGPD_OPT_FORCE_DEMOTE; >-@@ -158,12 +148,7 @@ main(int argc, char *argv[]) >- if (conf.opts & BGPD_OPT_VERBOSE) >- conf.opts |= BGPD_OPT_VERBOSE2; >- conf.opts |= BGPD_OPT_VERBOSE; >-- break; >-- case 'r': >-- conf.rcsock = optarg; >-- break; >-- case 's': >-- conf.csock = optarg; >-+ log_verbose(1); >- break; >- default: >- usage(); >-@@ -176,24 +161,22 @@ main(int argc, char *argv[]) >- if (argc > 0) >- usage(); >- >-- if (parse_config(conffile, &conf, &mrt_l, &peer_l, &net_l, rules_l)) { >-- free(rules_l); >-- exit(1); >-- } >-- >- if (conf.opts & BGPD_OPT_NOACTION) { >-+ struct network_head net_l; >-+ struct rdomain_head rdom_l; >-+ struct filter_head rules_l; >-+ >-+ if (parse_config(conffile, &conf, &mrt_l, &peer_l, &net_l, >-+ &rules_l, &rdom_l)) >-+ exit(1); >-+ >- if (conf.opts & BGPD_OPT_VERBOSE) >-- print_config(&conf, &ribnames, &net_l, peer_l, rules_l, >-- &mrt_l); >-+ print_config(&conf, &ribnames, &net_l, peer_l, &rules_l, >-+ &mrt_l, &rdom_l); >- else >- fprintf(stderr, "configuration OK\n"); >- exit(0); >- } >-- cflags = conf.flags; >-- connectset = &conf.connectset; >-- staticset = &conf.staticset; >-- connectset6 = &conf.connectset6; >-- staticset6 = &conf.staticset6; >- >- if (geteuid()) >- errx(1, "need root privileges"); >-@@ -202,6 +185,7 @@ main(int argc, char *argv[]) >- errx(1, "unknown user %s", BGPD_USER); >- >- log_init(debug); >-+ log_verbose(conf.opts & BGPD_OPT_VERBOSE); >- >- if (!debug) >- daemon(1, 0); >-@@ -225,13 +209,9 @@ main(int argc, char *argv[]) >- session_socket_blockmode(pipe_s2r_c[0], BM_NONBLOCK); >- session_socket_blockmode(pipe_s2r_c[1], BM_NONBLOCK); >- >-- prepare_listeners(&conf); >-- >- /* fork children */ >-- rde_pid = rde_main(&conf, peer_l, &net_l, rules_l, &mrt_l, &ribnames, >-- pipe_m2r, pipe_s2r, pipe_m2s, pipe_s2r_c, debug); >-- io_pid = session_main(&conf, peer_l, &net_l, rules_l, &mrt_l, &ribnames, >-- pipe_m2s, pipe_s2r, pipe_m2r, pipe_s2r_c); >-+ rde_pid = rde_main(pipe_m2r, pipe_s2r, pipe_m2s, pipe_s2r_c, debug); >-+ io_pid = session_main(pipe_m2s, pipe_s2r, pipe_m2r, pipe_s2r_c); >- >- setproctitle("parent"); >- >-@@ -254,33 +234,12 @@ main(int argc, char *argv[]) >- imsg_init(ibuf_se, pipe_m2s[0]); >- imsg_init(ibuf_rde, pipe_m2r[0]); >- mrt_init(ibuf_rde, ibuf_se); >-- if ((rfd = kr_init(!(conf.flags & BGPD_FLAG_NO_FIB_UPDATE), >-- conf.rtableid)) == -1) >-+ if ((rfd = kr_init()) == -1) >- quit = 1; >-+ quit = reconfigure(conffile, &conf, &mrt_l, &peer_l); >- if (pftable_clear_all() != 0) >- quit = 1; >- >-- while ((net = TAILQ_FIRST(&net_l)) != NULL) { >-- TAILQ_REMOVE(&net_l, net, entry); >-- filterset_free(&net->net.attrset); >-- free(net); >-- } >-- >-- while ((r = TAILQ_FIRST(rules_l)) != NULL) { >-- TAILQ_REMOVE(rules_l, r, entry); >-- free(r); >-- } >-- TAILQ_FOREACH(la, conf.listen_addrs, entry) { >-- close(la->fd); >-- la->fd = -1; >-- } >-- while ((rr = SIMPLEQ_FIRST(&ribnames))) { >-- SIMPLEQ_REMOVE_HEAD(&ribnames, entry); >-- free(rr); >-- } >-- >-- mrt_reconfigure(&mrt_l); >-- >- while (quit == 0) { >- bzero(pfd, sizeof(pfd)); >- pfd[PFD_PIPE_SESSION].fd = ibuf_se->fd; >-@@ -335,15 +294,16 @@ main(int argc, char *argv[]) >- u_int error; >- >- reconfig = 0; >-- log_info("rereading config"); >-- switch (reconfigure(conffile, &conf, &mrt_l, &peer_l, >-- rules_l)) { >-+ switch (reconfigure(conffile, &conf, &mrt_l, &peer_l)) { >- case -1: /* fatal error */ >- quit = 1; >- break; >- case 0: /* all OK */ >- error = 0; >- break; >-+ case 2: >-+ error = CTL_RES_PENDING; >-+ break; >- default: /* parse error */ >- error = CTL_RES_PARSE_ERROR; >- break; >-@@ -389,13 +349,13 @@ main(int argc, char *argv[]) >- LIST_REMOVE(m, entry); >- free(m); >- } >-- while ((la = TAILQ_FIRST(conf.listen_addrs)) != NULL) { >-- TAILQ_REMOVE(conf.listen_addrs, la, entry); >-- close(la->fd); >-- free(la); >-- } >-+ if (conf.listen_addrs) >-+ while ((la = TAILQ_FIRST(conf.listen_addrs)) != NULL) { >-+ TAILQ_REMOVE(conf.listen_addrs, la, entry); >-+ close(la->fd); >-+ free(la); >-+ } >- >-- free(rules_l); >- control_cleanup(conf.csock); >- control_cleanup(conf.rcsock); >- carp_demote_shutdown(); >-@@ -413,6 +373,8 @@ main(int argc, char *argv[]) >- free(ibuf_se); >- msgbuf_clear(&ibuf_rde->w); >- free(ibuf_rde); >-+ free(rcname); >-+ free(cname); >- >- log_info("Terminating"); >- return (0); >-@@ -452,27 +414,33 @@ send_filterset(struct imsgbuf *i, struct >- >- int >- reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l, >-- struct peer **peer_l, struct filter_head *rules_l) >-+ struct peer **peer_l) >- { >- struct network_head net_l; >-- struct network *n; >-+ struct rdomain_head rdom_l; >-+ struct filter_head rules_l; >- struct peer *p; >- struct filter_rule *r; >- struct listen_addr *la; >- struct rde_rib *rr; >-+ struct rdomain *rd; >- >-- if (parse_config(conffile, conf, mrt_l, peer_l, &net_l, rules_l)) { >-+ if (reconfpending) { >-+ log_info("previous reload still running"); >-+ return (2); >-+ } >-+ reconfpending = 2; /* one per child */ >-+ >-+ log_info("rereading config"); >-+ if (parse_config(conffile, conf, mrt_l, peer_l, &net_l, &rules_l, >-+ &rdom_l)) { >- log_warnx("config file %s has errors, not reloading", >- conffile); >-+ reconfpending = 0; >- return (1); >- } >- >- cflags = conf->flags; >-- connectset = &conf->connectset; >-- staticset = &conf->staticset; >-- connectset6 = &conf->connectset6; >-- staticset6 = &conf->staticset6; >-- >- prepare_listeners(conf); >- >- /* start reconfiguration */ >-@@ -483,12 +451,6 @@ reconfigure(char *conffile, struct bgpd_ >- conf, sizeof(struct bgpd_config)) == -1) >- return (-1); >- >-- /* send peer list and listeners to the SE */ >-- for (p = *peer_l; p != NULL; p = p->next) >-- if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1, >-- &p->conf, sizeof(struct peer_config)) == -1) >-- return (-1); >-- >- TAILQ_FOREACH(la, conf->listen_addrs, entry) { >- if (imsg_compose(ibuf_se, IMSG_RECONF_LISTENER, 0, 0, la->fd, >- la, sizeof(struct listen_addr)) == -1) >-@@ -496,51 +458,104 @@ reconfigure(char *conffile, struct bgpd_ >- la->fd = -1; >- } >- >-+ if (control_setup(conf) == -1) >-+ return (-1); >-+ >-+ /* adjust fib syncing on reload */ >-+ ktable_preload(); >-+ >- /* RIBs for the RDE */ >- while ((rr = SIMPLEQ_FIRST(&ribnames))) { >- SIMPLEQ_REMOVE_HEAD(&ribnames, entry); >-+ if (ktable_update(rr->rtableid, rr->name, NULL, >-+ rr->flags) == -1) { >-+ log_warnx("failed to load rdomain %d", >-+ rr->rtableid); >-+ return (-1); >-+ } >- if (imsg_compose(ibuf_rde, IMSG_RECONF_RIB, 0, 0, -1, >- rr, sizeof(struct rde_rib)) == -1) >- return (-1); >- free(rr); >- } >- >-- /* networks for the RDE */ >-- while ((n = TAILQ_FIRST(&net_l)) != NULL) { >-- if (imsg_compose(ibuf_rde, IMSG_NETWORK_ADD, 0, 0, -1, >-- &n->net, sizeof(struct network_config)) == -1) >-- return (-1); >-- if (send_filterset(ibuf_rde, &n->net.attrset) == -1) >-- return (-1); >-- if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, >-- NULL, 0) == -1) >-- return (-1); >-- TAILQ_REMOVE(&net_l, n, entry); >-- filterset_free(&n->net.attrset); >-- free(n); >-+ /* send peer list and listeners to the SE and RDE */ >-+ for (p = *peer_l; p != NULL; p = p->next) { >-+ if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1, >-+ &p->conf, sizeof(struct peer_config)) == -1) >-+ return (-1); >-+ if (imsg_compose(ibuf_rde, IMSG_RECONF_PEER, p->conf.id, 0, -1, >-+ &p->conf, sizeof(struct peer_config)) == -1) >-+ return (-1); >- } >- >-- /* redistribute list needs to be reloaded too */ >-- if (kr_reload() == -1) >-+ /* networks go via kroute to the RDE */ >-+ if (kr_net_reload(0, &net_l)) >- return (-1); >- >- /* filters for the RDE */ >-- while ((r = TAILQ_FIRST(rules_l)) != NULL) { >-+ while ((r = TAILQ_FIRST(&rules_l)) != NULL) { >-+ TAILQ_REMOVE(&rules_l, r, entry); >- if (imsg_compose(ibuf_rde, IMSG_RECONF_FILTER, 0, 0, -1, >- r, sizeof(struct filter_rule)) == -1) >- return (-1); >- if (send_filterset(ibuf_rde, &r->set) == -1) >- return (-1); >-- TAILQ_REMOVE(rules_l, r, entry); >- filterset_free(&r->set); >- free(r); >- } >- >-+ while ((rd = SIMPLEQ_FIRST(&rdom_l)) != NULL) { >-+ SIMPLEQ_REMOVE_HEAD(&rdom_l, entry); >-+ if (ktable_update(rd->rtableid, rd->descr, rd->ifmpe, >-+ rd->flags) == -1) { >-+ log_warnx("failed to load rdomain %d", >-+ rd->rtableid); >-+ return (-1); >-+ } >-+ /* networks go via kroute to the RDE */ >-+ if (kr_net_reload(rd->rtableid, &rd->net_l)) >-+ return (-1); >-+ >-+ if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN, 0, 0, -1, >-+ rd, sizeof(*rd)) == -1) >-+ return (-1); >-+ >-+ /* export targets */ >-+ if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN_EXPORT, 0, 0, >-+ -1, NULL, 0) == -1) >-+ return (-1); >-+ if (send_filterset(ibuf_rde, &rd->export) == -1) >-+ return (-1); >-+ filterset_free(&rd->export); >-+ >-+ /* import targets */ >-+ if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN_IMPORT, 0, 0, >-+ -1, NULL, 0) == -1) >-+ return (-1); >-+ if (send_filterset(ibuf_rde, &rd->import) == -1) >-+ return (-1); >-+ filterset_free(&rd->import); >-+ >-+ if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN_DONE, 0, 0, >-+ -1, NULL, 0) == -1) >-+ return (-1); >-+ >-+ free(rd); >-+ } >-+ >- /* signal both childs to replace their config */ >- if (imsg_compose(ibuf_se, IMSG_RECONF_DONE, 0, 0, -1, NULL, 0) == -1 || >- imsg_compose(ibuf_rde, IMSG_RECONF_DONE, 0, 0, -1, NULL, 0) == -1) >- return (-1); >- >-+ /* fix kroute information */ >-+ ktable_postload(); >-+ >-+ /* redistribute list needs to be reloaded too */ >-+ if (kr_reload() == -1) >-+ return (-1); >-+ >- /* mrt changes can be sent out of bound */ >- mrt_reconfigure(mrt_l); >- return (0); >-@@ -550,8 +565,8 @@ int >- dispatch_imsg(struct imsgbuf *ibuf, int idx) >- { >- struct imsg imsg; >-- int n; >-- int rv; >-+ ssize_t n; >-+ int rv, verbose; >- >- if ((n = imsg_read(ibuf)) == -1) >- return (-1); >-@@ -573,46 +588,39 @@ dispatch_imsg(struct imsgbuf *ibuf, int >- case IMSG_KROUTE_CHANGE: >- if (idx != PFD_PIPE_ROUTE) >- log_warnx("route request not from RDE"); >-- else if (kr_change(imsg.data)) >-+ else if (imsg.hdr.len != IMSG_HEADER_SIZE + >-+ sizeof(struct kroute_full)) >-+ log_warnx("wrong imsg len"); >-+ else if (kr_change(imsg.hdr.peerid, imsg.data)) >- rv = -1; >- break; >- case IMSG_KROUTE_DELETE: >- if (idx != PFD_PIPE_ROUTE) >- log_warnx("route request not from RDE"); >-- else if (kr_delete(imsg.data)) >-- rv = -1; >-- break; >-- case IMSG_KROUTE6_CHANGE: >-- if (idx != PFD_PIPE_ROUTE) >-- log_warnx("route request not from RDE"); >-- else if (kr6_change(imsg.data)) >-- rv = -1; >-- break; >-- case IMSG_KROUTE6_DELETE: >-- if (idx != PFD_PIPE_ROUTE) >-- log_warnx("route request not from RDE"); >-- else if (kr6_delete(imsg.data)) >-+ else if (imsg.hdr.len != IMSG_HEADER_SIZE + >-+ sizeof(struct kroute_full)) >-+ log_warnx("wrong imsg len"); >-+ else if (kr_delete(imsg.hdr.peerid, imsg.data)) >- rv = -1; >- break; >- case IMSG_NEXTHOP_ADD: >- if (idx != PFD_PIPE_ROUTE) >- log_warnx("nexthop request not from RDE"); >-- else >-- if (imsg.hdr.len != IMSG_HEADER_SIZE + >-- sizeof(struct bgpd_addr)) >-- log_warnx("wrong imsg len"); >-- else if (kr_nexthop_add(imsg.data) == -1) >-- rv = -1; >-+ else if (imsg.hdr.len != IMSG_HEADER_SIZE + >-+ sizeof(struct bgpd_addr)) >-+ log_warnx("wrong imsg len"); >-+ else if (kr_nexthop_add(imsg.hdr.peerid, imsg.data) == >-+ -1) >-+ rv = -1; >- break; >- case IMSG_NEXTHOP_REMOVE: >- if (idx != PFD_PIPE_ROUTE) >- log_warnx("nexthop request not from RDE"); >-+ else if (imsg.hdr.len != IMSG_HEADER_SIZE + >-+ sizeof(struct bgpd_addr)) >-+ log_warnx("wrong imsg len"); >- else >-- if (imsg.hdr.len != IMSG_HEADER_SIZE + >-- sizeof(struct bgpd_addr)) >-- log_warnx("wrong imsg len"); >-- else >-- kr_nexthop_delete(imsg.data); >-+ kr_nexthop_delete(imsg.hdr.peerid, imsg.data); >- break; >- case IMSG_PFTABLE_ADD: >- if (idx != PFD_PIPE_ROUTE) >-@@ -646,26 +654,28 @@ dispatch_imsg(struct imsgbuf *ibuf, int >- case IMSG_CTL_RELOAD: >- if (idx != PFD_PIPE_SESSION) >- log_warnx("reload request not from SE"); >-- else >-+ else { >- reconfig = 1; >- reconfpid = imsg.hdr.pid; >-+ } >- break; >- case IMSG_CTL_FIB_COUPLE: >- if (idx != PFD_PIPE_SESSION) >- log_warnx("couple request not from SE"); >- else >-- kr_fib_couple(); >-+ kr_fib_couple(imsg.hdr.peerid); >- break; >- case IMSG_CTL_FIB_DECOUPLE: >- if (idx != PFD_PIPE_SESSION) >- log_warnx("decouple request not from SE"); >- else >-- kr_fib_decouple(); >-+ kr_fib_decouple(imsg.hdr.peerid); >- break; >- case IMSG_CTL_KROUTE: >- case IMSG_CTL_KROUTE_ADDR: >- case IMSG_CTL_SHOW_NEXTHOP: >- case IMSG_CTL_SHOW_INTERFACE: >-+ case IMSG_CTL_SHOW_FIB_TABLES: >- if (idx != PFD_PIPE_SESSION) >- log_warnx("kroute request not from SE"); >- else >-@@ -692,6 +702,16 @@ dispatch_imsg(struct imsgbuf *ibuf, int >- carp_demote_set(msg->demote_group, msg->level); >- } >- break; >-+ case IMSG_CTL_LOG_VERBOSE: >-+ /* already checked by SE */ >-+ memcpy(&verbose, imsg.data, sizeof(verbose)); >-+ log_verbose(verbose); >-+ break; >-+ case IMSG_RECONF_DONE: >-+ if (reconfpending == 0) >-+ log_warnx("unexpected RECONF_DONE received"); >-+ reconfpending--; >-+ break; >- default: >- break; >- } >-@@ -707,7 +727,7 @@ send_nexthop_update(struct kroute_nextho >- { >- char *gw = NULL; >- >-- if (msg->gateway.af) >-+ if (msg->gateway.aid) >- if (asprintf(&gw, ": via %s", >- log_addr(&msg->gateway)) == -1) { >- log_warn("send_nexthop_update"); >-@@ -717,7 +737,7 @@ send_nexthop_update(struct kroute_nextho >- log_info("nexthop %s now %s%s%s", log_addr(&msg->nexthop), >- msg->valid ? "valid" : "invalid", >- msg->connected ? ": directly connected" : "", >-- msg->gateway.af ? gw : ""); >-+ msg->gateway.aid ? gw : ""); >- >- free(gw); >- >-@@ -733,56 +753,20 @@ send_imsg_session(int type, pid_t pid, v >- } >- >- int >--bgpd_redistribute(int type, struct kroute *kr, struct kroute6 *kr6) >-+send_network(int type, struct network_config *net, struct filter_set_head *h) >- { >-- struct network_config net; >-- struct filter_set_head *h; >-- >-- if ((cflags & BGPD_FLAG_REDIST_CONNECTED) && kr && >-- (kr->flags & F_CONNECTED)) >-- h = connectset; >-- else if ((cflags & BGPD_FLAG_REDIST_STATIC) && kr && >-- (kr->flags & F_STATIC)) >-- h = staticset; >-- else if ((cflags & BGPD_FLAG_REDIST6_CONNECTED) && kr6 && >-- (kr6->flags & F_CONNECTED)) >-- h = connectset6; >-- else if ((cflags & BGPD_FLAG_REDIST6_STATIC) && kr6 && >-- (kr6->flags & F_STATIC)) >-- h = staticset6; >-- else >-- return (0); >-- >-- bzero(&net, sizeof(net)); >-- if (kr && kr6) >-- fatalx("bgpd_redistribute: unable to redistribute v4 and v6" >-- "together"); >-- if (kr != NULL) { >-- net.prefix.af = AF_INET; >-- net.prefix.v4.s_addr = kr->prefix.s_addr; >-- net.prefixlen = kr->prefixlen; >-- } >-- if (kr6 != NULL) { >-- net.prefix.af = AF_INET6; >-- memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr)); >-- net.prefixlen = kr6->prefixlen; >-- } >-- >-- >-- if (imsg_compose(ibuf_rde, type, 0, 0, -1, &net, >-+ if (imsg_compose(ibuf_rde, type, 0, 0, -1, net, >- sizeof(struct network_config)) == -1) >- return (-1); >-- >- /* networks that get deleted don't need to send the filter set */ >- if (type == IMSG_NETWORK_REMOVE) >-- return (1); >-- >-+ return (0); >- if (send_filterset(ibuf_rde, h) == -1) >- return (-1); >- if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0) == -1) >- return (-1); >- >-- return (1); >-+ return (0); >- } >- >- int >-@@ -810,3 +794,45 @@ bgpd_filternexthop(struct kroute *kr, st >- >- return (1); >- } >-+ >-+int >-+control_setup(struct bgpd_config *conf) >-+{ >-+ int fd, restricted; >-+ >-+ /* control socket is outside chroot */ >-+ if (!cname || strcmp(cname, conf->csock)) { >-+ if (cname) { >-+ control_cleanup(cname); >-+ free(cname); >-+ } >-+ if ((cname = strdup(conf->csock)) == NULL) >-+ fatal("strdup"); >-+ if ((fd = control_init(0, cname)) == -1) >-+ fatalx("control socket setup failed"); >-+ restricted = 0; >-+ if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd, >-+ &restricted, sizeof(restricted)) == -1) >-+ return (-1); >-+ } >-+ if (!conf->rcsock) { >-+ /* remove restricted socket */ >-+ control_cleanup(rcname); >-+ free(rcname); >-+ rcname = NULL; >-+ } else if (!rcname || strcmp(rcname, conf->rcsock)) { >-+ if (rcname) { >-+ control_cleanup(rcname); >-+ free(rcname); >-+ } >-+ if ((rcname = strdup(conf->rcsock)) == NULL) >-+ fatal("strdup"); >-+ if ((fd = control_init(1, rcname)) == -1) >-+ fatalx("control socket setup failed"); >-+ restricted = 1; >-+ if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd, >-+ &restricted, sizeof(restricted)) == -1) >-+ return (-1); >-+ } >-+ return (0); >-+} > >Property changes on: files/patch-bgpd_bgpd.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_bgpd.conf.5 >=================================================================== >--- files/patch-bgpd_bgpd.conf.5 (revision 500577) >+++ files/patch-bgpd_bgpd.conf.5 (nonexistent) >@@ -1,746 +0,0 @@ >-Index: bgpd/bgpd.conf.5 >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.conf.5,v >-retrieving revision 1.1.1.7 >-retrieving revision 1.10 >-diff -u -p -r1.1.1.7 -r1.10 >---- bgpd/bgpd.conf.5 14 Feb 2010 20:19:57 -0000 1.1.1.7 >-+++ bgpd/bgpd.conf.5 8 Dec 2012 20:17:59 -0000 1.10 >-@@ -1,4 +1,4 @@ >--.\" $OpenBSD: bgpd.conf.5,v 1.94 2009/06/07 00:31:22 claudio Exp $ >-+.\" $OpenBSD: bgpd.conf.5,v 1.122 2012/11/13 09:47:20 claudio Exp $ >- .\" >- .\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> >- .\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-@@ -16,7 +16,7 @@ >- .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF >- .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >- .\" >--.Dd $Mdocdate: June 7 2009 $ >-+.Dd $Mdocdate: November 13 2012 $ >- .Dt BGPD.CONF 5 >- .Os >- .Sh NAME >-@@ -26,11 +26,11 @@ >- The >- .Xr bgpd 8 >- daemon implements the Border Gateway Protocol version 4 as described >--in RFC 1771. >-+in RFC 4271. >- .Sh SECTIONS >- The >- .Nm >--config file is divided into four main sections. >-+config file is divided into five main sections. >- .Bl -tag -width xxxx >- .It Sy Macros >- User-defined variables may be defined and used later, simplifying the >-@@ -38,6 +38,8 @@ configuration file. >- .It Sy Global Configuration >- Global settings for >- .Xr bgpd 8 . >-+.It Sy Routing Domain Configuration >-+The definition and properties for BGP MPLS VPNs are set in this section. >- .It Sy Neighbors and Groups >- .Xr bgpd 8 >- establishes sessions with >-@@ -54,9 +56,16 @@ the sections should be grouped and appea >- .Nm >- in the order shown above. >- .Pp >-+The current line can be extended over multiple lines using a backslash >-+.Pq Sq \e . >- Comments can be put anywhere in the file using a hash mark >- .Pq Sq # , >- and extend to the end of the current line. >-+Care should be taken when commenting out multi-line text: >-+the comment is effective until the end of the entire block. >-+.Pp >-+Argument names not beginning with a letter, digit, or underscore >-+must be quoted. >- .Pp >- Additional configuration files can be included with the >- .Ic include >-@@ -66,8 +75,8 @@ include "/etc/bgpd/bgpd-10.0.0.1.filter" >- .Ed >- .Sh MACROS >- Macros can be defined that will later be expanded in context. >--Macro names must start with a letter, and may contain letters, digits >--and underscores. >-+Macro names must start with a letter, digit, or underscore, >-+and may contain any of those characters. >- Macro names may not be reserved words (for example, >- .Ic AS , >- .Ic neighbor , >-@@ -93,7 +102,7 @@ Set the local >- .Em autonomous system >- number to >- .Ar as-number . >--If the first AS number is a 4-byte AS it is possible to specifiy a secondary >-+If the first AS number is a 4-byte AS it is possible to specify a secondary >- 2-byte AS number which is used for neighbors which do not support 4-byte AS >- numbers. >- The default for the secondary AS is 23456. >-@@ -143,29 +152,33 @@ The default is 120 seconds. >- .It Xo >- .Ic dump >- .Op Ic rib Ar name >--.Pq Ic table Ns \&| Ns Ic table-mp >-+.Pq Ic table Ns | Ns Ic table-mp Ns | Ns Ic table-v2 >- .Ar file Op Ar timeout >- .Xc >- .It Xo >- .Ic dump >--.Pq Ic all Ns \&| Ns Ic updates >--.Pq Ic in Ns \&| Ns Ic out >-+.Pq Ic all Ns | Ns Ic updates >-+.Pq Ic in Ns | Ns Ic out >- .Ar file Op Ar timeout >- .Xc >- Dump the RIB, a.k.a. the >- .Em routing information base , >- and all BGP messages in Multi-threaded Routing Toolkit (MRT) format. >--Dumping the RIB is normally an expensive operation, >--but it should not influence the session handling. >- It is possible to dump alternate RIB with the use of >- .Ar name . >- .Pp >- For example, the following will dump the entire table to the >- .Xr strftime 3 Ns -expanded >- filename. >--The >-+Only the >-+.Ic table-v2 >-+format is able to dump a multi-protocol RIB correctly. >-+Both >-+.Ic table >-+and >- .Ic table-mp >--format is multi-protocol capable but often not supported by 3rd-party tools. >-+formats are more or less limited when handling multi-protocol entries and >-+are only left around to support 3rd party tools not handling the new format. >- The timeout is optional: >- .Bd -literal -offset indent >- dump table "/tmp/rib-dump-%H%M" 300 >-@@ -195,7 +208,7 @@ dump updates out "/tmp/updates-out-%H%M" >- .Pp >- .It Xo >- .Ic fib-update >--.Pq Ic yes Ns \&| Ns Ic no >-+.Pq Ic yes Ns | Ns Ic no >- .Xc >- If set to >- .Ic no , >-@@ -242,12 +255,12 @@ Log received and sent updates. >- .Xc >- .It Xo >- .Ic network >--.Pq Ic inet Ns \&| Ns Ic inet6 >-+.Pq Ic inet Ns | Ns Ic inet6 >- .Ic static Op Ic set ...\& >- .Xc >- .It Xo >- .Ic network >--.Pq Ic inet Ns \&| Ns Ic inet6 >-+.Pq Ic inet Ns | Ns Ic inet6 >- .Ic connected Op Ic set ...\& >- .Xc >- Announce the specified network as belonging to our AS. >-@@ -278,7 +291,7 @@ section. >- .Ic nexthop >- .Ic qualify >- .Ic via >--.Pq Ic bgp Ns \&| Ns Ic default >-+.Pq Ic bgp Ns | Ns Ic default >- .Xc >- If set to >- .Ic bgp , >-@@ -295,38 +308,47 @@ daemons like >- .Ic rde >- .Ic med >- .Ic compare >--.Pq Ic always Ns \&| Ns Ic strict >-+.Pq Ic always Ns | Ns Ic strict >- .Xc >- If set to >- .Ic always , >- the >--.Em MED >-+.Em MULTI_EXIT_DISC >- attributes will always be compared. >- The default is >- .Ic strict , >--where the >--.Em MED >--is only compared between peers belonging to the same AS. >-+where the metric is only compared between peers belonging to the same AS. >- .Pp >- .It Xo >- .Ic rde >- .Ic rib Ar name >- .Op Ic no Ic evaluate >- .Xc >--Creat an additional RIB named >-+.It Xo >-+.Ic rde >-+.Ic rib Ar name >-+.Op Ic rtable Ar number >-+.Xc >-+Create an additional RIB named >- .Ar name . >- It is possible to disable the decision process per RIB with the >- .Ic no Ic evaluate >- flag. >-+If a >-+.Ic rtable >-+is specified, routes will be exported to the given kernel routing table. >-+Currently the routing table must belong to the default routing domain and >-+nexthop verification happens on table 0. >-+Routes in the specified table will not be considered for nexthop verification. >- .Ic Adj-RIB-In >- and >- .Ic Loc-RIB >--are created automaticaly and used as default. >-+are created automatically and used as default. >- .Pp >- .It Xo >- .Ic rde >- .Ic route-age >--.Pq Ic ignore Ns \&| Ns Ic evaluate >-+.Pq Ic ignore Ns | Ns Ic evaluate >- .Xc >- If set to >- .Ic evaluate , >-@@ -339,7 +361,7 @@ The default is >- .Pp >- .It Xo >- .Ic route-collector >--.Pq Ic yes Ns \&| Ns Ic no >-+.Pq Ic yes Ns | Ns Ic no >- .Xc >- If set to >- .Ic yes , >-@@ -361,13 +383,24 @@ to the local machine. >- Work with the given kernel routing table >- instead of the default table, >- .Ar 0 . >--Note that this table is used for nexthop verification as well. >--Directly connected networks are always taken into account, even though >--their routes live in table 0. >-+Note that table 0 is used for nexthop verification. >-+Routes in the specified table will not be considered for nexthop verification. >-+This is the same as using the following syntax: >-+.Bd -literal -offset indent >-+rde rib Loc-RIB rtable number >-+.Ed >-+.Pp >-+.It Ic socket Qo Ar path Qc Op Ic restricted >-+Set the control socket location to >-+.Ar path . >-+If >-+.Ic restricted >-+is specified a restricted control socket will be created. >-+By default /var/run/bgpd.sock is used and no restricted socket is created. >- .Pp >- .It Xo >- .Ic transparent-as >--.Pq Ic yes Ns \&| Ns Ic no >-+.Pq Ic yes Ns | Ns Ic no >- .Xc >- If set to >- .Ic yes , >-@@ -376,6 +409,110 @@ to EBGP neighbors are not prepended with >- The default is >- .Ic no . >- .El >-+.Sh ROUTING DOMAIN CONFIGURATION >-+.Xr bgpd 8 >-+supports the setup and distribution of Virtual Private Networks. >-+It is possible to import and export prefixes between routing domains. >-+Each routing domain is specified by an >-+.Ic rdomain >-+section, which allows properties to be set specifically for that rdomain: >-+.Bd -literal -offset indent >-+rdomain 1 { >-+ descr "a rdomain" >-+ rd 65002:1 >-+ import-target rt 65002:42 >-+ export-target rt 65002:42 >-+ network 192.168.1/24 >-+ depend on mpe0 >-+} >-+.Ed >-+.Pp >-+There are several routing domain properties: >-+.Pp >-+.Bl -tag -width Ds -compact >-+.It Ic depend on Ar interface >-+Routes added to the rdomain will use this interface as the outgoing interface. >-+Normally this will be an MPLS Provider Edge, >-+.Xr mpe 4 , >-+interface that is part of the rdomain. >-+Local networks will be announced with the MPLS label specified on the interface. >-+.Pp >-+.It Ic descr Ar description >-+Add a description. >-+The description is used when logging but has no further meaning to >-+.Xr bgpd 8 . >-+.Pp >-+.It Ic export-target Ar subtype Ar as-number Ns Li : Ns Ar local >-+.It Ic export-target Ar subtype Ar IP Ns Li : Ns Ar local >-+Specify an extended community which will be attached to announced networks. >-+More than one >-+.Ic export-target >-+can be specified. >-+See also the >-+.Sx ATTRIBUTE SET >-+section for further information about the encoding. >-+The >-+.Ar subtype >-+should be set to >-+.Ar rt >-+for best compatibility with other implementations. >-+.Pp >-+.It Xo >-+.Ic fib-update >-+.Pq Ic yes Ns | Ns Ic no >-+.Xc >-+If set to >-+.Ic no , >-+do not update the Forwarding Information Base, a.k.a. the kernel >-+routing table. >-+The default is >-+.Ic yes . >-+.Pp >-+.It Ic import-target Ar subtype Ar as-number Ns Li : Ns Ar local >-+.It Ic import-target Ar subtype Ar IP Ns Li : Ns Ar local >-+Only prefixes matching one of the specified >-+.Ic import-targets >-+will be imported into the rdomain. >-+More than one >-+.Ic import-target >-+can be specified. >-+See also the >-+.Sx ATTRIBUTE SET >-+section for further information about the encoding of extended communities. >-+The >-+.Ar subtype >-+should be set to >-+.Ar rt >-+for best compatibility with other implementations. >-+.Pp >-+.It Ic network Ar arguments ... >-+Define which networks should be exported into this VPN. >-+See also the >-+.Ic nexthop >-+section in >-+.Sx GLOBAL CONFIGURATION >-+for further information about the arguments. >-+.Pp >-+.It Ic rd Ar as-number Ns Li : Ns Ar local >-+.It Ic rd Ar IP Ns Li : Ns Ar local >-+The sole purpose of the Route Distinguisher >-+.Ic rd >-+is to ensure that possible common prefixes are destinct between VPNs. >-+The >-+.Ic rd >-+is neither used to identify the origin of the prefix nor to control into >-+which VPNs the prefix is distributed to. >-+The >-+.Ar as-number >-+or >-+.Ar IP >-+of a >-+.Ic rd >-+should be set to a number or IP that was assigned by an appropriate authority. >-+Whereas >-+.Ar local >-+can be chosen by the local operator. >-+.El >- .Sh NEIGHBORS AND GROUPS >- .Xr bgpd 8 >- establishes TCP connections to other BGP speakers called >-@@ -470,21 +607,35 @@ The default for IBGP peers is >- .Pp >- .It Xo >- .Ic announce >--.Pq Ic IPv4 Ns \&| Ns Ic IPv6 >--.Pq Ic none Ns \&| Ns Ic unicast >-+.Pq Ic IPv4 Ns | Ns Ic IPv6 >-+.Pq Ic none Ns | Ns Ic unicast Ns | Ns Ic vpn >- .Xc >- For the given address family, control which subsequent address families >- (at the moment, only >- .Em none , >--which disables the announcement of that address family, and >--.Em unicast >--are supported) are announced during the capabilities negotiation. >-+which disables the announcement of that address family, >-+.Em unicast , >-+and >-+.Em vpn , >-+which allows the distribution of BGP MPLS VPNs, are supported) are announced >-+during the capabilities negotiation. >- Only routes for that address family and subsequent address family will be >- announced and processed. >- .Pp >- .It Xo >-+.Ic announce as-4byte >-+.Pq Ic yes Ns | Ns Ic no >-+.Xc >-+If set to >-+.Ic no , >-+the 4-byte AS capability is not announced and so native 4-byte AS support is >-+disabled. >-+The default is >-+.Ic yes . >-+.Pp >-+.It Xo >- .Ic announce capabilities >--.Pq Ic yes Ns \&| Ns Ic no >-+.Pq Ic yes Ns | Ns Ic no >- .Xc >- If set to >- .Ic no , >-@@ -493,6 +644,29 @@ This can be helpful to connect to old or >- The default is >- .Ic yes . >- .Pp >-+.It Xo >-+.Ic announce refresh >-+.Pq Ic yes Ns | Ns Ic no >-+.Xc >-+If set to >-+.Ic no , >-+the route refresh capability is not announced. >-+The default is >-+.Ic yes . >-+.Pp >-+.It Xo >-+.Ic announce restart >-+.Pq Ic yes Ns | Ns Ic no >-+.Xc >-+If set to >-+.Ic yes , >-+the graceful restart capability is announced. >-+Currently only the End-of-RIB marker is supported and announced by the >-+.Ic restart >-+capability. >-+The default is >-+.Ic no . >-+.Pp >- .It Ic demote Ar group >- Increase the >- .Xr carp 4 >-@@ -504,7 +678,7 @@ The demotion counter will be increased a >- .Xr bgpd 8 >- starts and decreased >- 60 seconds after the session went to state >--.Em ESTABLISHED. >-+.Em ESTABLISHED . >- For neighbors added at runtime, the demotion counter is only increased after >- the session has been >- .Em ESTABLISHED >-@@ -548,8 +722,8 @@ Do not start the session when bgpd comes >- .Pp >- .It Xo >- .Ic dump >--.Pq Ic all Ns \&| Ns Ic updates >--.Pq Ic in Ns \&| Ns Ic out >-+.Pq Ic all Ns | Ns Ic updates >-+.Pq Ic in Ns | Ns Ic out >- .Ar file Op Ar timeout >- .Xc >- Do a peer specific MRT dump. >-@@ -564,7 +738,7 @@ section in >- .Pp >- .It Xo >- .Ic enforce neighbor-as >--.Pq Ic yes Ns \&| Ns Ic no >-+.Pq Ic yes Ns | Ns Ic no >- .Xc >- If set to >- .Ic yes , >-@@ -589,10 +763,16 @@ Inherited from the global configuration >- Set the minimal acceptable holdtime. >- Inherited from the global configuration if not given. >- .Pp >-+.It Ic interface Ar interface >-+Set an interface used for a nexthop with a link-local IPv6 address. >-+Note that if this is not specified and a link-local IPv6 address is >-+received as nexthop of the peer, it will be marked as invalid and >-+ignored. >-+.Pp >- .It Xo >- .Ic ipsec >--.Pq Ic ah Ns \&| Ns Ic esp >--.Pq Ic in Ns \&| Ns Ic out >-+.Pq Ic ah Ns | Ns Ic esp >-+.Pq Ic in Ns | Ns Ic out >- .Ic spi Ar spi-number authspec Op Ar encspec >- .Xc >- Enable IPsec with static keying. >-@@ -627,7 +807,7 @@ Keys must be given in hexadecimal format >- .Pp >- .It Xo >- .Ic ipsec >--.Pq Ic ah Ns \&| Ns Ic esp >-+.Pq Ic ah Ns | Ns Ic esp >- .Ic ike >- .Xc >- Enable IPsec with dynamic keying. >-@@ -639,11 +819,11 @@ is responsible for managing the session >- With >- .Xr isakmpd 8 , >- it is sufficient to copy the peer's public key, found in >--.Pa /etc/isakmpd/local.pub , >-+.Pa %%PREFIX%%/etc/isakmpd/private/local.pub , >- to the local machine. >- It must be stored in a file >- named after the peer's IP address and must be stored in >--.Pa /etc/isakmpd/pubkeys/ipv4/ . >-+.Pa %%PREFIX%%/etc/isakmpd/pubkeys/ipv4/ . >- The local public key must be copied to the peer in the same way. >- As >- .Xr bgpd 8 >-@@ -698,11 +878,11 @@ Do not attempt to actively open a TCP co >- .It Ic remote-as Ar as-number >- Set the AS number of the remote system. >- .Pp >--.It rib .Ar name >-+.It Ic rib Ar name >- Bind the neighbor to the specified RIB. >- .Pp >- .It Ic route-reflector Op Ar address >--Act as an RFC 2796 >-+Act as an RFC 4456 >- .Em route-reflector >- for this neighbor. >- An optional cluster ID can be specified; otherwise the BGP ID will be used. >-@@ -732,8 +912,8 @@ These sets are rewritten into filter rul >- .Pp >- .It Xo >- .Ic softreconfig >--.Pq Ic in Ns \&| Ns Ic out >--.Pq Ic yes Ns \&| Ns Ic no >-+.Pq Ic in Ns | Ns Ic out >-+.Pq Ic yes Ns | Ns Ic no >- .Xc >- Turn soft reconfiguration on or off for the specified direction. >- If soft reconfiguration is turned on, filter changes will be applied on >-@@ -760,7 +940,7 @@ tcp md5sig key deadbeef >- .Pp >- .It Xo >- .Ic transparent-as >--.Pq Ic yes Ns \&| Ns Ic no >-+.Pq Ic yes Ns | Ns Ic no >- .Xc >- If set to >- .Ic yes , >-@@ -772,7 +952,7 @@ setting. >- .Pp >- .It Xo >- .Ic ttl-security >--.Pq Ic yes Ns \&| Ns Ic no >-+.Pq Ic yes Ns | Ns Ic no >- .Xc >- Enable or disable ttl-security. >- When enabled, >-@@ -849,6 +1029,10 @@ is matched against a part of the >- .Em AS path >- specified by the >- .Ar as-type . >-+.Ar as-number >-+may be set to >-+.Ic neighbor-as , >-+which is expanded to the current neighbor remote AS number. >- .Ar as-type >- is one of the following operators: >- .Pp >-@@ -917,7 +1101,32 @@ may be set to >- which is expanded to the current neighbor remote AS number. >- .Pp >- .It Xo >--.Pq Ic from Ns \&| Ns Ic to >-+.Ic ext-community >-+.Ar subtype Ar as-number Ns Li : Ns Ar local >-+.Xc >-+.It Xo >-+.Ic ext-community >-+.Ar subtype Ar IP Ns Li : Ns Ar local >-+.Xc >-+.It Xo >-+.Ic ext-community >-+.Ar subtype Ar numvalue >-+.Xc >-+This rule applies only to >-+.Em UPDATES >-+where the >-+.Em extended community >-+path attribute is present and matches. >-+Extended Communities are specified by a >-+.Ar subtype >-+and normally two values, a globally unique part (e.g. the AS number) and a >-+local part. >-+See also the >-+.Sx ATTRIBUTE SET >-+section for further information about the encoding. >-+.Pp >-+.It Xo >-+.Pq Ic from Ns | Ns Ic to >- .Ar peer >- .Xc >- This rule applies only to >-@@ -945,7 +1154,7 @@ if enclosed in curly brackets: >- deny from { 128.251.16.1, 251.128.16.2, group hojo } >- .Ed >- .Pp >--.It Pq Ic inet Ns \&| Ns Ic inet6 >-+.It Pq Ic inet Ns | Ns Ic inet6 >- This rule applies only to routes matching the stated address family. >- The address family needs to be set only in rules that use >- .Ic prefixlen >-@@ -953,6 +1162,37 @@ without specifying a >- .Ic prefix >- beforehand. >- .Pp >-+.It Ic max-as-len Ar len >-+This rule applies only to >-+.Em UPDATES >-+where the >-+.Em AS path >-+has more than >-+.Ar len >-+elements. >-+.Pp >-+.It Ic max-as-seq Ar len >-+This rule applies only to >-+.Em UPDATES >-+where a single >-+.Em AS number >-+is repeated more than >-+.Ar len >-+times. >-+.Pp >-+.It Ic nexthop Ar address >-+This rule applies only to >-+.Em UPDATES >-+where the nexthop is equal to >-+.Ar address . >-+The >-+.Ar address >-+can be set to >-+.Em neighbor >-+in which case the nexthop is compared against the address of the neighbor. >-+Nexthop filtering is not supported on locally announced networks and one must >-+take into consideration previous rules overwriting nexthops. >-+.Pp >- .It Xo >- .Ic prefix >- .Ar address Ns Li / Ns Ar len >-@@ -1028,6 +1268,12 @@ matches a rule which has the >- option set, this rule is considered the last matching rule, and evaluation >- of subsequent rules is skipped. >- .Pp >-+.It Ic rib Ar name >-+Apply rule only to the specified RIB. >-+This only applies for received updates, so not for rules using the >-+.Ar to peer >-+parameter. >-+.Pp >- .It Ic set Ar attribute ... >- All matching rules can set the >- .Em AS path attributes >-@@ -1079,6 +1325,48 @@ Alternately, well-known communities may >- or >- .Ic NO_PEER . >- .Pp >-+.It Xo >-+.Ic ext-community Op Ar delete >-+.Ar subtype Ar as-number Ns Li : Ns Ar local >-+.Xc >-+.It Xo >-+.Ic ext-community Op Ar delete >-+.Ar subtype Ar IP Ns Li : Ns Ar local >-+.Xc >-+.It Xo >-+.Ic ext-community Op Ar delete >-+.Ar subtype Ar numvalue >-+.Xc >-+Set or delete the >-+.Em Extended Community >-+AS path attribute. >-+Extended Communities are specified by a >-+.Ar subtype >-+and normally two values, a globally unique part (e.g. the AS number) and a >-+local part. >-+The type is selected depending on the encoding of the global part. >-+Two-octet AS Specific Extended Communities and Four-octet AS Specific Extended >-+Communities are encoded as >-+.Ar as-number Ns Li : Ns Ar local . >-+Four-octet encoding is used if the >-+.Ar as-number >-+is bigger then 65535 or if the AS_DOT encoding is used. >-+IPv4 Address Specific Extended Communities are encoded as >-+.Ar IP Ns Li : Ns Ar local . >-+Opaque Extended Communities are encoded with a single numeric value. >-+Currently the following subtypes are supported: >-+.Bd -literal -offset indent >-+rt Route Target >-+soo Source of Origin >-+odi OSPF Domain Identifier >-+ort OSPF Route Type >-+ori OSPF Router ID >-+bdc BGP Data Collection >-+.Ed >-+.Pp >-+Not all type and subtype value pairs are allowed by IANA and the parser >-+will ensure that no invalid combination is created. >-+.Pp >- .It Ic localpref Ar number >- Set the >- .Em LOCAL_PREF >-@@ -1108,6 +1396,20 @@ otherwise it will be set to >- .Ar number . >- .Pp >- .It Xo >-+.Ic origin >-+.Sm off >-+.Po Ic igp \*(Ba >-+.Ic egp \*(Ba >-+.Ic incomplete Pc >-+.Sm on >-+.Xc >-+Set the >-+.Em ORIGIN >-+AS path attribute to mark the source of this >-+route as being injected from an igp protocol, an egp protocol >-+or being an aggregated route. >-+.Pp >-+.It Xo >- .Ic nexthop >- .Sm off >- .Po Ar address \*(Ba >-@@ -1157,9 +1459,8 @@ times to the >- .Em AS path . >- .Pp >- .It Ic rtlabel Ar label >--Add the prefix with the specified >--.Ar label >--to the kernel routing table. >-+Add the prefix to the kernel routing table with the specified >-+.Ar label . >- .Pp >- .It Ic weight Ar number >- The >-@@ -1181,8 +1482,8 @@ For prefixes with equally long paths, th >- is selected. >- .El >- .Sh FILES >--.Bl -tag -width "/etc/bgpd.conf" -compact >--.It Pa /etc/bgpd.conf >-+.Bl -tag -width "%%PREFIX%%/etc/bgpd.conf" -compact >-+.It Pa %%PREFIX%%/etc/bgpd.conf >- .Xr bgpd 8 >- configuration file >- .El > >Property changes on: files/patch-bgpd_bgpd.conf.5 >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_bgpd.h >=================================================================== >--- files/patch-bgpd_bgpd.h (revision 500577) >+++ files/patch-bgpd_bgpd.h (nonexistent) >@@ -1,872 +0,0 @@ >-Index: bgpd/bgpd.h >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.h,v >-retrieving revision 1.1.1.8 >-retrieving revision 1.15 >-diff -u -p -r1.1.1.8 -r1.15 >---- bgpd/bgpd.h 14 Feb 2010 20:19:57 -0000 1.1.1.8 >-+++ bgpd/bgpd.h 16 May 2014 00:36:26 -0000 1.15 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: bgpd.h,v 1.241 2009/06/12 16:42:53 claudio Exp $ */ >-+/* $OpenBSD: bgpd.h,v 1.273 2012/09/18 10:10:00 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-@@ -21,6 +21,7 @@ >- #include <sys/types.h> >- #include <sys/socket.h> >- #include <sys/queue.h> >-+#include <sys/tree.h> >- #include <net/route.h> >- #include <netinet/in.h> >- #include <arpa/inet.h> >-@@ -30,11 +31,16 @@ >- #include <poll.h> >- #include <stdarg.h> >- >--#include <imsg.h> >-+#if defined(__FreeBSD__) /* compat */ >-+#include "openbsd-compat.h" >-+#endif /* defined(__FreeBSD__) */ >-+#include "imsg.h" >- >- #define BGP_VERSION 4 >- #define BGP_PORT 179 >-+#ifndef CONFFILE >- #define CONFFILE "/etc/bgpd.conf" >-+#endif /* !CONFFILE */ >- #define BGPD_USER "_bgpd" >- #define PEER_DESCR_LEN 32 >- #define PFTABLE_LEN 16 >-@@ -42,8 +48,6 @@ >- #define IPSEC_ENC_KEY_LEN 32 >- #define IPSEC_AUTH_KEY_LEN 20 >- >--#define ASNUM_MAX 0xffffffff >-- >- #define MAX_PKTSIZE 4096 >- #define MIN_HOLDTIME 3 >- #define READ_BUF_SIZE 65535 >-@@ -55,13 +59,8 @@ >- #define BGPD_OPT_NOACTION 0x0004 >- #define BGPD_OPT_FORCE_DEMOTE 0x0008 >- >--#define BGPD_FLAG_NO_FIB_UPDATE 0x0001 >- #define BGPD_FLAG_NO_EVALUATE 0x0002 >- #define BGPD_FLAG_REFLECTOR 0x0004 >--#define BGPD_FLAG_REDIST_STATIC 0x0008 >--#define BGPD_FLAG_REDIST_CONNECTED 0x0010 >--#define BGPD_FLAG_REDIST6_STATIC 0x0020 >--#define BGPD_FLAG_REDIST6_CONNECTED 0x0040 >- #define BGPD_FLAG_NEXTHOP_BGP 0x0080 >- #define BGPD_FLAG_NEXTHOP_DEFAULT 0x1000 >- #define BGPD_FLAG_DECISION_MASK 0x0f00 >-@@ -83,9 +82,12 @@ >- #define F_REJECT 0x0080 >- #define F_BLACKHOLE 0x0100 >- #define F_LONGER 0x0200 >-+#define F_MPLS 0x0400 >-+#define F_REDISTRIBUTED 0x0800 >- #define F_CTL_DETAIL 0x1000 /* only used by bgpctl */ >- #define F_CTL_ADJ_IN 0x2000 >- #define F_CTL_ADJ_OUT 0x4000 >-+#define F_CTL_ACTIVE 0x8000 >- >- /* >- * Limit the number of control messages generated by the RDE and queued in >-@@ -109,18 +111,75 @@ enum reconf_action { >- RECONF_DELETE >- }; >- >-+/* Address Family Numbers as per RFC 1700 */ >-+#define AFI_UNSPEC 0 >-+#define AFI_IPv4 1 >-+#define AFI_IPv6 2 >-+ >-+/* Subsequent Address Family Identifier as per RFC 4760 */ >-+#define SAFI_NONE 0 >-+#define SAFI_UNICAST 1 >-+#define SAFI_MULTICAST 2 >-+#define SAFI_MPLS 4 >-+#define SAFI_MPLSVPN 128 >-+ >-+struct aid { >-+ u_int16_t afi; >-+ sa_family_t af; >-+ u_int8_t safi; >-+ char *name; >-+}; >-+ >-+extern const struct aid aid_vals[]; >-+ >-+#define AID_UNSPEC 0 >-+#define AID_INET 1 >-+#define AID_INET6 2 >-+#define AID_VPN_IPv4 3 >-+#define AID_MAX 4 >-+#define AID_MIN 1 /* skip AID_UNSPEC since that is a dummy */ >-+ >-+#define AID_VALS { \ >-+ /* afi, af, safii, name */ \ >-+ { AFI_UNSPEC, AF_UNSPEC, SAFI_NONE, "unspec"}, \ >-+ { AFI_IPv4, AF_INET, SAFI_UNICAST, "IPv4 unicast" }, \ >-+ { AFI_IPv6, AF_INET6, SAFI_UNICAST, "IPv6 unicast" }, \ >-+ { AFI_IPv4, AF_INET, SAFI_MPLSVPN, "IPv4 vpn" } \ >-+} >-+ >-+#define AID_PTSIZE { \ >-+ 0, \ >-+ sizeof(struct pt_entry4), \ >-+ sizeof(struct pt_entry6), \ >-+ sizeof(struct pt_entry_vpn4) \ >-+} >-+ >-+struct vpn4_addr { >-+ u_int64_t rd; >-+ struct in_addr addr; >-+ u_int8_t labelstack[21]; /* max that makes sense */ >-+ u_int8_t labellen; >-+ u_int8_t pad1; >-+ u_int8_t pad2; >-+}; >-+ >-+#define BGP_MPLS_BOS 0x01 >-+ >- struct bgpd_addr { >-- sa_family_t af; >- union { >- struct in_addr v4; >- struct in6_addr v6; >-- u_int8_t addr8[16]; >-- u_int16_t addr16[8]; >-- u_int32_t addr32[4]; >-+ struct vpn4_addr vpn4; >-+ /* maximum size for a prefix is 256 bits */ >-+ u_int8_t addr8[32]; >-+ u_int16_t addr16[16]; >-+ u_int32_t addr32[8]; >- } ba; /* 128-bit address */ >- u_int32_t scope_id; /* iface scope id for v6 */ >-+ u_int8_t aid; >- #define v4 ba.v4 >- #define v6 ba.v6 >-+#define vpn4 ba.vpn4 >- #define addr8 ba.addr8 >- #define addr16 ba.addr16 >- #define addr32 ba.addr32 >-@@ -141,17 +200,12 @@ TAILQ_HEAD(listen_addrs, listen_addr); >- TAILQ_HEAD(filter_set_head, filter_set); >- >- struct bgpd_config { >-- struct filter_set_head connectset; >-- struct filter_set_head connectset6; >-- struct filter_set_head staticset; >-- struct filter_set_head staticset6; >- struct listen_addrs *listen_addrs; >- char *csock; >- char *rcsock; >- int opts; >- int flags; >- int log; >-- u_int rtableid; >- u_int32_t bgpid; >- u_int32_t clusterid; >- u_int32_t as; >-@@ -205,12 +259,24 @@ struct peer_auth { >- }; >- >- struct capabilities { >-- u_int8_t mp_v4; /* multiprotocol extensions, RFC 4760 */ >-- u_int8_t mp_v6; >-- u_int8_t refresh; /* route refresh, RFC 2918 */ >-- u_int8_t restart; /* graceful restart, RFC 4724 */ >-- u_int8_t as4byte; /* draft-ietf-idr-as4bytes-13 */ >--}; >-+ struct { >-+ int16_t timeout; /* graceful restart timeout */ >-+ int8_t flags[AID_MAX]; /* graceful restart per AID flags */ >-+ int8_t restart; /* graceful restart, RFC 4724 */ >-+ } grestart; >-+ int8_t mp[AID_MAX]; /* multiprotocol extensions, RFC 4760 */ >-+ int8_t refresh; /* route refresh, RFC 2918 */ >-+ int8_t as4byte; /* 4-byte ASnum, RFC 4893 */ >-+}; >-+ >-+#define CAPA_GR_PRESENT 0x01 >-+#define CAPA_GR_RESTART 0x02 >-+#define CAPA_GR_FORWARD 0x04 >-+#define CAPA_GR_RESTARTING 0x08 >-+ >-+#define CAPA_GR_TIMEMASK 0x0fff >-+#define CAPA_GR_R_FLAG 0x8000 >-+#define CAPA_GR_F_FLAG 0x80 >- >- struct peer_config { >- struct bgpd_addr remote_addr; >-@@ -237,7 +303,7 @@ struct peer_config { >- u_int8_t template; >- u_int8_t remote_masklen; >- u_int8_t cloned; >-- u_int8_t ebgp; /* 1 = ebgp, 0 = ibgp */ >-+ u_int8_t ebgp; /* 0 = ibgp else ebgp */ >- u_int8_t distance; /* 1 = direct, >1 = multihop */ >- u_int8_t passive; >- u_int8_t down; >-@@ -248,21 +314,33 @@ struct peer_config { >- u_int8_t ttlsec; /* TTL security hack */ >- u_int8_t flags; >- u_int8_t pad[3]; >-+ char lliface[IFNAMSIZ]; >- }; >- >- #define PEERFLAG_TRANS_AS 0x01 >- >-+enum network_type { >-+ NETWORK_DEFAULT, >-+ NETWORK_STATIC, >-+ NETWORK_CONNECTED, >-+ NETWORK_MRTCLONE >-+}; >-+ >- struct network_config { >-- struct bgpd_addr prefix; >-- struct filter_set_head attrset; >-- u_int8_t prefixlen; >-+ struct bgpd_addr prefix; >-+ struct filter_set_head attrset; >-+ struct rde_aspath *asp; >-+ u_int rtableid; >-+ enum network_type type; >-+ u_int8_t prefixlen; >-+ u_int8_t old; /* used for reloading */ >- }; >- >- TAILQ_HEAD(network_head, network); >- >- struct network { >-- struct network_config net; >-- TAILQ_ENTRY(network) entry; >-+ struct network_config net; >-+ TAILQ_ENTRY(network) entry; >- }; >- >- enum imsg_type { >-@@ -276,7 +354,6 @@ enum imsg_type { >- IMSG_CTL_NEIGHBOR_CLEAR, >- IMSG_CTL_NEIGHBOR_RREFRESH, >- IMSG_CTL_KROUTE, >-- IMSG_CTL_KROUTE6, >- IMSG_CTL_KROUTE_ADDR, >- IMSG_CTL_RESULT, >- IMSG_CTL_SHOW_NEIGHBOR, >-@@ -288,11 +365,14 @@ enum imsg_type { >- IMSG_CTL_SHOW_RIB_ATTR, >- IMSG_CTL_SHOW_RIB_COMMUNITY, >- IMSG_CTL_SHOW_NETWORK, >-- IMSG_CTL_SHOW_NETWORK6, >- IMSG_CTL_SHOW_RIB_MEM, >- IMSG_CTL_SHOW_TERSE, >- IMSG_CTL_SHOW_TIMER, >-+ IMSG_CTL_LOG_VERBOSE, >-+ IMSG_CTL_SHOW_FIB_TABLES, >- IMSG_NETWORK_ADD, >-+ IMSG_NETWORK_ASPATH, >-+ IMSG_NETWORK_ATTR, >- IMSG_NETWORK_REMOVE, >- IMSG_NETWORK_FLUSH, >- IMSG_NETWORK_DONE, >-@@ -302,19 +382,25 @@ enum imsg_type { >- IMSG_RECONF_PEER, >- IMSG_RECONF_FILTER, >- IMSG_RECONF_LISTENER, >-+ IMSG_RECONF_CTRL, >-+ IMSG_RECONF_RDOMAIN, >-+ IMSG_RECONF_RDOMAIN_EXPORT, >-+ IMSG_RECONF_RDOMAIN_IMPORT, >-+ IMSG_RECONF_RDOMAIN_DONE, >- IMSG_RECONF_DONE, >- IMSG_UPDATE, >- IMSG_UPDATE_ERR, >- IMSG_SESSION_ADD, >- IMSG_SESSION_UP, >- IMSG_SESSION_DOWN, >-+ IMSG_SESSION_STALE, >-+ IMSG_SESSION_FLUSH, >-+ IMSG_SESSION_RESTARTED, >- IMSG_MRT_OPEN, >- IMSG_MRT_REOPEN, >- IMSG_MRT_CLOSE, >- IMSG_KROUTE_CHANGE, >- IMSG_KROUTE_DELETE, >-- IMSG_KROUTE6_CHANGE, >-- IMSG_KROUTE6_DELETE, >- IMSG_NEXTHOP_ADD, >- IMSG_NEXTHOP_REMOVE, >- IMSG_NEXTHOP_UPDATE, >-@@ -337,6 +423,7 @@ enum ctl_results { >- CTL_RES_DENIED, >- CTL_RES_NOCAP, >- CTL_RES_PARSE_ERROR, >-+ CTL_RES_PENDING, >- CTL_RES_NOMEM >- }; >- >-@@ -379,9 +466,43 @@ enum suberr_cease { >- ERR_CEASE_RSRC_EXHAUST >- }; >- >-+struct kroute_node; >-+struct kroute6_node; >-+struct knexthop_node; >-+RB_HEAD(kroute_tree, kroute_node); >-+RB_HEAD(kroute6_tree, kroute6_node); >-+RB_HEAD(knexthop_tree, knexthop_node); >-+ >-+struct ktable { >-+ char descr[PEER_DESCR_LEN]; >-+ char ifmpe[IFNAMSIZ]; >-+ struct kroute_tree krt; >-+ struct kroute6_tree krt6; >-+ struct knexthop_tree knt; >-+ struct network_head krn; >-+ u_int rtableid; >-+ u_int nhtableid; /* rdomain id for nexthop lookup */ >-+ u_int ifindex; /* ifindex of ifmpe */ >-+ int nhrefcnt; /* refcnt for nexthop table */ >-+ enum reconf_action state; >-+ u_int8_t fib_conf; /* configured FIB sync flag */ >-+ u_int8_t fib_sync; /* is FIB synced with kernel? */ >-+}; >-+ >-+struct kroute_full { >-+ struct bgpd_addr prefix; >-+ struct bgpd_addr nexthop; >-+ char label[RTLABEL_LEN]; >-+ u_int16_t flags; >-+ u_short ifindex; >-+ u_int8_t prefixlen; >-+ u_int8_t priority; >-+}; >-+ >- struct kroute { >- struct in_addr prefix; >- struct in_addr nexthop; >-+ u_int32_t mplslabel; >- u_int16_t flags; >- u_int16_t labelid; >- u_short ifindex; >-@@ -400,14 +521,12 @@ struct kroute6 { >- }; >- >- struct kroute_nexthop { >-- union { >-- struct kroute kr4; >-- struct kroute6 kr6; >-- } kr; >- struct bgpd_addr nexthop; >- struct bgpd_addr gateway; >-+ struct bgpd_addr net; >- u_int8_t valid; >- u_int8_t connected; >-+ u_int8_t netlen; >- }; >- >- struct kif { >-@@ -423,8 +542,7 @@ struct kif { >- struct session_up { >- struct bgpd_addr local_addr; >- struct bgpd_addr remote_addr; >-- struct capabilities capa_announced; >-- struct capabilities capa_received; >-+ struct capabilities capa; >- u_int32_t remote_bgpid; >- u_int16_t short_as; >- }; >-@@ -437,8 +555,13 @@ struct pftable_msg { >- >- struct ctl_show_nexthop { >- struct bgpd_addr addr; >-- u_int8_t valid; >- struct kif kif; >-+ union { >-+ struct kroute kr4; >-+ struct kroute6 kr6; >-+ } kr; >-+ u_int8_t valid; >-+ u_int8_t krvalid; >- }; >- >- struct ctl_neighbor { >-@@ -447,20 +570,11 @@ struct ctl_neighbor { >- int show_timers; >- }; >- >--struct kroute_label { >-- struct kroute kr; >-- char label[RTLABEL_LEN]; >--}; >-- >--struct kroute6_label { >-- struct kroute6 kr; >-- char label[RTLABEL_LEN]; >--}; >-- >--#define F_RIB_ELIGIBLE 0x01 >--#define F_RIB_ACTIVE 0x02 >--#define F_RIB_INTERNAL 0x04 >--#define F_RIB_ANNOUNCE 0x08 >-+#define F_PREF_ELIGIBLE 0x01 >-+#define F_PREF_ACTIVE 0x02 >-+#define F_PREF_INTERNAL 0x04 >-+#define F_PREF_ANNOUNCE 0x08 >-+#define F_PREF_STALE 0x10 >- >- struct ctl_show_rib { >- struct bgpd_addr true_nexthop; >-@@ -472,9 +586,7 @@ struct ctl_show_rib { >- u_int32_t remote_id; >- u_int32_t local_pref; >- u_int32_t med; >-- u_int32_t prefix_cnt; >-- u_int32_t active_cnt; >-- u_int32_t rib_cnt; >-+ u_int32_t weight; >- u_int16_t aspath_len; >- u_int16_t flags; >- u_int8_t prefixlen; >-@@ -482,13 +594,6 @@ struct ctl_show_rib { >- /* plus a aspath_len bytes long aspath */ >- }; >- >--struct ctl_show_rib_prefix { >-- struct bgpd_addr prefix; >-- time_t lastchange; >-- u_int16_t flags; >-- u_int8_t prefixlen; >--}; >-- >- enum as_spec { >- AS_NONE, >- AS_ALL, >-@@ -498,16 +603,52 @@ enum as_spec { >- AS_EMPTY >- }; >- >-+enum aslen_spec { >-+ ASLEN_NONE, >-+ ASLEN_MAX, >-+ ASLEN_SEQ >-+}; >-+ >- struct filter_as { >-- enum as_spec type; >- u_int32_t as; >-+ u_int16_t flags; >-+ enum as_spec type; >- }; >- >-+struct filter_aslen { >-+ u_int aslen; >-+ enum aslen_spec type; >-+}; >-+ >-+#define AS_FLAG_NEIGHBORAS 0x01 >-+ >- struct filter_community { >-- int as; >-- int type; >-+ int as; >-+ int type; >- }; >- >-+struct filter_extcommunity { >-+ u_int16_t flags; >-+ u_int8_t type; >-+ u_int8_t subtype; /* if extended type */ >-+ union { >-+ struct ext_as { >-+ u_int16_t as; >-+ u_int32_t val; >-+ } ext_as; >-+ struct ext_as4 { >-+ u_int32_t as4; >-+ u_int16_t val; >-+ } ext_as4; >-+ struct ext_ip { >-+ struct in_addr addr; >-+ u_int16_t val; >-+ } ext_ip; >-+ u_int64_t ext_opaq; /* only 48 bits */ >-+ } data; >-+}; >-+ >-+ >- struct ctl_show_rib_request { >- char rib[PEER_DESCR_LEN]; >- struct ctl_neighbor neighbor; >-@@ -518,8 +659,8 @@ struct ctl_show_rib_request { >- pid_t pid; >- u_int16_t flags; >- enum imsg_type type; >-- sa_family_t af; >- u_int8_t prefixlen; >-+ u_int8_t aid; >- }; >- >- enum filter_actions { >-@@ -585,6 +726,28 @@ struct filter_peers { >- #define EXT_COMMUNITY_OSPF_RTR_TYPE 6 /* RFC 4577 */ >- #define EXT_COMMUNITY_OSPF_RTR_ID 7 /* RFC 4577 */ >- #define EXT_COMMUNITY_BGP_COLLECT 8 /* RFC 4384 */ >-+/* other handy defines */ >-+#define EXT_COMMUNITY_OPAQUE_MAX 0xffffffffffffULL >-+#define EXT_COMMUNITY_FLAG_VALID 0x01 >-+ >-+struct ext_comm_pairs { >-+ u_int8_t type; >-+ u_int8_t subtype; >-+ u_int8_t transitive; /* transitive bit needs to be set */ >-+}; >-+ >-+#define IANA_EXT_COMMUNITIES { \ >-+ { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_ROUTE_TGT, 0 }, \ >-+ { EXT_COMMUNITY_TWO_AS, EXT_CUMMUNITY_ROUTE_ORIG, 0 }, \ >-+ { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_OSPF_DOM_ID, 0 }, \ >-+ { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_BGP_COLLECT, 0 }, \ >-+ { EXT_COMMUNITY_FOUR_AS, EXT_COMMUNITY_ROUTE_TGT, 0 }, \ >-+ { EXT_COMMUNITY_FOUR_AS, EXT_CUMMUNITY_ROUTE_ORIG, 0 }, \ >-+ { EXT_COMMUNITY_IPV4, EXT_COMMUNITY_ROUTE_TGT, 0 }, \ >-+ { EXT_COMMUNITY_IPV4, EXT_CUMMUNITY_ROUTE_ORIG, 0 }, \ >-+ { EXT_COMMUNITY_IPV4, EXT_COMMUNITY_OSPF_RTR_ID, 0 }, \ >-+ { EXT_COMMUNITY_OPAQUE, EXT_COMMUNITY_OSPF_RTR_TYPE, 0 } \ >-+} >- >- >- struct filter_prefix { >-@@ -592,18 +755,28 @@ struct filter_prefix { >- u_int8_t len; >- }; >- >-+struct filter_nexthop { >-+ struct bgpd_addr addr; >-+ u_int8_t flags; >-+#define FILTER_NEXTHOP_ADDR 1 >-+#define FILTER_NEXTHOP_NEIGHBOR 2 >-+}; >-+ >- struct filter_prefixlen { >- enum comp_ops op; >-- sa_family_t af; >-+ u_int8_t aid; >- u_int8_t len_min; >- u_int8_t len_max; >- }; >- >- struct filter_match { >-- struct filter_prefix prefix; >-- struct filter_prefixlen prefixlen; >-- struct filter_as as; >-- struct filter_community community; >-+ struct filter_prefix prefix; >-+ struct filter_prefixlen prefixlen; >-+ struct filter_nexthop nexthop; >-+ struct filter_as as; >-+ struct filter_aslen aslen; >-+ struct filter_community community; >-+ struct filter_extcommunity ext_community; >- }; >- >- TAILQ_HEAD(filter_head, filter_rule); >-@@ -635,10 +808,13 @@ enum action_types { >- ACTION_SET_NEXTHOP_SELF, >- ACTION_SET_COMMUNITY, >- ACTION_DEL_COMMUNITY, >-+ ACTION_SET_EXT_COMMUNITY, >-+ ACTION_DEL_EXT_COMMUNITY, >- ACTION_PFTABLE, >- ACTION_PFTABLE_ID, >- ACTION_RTLABEL, >-- ACTION_RTLABEL_ID >-+ ACTION_RTLABEL_ID, >-+ ACTION_SET_ORIGIN >- }; >- >- struct filter_set { >-@@ -650,23 +826,53 @@ struct filter_set { >- int32_t relative; >- struct bgpd_addr nexthop; >- struct filter_community community; >-+ struct filter_extcommunity ext_community; >- char pftable[PFTABLE_LEN]; >- char rtlabel[RTLABEL_LEN]; >-+ u_int8_t origin; >- } action; >- enum action_types type; >- }; >- >--struct rrefresh { >-- u_int16_t afi; >-- u_int8_t safi; >-+struct rdomain { >-+ SIMPLEQ_ENTRY(rdomain) entry; >-+ char descr[PEER_DESCR_LEN]; >-+ char ifmpe[IFNAMSIZ]; >-+ struct filter_set_head import; >-+ struct filter_set_head export; >-+ struct network_head net_l; >-+ u_int64_t rd; >-+ u_int rtableid; >-+ u_int label; >-+ int flags; >- }; >-+SIMPLEQ_HEAD(rdomain_head, rdomain); >-+ >-+struct rde_rib { >-+ SIMPLEQ_ENTRY(rde_rib) entry; >-+ char name[PEER_DESCR_LEN]; >-+ u_int rtableid; >-+ u_int16_t id; >-+ u_int16_t flags; >-+}; >-+SIMPLEQ_HEAD(rib_names, rde_rib); >-+extern struct rib_names ribnames; >-+ >-+/* rde_rib flags */ >-+#define F_RIB_ENTRYLOCK 0x0001 >-+#define F_RIB_NOEVALUATE 0x0002 >-+#define F_RIB_NOFIB 0x0004 >-+#define F_RIB_NOFIBSYNC 0x0008 >-+#define F_RIB_HASNOFIB (F_RIB_NOFIB | F_RIB_NOEVALUATE) >-+ >-+/* 4-byte magic AS number */ >-+#define AS_TRANS 23456 >- >- struct rde_memstats { >- int64_t path_cnt; >- int64_t prefix_cnt; >- int64_t rib_cnt; >-- int64_t pt4_cnt; >-- int64_t pt6_cnt; >-+ int64_t pt_cnt[AID_MAX]; >- int64_t nexthop_cnt; >- int64_t aspath_cnt; >- int64_t aspath_size; >-@@ -677,82 +883,117 @@ struct rde_memstats { >- int64_t attr_dcnt; >- }; >- >--struct rde_rib { >-- SIMPLEQ_ENTRY(rde_rib) entry; >-- char name[PEER_DESCR_LEN]; >-- u_int16_t id; >-- u_int16_t flags; >-+/* macros for IPv6 link-local address */ >-+#ifdef __KAME__ >-+#define IN6_LINKLOCAL_IFINDEX(addr) \ >-+ ((addr).s6_addr[2] << 8 | (addr).s6_addr[3]) >-+ >-+#define SET_IN6_LINKLOCAL_IFINDEX(addr, index) \ >-+ do { \ >-+ (addr).s6_addr[2] = ((index) >> 8) & 0xff; \ >-+ (addr).s6_addr[3] = (index) & 0xff; \ >-+ } while (0) >-+#endif >-+ >-+#define MRT_FILE_LEN 512 >-+#define MRT2MC(x) ((struct mrt_config *)(x)) >-+#define MRT_MAX_TIMEOUT 7200 >-+ >-+enum mrt_type { >-+ MRT_NONE, >-+ MRT_TABLE_DUMP, >-+ MRT_TABLE_DUMP_MP, >-+ MRT_TABLE_DUMP_V2, >-+ MRT_ALL_IN, >-+ MRT_ALL_OUT, >-+ MRT_UPDATE_IN, >-+ MRT_UPDATE_OUT >-+}; >-+ >-+enum mrt_state { >-+ MRT_STATE_RUNNING, >-+ MRT_STATE_OPEN, >-+ MRT_STATE_REOPEN, >-+ MRT_STATE_REMOVE >- }; >--SIMPLEQ_HEAD(rib_names, rde_rib); >--extern struct rib_names ribnames; >- >--/* Address Family Numbers as per RFC 1700 */ >--#define AFI_IPv4 1 >--#define AFI_IPv6 2 >--#define AFI_ALL 0xffff >-- >--/* Subsequent Address Family Identifier as per RFC 4760 */ >--#define SAFI_NONE 0x00 >--#define SAFI_UNICAST 0x01 >--#define SAFI_MULTICAST 0x02 >--#define SAFI_ALL 0xff >-+struct mrt { >-+ char rib[PEER_DESCR_LEN]; >-+ struct msgbuf wbuf; >-+ LIST_ENTRY(mrt) entry; >-+ u_int32_t peer_id; >-+ u_int32_t group_id; >-+ enum mrt_type type; >-+ enum mrt_state state; >-+ u_int16_t seqnum; >-+}; >- >--/* 4-byte magic AS number */ >--#define AS_TRANS 23456 >-+struct mrt_config { >-+ struct mrt conf; >-+ char name[MRT_FILE_LEN]; /* base file name */ >-+ char file[MRT_FILE_LEN]; /* actual file name */ >-+ time_t ReopenTimer; >-+ time_t ReopenTimerInterval; >-+}; >- >- /* prototypes */ >- /* bgpd.c */ >- void send_nexthop_update(struct kroute_nexthop *); >- void send_imsg_session(int, pid_t, void *, u_int16_t); >--int bgpd_redistribute(int, struct kroute *, struct kroute6 *); >-+int send_network(int, struct network_config *, >-+ struct filter_set_head *); >- int bgpd_filternexthop(struct kroute *, struct kroute6 *); >- >--/* log.c */ >--void log_init(int); >--void vlog(int, const char *, va_list); >--void log_peer_warn(const struct peer_config *, const char *, ...); >--void log_peer_warnx(const struct peer_config *, const char *, ...); >--void log_warn(const char *, ...); >--void log_warnx(const char *, ...); >--void log_info(const char *, ...); >--void log_debug(const char *, ...); >--void fatal(const char *) __dead; >--void fatalx(const char *) __dead; >-- >--/* parse.y */ >--int cmdline_symset(char *); >-+/* control.c */ >-+void control_cleanup(const char *); >-+int control_imsg_relay(struct imsg *); >- >- /* config.c */ >- int host(const char *, struct bgpd_addr *, u_int8_t *); >- >- /* kroute.c */ >--int kr_init(int, u_int); >--int kr_change(struct kroute_label *); >--int kr_delete(struct kroute_label *); >--int kr6_change(struct kroute6_label *); >--int kr6_delete(struct kroute6_label *); >-+int kr_init(void); >-+int ktable_update(u_int, char *, char *, int); >-+void ktable_preload(void); >-+void ktable_postload(void); >-+int ktable_exists(u_int, u_int *); >-+int kr_change(u_int, struct kroute_full *); >-+int kr_delete(u_int, struct kroute_full *); >- void kr_shutdown(void); >--void kr_fib_couple(void); >--void kr_fib_decouple(void); >-+void kr_fib_couple(u_int); >-+void kr_fib_decouple(u_int); >- int kr_dispatch_msg(void); >--int kr_nexthop_add(struct bgpd_addr *); >--void kr_nexthop_delete(struct bgpd_addr *); >-+int kr_nexthop_add(u_int32_t, struct bgpd_addr *); >-+void kr_nexthop_delete(u_int32_t, struct bgpd_addr *); >- void kr_show_route(struct imsg *); >- void kr_ifinfo(char *); >-+int kr_net_reload(u_int, struct network_head *); >- int kr_reload(void); >- struct in6_addr *prefixlen2mask6(u_int8_t prefixlen); >- >--/* control.c */ >--void control_cleanup(const char *); >--int control_imsg_relay(struct imsg *); >-+/* log.c */ >-+void log_init(int); >-+void log_verbose(int); >-+void vlog(int, const char *, va_list); >-+void log_peer_warn(const struct peer_config *, const char *, ...); >-+void log_peer_warnx(const struct peer_config *, const char *, ...); >-+void log_warn(const char *, ...); >-+void log_warnx(const char *, ...); >-+void log_info(const char *, ...); >-+void log_debug(const char *, ...); >-+void fatal(const char *) __dead; >-+void fatalx(const char *) __dead; >- >--/* pftable.c */ >--int pftable_exists(const char *); >--int pftable_add(const char *); >--int pftable_clear_all(void); >--int pftable_addr_add(struct pftable_msg *); >--int pftable_addr_remove(struct pftable_msg *); >--int pftable_commit(void); >-+/* mrt.c */ >-+void mrt_clear_seq(void); >-+void mrt_write(struct mrt *); >-+void mrt_clean(struct mrt *); >-+void mrt_init(struct imsgbuf *, struct imsgbuf *); >-+int mrt_timeout(struct mrt_head *); >-+void mrt_reconfigure(struct mrt_head *); >-+void mrt_handler(struct mrt_head *); >-+struct mrt *mrt_get(struct mrt_head *, struct mrt *); >-+int mrt_mergeconfig(struct mrt_head *, struct mrt_head *); >- >- /* name2id.c */ >- u_int16_t rib_name2id(const char *); >-@@ -768,10 +1009,22 @@ const char *pftable_id2name(u_int16_t); >- void pftable_unref(u_int16_t); >- void pftable_ref(u_int16_t); >- >-+/* parse.y */ >-+int cmdline_symset(char *); >-+ >-+/* pftable.c */ >-+int pftable_exists(const char *); >-+int pftable_add(const char *); >-+int pftable_clear_all(void); >-+int pftable_addr_add(struct pftable_msg *); >-+int pftable_addr_remove(struct pftable_msg *); >-+int pftable_commit(void); >- >- /* rde_filter.c */ >- void filterset_free(struct filter_set_head *); >- int filterset_cmp(struct filter_set *, struct filter_set *); >-+void filterset_move(struct filter_set_head *, >-+ struct filter_set_head *); >- const char *filterset_name(enum action_types); >- >- /* util.c */ >-@@ -779,11 +1032,24 @@ const char *log_addr(const struct bgpd_a >- const char *log_in6addr(const struct in6_addr *); >- const char *log_sockaddr(struct sockaddr *); >- const char *log_as(u_int32_t); >-+const char *log_rd(u_int64_t); >-+const char *log_ext_subtype(u_int8_t); >- int aspath_snprint(char *, size_t, void *, u_int16_t); >- int aspath_asprint(char **, void *, u_int16_t); >- size_t aspath_strlen(void *, u_int16_t); >-+int aspath_match(void *, u_int16_t, enum as_spec, u_int32_t); >-+u_int32_t aspath_extract(const void *, int); >-+int prefix_compare(const struct bgpd_addr *, >-+ const struct bgpd_addr *, int); >- in_addr_t prefixlen2mask(u_int8_t); >- void inet6applymask(struct in6_addr *, const struct in6_addr *, >- int); >-+const char *aid2str(u_int8_t); >-+int aid2afi(u_int8_t, u_int16_t *, u_int8_t *); >-+int afi2aid(u_int16_t, u_int8_t, u_int8_t *); >-+sa_family_t aid2af(u_int8_t); >-+int af2aid(sa_family_t, u_int8_t, u_int8_t *); >-+struct sockaddr *addr2sa(struct bgpd_addr *, u_int16_t); >-+void sa2addr(struct sockaddr *, struct bgpd_addr *); >- >- #endif /* __BGPD_H__ */ > >Property changes on: files/patch-bgpd_bgpd.h >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_buffer.c >=================================================================== >--- files/patch-bgpd_buffer.c (revision 500577) >+++ files/patch-bgpd_buffer.c (nonexistent) >@@ -1,104 +0,0 @@ >-Index: bgpd/buffer.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/buffer.c,v >-retrieving revision 1.1.1.7 >-retrieving revision 1.3 >-diff -u -p -r1.1.1.7 -r1.3 >---- bgpd/buffer.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 >-+++ bgpd/buffer.c 8 Dec 2012 20:17:59 -0000 1.3 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: buffer.c,v 1.43 2009/06/06 06:33:15 eric Exp $ */ >-+/* $OpenBSD: buffer.c,v 1.44 2009/07/23 18:58:42 eric Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-@@ -144,7 +144,7 @@ int >- buf_write(struct msgbuf *msgbuf) >- { >- struct iovec iov[IOV_MAX]; >-- struct buf *buf, *next; >-+ struct buf *buf; >- unsigned int i = 0; >- ssize_t n; >- >-@@ -153,7 +153,7 @@ buf_write(struct msgbuf *msgbuf) >- if (i >= IOV_MAX) >- break; >- iov[i].iov_base = buf->buf + buf->rpos; >-- iov[i].iov_len = buf->size - buf->rpos; >-+ iov[i].iov_len = buf->wpos - buf->rpos; >- i++; >- } >- >-@@ -170,17 +170,7 @@ buf_write(struct msgbuf *msgbuf) >- return (-2); >- } >- >-- for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; >-- buf = next) { >-- next = TAILQ_NEXT(buf, entry); >-- if (buf->rpos + n >= buf->size) { >-- n -= buf->size - buf->rpos; >-- buf_dequeue(msgbuf, buf); >-- } else { >-- buf->rpos += n; >-- n = 0; >-- } >-- } >-+ msgbuf_drain(msgbuf, n); >- >- return (0); >- } >-@@ -201,6 +191,24 @@ msgbuf_init(struct msgbuf *msgbuf) >- } >- >- void >-+msgbuf_drain(struct msgbuf *msgbuf, size_t n) >-+{ >-+ struct buf *buf, *next; >-+ >-+ for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; >-+ buf = next) { >-+ next = TAILQ_NEXT(buf, entry); >-+ if (buf->rpos + n >= buf->wpos) { >-+ n -= buf->wpos - buf->rpos; >-+ buf_dequeue(msgbuf, buf); >-+ } else { >-+ buf->rpos += n; >-+ n = 0; >-+ } >-+ } >-+} >-+ >-+void >- msgbuf_clear(struct msgbuf *msgbuf) >- { >- struct buf *buf; >-@@ -213,7 +221,7 @@ int >- msgbuf_write(struct msgbuf *msgbuf) >- { >- struct iovec iov[IOV_MAX]; >-- struct buf *buf, *next; >-+ struct buf *buf; >- unsigned int i = 0; >- ssize_t n; >- struct msghdr msg; >-@@ -270,17 +278,7 @@ msgbuf_write(struct msgbuf *msgbuf) >- buf->fd = -1; >- } >- >-- for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; >-- buf = next) { >-- next = TAILQ_NEXT(buf, entry); >-- if (buf->rpos + n >= buf->wpos) { >-- n -= buf->wpos - buf->rpos; >-- buf_dequeue(msgbuf, buf); >-- } else { >-- buf->rpos += n; >-- n = 0; >-- } >-- } >-+ msgbuf_drain(msgbuf, n); >- >- return (0); >- } > >Property changes on: files/patch-bgpd_buffer.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_carp.c >=================================================================== >--- files/patch-bgpd_carp.c (revision 500577) >+++ files/patch-bgpd_carp.c (nonexistent) >@@ -1,54 +0,0 @@ >-Index: bgpd/carp.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/carp.c,v >-retrieving revision 1.1.1.6 >-retrieving revision 1.4 >-diff -u -p -r1.1.1.6 -r1.4 >---- bgpd/carp.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 >-+++ bgpd/carp.c 22 Oct 2009 15:10:02 -0000 1.4 >-@@ -93,9 +93,8 @@ carp_demote_shutdown(void) >- >- while ((c = TAILQ_FIRST(&carpgroups)) != NULL) { >- TAILQ_REMOVE(&carpgroups, c, entry); >-- for (; c->changed_by > 0; c->changed_by--) >-- if (c->do_demote) >-- carp_demote_ioctl(c->group, -1); >-+ if (c->do_demote && c->changed_by > 0) >-+ carp_demote_ioctl(c->group, -c->changed_by); >- >- free(c->group); >- free(c); >-@@ -105,6 +104,9 @@ carp_demote_shutdown(void) >- int >- carp_demote_get(char *group) >- { >-+#if defined(__FreeBSD__) /* FreeBSD does not have support for CARP */ >-+ return (-1); >-+#else >- int s; >- struct ifgroupreq ifgr; >- >-@@ -127,6 +129,7 @@ carp_demote_get(char *group) >- >- close(s); >- return ((int)ifgr.ifgr_attrib.ifg_carp_demoted); >-+#endif /* defined(__FreeBSD__) */ >- } >- >- int >-@@ -159,6 +162,9 @@ carp_demote_set(char *group, int demote) >- int >- carp_demote_ioctl(char *group, int demote) >- { >-+#if defined(__FreeBSD__) /* FreeBSD does not have support for CARP */ >-+ return (-1); >-+#else >- int s, res; >- struct ifgroupreq ifgr; >- >-@@ -181,4 +187,5 @@ carp_demote_ioctl(char *group, int demot >- >- close(s); >- return (res); >-+#endif /* defined(__FreeBSD__) */ >- } > >Property changes on: files/patch-bgpd_carp.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_config.c >=================================================================== >--- files/patch-bgpd_config.c (revision 500577) >+++ files/patch-bgpd_config.c (nonexistent) >@@ -1,109 +0,0 @@ >-Index: bgpd/config.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/config.c,v >-retrieving revision 1.1.1.6 >-retrieving revision 1.3 >-diff -u -p -r1.1.1.6 -r1.3 >---- bgpd/config.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 >-+++ bgpd/config.c 13 Oct 2012 18:36:00 -0000 1.3 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: config.c,v 1.51 2009/01/26 23:10:02 claudio Exp $ */ >-+/* $OpenBSD: config.c,v 1.55 2010/09/02 14:03:21 sobrado Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> >-@@ -20,6 +20,11 @@ >- #include <sys/socket.h> >- #include <sys/stat.h> >- #include <sys/mman.h> >-+#include <sys/ioctl.h> >-+ >-+#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */ >-+#include <netmpls/mpls.h> >-+#endif >- >- #include <errno.h> >- #include <ifaddrs.h> >-@@ -47,8 +52,6 @@ merge_config(struct bgpd_config *xconf, >- >- /* preserve cmd line opts */ >- conf->opts = xconf->opts; >-- conf->csock = xconf->csock; >-- conf->rcsock = xconf->rcsock; >- >- if (!conf->as) { >- log_warnx("configuration error: AS not given"); >-@@ -64,6 +67,9 @@ merge_config(struct bgpd_config *xconf, >- if ((conf->flags & BGPD_FLAG_REFLECTOR) && conf->clusterid == 0) >- conf->clusterid = conf->bgpid; >- >-+ free(xconf->csock); >-+ free(xconf->rcsock); >-+ >- conf->listen_addrs = xconf->listen_addrs; >- memcpy(xconf, conf, sizeof(struct bgpd_config)); >- >-@@ -74,7 +80,7 @@ merge_config(struct bgpd_config *xconf, >- nla->reconf = RECONF_REINIT; >- >- } else { >-- /* >-+ /* >- * merge new listeners: >- * -flag all existing ones as to be deleted >- * -those that are in both new and old: flag to keep >-@@ -208,7 +214,7 @@ host_v4(const char *s, struct bgpd_addr >- return (0); >- } >- >-- h->af = AF_INET; >-+ h->aid = AID_INET; >- h->v4.s_addr = ina.s_addr; >- *len = bits; >- >-@@ -225,13 +231,7 @@ host_v6(const char *s, struct bgpd_addr >- hints.ai_socktype = SOCK_DGRAM; /*dummy*/ >- hints.ai_flags = AI_NUMERICHOST; >- if (getaddrinfo(s, "0", &hints, &res) == 0) { >-- h->af = AF_INET6; >-- memcpy(&h->v6, >-- &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, >-- sizeof(h->v6)); >-- h->scope_id = >-- ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; >-- >-+ sa2addr(res->ai_addr, h); >- freeaddrinfo(res); >- return (1); >- } >-@@ -317,3 +317,30 @@ prepare_listeners(struct bgpd_config *co >- } >- } >- } >-+ >-+int >-+get_mpe_label(struct rdomain *r) >-+{ >-+#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */ >-+ struct ifreq ifr; >-+ struct shim_hdr shim; >-+ int s; >-+ >-+ s = socket(AF_INET, SOCK_DGRAM, 0); >-+ if (s == -1) >-+ return (-1); >-+ >-+ bzero(&shim, sizeof(shim)); >-+ bzero(&ifr, sizeof(ifr)); >-+ strlcpy(ifr.ifr_name, r->ifmpe, sizeof(ifr.ifr_name)); >-+ ifr.ifr_data = (caddr_t)&shim; >-+ >-+ if (ioctl(s, SIOCGETLABEL, (caddr_t)&ifr) == -1) { >-+ close(s); >-+ return (-1); >-+ } >-+ close(s); >-+ r->label = shim.shim_label; >-+#endif >-+ return (0); >-+} > >Property changes on: files/patch-bgpd_config.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_control.c >=================================================================== >--- files/patch-bgpd_control.c (revision 500577) >+++ files/patch-bgpd_control.c (nonexistent) >@@ -1,171 +0,0 @@ >-Index: bgpd/control.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/control.c,v >-retrieving revision 1.1.1.7 >-retrieving revision 1.1.1.10 >-diff -u -p -r1.1.1.7 -r1.1.1.10 >---- bgpd/control.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 >-+++ bgpd/control.c 13 Oct 2012 18:22:41 -0000 1.1.1.10 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: control.c,v 1.61 2009/05/05 20:09:19 sthen Exp $ */ >-+/* $OpenBSD: control.c,v 1.71 2012/04/12 17:26:09 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-@@ -53,7 +53,7 @@ control_init(int restricted, char *path) >- >- if (unlink(path) == -1) >- if (errno != ENOENT) { >-- log_warn("unlink %s", path); >-+ log_warn("control_init: unlink %s", path); >- close(fd); >- return (-1); >- } >-@@ -122,15 +122,18 @@ control_accept(int listenfd, int restric >- len = sizeof(sun); >- if ((connfd = accept(listenfd, >- (struct sockaddr *)&sun, &len)) == -1) { >-- if (errno != EWOULDBLOCK && errno != EINTR) >-- log_warn("session_control_accept"); >-+ if (errno == ENFILE || errno == EMFILE) { >-+ pauseaccept = getmonotime(); >-+ return (0); >-+ } else if (errno != EWOULDBLOCK && errno != EINTR) >-+ log_warn("control_accept: accept"); >- return (0); >- } >- >- session_socket_blockmode(connfd, BM_NONBLOCK); >- >-- if ((ctl_conn = malloc(sizeof(struct ctl_conn))) == NULL) { >-- log_warn("session_control_accept"); >-+ if ((ctl_conn = calloc(1, sizeof(struct ctl_conn))) == NULL) { >-+ log_warn("control_accept"); >- close(connfd); >- return (0); >- } >-@@ -182,7 +185,7 @@ control_close(int fd) >- >- close(c->ibuf.fd); >- free(c); >-- >-+ pauseaccept = 0; >- return (1); >- } >- >-@@ -191,7 +194,8 @@ control_dispatch_msg(struct pollfd *pfd, >- { >- struct imsg imsg; >- struct ctl_conn *c; >-- int n; >-+ ssize_t n; >-+ int verbose; >- struct peer *p; >- struct ctl_neighbor *neighbor; >- struct ctl_show_rib_request *ribreq; >-@@ -305,7 +309,8 @@ control_dispatch_msg(struct pollfd *pfd, >- break; >- case IMSG_CTL_FIB_COUPLE: >- case IMSG_CTL_FIB_DECOUPLE: >-- imsg_compose_parent(imsg.hdr.type, 0, NULL, 0); >-+ imsg_compose_parent(imsg.hdr.type, imsg.hdr.peerid, >-+ 0, NULL, 0); >- break; >- case IMSG_CTL_NEIGHBOR_UP: >- case IMSG_CTL_NEIGHBOR_DOWN: >-@@ -328,13 +333,19 @@ control_dispatch_msg(struct pollfd *pfd, >- control_result(c, CTL_RES_OK); >- break; >- case IMSG_CTL_NEIGHBOR_DOWN: >-- bgp_fsm(p, EVNT_STOP); >-+ session_stop(p, ERR_CEASE_ADMIN_DOWN); >- control_result(c, CTL_RES_OK); >- break; >- case IMSG_CTL_NEIGHBOR_CLEAR: >-- bgp_fsm(p, EVNT_STOP); >-- timer_set(p, Timer_IdleHold, >-- SESSION_CLEAR_DELAY); >-+ if (!p->conf.down) { >-+ session_stop(p, >-+ ERR_CEASE_ADMIN_RESET); >-+ timer_set(p, Timer_IdleHold, >-+ SESSION_CLEAR_DELAY); >-+ } else { >-+ session_stop(p, >-+ ERR_CEASE_ADMIN_DOWN); >-+ } >- control_result(c, CTL_RES_OK); >- break; >- case IMSG_CTL_NEIGHBOR_RREFRESH: >-@@ -352,13 +363,19 @@ control_dispatch_msg(struct pollfd *pfd, >- "wrong length"); >- break; >- case IMSG_CTL_RELOAD: >-+ case IMSG_CTL_SHOW_INTERFACE: >-+ case IMSG_CTL_SHOW_FIB_TABLES: >-+ c->ibuf.pid = imsg.hdr.pid; >-+ imsg_compose_parent(imsg.hdr.type, 0, imsg.hdr.pid, >-+ imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); >-+ break; >- case IMSG_CTL_KROUTE: >- case IMSG_CTL_KROUTE_ADDR: >- case IMSG_CTL_SHOW_NEXTHOP: >-- case IMSG_CTL_SHOW_INTERFACE: >- c->ibuf.pid = imsg.hdr.pid; >-- imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid, >-- imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); >-+ imsg_compose_parent(imsg.hdr.type, imsg.hdr.peerid, >-+ imsg.hdr.pid, imsg.data, imsg.hdr.len - >-+ IMSG_HEADER_SIZE); >- break; >- case IMSG_CTL_SHOW_RIB: >- case IMSG_CTL_SHOW_RIB_AS: >-@@ -370,7 +387,7 @@ control_dispatch_msg(struct pollfd *pfd, >- neighbor->descr[PEER_DESCR_LEN - 1] = 0; >- ribreq->peerid = 0; >- p = NULL; >-- if (neighbor->addr.af) { >-+ if (neighbor->addr.aid) { >- p = getpeerbyaddr(&neighbor->addr); >- if (p == NULL) { >- control_result(c, >-@@ -397,8 +414,7 @@ control_dispatch_msg(struct pollfd *pfd, >- break; >- } >- if ((imsg.hdr.type == IMSG_CTL_SHOW_RIB_PREFIX) >-- && (ribreq->prefix.af != AF_INET) >-- && (ribreq->prefix.af != AF_INET6)) { >-+ && (ribreq->prefix.aid == AID_UNSPEC)) { >- /* malformed request, must specify af */ >- control_result(c, CTL_RES_PARSE_ERROR); >- break; >-@@ -418,6 +434,8 @@ control_dispatch_msg(struct pollfd *pfd, >- imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); >- break; >- case IMSG_NETWORK_ADD: >-+ case IMSG_NETWORK_ASPATH: >-+ case IMSG_NETWORK_ATTR: >- case IMSG_NETWORK_REMOVE: >- case IMSG_NETWORK_FLUSH: >- case IMSG_NETWORK_DONE: >-@@ -425,6 +443,20 @@ control_dispatch_msg(struct pollfd *pfd, >- imsg_compose_rde(imsg.hdr.type, 0, >- imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); >- break; >-+ case IMSG_CTL_LOG_VERBOSE: >-+ if (imsg.hdr.len != IMSG_HEADER_SIZE + >-+ sizeof(verbose)) >-+ break; >-+ >-+ /* forward to other processes */ >-+ imsg_compose_parent(imsg.hdr.type, 0, imsg.hdr.pid, >-+ imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); >-+ imsg_compose_rde(imsg.hdr.type, 0, >-+ imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); >-+ >-+ memcpy(&verbose, imsg.data, sizeof(verbose)); >-+ log_verbose(verbose); >-+ break; >- default: >- break; >- } > >Property changes on: files/patch-bgpd_control.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_imsg.c >=================================================================== >--- files/patch-bgpd_imsg.c (revision 500577) >+++ files/patch-bgpd_imsg.c (nonexistent) >@@ -1,275 +0,0 @@ >-Index: bgpd/imsg.c >-=================================================================== >-RCS file: bgpd/imsg.c >-diff -N bgpd/imsg.c >---- bgpd/imsg.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 >-+++ /dev/null 1 Jan 1970 00:00:00 -0000 >-@@ -1,268 +0,0 @@ >--/* $OpenBSD: imsg.c,v 1.47 2009/06/08 08:30:06 dlg Exp $ */ >-- >--/* >-- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-- * >-- * Permission to use, copy, modify, and distribute this software for any >-- * purpose with or without fee is hereby granted, provided that the above >-- * copyright notice and this permission notice appear in all copies. >-- * >-- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES >-- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF >-- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR >-- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES >-- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN >-- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF >-- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >-- */ >-- >--#include <sys/param.h> >--#include <sys/queue.h> >--#include <sys/socket.h> >--#include <sys/uio.h> >-- >--#include <errno.h> >--#include <stdlib.h> >--#include <string.h> >--#include <unistd.h> >-- >--#include "imsg.h" >-- >--int imsg_get_fd(struct imsgbuf *); >-- >--void >--imsg_init(struct imsgbuf *ibuf, int fd) >--{ >-- msgbuf_init(&ibuf->w); >-- bzero(&ibuf->r, sizeof(ibuf->r)); >-- ibuf->fd = fd; >-- ibuf->w.fd = fd; >-- ibuf->pid = getpid(); >-- TAILQ_INIT(&ibuf->fds); >--} >-- >--ssize_t >--imsg_read(struct imsgbuf *ibuf) >--{ >-- struct msghdr msg; >-- struct cmsghdr *cmsg; >-- union { >-- struct cmsghdr hdr; >-- char buf[CMSG_SPACE(sizeof(int) * 16)]; >-- } cmsgbuf; >-- struct iovec iov; >-- ssize_t n; >-- int fd; >-- struct imsg_fd *ifd; >-- >-- bzero(&msg, sizeof(msg)); >-- >-- iov.iov_base = ibuf->r.buf + ibuf->r.wpos; >-- iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos; >-- msg.msg_iov = &iov; >-- msg.msg_iovlen = 1; >-- msg.msg_control = &cmsgbuf.buf; >-- msg.msg_controllen = sizeof(cmsgbuf.buf); >-- >-- if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) { >-- if (errno != EINTR && errno != EAGAIN) { >-- return (-1); >-- } >-- return (-2); >-- } >-- >-- ibuf->r.wpos += n; >-- >-- for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; >-- cmsg = CMSG_NXTHDR(&msg, cmsg)) { >-- if (cmsg->cmsg_level == SOL_SOCKET && >-- cmsg->cmsg_type == SCM_RIGHTS) { >-- fd = (*(int *)CMSG_DATA(cmsg)); >-- if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) { >-- /* XXX: this return can leak */ >-- return (-1); >-- } >-- ifd->fd = fd; >-- TAILQ_INSERT_TAIL(&ibuf->fds, ifd, entry); >-- } >-- /* we do not handle other ctl data level */ >-- } >-- >-- return (n); >--} >-- >--ssize_t >--imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) >--{ >-- size_t av, left, datalen; >-- >-- av = ibuf->r.wpos; >-- >-- if (IMSG_HEADER_SIZE > av) >-- return (0); >-- >-- memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr)); >-- if (imsg->hdr.len < IMSG_HEADER_SIZE || >-- imsg->hdr.len > MAX_IMSGSIZE) { >-- errno = ERANGE; >-- return (-1); >-- } >-- if (imsg->hdr.len > av) >-- return (0); >-- datalen = imsg->hdr.len - IMSG_HEADER_SIZE; >-- ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE; >-- if ((imsg->data = malloc(datalen)) == NULL) >-- return (-1); >-- >-- if (imsg->hdr.flags & IMSGF_HASFD) >-- imsg->fd = imsg_get_fd(ibuf); >-- else >-- imsg->fd = -1; >-- >-- memcpy(imsg->data, ibuf->r.rptr, datalen); >-- >-- if (imsg->hdr.len < av) { >-- left = av - imsg->hdr.len; >-- memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left); >-- ibuf->r.wpos = left; >-- } else >-- ibuf->r.wpos = 0; >-- >-- return (datalen + IMSG_HEADER_SIZE); >--} >-- >--int >--imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, >-- pid_t pid, int fd, void *data, u_int16_t datalen) >--{ >-- struct buf *wbuf; >-- >-- if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) >-- return (-1); >-- >-- if (imsg_add(wbuf, data, datalen) == -1) >-- return (-1); >-- >-- wbuf->fd = fd; >-- >-- imsg_close(ibuf, wbuf); >-- >-- return (1); >--} >-- >--int >--imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, >-- pid_t pid, int fd, const struct iovec *iov, int iovcnt) >--{ >-- struct buf *wbuf; >-- int i, datalen = 0; >-- >-- for (i = 0; i < iovcnt; i++) >-- datalen += iov[i].iov_len; >-- >-- if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) >-- return (-1); >-- >-- for (i = 0; i < iovcnt; i++) >-- if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1) >-- return (-1); >-- >-- wbuf->fd = fd; >-- >-- imsg_close(ibuf, wbuf); >-- >-- return (1); >--} >-- >--/* ARGSUSED */ >--struct buf * >--imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, >-- pid_t pid, u_int16_t datalen) >--{ >-- struct buf *wbuf; >-- struct imsg_hdr hdr; >-- >-- datalen += IMSG_HEADER_SIZE; >-- if (datalen > MAX_IMSGSIZE) { >-- errno = ERANGE; >-- return (NULL); >-- } >-- >-- hdr.type = type; >-- hdr.flags = 0; >-- hdr.peerid = peerid; >-- if ((hdr.pid = pid) == 0) >-- hdr.pid = ibuf->pid; >-- if ((wbuf = buf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) { >-- return (NULL); >-- } >-- if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1) >-- return (NULL); >-- >-- return (wbuf); >--} >-- >--int >--imsg_add(struct buf *msg, void *data, u_int16_t datalen) >--{ >-- if (datalen) >-- if (buf_add(msg, data, datalen) == -1) { >-- buf_free(msg); >-- return (-1); >-- } >-- return (datalen); >--} >-- >--void >--imsg_close(struct imsgbuf *ibuf, struct buf *msg) >--{ >-- struct imsg_hdr *hdr; >-- >-- hdr = (struct imsg_hdr *)msg->buf; >-- >-- hdr->flags &= ~IMSGF_HASFD; >-- if (msg->fd != -1) >-- hdr->flags |= IMSGF_HASFD; >-- >-- hdr->len = (u_int16_t)msg->wpos; >-- >-- buf_close(&ibuf->w, msg); >--} >-- >--void >--imsg_free(struct imsg *imsg) >--{ >-- free(imsg->data); >--} >-- >--int >--imsg_get_fd(struct imsgbuf *ibuf) >--{ >-- int fd; >-- struct imsg_fd *ifd; >-- >-- if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL) >-- return (-1); >-- >-- fd = ifd->fd; >-- TAILQ_REMOVE(&ibuf->fds, ifd, entry); >-- free(ifd); >-- >-- return (fd); >--} >-- >--int >--imsg_flush(struct imsgbuf *ibuf) >--{ >-- while (ibuf->w.queued) >-- if (msgbuf_write(&ibuf->w) < 0) >-- return (-1); >-- return (0); >--} >-- >--void >--imsg_clear(struct imsgbuf *ibuf) >--{ >-- while (ibuf->w.queued) >-- msgbuf_clear(&ibuf->w); >--} > >Property changes on: files/patch-bgpd_imsg.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_imsg.h >=================================================================== >--- files/patch-bgpd_imsg.h (revision 500577) >+++ files/patch-bgpd_imsg.h (nonexistent) >@@ -1,115 +0,0 @@ >-Index: bgpd/imsg.h >-=================================================================== >-RCS file: bgpd/imsg.h >-diff -N bgpd/imsg.h >---- bgpd/imsg.h 14 Feb 2010 20:19:57 -0000 1.1.1.5 >-+++ /dev/null 1 Jan 1970 00:00:00 -0000 >-@@ -1,108 +0,0 @@ >--/* $OpenBSD: imsg.h,v 1.3 2009/06/07 05:56:24 eric Exp $ */ >-- >--/* >-- * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org> >-- * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org> >-- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-- * >-- * Permission to use, copy, modify, and distribute this software for any >-- * purpose with or without fee is hereby granted, provided that the above >-- * copyright notice and this permission notice appear in all copies. >-- * >-- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES >-- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF >-- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR >-- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES >-- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN >-- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF >-- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >-- */ >-- >--#include <sys/tree.h> >-- >--#define READ_BUF_SIZE 65535 >--#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr) >--#define MAX_IMSGSIZE 16384 >-- >--struct buf { >-- TAILQ_ENTRY(buf) entry; >-- u_char *buf; >-- size_t size; >-- size_t max; >-- size_t wpos; >-- size_t rpos; >-- int fd; >--}; >-- >--struct msgbuf { >-- TAILQ_HEAD(, buf) bufs; >-- u_int32_t queued; >-- int fd; >--}; >-- >--struct buf_read { >-- u_char buf[READ_BUF_SIZE]; >-- u_char *rptr; >-- size_t wpos; >--}; >-- >--struct imsg_fd { >-- TAILQ_ENTRY(imsg_fd) entry; >-- int fd; >--}; >-- >--struct imsgbuf { >-- TAILQ_HEAD(, imsg_fd) fds; >-- struct buf_read r; >-- struct msgbuf w; >-- int fd; >-- pid_t pid; >--}; >-- >--#define IMSGF_HASFD 1 >-- >--struct imsg_hdr { >-- u_int32_t type; >-- u_int16_t len; >-- u_int16_t flags; >-- u_int32_t peerid; >-- u_int32_t pid; >--}; >-- >--struct imsg { >-- struct imsg_hdr hdr; >-- int fd; >-- void *data; >--}; >-- >-- >--/* buffer.c */ >--struct buf *buf_open(size_t); >--struct buf *buf_dynamic(size_t, size_t); >--int buf_add(struct buf *, const void *, size_t); >--void *buf_reserve(struct buf *, size_t); >--void *buf_seek(struct buf *, size_t, size_t); >--size_t buf_size(struct buf *); >--size_t buf_left(struct buf *); >--void buf_close(struct msgbuf *, struct buf *); >--int buf_write(struct msgbuf *); >--void buf_free(struct buf *); >--void msgbuf_init(struct msgbuf *); >--void msgbuf_clear(struct msgbuf *); >--int msgbuf_write(struct msgbuf *); >-- >--/* imsg.c */ >--void imsg_init(struct imsgbuf *, int); >--ssize_t imsg_read(struct imsgbuf *); >--ssize_t imsg_get(struct imsgbuf *, struct imsg *); >--int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, >-- int, void *, u_int16_t); >--int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, >-- int, const struct iovec *, int); >--struct buf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, >-- u_int16_t); >--int imsg_add(struct buf *, void *, u_int16_t); >--void imsg_close(struct imsgbuf *, struct buf *); >--void imsg_free(struct imsg *); >--int imsg_flush(struct imsgbuf *); >--void imsg_clear(struct imsgbuf *); > >Property changes on: files/patch-bgpd_imsg.h >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_kroute.c >=================================================================== >--- files/patch-bgpd_kroute.c (revision 500577) >+++ files/patch-bgpd_kroute.c (nonexistent) >@@ -1,3140 +0,0 @@ >-Index: bgpd/kroute.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/kroute.c,v >-retrieving revision 1.1.1.7 >-retrieving revision 1.15 >-diff -u -p -r1.1.1.7 -r1.15 >---- bgpd/kroute.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 >-+++ bgpd/kroute.c 16 May 2014 00:36:26 -0000 1.15 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: kroute.c,v 1.169 2009/06/25 15:54:22 claudio Exp $ */ >-+/* $OpenBSD: kroute.c,v 1.190 2012/07/13 16:57:35 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-@@ -27,6 +27,9 @@ >- #include <net/if.h> >- #include <net/if_dl.h> >- #include <net/route.h> >-+#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */ >-+#include <netmpls/mpls.h> >-+#endif >- #include <err.h> >- #include <errno.h> >- #include <fcntl.h> >-@@ -37,11 +40,12 @@ >- >- #include "bgpd.h" >- >-+struct ktable **krt; >-+u_int krt_size; >-+ >- struct { >- u_int32_t rtseq; >- pid_t pid; >-- u_int rtableid; >-- int fib_sync; >- int fd; >- } kr_state; >- >-@@ -83,32 +87,52 @@ struct kif_node { >- struct kif_kr6_head kroute6_l; >- }; >- >--int kr_redistribute(int, struct kroute *); >--int kr_redistribute6(int, struct kroute6 *); >-+int ktable_new(u_int, u_int, char *, char *, int); >-+void ktable_free(u_int); >-+void ktable_destroy(struct ktable *); >-+struct ktable *ktable_get(u_int); >-+ >-+int kr4_change(struct ktable *, struct kroute_full *); >-+int kr6_change(struct ktable *, struct kroute_full *); >-+int krVPN4_change(struct ktable *, struct kroute_full *); >-+int kr4_delete(struct ktable *, struct kroute_full *); >-+int kr6_delete(struct ktable *, struct kroute_full *); >-+int krVPN4_delete(struct ktable *, struct kroute_full *); >-+void kr_net_delete(struct network *); >-+struct network *kr_net_match(struct ktable *, struct kroute *); >-+struct network *kr_net_match6(struct ktable *, struct kroute6 *); >-+struct network *kr_net_find(struct ktable *, struct network *); >-+int kr_redistribute(int, struct ktable *, struct kroute *); >-+int kr_redistribute6(int, struct ktable *, struct kroute6 *); >-+struct kroute_full *kr_tofull(struct kroute *); >-+struct kroute_full *kr6_tofull(struct kroute6 *); >- int kroute_compare(struct kroute_node *, struct kroute_node *); >- int kroute6_compare(struct kroute6_node *, struct kroute6_node *); >- int knexthop_compare(struct knexthop_node *, struct knexthop_node *); >- int kif_compare(struct kif_node *, struct kif_node *); >- >--struct kroute_node *kroute_find(in_addr_t, u_int8_t, u_int8_t); >-+struct kroute_node *kroute_find(struct ktable *, in_addr_t, u_int8_t, >-+ u_int8_t); >- struct kroute_node *kroute_matchgw(struct kroute_node *, >- struct sockaddr_in *); >--int kroute_insert(struct kroute_node *); >--int kroute_remove(struct kroute_node *); >--void kroute_clear(void); >-+int kroute_insert(struct ktable *, struct kroute_node *); >-+int kroute_remove(struct ktable *, struct kroute_node *); >-+void kroute_clear(struct ktable *); >- >--struct kroute6_node *kroute6_find(const struct in6_addr *, u_int8_t, >-- u_int8_t); >-+struct kroute6_node *kroute6_find(struct ktable *, const struct in6_addr *, >-+ u_int8_t, u_int8_t); >- struct kroute6_node *kroute6_matchgw(struct kroute6_node *, >- struct sockaddr_in6 *); >--int kroute6_insert(struct kroute6_node *); >--int kroute6_remove(struct kroute6_node *); >--void kroute6_clear(void); >-- >--struct knexthop_node *knexthop_find(struct bgpd_addr *); >--int knexthop_insert(struct knexthop_node *); >--int knexthop_remove(struct knexthop_node *); >--void knexthop_clear(void); >-+int kroute6_insert(struct ktable *, struct kroute6_node *); >-+int kroute6_remove(struct ktable *, struct kroute6_node *); >-+void kroute6_clear(struct ktable *); >-+ >-+struct knexthop_node *knexthop_find(struct ktable *, struct bgpd_addr *); >-+int knexthop_insert(struct ktable *, >-+ struct knexthop_node *); >-+int knexthop_remove(struct ktable *, >-+ struct knexthop_node *); >-+void knexthop_clear(struct ktable *); >- >- struct kif_node *kif_find(int); >- int kif_insert(struct kif_node *); >-@@ -124,13 +148,16 @@ int kif_kr6_remove(struct kroute6_nod >- int kif_validate(struct kif *); >- int kroute_validate(struct kroute *); >- int kroute6_validate(struct kroute6 *); >--void knexthop_validate(struct knexthop_node *); >--void knexthop_track(void *); >--struct kroute_node *kroute_match(in_addr_t, int); >--struct kroute6_node *kroute6_match(struct in6_addr *, int); >--void kroute_detach_nexthop(struct knexthop_node *); >-+void knexthop_validate(struct ktable *, >-+ struct knexthop_node *); >-+void knexthop_track(struct ktable *, void *); >-+void knexthop_send_update(struct knexthop_node *); >-+struct kroute_node *kroute_match(struct ktable *, in_addr_t, int); >-+struct kroute6_node *kroute6_match(struct ktable *, struct in6_addr *, int); >-+void kroute_detach_nexthop(struct ktable *, >-+ struct knexthop_node *); >- >--int protect_lo(void); >-+int protect_lo(struct ktable *); >- u_int8_t prefixlen_classful(in_addr_t); >- u_int8_t mask2prefixlen(in_addr_t); >- u_int8_t mask2prefixlen6(struct sockaddr_in6 *); >-@@ -138,23 +165,20 @@ void get_rtaddrs(int, struct sockaddr * >- void if_change(u_short, int, struct if_data *); >- void if_announce(void *); >- >--int send_rtmsg(int, int, struct kroute *); >--int send_rt6msg(int, int, struct kroute6 *); >-+int send_rtmsg(int, int, struct ktable *, struct kroute *); >-+int send_rt6msg(int, int, struct ktable *, struct kroute6 *); >- int dispatch_rtmsg(void); >--int fetchtable(u_int, int); >-+int fetchtable(struct ktable *); >- int fetchifs(int); >- int dispatch_rtmsg_addr(struct rt_msghdr *, >-- struct sockaddr *[RTAX_MAX], int); >-+ struct sockaddr *[RTAX_MAX], struct ktable *); >- >--RB_HEAD(kroute_tree, kroute_node) krt; >- RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare) >- RB_GENERATE(kroute_tree, kroute_node, entry, kroute_compare) >- >--RB_HEAD(kroute6_tree, kroute6_node) krt6; >- RB_PROTOTYPE(kroute6_tree, kroute6_node, entry, kroute6_compare) >- RB_GENERATE(kroute6_tree, kroute6_node, entry, kroute6_compare) >- >--RB_HEAD(knexthop_tree, knexthop_node) knt; >- RB_PROTOTYPE(knexthop_tree, knexthop_node, entry, knexthop_compare) >- RB_GENERATE(knexthop_tree, knexthop_node, entry, knexthop_compare) >- >-@@ -162,19 +186,21 @@ RB_HEAD(kif_tree, kif_node) kit; >- RB_PROTOTYPE(kif_tree, kif_node, entry, kif_compare) >- RB_GENERATE(kif_tree, kif_node, entry, kif_compare) >- >-+#define KT2KNT(x) (&(ktable_get((x)->nhtableid)->knt)) >-+ >- /* >- * exported functions >- */ >- >- int >--kr_init(int fs, u_int rtableid) >-+kr_init(void) >- { >- int opt = 0, rcvbuf, default_rcvbuf; >-+#if !defined(__FreeBSD__) /* FreeBSD does not have ROUTE_TABLEFILTER. */ >-+ unsigned int tid = RTABLE_ANY; >-+#endif >- socklen_t optlen; >- >-- kr_state.rtableid = rtableid; >-- kr_state.fib_sync = fs; >-- >- if ((kr_state.fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) { >- log_warn("kr_init: socket"); >- return (-1); >-@@ -198,194 +224,533 @@ kr_init(int fs, u_int rtableid) >- rcvbuf /= 2) >- ; /* nothing */ >- >-+#if !defined(__FreeBSD__) /* FreeBSD does not have ROUTE_TABLEFILTER. */ >-+ if (setsockopt(kr_state.fd, AF_ROUTE, ROUTE_TABLEFILTER, &tid, >-+ sizeof(tid)) == -1) { >-+ log_warn("kr_init: setsockopt AF_ROUTE ROUTE_TABLEFILTER"); >-+ return (-1); >-+ } >-+#endif >-+ >- kr_state.pid = getpid(); >- kr_state.rtseq = 1; >- >-- RB_INIT(&krt); >-- RB_INIT(&krt6); >-- RB_INIT(&knt); >- RB_INIT(&kit); >- >- if (fetchifs(0) == -1) >- return (-1); >- >-- if (fetchtable(kr_state.rtableid, 0) == -1) >-- return (-1); >-- if (kr_state.rtableid != 0) >-- if (fetchtable(0, 1) == -1) >-+ return (kr_state.fd); >-+} >-+ >-+int >-+ktable_new(u_int rtableid, u_int rdomid, char *name, char *ifname, int fs) >-+{ >-+ struct ktable **xkrt; >-+ struct ktable *kt; >-+ size_t newsize, oldsize; >-+ >-+ /* resize index table if needed */ >-+ if (rtableid >= krt_size) { >-+ oldsize = sizeof(struct ktable *) * krt_size; >-+ newsize = sizeof(struct ktable *) * (rtableid + 1); >-+ if ((xkrt = realloc(krt, newsize)) == NULL) { >-+ log_warn("ktable_new"); >- return (-1); >-+ } >-+ krt = xkrt; >-+ krt_size = rtableid + 1; >-+ bzero((char *)krt + oldsize, newsize - oldsize); >-+ } >-+ >-+ if (krt[rtableid]) >-+ fatalx("ktable_new: table already exists."); >- >-- if (protect_lo() == -1) >-+ /* allocate new element */ >-+ kt = krt[rtableid] = calloc(1, sizeof(struct ktable)); >-+ if (kt == NULL) { >-+ log_warn("ktable_new"); >- return (-1); >-+ } >- >-- return (kr_state.fd); >-+ /* initialize structure ... */ >-+ strlcpy(kt->descr, name, sizeof(kt->descr)); >-+ RB_INIT(&kt->krt); >-+ RB_INIT(&kt->krt6); >-+ RB_INIT(&kt->knt); >-+ TAILQ_INIT(&kt->krn); >-+ kt->fib_conf = kt->fib_sync = fs; >-+ kt->rtableid = rtableid; >-+ kt->nhtableid = rdomid; >-+ /* bump refcount of rdomain table for the nexthop lookups */ >-+ ktable_get(kt->nhtableid)->nhrefcnt++; >-+ if (ifname) { >-+ strlcpy(kt->ifmpe, ifname, IFNAMSIZ); >-+ kt->ifindex = if_nametoindex(ifname); >-+ } >-+ >-+ /* ... and load it */ >-+ if (fetchtable(kt) == -1) >-+ return (-1); >-+ if (protect_lo(kt) == -1) >-+ return (-1); >-+ >-+ /* everything is up and running */ >-+ kt->state = RECONF_REINIT; >-+ log_debug("new ktable %s for rtableid %d", name, rtableid); >-+ return (0); >-+} >-+ >-+void >-+ktable_free(u_int rtableid) >-+{ >-+ struct ktable *kt, *nkt; >-+ >-+ if ((kt = ktable_get(rtableid)) == NULL) >-+ return; >-+ >-+ /* decouple from kernel, no new routes will be entered from here */ >-+ kr_fib_decouple(kt->rtableid); >-+ >-+ /* first unhook from the nexthop table */ >-+ nkt = ktable_get(kt->nhtableid); >-+ nkt->nhrefcnt--; >-+ >-+ /* >-+ * Evil little details: >-+ * If kt->nhrefcnt > 0 then kt == nkt and nothing needs to be done. >-+ * If kt != nkt then kt->nhrefcnt must be 0 and kt must be killed. >-+ * If nkt is no longer referenced it must be killed (possible double >-+ * free so check that kt != nkt). >-+ */ >-+ if (kt != nkt && nkt->nhrefcnt <= 0) >-+ ktable_destroy(nkt); >-+ if (kt->nhrefcnt <= 0) >-+ ktable_destroy(kt); >-+} >-+ >-+void >-+ktable_destroy(struct ktable *kt) >-+{ >-+ /* decouple just to be sure, does not hurt */ >-+ kr_fib_decouple(kt->rtableid); >-+ >-+ log_debug("freeing ktable %s rtableid %u", kt->descr, kt->rtableid); >-+ knexthop_clear(kt); >-+ kroute_clear(kt); >-+ kroute6_clear(kt); >-+ >-+ krt[kt->rtableid] = NULL; >-+ free(kt); >-+} >-+ >-+struct ktable * >-+ktable_get(u_int rtableid) >-+{ >-+ if (rtableid >= krt_size) >-+ return (NULL); >-+ return (krt[rtableid]); >-+} >-+ >-+int >-+ktable_update(u_int rtableid, char *name, char *ifname, int flags) >-+{ >-+ struct ktable *kt, *rkt; >-+ u_int rdomid; >-+ >-+ if (!ktable_exists(rtableid, &rdomid)) >-+ fatalx("King Bula lost a table"); /* may not happen */ >-+ >-+ if (rdomid != rtableid || flags & F_RIB_NOFIB) { >-+ rkt = ktable_get(rdomid); >-+ if (rkt == NULL) { >-+ char buf[32]; >-+ snprintf(buf, sizeof(buf), "rdomain_%d", rdomid); >-+ if (ktable_new(rdomid, rdomid, buf, NULL, 0)) >-+ return (-1); >-+ } else { >-+ /* there is no need for full fib synchronisation if >-+ * the table is only used for nexthop lookups. >-+ */ >-+ if (rkt->state == RECONF_DELETE) { >-+ rkt->fib_conf = 0; >-+ rkt->state = RECONF_KEEP; >-+ } >-+ } >-+ } >-+ >-+ if (flags & (F_RIB_NOEVALUATE | F_RIB_NOFIB)) >-+ /* only rdomain table must exist */ >-+ return (0); >-+ >-+ kt = ktable_get(rtableid); >-+ if (kt == NULL) { >-+ if (ktable_new(rtableid, rdomid, name, ifname, >-+ !(flags & F_RIB_NOFIBSYNC))) >-+ return (-1); >-+ } else { >-+ /* fib sync has higher preference then no sync */ >-+ if (kt->state == RECONF_DELETE) { >-+ kt->fib_conf = !(flags & F_RIB_NOFIBSYNC); >-+ kt->state = RECONF_KEEP; >-+ } else if (!kt->fib_conf) >-+ kt->fib_conf = !(flags & F_RIB_NOFIBSYNC); >-+ >-+ strlcpy(kt->descr, name, sizeof(kt->descr)); >-+ } >-+ return (0); >-+} >-+ >-+void >-+ktable_preload(void) >-+{ >-+ struct ktable *kt; >-+ u_int i; >-+ >-+ for (i = 0; i < krt_size; i++) { >-+ if ((kt = ktable_get(i)) == NULL) >-+ continue; >-+ kt->state = RECONF_DELETE; >-+ } >-+} >-+ >-+void >-+ktable_postload(void) >-+{ >-+ struct ktable *kt; >-+ u_int i; >-+ >-+ for (i = krt_size; i > 0; i--) { >-+ if ((kt = ktable_get(i - 1)) == NULL) >-+ continue; >-+ if (kt->state == RECONF_DELETE) >-+ ktable_free(i - 1); >-+ else if (kt->state == RECONF_REINIT) >-+ kt->fib_sync = kt->fib_conf; >-+ } >-+} >-+ >-+int >-+ktable_exists(u_int rtableid, u_int *rdomid) >-+{ >-+#if !defined(__FreeBSD__) /* FreeBSD does not have NET_RT_TABLE. */ >-+ size_t len; >-+ struct rt_tableinfo info; >-+ int mib[6]; >-+ >-+ mib[0] = CTL_NET; >-+ mib[1] = AF_ROUTE; >-+ mib[2] = 0; >-+ mib[3] = 0; >-+ mib[4] = NET_RT_TABLE; >-+ mib[5] = rtableid; >-+ >-+ len = sizeof(info); >-+ if (sysctl(mib, 6, &info, &len, NULL, 0) == -1) { >-+ if (errno == ENOENT) >-+ /* table nonexistent */ >-+ return (0); >-+ log_warn("sysctl"); >-+ /* must return 0 so that the table is considered non-existent */ >-+ return (0); >-+ } >-+ if (rdomid) >-+ *rdomid = info.rti_domainid; >-+#else >-+ *rdomid = 0; >-+#endif >-+ return (1); >- } >- >- int >--kr_change(struct kroute_label *kl) >-+kr_change(u_int rtableid, struct kroute_full *kl) >-+{ >-+ struct ktable *kt; >-+ >-+ if ((kt = ktable_get(rtableid)) == NULL) >-+ /* too noisy during reloads, just ignore */ >-+ return (0); >-+ switch (kl->prefix.aid) { >-+ case AID_INET: >-+ return (kr4_change(kt, kl)); >-+ case AID_INET6: >-+ return (kr6_change(kt, kl)); >-+ case AID_VPN_IPv4: >-+ return (krVPN4_change(kt, kl)); >-+ } >-+ log_warnx("kr_change: not handled AID"); >-+ return (-1); >-+} >-+ >-+int >-+kr4_change(struct ktable *kt, struct kroute_full *kl) >- { >- struct kroute_node *kr; >- int action = RTM_ADD; >-+ u_int16_t labelid; >- >-- if ((kr = kroute_find(kl->kr.prefix.s_addr, kl->kr.prefixlen, RTP_BGP)) >-- != NULL) >-+ if ((kr = kroute_find(kt, kl->prefix.v4.s_addr, kl->prefixlen, >-+ RTP_BGP)) != NULL) >- action = RTM_CHANGE; >- >- /* nexthop within 127/8 -> ignore silently */ >-- if ((kl->kr.nexthop.s_addr & htonl(IN_CLASSA_NET)) == >-+ if ((kl->nexthop.v4.s_addr & htonl(IN_CLASSA_NET)) == >- htonl(INADDR_LOOPBACK & IN_CLASSA_NET)) >- return (0); >- >-- if (kr) >-- rtlabel_unref(kr->r.labelid); >-- kl->kr.labelid = rtlabel_name2id(kl->label); >-+ labelid = rtlabel_name2id(kl->label); >- >- /* for blackhole and reject routes nexthop needs to be 127.0.0.1 */ >-- if (kl->kr.flags & (F_BLACKHOLE|F_REJECT)) >-- kl->kr.nexthop.s_addr = htonl(INADDR_LOOPBACK); >-- >-- if (send_rtmsg(kr_state.fd, action, &kl->kr) == -1) >-- return (-1); >-+ if (kl->flags & (F_BLACKHOLE|F_REJECT)) >-+ kl->nexthop.v4.s_addr = htonl(INADDR_LOOPBACK); >- >- if (action == RTM_ADD) { >- if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) { >- log_warn("kr_change"); >- return (-1); >- } >-- kr->r.prefix.s_addr = kl->kr.prefix.s_addr; >-- kr->r.prefixlen = kl->kr.prefixlen; >-- kr->r.nexthop.s_addr = kl->kr.nexthop.s_addr; >-- kr->r.flags = kl->kr.flags | F_BGPD_INSERTED; >-+ kr->r.prefix.s_addr = kl->prefix.v4.s_addr; >-+ kr->r.prefixlen = kl->prefixlen; >-+ kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr; >-+ kr->r.flags = kl->flags | F_BGPD_INSERTED; >- kr->r.priority = RTP_BGP; >-- kr->r.labelid = kl->kr.labelid; >-+ kr->r.labelid = labelid; >- >-- if (kroute_insert(kr) == -1) >-+ if (kroute_insert(kt, kr) == -1) >- free(kr); >- } else { >-- kr->r.nexthop.s_addr = kl->kr.nexthop.s_addr; >-- kr->r.labelid = kl->kr.labelid; >-- if (kl->kr.flags & F_BLACKHOLE) >-+ kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr; >-+ rtlabel_unref(kr->r.labelid); >-+ kr->r.labelid = labelid; >-+ if (kl->flags & F_BLACKHOLE) >- kr->r.flags |= F_BLACKHOLE; >- else >- kr->r.flags &= ~F_BLACKHOLE; >-- if (kl->kr.flags & F_REJECT) >-+ if (kl->flags & F_REJECT) >- kr->r.flags |= F_REJECT; >- else >- kr->r.flags &= ~F_REJECT; >- } >- >-+ if (send_rtmsg(kr_state.fd, action, kt, &kr->r) == -1) >-+ return (-1); >-+ >- return (0); >- } >- >- int >--kr_delete(struct kroute_label *kl) >-+kr6_change(struct ktable *kt, struct kroute_full *kl) >- { >-- struct kroute_node *kr; >-+ struct kroute6_node *kr6; >-+ struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; >-+ int action = RTM_ADD; >-+ u_int16_t labelid; >- >-- if ((kr = kroute_find(kl->kr.prefix.s_addr, kl->kr.prefixlen, RTP_BGP)) >-- == NULL) >-- return (0); >-+ if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen, RTP_BGP)) != >-+ NULL) >-+ action = RTM_CHANGE; >- >-- if (!(kr->r.flags & F_BGPD_INSERTED)) >-+ /* nexthop to loopback -> ignore silently */ >-+ if (IN6_IS_ADDR_LOOPBACK(&kl->nexthop.v6)) >- return (0); >- >-- /* nexthop within 127/8 -> ignore silently */ >-- if ((kl->kr.nexthop.s_addr & htonl(IN_CLASSA_NET)) == >-- htonl(INADDR_LOOPBACK & IN_CLASSA_NET)) >-- return (0); >-+ labelid = rtlabel_name2id(kl->label); >- >-- if (send_rtmsg(kr_state.fd, RTM_DELETE, &kl->kr) == -1) >-- return (-1); >-+ /* for blackhole and reject routes nexthop needs to be ::1 */ >-+ if (kl->flags & (F_BLACKHOLE|F_REJECT)) >-+ bcopy(&lo6, &kl->nexthop.v6, sizeof(kl->nexthop.v6)); >- >-- rtlabel_unref(kl->kr.labelid); >-+ if (action == RTM_ADD) { >-+ if ((kr6 = calloc(1, sizeof(struct kroute6_node))) == NULL) { >-+ log_warn("kr_change"); >-+ return (-1); >-+ } >-+ memcpy(&kr6->r.prefix, &kl->prefix.v6, sizeof(struct in6_addr)); >-+ kr6->r.prefixlen = kl->prefixlen; >-+ memcpy(&kr6->r.nexthop, &kl->nexthop.v6, >-+ sizeof(struct in6_addr)); >-+ kr6->r.flags = kl->flags | F_BGPD_INSERTED; >-+ kr6->r.priority = RTP_BGP; >-+ kr6->r.labelid = labelid; >- >-- if (kroute_remove(kr) == -1) >-+ if (kroute6_insert(kt, kr6) == -1) >-+ free(kr6); >-+ } else { >-+ memcpy(&kr6->r.nexthop, &kl->nexthop.v6, >-+ sizeof(struct in6_addr)); >-+ rtlabel_unref(kr6->r.labelid); >-+ kr6->r.labelid = labelid; >-+ if (kl->flags & F_BLACKHOLE) >-+ kr6->r.flags |= F_BLACKHOLE; >-+ else >-+ kr6->r.flags &= ~F_BLACKHOLE; >-+ if (kl->flags & F_REJECT) >-+ kr6->r.flags |= F_REJECT; >-+ else >-+ kr6->r.flags &= ~F_REJECT; >-+ } >-+ >-+ if (send_rt6msg(kr_state.fd, action, kt, &kr6->r) == -1) >- return (-1); >- >- return (0); >- } >- >- int >--kr6_change(struct kroute6_label *kl) >-+krVPN4_change(struct ktable *kt, struct kroute_full *kl) >- { >-- struct kroute6_node *kr6; >-+ struct kroute_node *kr; >- int action = RTM_ADD; >-- struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; >-+ u_int32_t mplslabel = 0; >-+ u_int16_t labelid; >- >-- if ((kr6 = kroute6_find(&kl->kr.prefix, kl->kr.prefixlen, RTP_BGP)) >-- != NULL) >-+ if ((kr = kroute_find(kt, kl->prefix.vpn4.addr.s_addr, kl->prefixlen, >-+ RTP_BGP)) != NULL) >- action = RTM_CHANGE; >- >-- /* nexthop to loopback -> ignore silently */ >-- if (IN6_IS_ADDR_LOOPBACK(&kl->kr.nexthop)) >-+ /* nexthop within 127/8 -> ignore silently */ >-+ if ((kl->nexthop.v4.s_addr & htonl(IN_CLASSA_NET)) == >-+ htonl(INADDR_LOOPBACK & IN_CLASSA_NET)) >- return (0); >- >-- if (kr6) >-- rtlabel_unref(kr6->r.labelid); >-- kl->kr.labelid = rtlabel_name2id(kl->label); >-+ /* only single MPLS label are supported for now */ >-+ if (kl->prefix.vpn4.labellen != 3) { >-+ log_warnx("krVPN4_change: %s/%u has not a single label", >-+ log_addr(&kl->prefix), kl->prefixlen); >-+ return (0); >-+ } >-+ mplslabel = (kl->prefix.vpn4.labelstack[0] << 24) | >-+ (kl->prefix.vpn4.labelstack[1] << 16) | >-+ (kl->prefix.vpn4.labelstack[2] << 8); >-+ mplslabel = htonl(mplslabel); >- >-- /* for blackhole and reject routes nexthop needs to be ::1 */ >-- if (kl->kr.flags & (F_BLACKHOLE|F_REJECT)) >-- bcopy(&lo6, &kl->kr.nexthop, sizeof(kl->kr.nexthop)); >-+ labelid = rtlabel_name2id(kl->label); >- >-- if (send_rt6msg(kr_state.fd, action, &kl->kr) == -1) >-- return (-1); >-+ /* for blackhole and reject routes nexthop needs to be 127.0.0.1 */ >-+ if (kl->flags & (F_BLACKHOLE|F_REJECT)) >-+ kl->nexthop.v4.s_addr = htonl(INADDR_LOOPBACK); >- >- if (action == RTM_ADD) { >-- if ((kr6 = calloc(1, sizeof(struct kroute6_node))) == NULL) { >-+ if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) { >- log_warn("kr_change"); >- return (-1); >- } >-- memcpy(&kr6->r.prefix, &kl->kr.prefix, >-- sizeof(struct in6_addr)); >-- kr6->r.prefixlen = kl->kr.prefixlen; >-- memcpy(&kr6->r.nexthop, &kl->kr.nexthop, >-- sizeof(struct in6_addr)); >-- kr6->r.flags = kl->kr.flags | F_BGPD_INSERTED; >-- kr6->r.priority = RTP_BGP; >-- kr6->r.labelid = kl->kr.labelid; >-+ kr->r.prefix.s_addr = kl->prefix.vpn4.addr.s_addr; >-+ kr->r.prefixlen = kl->prefixlen; >-+ kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr; >-+ kr->r.flags = kl->flags | F_BGPD_INSERTED | F_MPLS; >-+ kr->r.priority = RTP_BGP; >-+ kr->r.labelid = labelid; >-+ kr->r.mplslabel = mplslabel; >- >-- if (kroute6_insert(kr6) == -1) >-- free(kr6); >-+ if (kroute_insert(kt, kr) == -1) >-+ free(kr); >- } else { >-- memcpy(&kr6->r.nexthop, &kl->kr.nexthop, >-- sizeof(struct in6_addr)); >-- kr6->r.labelid = kl->kr.labelid; >-- if (kl->kr.flags & F_BLACKHOLE) >-- kr6->r.flags |= F_BLACKHOLE; >-+ kr->r.mplslabel = mplslabel; >-+ kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr; >-+ rtlabel_unref(kr->r.labelid); >-+ kr->r.labelid = labelid; >-+ if (kl->flags & F_BLACKHOLE) >-+ kr->r.flags |= F_BLACKHOLE; >- else >-- kr6->r.flags &= ~F_BLACKHOLE; >-- if (kl->kr.flags & F_REJECT) >-- kr6->r.flags |= F_REJECT; >-+ kr->r.flags &= ~F_BLACKHOLE; >-+ if (kl->flags & F_REJECT) >-+ kr->r.flags |= F_REJECT; >- else >-- kr6->r.flags &= ~F_REJECT; >-+ kr->r.flags &= ~F_REJECT; >- } >- >-+ if (send_rtmsg(kr_state.fd, action, kt, &kr->r) == -1) >-+ return (-1); >-+ >- return (0); >- } >- >- int >--kr6_delete(struct kroute6_label *kl) >-+kr_delete(u_int rtableid, struct kroute_full *kl) >-+{ >-+ struct ktable *kt; >-+ >-+ if ((kt = ktable_get(rtableid)) == NULL) >-+ /* too noisy during reloads, just ignore */ >-+ return (0); >-+ >-+ switch (kl->prefix.aid) { >-+ case AID_INET: >-+ return (kr4_delete(kt, kl)); >-+ case AID_INET6: >-+ return (kr6_delete(kt, kl)); >-+ case AID_VPN_IPv4: >-+ return (krVPN4_delete(kt, kl)); >-+ } >-+ log_warnx("kr_change: not handled AID"); >-+ return (-1); >-+} >-+ >-+int >-+kr4_delete(struct ktable *kt, struct kroute_full *kl) >-+{ >-+ struct kroute_node *kr; >-+ >-+ if ((kr = kroute_find(kt, kl->prefix.v4.s_addr, kl->prefixlen, >-+ RTP_BGP)) == NULL) >-+ return (0); >-+ >-+ if (!(kr->r.flags & F_BGPD_INSERTED)) >-+ return (0); >-+ >-+ if (send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r) == -1) >-+ return (-1); >-+ >-+ rtlabel_unref(kr->r.labelid); >-+ >-+ if (kroute_remove(kt, kr) == -1) >-+ return (-1); >-+ >-+ return (0); >-+} >-+ >-+int >-+kr6_delete(struct ktable *kt, struct kroute_full *kl) >- { >- struct kroute6_node *kr6; >- >-- if ((kr6 = kroute6_find(&kl->kr.prefix, kl->kr.prefixlen, RTP_BGP)) >-- == NULL) >-+ if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen, RTP_BGP)) == >-+ NULL) >- return (0); >- >- if (!(kr6->r.flags & F_BGPD_INSERTED)) >- return (0); >- >-- /* nexthop to loopback -> ignore silently */ >-- if (IN6_IS_ADDR_LOOPBACK(&kl->kr.nexthop)) >-+ if (send_rt6msg(kr_state.fd, RTM_DELETE, kt, &kr6->r) == -1) >-+ return (-1); >-+ >-+ rtlabel_unref(kr6->r.labelid); >-+ >-+ if (kroute6_remove(kt, kr6) == -1) >-+ return (-1); >-+ >-+ return (0); >-+} >-+ >-+int >-+krVPN4_delete(struct ktable *kt, struct kroute_full *kl) >-+{ >-+ struct kroute_node *kr; >-+ >-+ if ((kr = kroute_find(kt, kl->prefix.vpn4.addr.s_addr, kl->prefixlen, >-+ RTP_BGP)) == NULL) >- return (0); >- >-- if (send_rt6msg(kr_state.fd, RTM_DELETE, &kl->kr) == -1) >-+ if (!(kr->r.flags & F_BGPD_INSERTED)) >-+ return (0); >-+ >-+ if (send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r) == -1) >- return (-1); >- >-- rtlabel_unref(kl->kr.labelid); >-+ rtlabel_unref(kr->r.labelid); >- >-- if (kroute6_remove(kr6) == -1) >-+ if (kroute_remove(kt, kr) == -1) >- return (-1); >- >- return (0); >-@@ -394,53 +759,63 @@ kr6_delete(struct kroute6_label *kl) >- void >- kr_shutdown(void) >- { >-- kr_fib_decouple(); >-- knexthop_clear(); >-- kroute_clear(); >-- kroute6_clear(); >-+ u_int i; >-+ >-+ for (i = krt_size; i > 0; i--) >-+ ktable_free(i - 1); >- kif_clear(); >- } >- >- void >--kr_fib_couple(void) >-+kr_fib_couple(u_int rtableid) >- { >-+ struct ktable *kt; >- struct kroute_node *kr; >- struct kroute6_node *kr6; >- >-- if (kr_state.fib_sync == 1) /* already coupled */ >-+ if ((kt = ktable_get(rtableid)) == NULL) /* table does not exist */ >- return; >- >-- kr_state.fib_sync = 1; >-+ if (kt->fib_sync) /* already coupled */ >-+ return; >- >-- RB_FOREACH(kr, kroute_tree, &krt) >-+ kt->fib_sync = 1; >-+ >-+ RB_FOREACH(kr, kroute_tree, &kt->krt) >- if ((kr->r.flags & F_BGPD_INSERTED)) >-- send_rtmsg(kr_state.fd, RTM_ADD, &kr->r); >-- RB_FOREACH(kr6, kroute6_tree, &krt6) >-+ send_rtmsg(kr_state.fd, RTM_ADD, kt, &kr->r); >-+ RB_FOREACH(kr6, kroute6_tree, &kt->krt6) >- if ((kr6->r.flags & F_BGPD_INSERTED)) >-- send_rt6msg(kr_state.fd, RTM_ADD, &kr6->r); >-+ send_rt6msg(kr_state.fd, RTM_ADD, kt, &kr6->r); >- >-- log_info("kernel routing table coupled"); >-+ log_info("kernel routing table %u (%s) coupled", kt->rtableid, >-+ kt->descr); >- } >- >- void >--kr_fib_decouple(void) >-+kr_fib_decouple(u_int rtableid) >- { >-+ struct ktable *kt; >- struct kroute_node *kr; >- struct kroute6_node *kr6; >- >-- if (kr_state.fib_sync == 0) /* already decoupled */ >-+ if ((kt = ktable_get(rtableid)) == NULL) /* table does not exist */ >-+ return; >-+ >-+ if (!kt->fib_sync) /* already decoupled */ >- return; >- >-- RB_FOREACH(kr, kroute_tree, &krt) >-+ RB_FOREACH(kr, kroute_tree, &kt->krt) >- if ((kr->r.flags & F_BGPD_INSERTED)) >-- send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r); >-- RB_FOREACH(kr6, kroute6_tree, &krt6) >-+ send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r); >-+ RB_FOREACH(kr6, kroute6_tree, &kt->krt6) >- if ((kr6->r.flags & F_BGPD_INSERTED)) >-- send_rt6msg(kr_state.fd, RTM_DELETE, &kr6->r); >-+ send_rt6msg(kr_state.fd, RTM_DELETE, kt, &kr6->r); >- >-- kr_state.fib_sync = 0; >-+ kt->fib_sync = 0; >- >-- log_info("kernel routing table decoupled"); >-+ log_info("kernel routing table %u (%s) decoupled", kt->rtableid, >-+ kt->descr); >- } >- >- int >-@@ -450,41 +825,18 @@ kr_dispatch_msg(void) >- } >- >- int >--kr_nexthop_add(struct bgpd_addr *addr) >-+kr_nexthop_add(u_int rtableid, struct bgpd_addr *addr) >- { >-+ struct ktable *kt; >- struct knexthop_node *h; >- >-- if ((h = knexthop_find(addr)) != NULL) { >-+ if ((kt = ktable_get(rtableid)) == NULL) { >-+ log_warnx("kr_nexthop_add: non-existent rtableid %d", rtableid); >-+ return (0); >-+ } >-+ if ((h = knexthop_find(kt, addr)) != NULL) { >- /* should not happen... this is actually an error path */ >-- struct kroute_nexthop nh; >-- struct kroute_node *k; >-- struct kroute6_node *k6; >-- >-- bzero(&nh, sizeof(nh)); >-- memcpy(&nh.nexthop, addr, sizeof(nh.nexthop)); >-- nh.valid = 1; >-- if (h->kroute != NULL && addr->af == AF_INET) { >-- k = h->kroute; >-- nh.connected = k->r.flags & F_CONNECTED; >-- if (k->r.nexthop.s_addr != 0) { >-- nh.gateway.af = AF_INET; >-- nh.gateway.v4.s_addr = >-- k->r.nexthop.s_addr; >-- } >-- memcpy(&nh.kr.kr4, &k->r, sizeof(nh.kr.kr4)); >-- } else if (h->kroute != NULL && addr->af == AF_INET6) { >-- k6 = h->kroute; >-- nh.connected = k6->r.flags & F_CONNECTED; >-- if (memcmp(&k6->r.nexthop, &in6addr_any, >-- sizeof(struct in6_addr)) != 0) { >-- nh.gateway.af = AF_INET6; >-- memcpy(&nh.gateway.v6, &k6->r.nexthop, >-- sizeof(struct in6_addr)); >-- } >-- memcpy(&nh.kr.kr6, &k6->r, sizeof(nh.kr.kr6)); >-- } >-- >-- send_nexthop_update(&nh); >-+ knexthop_send_update(h); >- } else { >- if ((h = calloc(1, sizeof(struct knexthop_node))) == NULL) { >- log_warn("kr_nexthop_add"); >-@@ -492,7 +844,7 @@ kr_nexthop_add(struct bgpd_addr *addr) >- } >- memcpy(&h->nexthop, addr, sizeof(h->nexthop)); >- >-- if (knexthop_insert(h) == -1) >-+ if (knexthop_insert(kt, h) == -1) >- return (-1); >- } >- >-@@ -500,19 +852,26 @@ kr_nexthop_add(struct bgpd_addr *addr) >- } >- >- void >--kr_nexthop_delete(struct bgpd_addr *addr) >-+kr_nexthop_delete(u_int rtableid, struct bgpd_addr *addr) >- { >-+ struct ktable *kt; >- struct knexthop_node *kn; >- >-- if ((kn = knexthop_find(addr)) == NULL) >-+ if ((kt = ktable_get(rtableid)) == NULL) { >-+ log_warnx("kr_nexthop_delete: non-existent rtableid %d", >-+ rtableid); >-+ return; >-+ } >-+ if ((kn = knexthop_find(kt, addr)) == NULL) >- return; >- >-- knexthop_remove(kn); >-+ knexthop_remove(kt, kn); >- } >- >- void >- kr_show_route(struct imsg *imsg) >- { >-+ struct ktable *kt; >- struct kroute_node *kr, *kn; >- struct kroute6_node *kr6, *kn6; >- struct bgpd_addr *addr; >-@@ -521,6 +880,7 @@ kr_show_route(struct imsg *imsg) >- struct ctl_show_nexthop snh; >- struct knexthop_node *h; >- struct kif_node *kif; >-+ u_int i; >- u_short ifindex = 0; >- >- switch (imsg->hdr.type) { >-@@ -528,70 +888,96 @@ kr_show_route(struct imsg *imsg) >- if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(flags) + >- sizeof(af)) { >- log_warnx("kr_show_route: wrong imsg len"); >-- return; >-+ break; >-+ } >-+ kt = ktable_get(imsg->hdr.peerid); >-+ if (kt == NULL) { >-+ log_warnx("kr_show_route: table %u does not exist", >-+ imsg->hdr.peerid); >-+ break; >- } >- memcpy(&flags, imsg->data, sizeof(flags)); >- memcpy(&af, (char *)imsg->data + sizeof(flags), sizeof(af)); >- if (!af || af == AF_INET) >-- RB_FOREACH(kr, kroute_tree, &krt) >-- if (!flags || kr->r.flags & flags) { >-- kn = kr; >-- do { >-- send_imsg_session( >-- IMSG_CTL_KROUTE, >-- imsg->hdr.pid, &kn->r, >-- sizeof(kn->r)); >-- } while ((kn = kn->next) != NULL); >-- } >-+ RB_FOREACH(kr, kroute_tree, &kt->krt) { >-+ if (flags && (kr->r.flags & flags) == 0) >-+ continue; >-+ kn = kr; >-+ do { >-+ send_imsg_session(IMSG_CTL_KROUTE, >-+ imsg->hdr.pid, kr_tofull(&kn->r), >-+ sizeof(struct kroute_full)); >-+ } while ((kn = kn->next) != NULL); >-+ } >- if (!af || af == AF_INET6) >-- RB_FOREACH(kr6, kroute6_tree, &krt6) >-- if (!flags || kr6->r.flags & flags) { >-- kn6 = kr6; >-- do { >-- send_imsg_session( >-- IMSG_CTL_KROUTE6, >-- imsg->hdr.pid, &kn6->r, >-- sizeof(kn6->r)); >-- } while ((kn6 = kn6->next) != NULL); >-- } >-+ RB_FOREACH(kr6, kroute6_tree, &kt->krt6) { >-+ if (flags && (kr6->r.flags & flags) == 0) >-+ continue; >-+ kn6 = kr6; >-+ do { >-+ send_imsg_session(IMSG_CTL_KROUTE, >-+ imsg->hdr.pid, kr6_tofull(&kn6->r), >-+ sizeof(struct kroute_full)); >-+ } while ((kn6 = kn6->next) != NULL); >-+ } >- break; >- case IMSG_CTL_KROUTE_ADDR: >- if (imsg->hdr.len != IMSG_HEADER_SIZE + >- sizeof(struct bgpd_addr)) { >- log_warnx("kr_show_route: wrong imsg len"); >-- return; >-+ break; >-+ } >-+ kt = ktable_get(imsg->hdr.peerid); >-+ if (kt == NULL) { >-+ log_warnx("kr_show_route: table %u does not exist", >-+ imsg->hdr.peerid); >-+ break; >- } >- addr = imsg->data; >- kr = NULL; >-- switch (addr->af) { >-- case AF_INET: >-- kr = kroute_match(addr->v4.s_addr, 1); >-+ switch (addr->aid) { >-+ case AID_INET: >-+ kr = kroute_match(kt, addr->v4.s_addr, 1); >- if (kr != NULL) >- send_imsg_session(IMSG_CTL_KROUTE, >-- imsg->hdr.pid, &kr->r, sizeof(kr->r)); >-+ imsg->hdr.pid, kr_tofull(&kr->r), >-+ sizeof(struct kroute_full)); >- break; >-- case AF_INET6: >-- kr6 = kroute6_match(&addr->v6, 1); >-+ case AID_INET6: >-+ kr6 = kroute6_match(kt, &addr->v6, 1); >- if (kr6 != NULL) >-- send_imsg_session(IMSG_CTL_KROUTE6, >-- imsg->hdr.pid, &kr6->r, sizeof(kr6->r)); >-+ send_imsg_session(IMSG_CTL_KROUTE, >-+ imsg->hdr.pid, kr6_tofull(&kr6->r), >-+ sizeof(struct kroute_full)); >- break; >- } >- break; >- case IMSG_CTL_SHOW_NEXTHOP: >-- RB_FOREACH(h, knexthop_tree, &knt) { >-+ kt = ktable_get(imsg->hdr.peerid); >-+ if (kt == NULL) { >-+ log_warnx("kr_show_route: table %u does not exist", >-+ imsg->hdr.peerid); >-+ break; >-+ } >-+ RB_FOREACH(h, knexthop_tree, KT2KNT(kt)) { >- bzero(&snh, sizeof(snh)); >- memcpy(&snh.addr, &h->nexthop, sizeof(snh.addr)); >- if (h->kroute != NULL) { >-- switch (h->nexthop.af) { >-- case AF_INET: >-+ switch (h->nexthop.aid) { >-+ case AID_INET: >- kr = h->kroute; >- snh.valid = kroute_validate(&kr->r); >-+ snh.krvalid = 1; >-+ memcpy(&snh.kr.kr4, &kr->r, >-+ sizeof(snh.kr.kr4)); >- ifindex = kr->r.ifindex; >- break; >-- case AF_INET6: >-+ case AID_INET6: >- kr6 = h->kroute; >- snh.valid = kroute6_validate(&kr6->r); >-+ snh.krvalid = 1; >-+ memcpy(&snh.kr.kr6, &kr6->r, >-+ sizeof(snh.kr.kr6)); >- ifindex = kr6->r.ifindex; >- break; >- } >-@@ -608,41 +994,190 @@ kr_show_route(struct imsg *imsg) >- send_imsg_session(IMSG_CTL_SHOW_INTERFACE, >- imsg->hdr.pid, &kif->k, sizeof(kif->k)); >- break; >-+ case IMSG_CTL_SHOW_FIB_TABLES: >-+ for (i = 0; i < krt_size; i++) { >-+ struct ktable ktab; >-+ >-+ if ((kt = ktable_get(i)) == NULL) >-+ continue; >-+ >-+ ktab = *kt; >-+ /* do not leak internal information */ >-+ RB_INIT(&ktab.krt); >-+ RB_INIT(&ktab.krt6); >-+ RB_INIT(&ktab.knt); >-+ TAILQ_INIT(&ktab.krn); >-+ >-+ send_imsg_session(IMSG_CTL_SHOW_FIB_TABLES, >-+ imsg->hdr.pid, &ktab, sizeof(ktab)); >-+ } >-+ break; >- default: /* nada */ >- break; >- } >-- >-- send_imsg_session(IMSG_CTL_END, imsg->hdr.pid, NULL, 0); >-+ >-+ send_imsg_session(IMSG_CTL_END, imsg->hdr.pid, NULL, 0); >-+} >-+ >-+void >-+kr_ifinfo(char *ifname) >-+{ >-+ struct kif_node *kif; >-+ >-+ RB_FOREACH(kif, kif_tree, &kit) >-+ if (!strcmp(ifname, kif->k.ifname)) { >-+ send_imsg_session(IMSG_IFINFO, 0, >-+ &kif->k, sizeof(kif->k)); >-+ return; >-+ } >-+} >-+ >-+void >-+kr_net_delete(struct network *n) >-+{ >-+ filterset_free(&n->net.attrset); >-+ free(n); >-+} >-+ >-+struct network * >-+kr_net_match(struct ktable *kt, struct kroute *kr) >-+{ >-+ struct network *xn; >-+ >-+ TAILQ_FOREACH(xn, &kt->krn, entry) { >-+ if (xn->net.prefix.aid != AID_INET) >-+ continue; >-+ switch (xn->net.type) { >-+ case NETWORK_DEFAULT: >-+ if (xn->net.prefixlen == kr->prefixlen && >-+ xn->net.prefix.v4.s_addr == kr->prefix.s_addr) >-+ /* static match already redistributed */ >-+ return (NULL); >-+ break; >-+ case NETWORK_STATIC: >-+ if (kr->flags & F_STATIC) >-+ return (xn); >-+ break; >-+ case NETWORK_CONNECTED: >-+ if (kr->flags & F_CONNECTED) >-+ return (xn); >-+ break; >-+ case NETWORK_MRTCLONE: >-+ /* can not happen */ >-+ break; >-+ } >-+ } >-+ return (NULL); >- } >- >--void >--kr_ifinfo(char *ifname) >-+struct network * >-+kr_net_match6(struct ktable *kt, struct kroute6 *kr6) >- { >-- struct kif_node *kif; >-+ struct network *xn; >- >-- RB_FOREACH(kif, kif_tree, &kit) >-- if (!strcmp(ifname, kif->k.ifname)) { >-- send_imsg_session(IMSG_IFINFO, 0, >-- &kif->k, sizeof(kif->k)); >-- return; >-+ TAILQ_FOREACH(xn, &kt->krn, entry) { >-+ if (xn->net.prefix.aid != AID_INET6) >-+ continue; >-+ switch (xn->net.type) { >-+ case NETWORK_DEFAULT: >-+ if (xn->net.prefixlen == kr6->prefixlen && >-+ memcmp(&xn->net.prefix.v6, &kr6->prefix, >-+ sizeof(struct in6_addr)) == 0) >-+ /* static match already redistributed */ >-+ return (NULL); >-+ break; >-+ case NETWORK_STATIC: >-+ if (kr6->flags & F_STATIC) >-+ return (xn); >-+ break; >-+ case NETWORK_CONNECTED: >-+ if (kr6->flags & F_CONNECTED) >-+ return (xn); >-+ break; >-+ case NETWORK_MRTCLONE: >-+ /* can not happen */ >-+ break; >- } >-+ } >-+ return (NULL); >- } >- >--struct redist_node { >-- LIST_ENTRY(redist_node) entry; >-- struct kroute *kr; >-- struct kroute6 *kr6; >--}; >-+struct network * >-+kr_net_find(struct ktable *kt, struct network *n) >-+{ >-+ struct network *xn; >-+ >-+ TAILQ_FOREACH(xn, &kt->krn, entry) { >-+ if (n->net.type != xn->net.type || >-+ n->net.prefixlen != xn->net.prefixlen || >-+ n->net.rtableid != xn->net.rtableid) >-+ continue; >-+ if (memcmp(&n->net.prefix, &xn->net.prefix, >-+ sizeof(n->net.prefix)) == 0) >-+ return (xn); >-+ } >-+ return (NULL); >-+} >-+ >-+int >-+kr_net_reload(u_int rtableid, struct network_head *nh) >-+{ >-+ struct network *n, *xn; >-+ struct ktable *kt; >-+ >-+ if ((kt = ktable_get(rtableid)) == NULL) { >-+ log_warnx("kr_net_reload: non-existent rtableid %d", rtableid); >-+ return (-1); >-+ } >-+ >-+ TAILQ_FOREACH(n, &kt->krn, entry) >-+ n->net.old = 1; >-+ >-+ while ((n = TAILQ_FIRST(nh)) != NULL) { >-+ TAILQ_REMOVE(nh, n, entry); >-+ n->net.old = 0; >-+ n->net.rtableid = rtableid; >-+ xn = kr_net_find(kt, n); >-+ if (xn) { >-+ xn->net.old = 0; >-+ filterset_free(&xn->net.attrset); >-+ filterset_move(&n->net.attrset, &xn->net.attrset); >-+ kr_net_delete(n); >-+ } else >-+ TAILQ_INSERT_TAIL(&kt->krn, n, entry); >-+ } >- >-+ for (n = TAILQ_FIRST(&kt->krn); n != NULL; n = xn) { >-+ xn = TAILQ_NEXT(n, entry); >-+ if (n->net.old) { >-+ if (n->net.type == NETWORK_DEFAULT) >-+ if (send_network(IMSG_NETWORK_REMOVE, &n->net, >-+ NULL)) >-+ return (-1); >-+ TAILQ_REMOVE(&kt->krn, n, entry); >-+ kr_net_delete(n); >-+ } >-+ } >- >--LIST_HEAD(, redist_node) redistlist; >-+ return (0); >-+} >- >- int >--kr_redistribute(int type, struct kroute *kr) >-+kr_redistribute(int type, struct ktable *kt, struct kroute *kr) >- { >-- struct redist_node *rn; >-+ struct network *match; >-+ struct network_config net; >- u_int32_t a; >- >-+ /* shortcut for removals */ >-+ if (type == IMSG_NETWORK_REMOVE) { >-+ if (!(kr->flags & F_REDISTRIBUTED)) >-+ return (0); /* no match, don't redistribute */ >-+ kr->flags &= ~F_REDISTRIBUTED; >-+ match = NULL; >-+ goto sendit; >-+ } >-+ >- if (!(kr->flags & F_KERNEL)) >- return (0); >- >-@@ -670,41 +1205,40 @@ kr_redistribute(int type, struct kroute >- if (kr->prefix.s_addr == INADDR_ANY && kr->prefixlen == 0) >- return (0); >- >-- /* Add or delete kr from list ... */ >-- LIST_FOREACH(rn, &redistlist, entry) >-- if (rn->kr == kr) >-- break; >-- >-- switch (type) { >-- case IMSG_NETWORK_ADD: >-- if (rn == NULL) { >-- if ((rn = calloc(1, sizeof(struct redist_node))) == >-- NULL) { >-- log_warn("kr_redistribute"); >-- return (-1); >-- } >-- rn->kr = kr; >-- LIST_INSERT_HEAD(&redistlist, rn, entry); >-- } >-- break; >-- case IMSG_NETWORK_REMOVE: >-- if (rn != NULL) { >-- LIST_REMOVE(rn, entry); >-- free(rn); >-- } >-- break; >-- default: >-- errno = EINVAL; >-- return (-1); >-- } >-- >-- return (bgpd_redistribute(type, kr, NULL)); >-+ match = kr_net_match(kt, kr); >-+ if (match == NULL) { >-+ if (!(kr->flags & F_REDISTRIBUTED)) >-+ return (0); /* no match, don't redistribute */ >-+ /* route no longer matches but is redistributed, so remove */ >-+ kr->flags &= ~F_REDISTRIBUTED; >-+ type = IMSG_NETWORK_REMOVE; >-+ } else >-+ kr->flags |= F_REDISTRIBUTED; >-+ >-+sendit: >-+ bzero(&net, sizeof(net)); >-+ net.prefix.aid = AID_INET; >-+ net.prefix.v4.s_addr = kr->prefix.s_addr; >-+ net.prefixlen = kr->prefixlen; >-+ net.rtableid = kt->rtableid; >-+ >-+ return (send_network(type, &net, match ? &match->net.attrset : NULL)); >- } >- >- int >--kr_redistribute6(int type, struct kroute6 *kr6) >--{ >-- struct redist_node *rn; >-+kr_redistribute6(int type, struct ktable *kt, struct kroute6 *kr6) >-+{ >-+ struct network *match; >-+ struct network_config net; >-+ >-+ /* shortcut for removals */ >-+ if (type == IMSG_NETWORK_REMOVE) { >-+ if (!(kr6->flags & F_REDISTRIBUTED)) >-+ return (0); /* no match, don't redistribute */ >-+ kr6->flags &= ~F_REDISTRIBUTED; >-+ match = NULL; >-+ goto sendit; >-+ } >- >- if (!(kr6->flags & F_KERNEL)) >- return (0); >-@@ -736,60 +1270,107 @@ kr_redistribute6(int type, struct kroute >- * never allow ::/0 the default route can only be redistributed >- * with announce default. >- */ >-- if (memcmp(&kr6->prefix, &in6addr_any, sizeof(struct in6_addr)) == 0 && >-- kr6->prefixlen == 0) >-+ if (kr6->prefixlen == 0 && >-+ memcmp(&kr6->prefix, &in6addr_any, sizeof(struct in6_addr)) == 0) >- return (0); >- >-- /* Add or delete kr from list ... >-- * using a linear list to store the redistributed networks will hurt >-- * as soon as redistribute ospf comes but until then keep it simple. >-- */ >-- LIST_FOREACH(rn, &redistlist, entry) >-- if (rn->kr6 == kr6) >-- break; >-- >-- switch (type) { >-- case IMSG_NETWORK_ADD: >-- if (rn == NULL) { >-- if ((rn = calloc(1, sizeof(struct redist_node))) == >-- NULL) { >-- log_warn("kr_redistribute"); >-- return (-1); >-- } >-- rn->kr6 = kr6; >-- LIST_INSERT_HEAD(&redistlist, rn, entry); >-- } >-- break; >-- case IMSG_NETWORK_REMOVE: >-- if (rn != NULL) { >-- LIST_REMOVE(rn, entry); >-- free(rn); >-- } >-- break; >-- default: >-- errno = EINVAL; >-- return (-1); >-- } >-+ match = kr_net_match6(kt, kr6); >-+ if (match == NULL) { >-+ if (!(kr6->flags & F_REDISTRIBUTED)) >-+ return (0); /* no match, don't redistribute */ >-+ /* route no longer matches but is redistributed, so remove */ >-+ kr6->flags &= ~F_REDISTRIBUTED; >-+ type = IMSG_NETWORK_REMOVE; >-+ } else >-+ kr6->flags |= F_REDISTRIBUTED; >-+sendit: >-+ bzero(&net, sizeof(net)); >-+ net.prefix.aid = AID_INET6; >-+ memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr)); >-+ net.prefixlen = kr6->prefixlen; >-+ net.rtableid = kt->rtableid; >- >-- return (bgpd_redistribute(type, NULL, kr6)); >-+ return (send_network(type, &net, match ? &match->net.attrset : NULL)); >- } >- >- int >- kr_reload(void) >- { >-- struct redist_node *rn; >-+ struct ktable *kt; >-+ struct kroute_node *kr; >-+ struct kroute6_node *kr6; >- struct knexthop_node *nh; >-+ struct network *n; >-+ u_int rid; >-+ int hasdyn = 0; >- >-- LIST_FOREACH(rn, &redistlist, entry) >-- if (bgpd_redistribute(IMSG_NETWORK_ADD, rn->kr, rn->kr6) == -1) >-- return (-1); >-+ for (rid = 0; rid < krt_size; rid++) { >-+ if ((kt = ktable_get(rid)) == NULL) >-+ continue; >- >-- RB_FOREACH(nh, knexthop_tree, &knt) >-- knexthop_validate(nh); >-+ RB_FOREACH(nh, knexthop_tree, KT2KNT(kt)) >-+ knexthop_validate(kt, nh); >-+ >-+ TAILQ_FOREACH(n, &kt->krn, entry) >-+ if (n->net.type == NETWORK_DEFAULT) { >-+ if (send_network(IMSG_NETWORK_ADD, &n->net, >-+ &n->net.attrset)) >-+ return (-1); >-+ } else >-+ hasdyn = 1; >-+ >-+ if (hasdyn) { >-+ /* only evaluate the full tree if we need */ >-+ RB_FOREACH(kr, kroute_tree, &kt->krt) >-+ kr_redistribute(IMSG_NETWORK_ADD, kt, &kr->r); >-+ RB_FOREACH(kr6, kroute6_tree, &kt->krt6) >-+ kr_redistribute6(IMSG_NETWORK_ADD, kt, &kr6->r); >-+ } >-+ } >- >- return (0); >- } >- >-+struct kroute_full * >-+kr_tofull(struct kroute *kr) >-+{ >-+ static struct kroute_full kf; >-+ >-+ bzero(&kf, sizeof(kf)); >-+ >-+ kf.prefix.aid = AID_INET; >-+ kf.prefix.v4.s_addr = kr->prefix.s_addr; >-+ kf.nexthop.aid = AID_INET; >-+ kf.nexthop.v4.s_addr = kr->nexthop.s_addr; >-+ strlcpy(kf.label, rtlabel_id2name(kr->labelid), sizeof(kf.label)); >-+ kf.flags = kr->flags; >-+ kf.ifindex = kr->ifindex; >-+ kf.prefixlen = kr->prefixlen; >-+ kf.priority = kr->priority; >-+ >-+ return (&kf); >-+} >-+ >-+struct kroute_full * >-+kr6_tofull(struct kroute6 *kr6) >-+{ >-+ static struct kroute_full kf; >-+ >-+ bzero(&kf, sizeof(kf)); >-+ >-+ kf.prefix.aid = AID_INET6; >-+ memcpy(&kf.prefix.v6, &kr6->prefix, sizeof(struct in6_addr)); >-+ kf.nexthop.aid = AID_INET6; >-+ memcpy(&kf.nexthop.v6, &kr6->nexthop, sizeof(struct in6_addr)); >-+ strlcpy(kf.label, rtlabel_id2name(kr6->labelid), sizeof(kf.label)); >-+ kf.flags = kr6->flags; >-+ kf.ifindex = kr6->ifindex; >-+ kf.prefixlen = kr6->prefixlen; >-+ kf.priority = kr6->priority; >-+ >-+ return (&kf); >-+} >-+ >- /* >- * RB-tree compare functions >- */ >-@@ -846,26 +1427,28 @@ kroute6_compare(struct kroute6_node *a, >- int >- knexthop_compare(struct knexthop_node *a, struct knexthop_node *b) >- { >-- u_int32_t r; >-+ int i; >- >-- if (a->nexthop.af != b->nexthop.af) >-- return (b->nexthop.af - a->nexthop.af); >-+ if (a->nexthop.aid != b->nexthop.aid) >-+ return (b->nexthop.aid - a->nexthop.aid); >- >-- switch (a->nexthop.af) { >-- case AF_INET: >-- if ((r = b->nexthop.addr32[0] - a->nexthop.addr32[0]) != 0) >-- return (r); >-+ switch (a->nexthop.aid) { >-+ case AID_INET: >-+ if (ntohl(a->nexthop.v4.s_addr) < ntohl(b->nexthop.v4.s_addr)) >-+ return (-1); >-+ if (ntohl(a->nexthop.v4.s_addr) > ntohl(b->nexthop.v4.s_addr)) >-+ return (1); >- break; >-- case AF_INET6: >-- if ((r = b->nexthop.addr32[3] - a->nexthop.addr32[3]) != 0) >-- return (r); >-- if ((r = b->nexthop.addr32[2] - a->nexthop.addr32[2]) != 0) >-- return (r); >-- if ((r = b->nexthop.addr32[1] - a->nexthop.addr32[1]) != 0) >-- return (r); >-- if ((r = b->nexthop.addr32[0] - a->nexthop.addr32[0]) != 0) >-- return (r); >-+ case AID_INET6: >-+ for (i = 0; i < 16; i++) { >-+ if (a->nexthop.v6.s6_addr[i] < b->nexthop.v6.s6_addr[i]) >-+ return (-1); >-+ if (a->nexthop.v6.s6_addr[i] > b->nexthop.v6.s6_addr[i]) >-+ return (1); >-+ } >- break; >-+ default: >-+ fatalx("knexthop_compare: unknown AF"); >- } >- >- return (0); >-@@ -883,7 +1466,8 @@ kif_compare(struct kif_node *a, struct k >- */ >- >- struct kroute_node * >--kroute_find(in_addr_t prefix, u_int8_t prefixlen, u_int8_t prio) >-+kroute_find(struct ktable *kt, in_addr_t prefix, u_int8_t prefixlen, >-+ u_int8_t prio) >- { >- struct kroute_node s; >- struct kroute_node *kn, *tmp; >-@@ -892,15 +1476,15 @@ kroute_find(in_addr_t prefix, u_int8_t p >- s.r.prefixlen = prefixlen; >- s.r.priority = prio; >- >-- kn = RB_FIND(kroute_tree, &krt, &s); >-+ kn = RB_FIND(kroute_tree, &kt->krt, &s); >- if (kn && prio == RTP_ANY) { >-- tmp = RB_PREV(kroute_tree, &krt, kn); >-+ tmp = RB_PREV(kroute_tree, &kt->krt, kn); >- while (tmp) { >- if (kroute_compare(&s, tmp) == 0) >- kn = tmp; >- else >- break; >-- tmp = RB_PREV(kroute_tree, &krt, kn); >-+ tmp = RB_PREV(kroute_tree, &kt->krt, kn); >- } >- } >- return (kn); >-@@ -927,13 +1511,13 @@ kroute_matchgw(struct kroute_node *kr, s >- } >- >- int >--kroute_insert(struct kroute_node *kr) >-+kroute_insert(struct ktable *kt, struct kroute_node *kr) >- { >- struct kroute_node *krm; >- struct knexthop_node *h; >- in_addr_t mask, ina; >- >-- if ((krm = RB_INSERT(kroute_tree, &krt, kr)) != NULL) { >-+ if ((krm = RB_INSERT(kroute_tree, &kt->krt, kr)) != NULL) { >- /* multipath route, add at end of list */ >- while (krm->next != NULL) >- krm = krm->next; >-@@ -941,13 +1525,14 @@ kroute_insert(struct kroute_node *kr) >- kr->next = NULL; /* to be sure */ >- } >- >-+ /* XXX this is wrong for nexthop validated via BGP */ >- if (kr->r.flags & F_KERNEL) { >- mask = prefixlen2mask(kr->r.prefixlen); >- ina = ntohl(kr->r.prefix.s_addr); >-- RB_FOREACH(h, knexthop_tree, &knt) >-- if (h->nexthop.af == AF_INET && >-+ RB_FOREACH(h, knexthop_tree, KT2KNT(kt)) >-+ if (h->nexthop.aid == AID_INET && >- (ntohl(h->nexthop.v4.s_addr) & mask) == ina) >-- knexthop_validate(h); >-+ knexthop_validate(kt, h); >- >- if (kr->r.flags & F_CONNECTED) >- if (kif_kr_insert(kr) == -1) >-@@ -955,19 +1540,19 @@ kroute_insert(struct kroute_node *kr) >- >- if (krm == NULL) >- /* redistribute multipath routes only once */ >-- kr_redistribute(IMSG_NETWORK_ADD, &kr->r); >-+ kr_redistribute(IMSG_NETWORK_ADD, kt, &kr->r); >- } >- return (0); >- } >- >- >- int >--kroute_remove(struct kroute_node *kr) >-+kroute_remove(struct ktable *kt, struct kroute_node *kr) >- { >- struct kroute_node *krm; >- struct knexthop_node *s; >- >-- if ((krm = RB_FIND(kroute_tree, &krt, kr)) == NULL) { >-+ if ((krm = RB_FIND(kroute_tree, &kt->krt, kr)) == NULL) { >- log_warnx("kroute_remove failed to find %s/%u", >- inet_ntoa(kr->r.prefix), kr->r.prefixlen); >- return (-1); >-@@ -975,13 +1560,14 @@ kroute_remove(struct kroute_node *kr) >- >- if (krm == kr) { >- /* head element */ >-- if (RB_REMOVE(kroute_tree, &krt, kr) == NULL) { >-+ if (RB_REMOVE(kroute_tree, &kt->krt, kr) == NULL) { >- log_warnx("kroute_remove failed for %s/%u", >- inet_ntoa(kr->r.prefix), kr->r.prefixlen); >- return (-1); >- } >- if (kr->next != NULL) { >-- if (RB_INSERT(kroute_tree, &krt, kr->next) != NULL) { >-+ if (RB_INSERT(kroute_tree, &kt->krt, kr->next) != >-+ NULL) { >- log_warnx("kroute_remove failed to add %s/%u", >- inet_ntoa(kr->r.prefix), kr->r.prefixlen); >- return (-1); >-@@ -1001,14 +1587,14 @@ kroute_remove(struct kroute_node *kr) >- } >- >- /* check whether a nexthop depends on this kroute */ >-- if ((kr->r.flags & F_KERNEL) && (kr->r.flags & F_NEXTHOP)) >-- RB_FOREACH(s, knexthop_tree, &knt) >-+ if (kr->r.flags & F_NEXTHOP) >-+ RB_FOREACH(s, knexthop_tree, KT2KNT(kt)) >- if (s->kroute == kr) >-- knexthop_validate(s); >-+ knexthop_validate(kt, s); >- >- if (kr->r.flags & F_KERNEL && kr == krm && kr->next == NULL) >- /* again remove only once */ >-- kr_redistribute(IMSG_NETWORK_REMOVE, &kr->r); >-+ kr_redistribute(IMSG_NETWORK_REMOVE, kt, &kr->r); >- >- if (kr->r.flags & F_CONNECTED) >- if (kif_kr_remove(kr) == -1) { >-@@ -1021,16 +1607,17 @@ kroute_remove(struct kroute_node *kr) >- } >- >- void >--kroute_clear(void) >-+kroute_clear(struct ktable *kt) >- { >- struct kroute_node *kr; >- >-- while ((kr = RB_MIN(kroute_tree, &krt)) != NULL) >-- kroute_remove(kr); >-+ while ((kr = RB_MIN(kroute_tree, &kt->krt)) != NULL) >-+ kroute_remove(kt, kr); >- } >- >- struct kroute6_node * >--kroute6_find(const struct in6_addr *prefix, u_int8_t prefixlen, u_int8_t prio) >-+kroute6_find(struct ktable *kt, const struct in6_addr *prefix, >-+ u_int8_t prefixlen, u_int8_t prio) >- { >- struct kroute6_node s; >- struct kroute6_node *kn6, *tmp; >-@@ -1039,15 +1626,15 @@ kroute6_find(const struct in6_addr *pref >- s.r.prefixlen = prefixlen; >- s.r.priority = prio; >- >-- kn6 = RB_FIND(kroute6_tree, &krt6, &s); >-+ kn6 = RB_FIND(kroute6_tree, &kt->krt6, &s); >- if (kn6 && prio == RTP_ANY) { >-- tmp = RB_PREV(kroute6_tree, &krt6, kn6); >-+ tmp = RB_PREV(kroute6_tree, &kt->krt6, kn6); >- while (tmp) { >- if (kroute6_compare(&s, tmp) == 0) >- kn6 = tmp; >-- else >-+ else >- break; >-- tmp = RB_PREV(kroute6_tree, &krt6, kn6); >-+ tmp = RB_PREV(kroute6_tree, &kt->krt6, kn6); >- } >- } >- return (kn6); >-@@ -1056,17 +1643,29 @@ kroute6_find(const struct in6_addr *pref >- struct kroute6_node * >- kroute6_matchgw(struct kroute6_node *kr, struct sockaddr_in6 *sa_in6) >- { >-- struct in6_addr nexthop; >-+ struct sockaddr_in6 nexthop; >- >- if (sa_in6 == NULL) { >- log_warnx("kroute6_matchgw: no nexthop defined"); >- return (NULL); >- } >-- memcpy(&nexthop, &sa_in6->sin6_addr, sizeof(nexthop)); >-+ memcpy(&nexthop, sa_in6, sizeof(nexthop)); >-+#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER) >-+ if (IN6_IS_ADDR_LINKLOCAL(&nexthop.sin6_addr)) { >-+ /* Embed scope id and set sin6_scope_id. */ >-+ if (nexthop.sin6_scope_id == 0) >-+ nexthop.sin6_scope_id = >-+ IN6_LINKLOCAL_IFINDEX(nexthop.sin6_addr); >-+ else >-+ SET_IN6_LINKLOCAL_IFINDEX(nexthop.sin6_addr, >-+ nexthop.sin6_scope_id); >-+ } >-+#endif >- >- while (kr) { >-- if (memcmp(&kr->r.nexthop, &nexthop, sizeof(nexthop)) == NULL) >-- return (kr); >-+ if (memcmp(&kr->r.nexthop, &nexthop.sin6_addr, >-+ sizeof(nexthop.sin6_addr)) == 0) >-+ return (kr); >- kr = kr->next; >- } >- >-@@ -1074,13 +1673,13 @@ kroute6_matchgw(struct kroute6_node *kr, >- } >- >- int >--kroute6_insert(struct kroute6_node *kr) >-+kroute6_insert(struct ktable *kt, struct kroute6_node *kr) >- { >- struct kroute6_node *krm; >- struct knexthop_node *h; >- struct in6_addr ina, inb; >- >-- if ((krm = RB_INSERT(kroute6_tree, &krt6, kr)) != NULL) { >-+ if ((krm = RB_INSERT(kroute6_tree, &kt->krt6, kr)) != NULL) { >- /* multipath route, add at end of list */ >- while (krm->next != NULL) >- krm = krm->next; >-@@ -1088,14 +1687,15 @@ kroute6_insert(struct kroute6_node *kr) >- kr->next = NULL; /* to be sure */ >- } >- >-+ /* XXX this is wrong for nexthop validated via BGP */ >- if (kr->r.flags & F_KERNEL) { >- inet6applymask(&ina, &kr->r.prefix, kr->r.prefixlen); >-- RB_FOREACH(h, knexthop_tree, &knt) >-- if (h->nexthop.af == AF_INET6) { >-+ RB_FOREACH(h, knexthop_tree, KT2KNT(kt)) >-+ if (h->nexthop.aid == AID_INET6) { >- inet6applymask(&inb, &h->nexthop.v6, >- kr->r.prefixlen); >- if (memcmp(&ina, &inb, sizeof(ina)) == 0) >-- knexthop_validate(h); >-+ knexthop_validate(kt, h); >- } >- >- if (kr->r.flags & F_CONNECTED) >-@@ -1104,19 +1704,19 @@ kroute6_insert(struct kroute6_node *kr) >- >- if (krm == NULL) >- /* redistribute multipath routes only once */ >-- kr_redistribute6(IMSG_NETWORK_ADD, &kr->r); >-+ kr_redistribute6(IMSG_NETWORK_ADD, kt, &kr->r); >- } >- >- return (0); >- } >- >- int >--kroute6_remove(struct kroute6_node *kr) >-+kroute6_remove(struct ktable *kt, struct kroute6_node *kr) >- { >- struct kroute6_node *krm; >- struct knexthop_node *s; >- >-- if ((krm = RB_FIND(kroute6_tree, &krt6, kr)) == NULL) { >-+ if ((krm = RB_FIND(kroute6_tree, &kt->krt6, kr)) == NULL) { >- log_warnx("kroute6_remove failed for %s/%u", >- log_in6addr(&kr->r.prefix), kr->r.prefixlen); >- return (-1); >-@@ -1124,13 +1724,14 @@ kroute6_remove(struct kroute6_node *kr) >- >- if (krm == kr) { >- /* head element */ >-- if (RB_REMOVE(kroute6_tree, &krt6, kr) == NULL) { >-+ if (RB_REMOVE(kroute6_tree, &kt->krt6, kr) == NULL) { >- log_warnx("kroute6_remove failed for %s/%u", >- log_in6addr(&kr->r.prefix), kr->r.prefixlen); >- return (-1); >- } >- if (kr->next != NULL) { >-- if (RB_INSERT(kroute6_tree, &krt6, kr->next) != NULL) { >-+ if (RB_INSERT(kroute6_tree, &kt->krt6, kr->next) != >-+ NULL) { >- log_warnx("kroute6_remove failed to add %s/%u", >- log_in6addr(&kr->r.prefix), >- kr->r.prefixlen); >-@@ -1151,14 +1752,14 @@ kroute6_remove(struct kroute6_node *kr) >- } >- >- /* check whether a nexthop depends on this kroute */ >-- if ((kr->r.flags & F_KERNEL) && (kr->r.flags & F_NEXTHOP)) >-- RB_FOREACH(s, knexthop_tree, &knt) >-+ if (kr->r.flags & F_NEXTHOP) >-+ RB_FOREACH(s, knexthop_tree, KT2KNT(kt)) >- if (s->kroute == kr) >-- knexthop_validate(s); >-+ knexthop_validate(kt, s); >- >- if (kr->r.flags & F_KERNEL && kr == krm && kr->next == NULL) >- /* again remove only once */ >-- kr_redistribute6(IMSG_NETWORK_REMOVE, &kr->r); >-+ kr_redistribute6(IMSG_NETWORK_REMOVE, kt, &kr->r); >- >- if (kr->r.flags & F_CONNECTED) >- if (kif_kr6_remove(kr) == -1) { >-@@ -1171,45 +1772,46 @@ kroute6_remove(struct kroute6_node *kr) >- } >- >- void >--kroute6_clear(void) >-+kroute6_clear(struct ktable *kt) >- { >- struct kroute6_node *kr; >- >-- while ((kr = RB_MIN(kroute6_tree, &krt6)) != NULL) >-- kroute6_remove(kr); >-+ while ((kr = RB_MIN(kroute6_tree, &kt->krt6)) != NULL) >-+ kroute6_remove(kt, kr); >- } >- >- struct knexthop_node * >--knexthop_find(struct bgpd_addr *addr) >-+knexthop_find(struct ktable *kt, struct bgpd_addr *addr) >- { >- struct knexthop_node s; >- >-+ bzero(&s, sizeof(s)); >- memcpy(&s.nexthop, addr, sizeof(s.nexthop)); >- >-- return (RB_FIND(knexthop_tree, &knt, &s)); >-+ return (RB_FIND(knexthop_tree, KT2KNT(kt), &s)); >- } >- >- int >--knexthop_insert(struct knexthop_node *kn) >-+knexthop_insert(struct ktable *kt, struct knexthop_node *kn) >- { >-- if (RB_INSERT(knexthop_tree, &knt, kn) != NULL) { >-+ if (RB_INSERT(knexthop_tree, KT2KNT(kt), kn) != NULL) { >- log_warnx("knexthop_tree insert failed for %s", >- log_addr(&kn->nexthop)); >- free(kn); >- return (-1); >- } >- >-- knexthop_validate(kn); >-+ knexthop_validate(kt, kn); >- >- return (0); >- } >- >- int >--knexthop_remove(struct knexthop_node *kn) >-+knexthop_remove(struct ktable *kt, struct knexthop_node *kn) >- { >-- kroute_detach_nexthop(kn); >-+ kroute_detach_nexthop(kt, kn); >- >-- if (RB_REMOVE(knexthop_tree, &knt, kn) == NULL) { >-+ if (RB_REMOVE(knexthop_tree, KT2KNT(kt), kn) == NULL) { >- log_warnx("knexthop_remove failed for %s", >- log_addr(&kn->nexthop)); >- return (-1); >-@@ -1220,12 +1822,12 @@ knexthop_remove(struct knexthop_node *kn >- } >- >- void >--knexthop_clear(void) >-+knexthop_clear(struct ktable *kt) >- { >- struct knexthop_node *kn; >- >-- while ((kn = RB_MIN(knexthop_tree, &knt)) != NULL) >-- knexthop_remove(kn); >-+ while ((kn = RB_MIN(knexthop_tree, KT2KNT(kt))) != NULL) >-+ knexthop_remove(kt, kn); >- } >- >- struct kif_node * >-@@ -1257,6 +1859,7 @@ kif_insert(struct kif_node *kif) >- int >- kif_remove(struct kif_node *kif) >- { >-+ struct ktable *kt; >- struct kif_kr *kkr; >- struct kif_kr6 *kkr6; >- >-@@ -1265,20 +1868,23 @@ kif_remove(struct kif_node *kif) >- return (-1); >- } >- >-+ if ((kt = ktable_get(/* XXX */ 0)) == NULL) >-+ goto done; >-+ >- while ((kkr = LIST_FIRST(&kif->kroute_l)) != NULL) { >- LIST_REMOVE(kkr, entry); >- kkr->kr->r.flags &= ~F_NEXTHOP; >-- kroute_remove(kkr->kr); >-+ kroute_remove(kt, kkr->kr); >- free(kkr); >- } >- >- while ((kkr6 = LIST_FIRST(&kif->kroute6_l)) != NULL) { >- LIST_REMOVE(kkr6, entry); >- kkr6->kr->r.flags &= ~F_NEXTHOP; >-- kroute6_remove(kkr6->kr); >-+ kroute6_remove(kt, kkr6->kr); >- free(kkr6); >- } >-- >-+done: >- free(kif); >- return (0); >- } >-@@ -1473,113 +2079,109 @@ kroute6_validate(struct kroute6 *kr) >- } >- >- void >--knexthop_validate(struct knexthop_node *kn) >-+knexthop_validate(struct ktable *kt, struct knexthop_node *kn) >- { >-+ void *oldk; >- struct kroute_node *kr; >- struct kroute6_node *kr6; >-- struct kroute_nexthop n; >-- int was_valid = 0; >- >-- if (kn->nexthop.af == AF_INET && (kr = kn->kroute) != NULL) >-- was_valid = kroute_validate(&kr->r); >-- if (kn->nexthop.af == AF_INET6 && (kr6 = kn->kroute) != NULL) >-- was_valid = kroute6_validate(&kr6->r); >-+ oldk = kn->kroute; >-+ kroute_detach_nexthop(kt, kn); >- >-- bzero(&n, sizeof(n)); >-- memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop)); >-- kroute_detach_nexthop(kn); >-- >-- switch (kn->nexthop.af) { >-- case AF_INET: >-- if ((kr = kroute_match(kn->nexthop.v4.s_addr, 0)) == NULL) { >-- if (was_valid) >-- send_nexthop_update(&n); >-- } else { /* match */ >-- if (kroute_validate(&kr->r)) { /* valid */ >-- n.valid = 1; >-- n.connected = kr->r.flags & F_CONNECTED; >-- if ((n.gateway.v4.s_addr = >-- kr->r.nexthop.s_addr) != 0) >-- n.gateway.af = AF_INET; >-- memcpy(&n.kr.kr4, &kr->r, sizeof(n.kr.kr4)); >-- send_nexthop_update(&n); >-- } else /* down */ >-- if (was_valid) >-- send_nexthop_update(&n); >-+ switch (kn->nexthop.aid) { >-+ case AID_INET: >-+ kr = kroute_match(kt, kn->nexthop.v4.s_addr, 0); >- >-+ if (kr) { >- kn->kroute = kr; >- kr->r.flags |= F_NEXTHOP; >- } >-+ >-+ /* >-+ * Send update if nexthop route changed under us if >-+ * the route remains the same then the NH state has not >-+ * changed. State changes are tracked by knexthop_track(). >-+ */ >-+ if (kr != oldk) >-+ knexthop_send_update(kn); >- break; >-- case AF_INET6: >-- if ((kr6 = kroute6_match(&kn->nexthop.v6, 0)) == NULL) { >-- if (was_valid) >-- send_nexthop_update(&n); >-- } else { /* match */ >-- if (kroute6_validate(&kr6->r)) { /* valid */ >-- n.valid = 1; >-- n.connected = kr6->r.flags & F_CONNECTED; >-- if (memcmp(&kr6->r.nexthop, &in6addr_any, >-- sizeof(struct in6_addr)) != 0) { >-- n.gateway.af = AF_INET6; >-- memcpy(&n.gateway.v6, &kr6->r.nexthop, >-- sizeof(struct in6_addr)); >-- } >-- memcpy(&n.kr.kr6, &kr6->r, sizeof(n.kr.kr6)); >-- send_nexthop_update(&n); >-- } else /* down */ >-- if (was_valid) >-- send_nexthop_update(&n); >-+ case AID_INET6: >-+ kr6 = kroute6_match(kt, &kn->nexthop.v6, 0); >- >-+ if (kr6) { >- kn->kroute = kr6; >- kr6->r.flags |= F_NEXTHOP; >- } >-+ >-+ if (kr6 != oldk) >-+ knexthop_send_update(kn); >- break; >- } >- } >- >- void >--knexthop_track(void *krn) >-+knexthop_track(struct ktable *kt, void *krp) >- { >- struct knexthop_node *kn; >-+ >-+ RB_FOREACH(kn, knexthop_tree, KT2KNT(kt)) >-+ if (kn->kroute == krp) >-+ knexthop_send_update(kn); >-+} >-+ >-+void >-+knexthop_send_update(struct knexthop_node *kn) >-+{ >-+ struct kroute_nexthop n; >- struct kroute_node *kr; >- struct kroute6_node *kr6; >-- struct kroute_nexthop n; >- >-- RB_FOREACH(kn, knexthop_tree, &knt) >-- if (kn->kroute == krn) { >-- bzero(&n, sizeof(n)); >-- memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop)); >-+ bzero(&n, sizeof(n)); >-+ memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop)); >- >-- switch (kn->nexthop.af) { >-- case AF_INET: >-- kr = krn; >-- n.valid = 1; >-- n.connected = kr->r.flags & F_CONNECTED; >-- if ((n.gateway.v4.s_addr = >-- kr->r.nexthop.s_addr) != 0) >-- n.gateway.af = AF_INET; >-- memcpy(&n.kr.kr4, &kr->r, sizeof(n.kr.kr4)); >-- break; >-- case AF_INET6: >-- kr6 = krn; >-- n.valid = 1; >-- n.connected = kr6->r.flags & F_CONNECTED; >-- if (memcmp(&kr6->r.nexthop, &in6addr_any, >-- sizeof(struct in6_addr)) != 0) { >-- n.gateway.af = AF_INET6; >-- memcpy(&n.gateway.v6, &kr6->r.nexthop, >-- sizeof(struct in6_addr)); >-- } >-- memcpy(&n.kr.kr6, &kr6->r, sizeof(n.kr.kr6)); >-- break; >-- } >-- send_nexthop_update(&n); >-+ if (kn->kroute == NULL) { >-+ n.valid = 0; /* NH is not valid */ >-+ send_nexthop_update(&n); >-+ return; >-+ } >-+ >-+ switch (kn->nexthop.aid) { >-+ case AID_INET: >-+ kr = kn->kroute; >-+ n.valid = kroute_validate(&kr->r); >-+ n.connected = kr->r.flags & F_CONNECTED; >-+ if ((n.gateway.v4.s_addr = >-+ kr->r.nexthop.s_addr) != 0) >-+ n.gateway.aid = AID_INET; >-+ if (n.connected) { >-+ n.net.aid = AID_INET; >-+ n.net.v4.s_addr = kr->r.prefix.s_addr; >-+ n.netlen = kr->r.prefixlen; >- } >-+ break; >-+ case AID_INET6: >-+ kr6 = kn->kroute; >-+ n.valid = kroute6_validate(&kr6->r); >-+ n.connected = kr6->r.flags & F_CONNECTED; >-+ if (memcmp(&kr6->r.nexthop, &in6addr_any, >-+ sizeof(struct in6_addr)) != 0) { >-+ n.gateway.aid = AID_INET6; >-+ memcpy(&n.gateway.v6, &kr6->r.nexthop, >-+ sizeof(struct in6_addr)); >-+ } >-+ if (n.connected) { >-+ n.net.aid = AID_INET6; >-+ memcpy(&n.net.v6, &kr6->r.nexthop, >-+ sizeof(struct in6_addr)); >-+ n.netlen = kr6->r.prefixlen; >-+ } >-+ break; >-+ } >-+ send_nexthop_update(&n); >- } >- >- struct kroute_node * >--kroute_match(in_addr_t key, int matchall) >-+kroute_match(struct ktable *kt, in_addr_t key, int matchall) >- { >- int i; >- struct kroute_node *kr; >-@@ -1589,13 +2191,13 @@ kroute_match(in_addr_t key, int matchall >- >- /* we will never match the default route */ >- for (i = 32; i > 0; i--) >-- if ((kr = kroute_find(htonl(ina & prefixlen2mask(i)), i, >-+ if ((kr = kroute_find(kt, htonl(ina & prefixlen2mask(i)), i, >- RTP_ANY)) != NULL) >- if (matchall || bgpd_filternexthop(&kr->r, NULL) == 0) >- return (kr); >- >- /* if we don't have a match yet, try to find a default route */ >-- if ((kr = kroute_find(0, 0, RTP_ANY)) != NULL) >-+ if ((kr = kroute_find(kt, 0, 0, RTP_ANY)) != NULL) >- if (matchall || bgpd_filternexthop(&kr->r, NULL) == 0) >- return (kr); >- >-@@ -1603,7 +2205,7 @@ kroute_match(in_addr_t key, int matchall >- } >- >- struct kroute6_node * >--kroute6_match(struct in6_addr *key, int matchall) >-+kroute6_match(struct ktable *kt, struct in6_addr *key, int matchall) >- { >- int i; >- struct kroute6_node *kr6; >-@@ -1612,13 +2214,13 @@ kroute6_match(struct in6_addr *key, int >- /* we will never match the default route */ >- for (i = 128; i > 0; i--) { >- inet6applymask(&ina, key, i); >-- if ((kr6 = kroute6_find(&ina, i, RTP_ANY)) != NULL) >-+ if ((kr6 = kroute6_find(kt, &ina, i, RTP_ANY)) != NULL) >- if (matchall || bgpd_filternexthop(NULL, &kr6->r) == 0) >- return (kr6); >- } >- >- /* if we don't have a match yet, try to find a default route */ >-- if ((kr6 = kroute6_find(&in6addr_any, 0, RTP_ANY)) != NULL) >-+ if ((kr6 = kroute6_find(kt, &in6addr_any, 0, RTP_ANY)) != NULL) >- if (matchall || bgpd_filternexthop(NULL, &kr6->r) == 0) >- return (kr6); >- >-@@ -1626,31 +2228,30 @@ kroute6_match(struct in6_addr *key, int >- } >- >- void >--kroute_detach_nexthop(struct knexthop_node *kn) >-+kroute_detach_nexthop(struct ktable *kt, struct knexthop_node *kn) >- { >- struct knexthop_node *s; >- struct kroute_node *k; >- struct kroute6_node *k6; >- >-+ if (kn->kroute == NULL) >-+ return; >-+ >- /* >- * check whether there's another nexthop depending on this kroute >- * if not remove the flag >- */ >-- >-- if (kn->kroute == NULL) >-- return; >-- >-- for (s = RB_MIN(knexthop_tree, &knt); s != NULL && >-- s->kroute != kn->kroute; s = RB_NEXT(knexthop_tree, &knt, s)) >-- ; /* nothing */ >-+ RB_FOREACH(s, knexthop_tree, KT2KNT(kt)) >-+ if (s->kroute == kn->kroute && s != kn) >-+ break; >- >- if (s == NULL) { >-- switch (kn->nexthop.af) { >-- case AF_INET: >-+ switch (kn->nexthop.aid) { >-+ case AID_INET: >- k = kn->kroute; >- k->r.flags &= ~F_NEXTHOP; >- break; >-- case AF_INET6: >-+ case AID_INET6: >- k6 = kn->kroute; >- k6->r.flags &= ~F_NEXTHOP; >- break; >-@@ -1665,7 +2266,7 @@ kroute_detach_nexthop(struct knexthop_no >- */ >- >- int >--protect_lo(void) >-+protect_lo(struct ktable *kt) >- { >- struct kroute_node *kr; >- struct kroute6_node *kr6; >-@@ -1675,11 +2276,11 @@ protect_lo(void) >- log_warn("protect_lo"); >- return (-1); >- } >-- kr->r.prefix.s_addr = htonl(INADDR_LOOPBACK); >-+ kr->r.prefix.s_addr = htonl(INADDR_LOOPBACK & IN_CLASSA_NET); >- kr->r.prefixlen = 8; >- kr->r.flags = F_KERNEL|F_CONNECTED; >- >-- if (RB_INSERT(kroute_tree, &krt, kr) != NULL) >-+ if (RB_INSERT(kroute_tree, &kt->krt, kr) != NULL) >- free(kr); /* kernel route already there, no problem */ >- >- /* special protection for loopback */ >-@@ -1689,9 +2290,9 @@ protect_lo(void) >- } >- memcpy(&kr6->r.prefix, &in6addr_loopback, sizeof(kr6->r.prefix)); >- kr6->r.prefixlen = 128; >-- kr->r.flags = F_KERNEL|F_CONNECTED; >-+ kr6->r.flags = F_KERNEL|F_CONNECTED; >- >-- if (RB_INSERT(kroute6_tree, &krt6, kr6) != NULL) >-+ if (RB_INSERT(kroute6_tree, &kt->krt6, kr6) != NULL) >- free(kr6); /* kernel route already there, no problem */ >- >- return (0); >-@@ -1726,17 +2327,17 @@ mask2prefixlen(in_addr_t ina) >- u_int8_t >- mask2prefixlen6(struct sockaddr_in6 *sa_in6) >- { >-- u_int8_t l = 0, i, len; >-+ u_int8_t l = 0, *ap, *ep; >- >- /* >- * sin6_len is the size of the sockaddr so substract the offset of >- * the possibly truncated sin6_addr struct. >- */ >-- len = sa_in6->sin6_len - >-- (u_int8_t)(&((struct sockaddr_in6 *)NULL)->sin6_addr); >-- for (i = 0; i < len; i++) { >-+ ap = (u_int8_t *)&sa_in6->sin6_addr; >-+ ep = (u_int8_t *)sa_in6 + sa_in6->sin6_len; >-+ for (; ap < ep; ap++) { >- /* this "beauty" is adopted from sbin/route/show.c ... */ >-- switch (sa_in6->sin6_addr.s6_addr[i]) { >-+ switch (*ap) { >- case 0xff: >- l += 8; >- break; >-@@ -1764,7 +2365,7 @@ mask2prefixlen6(struct sockaddr_in6 *sa_ >- case 0x00: >- return (l); >- default: >-- fatalx("non continguous inet6 netmask"); >-+ fatalx("non contiguous inet6 netmask"); >- } >- } >- >-@@ -1788,7 +2389,7 @@ prefixlen2mask6(u_int8_t prefixlen) >- } >- >- #define ROUNDUP(a) \ >-- (((a) & ((sizeof(long)) - 1)) ? (1 + ((a) | ((sizeof(long)) - 1))) : (a)) >-+ (((a) & (sizeof(long) - 1)) ? (1 + ((a) | (sizeof(long) - 1))) : (a)) >- >- void >- get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) >-@@ -1808,11 +2409,10 @@ get_rtaddrs(int addrs, struct sockaddr * >- void >- if_change(u_short ifindex, int flags, struct if_data *ifd) >- { >-+ struct ktable *kt; >- struct kif_node *kif; >- struct kif_kr *kkr; >- struct kif_kr6 *kkr6; >-- struct kroute_nexthop nh; >-- struct knexthop_node *n; >- u_int8_t reachable; >- >- if ((kif = kif_find(ifindex)) == NULL) { >-@@ -1833,28 +2433,18 @@ if_change(u_short ifindex, int flags, st >- >- kif->k.nh_reachable = reachable; >- >-+ kt = ktable_get(/* XXX */ 0); >-+ >- LIST_FOREACH(kkr, &kif->kroute_l, entry) { >- if (reachable) >- kkr->kr->r.flags &= ~F_DOWN; >- else >- kkr->kr->r.flags |= F_DOWN; >- >-- RB_FOREACH(n, knexthop_tree, &knt) >-- if (n->kroute == kkr->kr) { >-- bzero(&nh, sizeof(nh)); >-- memcpy(&nh.nexthop, &n->nexthop, >-- sizeof(nh.nexthop)); >-- if (kroute_validate(&kkr->kr->r)) { >-- nh.valid = 1; >-- nh.connected = 1; >-- if ((nh.gateway.v4.s_addr = >-- kkr->kr->r.nexthop.s_addr) != 0) >-- nh.gateway.af = AF_INET; >-- } >-- memcpy(&nh.kr.kr4, &kkr->kr->r, >-- sizeof(nh.kr.kr4)); >-- send_nexthop_update(&nh); >-- } >-+ if (kt == NULL) >-+ continue; >-+ >-+ knexthop_track(kt, kkr->kr); >- } >- LIST_FOREACH(kkr6, &kif->kroute6_l, entry) { >- if (reachable) >-@@ -1862,27 +2452,10 @@ if_change(u_short ifindex, int flags, st >- else >- kkr6->kr->r.flags |= F_DOWN; >- >-- RB_FOREACH(n, knexthop_tree, &knt) >-- if (n->kroute == kkr6->kr) { >-- bzero(&nh, sizeof(nh)); >-- memcpy(&nh.nexthop, &n->nexthop, >-- sizeof(nh.nexthop)); >-- if (kroute6_validate(&kkr6->kr->r)) { >-- nh.valid = 1; >-- nh.connected = 1; >-- if (memcmp(&kkr6->kr->r.nexthop, >-- &in6addr_any, sizeof(struct >-- in6_addr))) { >-- nh.gateway.af = AF_INET6; >-- memcpy(&nh.gateway.v6, >-- &kkr6->kr->r.nexthop, >-- sizeof(struct in6_addr)); >-- } >-- } >-- memcpy(&nh.kr.kr6, &kkr6->kr->r, >-- sizeof(nh.kr.kr6)); >-- send_nexthop_update(&nh); >-- } >-+ if (kt == NULL) >-+ continue; >-+ >-+ knexthop_track(kt, kkr6->kr); >- } >- } >- >-@@ -1917,25 +2490,38 @@ if_announce(void *msg) >- */ >- >- int >--send_rtmsg(int fd, int action, struct kroute *kroute) >-+send_rtmsg(int fd, int action, struct ktable *kt, struct kroute *kroute) >- { >-- struct iovec iov[5]; >-+ struct iovec iov[7]; >- struct rt_msghdr hdr; >- struct sockaddr_in prefix; >- struct sockaddr_in nexthop; >- struct sockaddr_in mask; >-+ struct { >-+ struct sockaddr_dl dl; >-+ char pad[sizeof(long)]; >-+ } ifp; >-+#if !defined(__FreeBSD__) /* FreeBSD has no route labeling. */ >-+ struct sockaddr_mpls mpls; >- struct sockaddr_rtlabel label; >-+#endif /* !defined(__FreeBSD__) */ >- int iovcnt = 0; >- >-- if (kr_state.fib_sync == 0) >-+ if (!kt->fib_sync) >- return (0); >- >- /* initialize header */ >- bzero(&hdr, sizeof(hdr)); >- hdr.rtm_version = RTM_VERSION; >- hdr.rtm_type = action; >-- hdr.rtm_tableid = kr_state.rtableid; >-+#if !defined(__FreeBSD__) /* XXX: FreeBSD has no multiple routing tables */ >-+ hdr.rtm_tableid = kt->rtableid; >-+#endif /* !defined(__FreeBSD__) */ >-+#if !defined(__FreeBSD__) /* XXX: FreeBSD has no rtm_priority */ >- hdr.rtm_priority = RTP_BGP; >-+#else >-+ hdr.rtm_flags = RTF_PROTO1; >-+#endif /* !defined(__FreeBSD__) */ >- if (kroute->flags & F_BLACKHOLE) >- hdr.rtm_flags |= RTF_BLACKHOLE; >- if (kroute->flags & F_REJECT) >-@@ -1984,6 +2570,37 @@ send_rtmsg(int fd, int action, struct kr >- iov[iovcnt].iov_base = &mask; >- iov[iovcnt++].iov_len = sizeof(mask); >- >-+ if (kt->ifindex) { >-+ bzero(&ifp, sizeof(ifp)); >-+ ifp.dl.sdl_len = sizeof(struct sockaddr_dl); >-+ ifp.dl.sdl_family = AF_LINK; >-+ ifp.dl.sdl_index = kt->ifindex; >-+ /* adjust header */ >-+ hdr.rtm_addrs |= RTA_IFP; >-+ hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_dl)); >-+ /* adjust iovec */ >-+ iov[iovcnt].iov_base = &ifp; >-+ iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_dl)); >-+ } >-+ >-+#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */ >-+ if (kroute->flags & F_MPLS) { >-+ bzero(&mpls, sizeof(mpls)); >-+ mpls.smpls_len = sizeof(mpls); >-+ mpls.smpls_family = AF_MPLS; >-+ mpls.smpls_label = kroute->mplslabel; >-+ /* adjust header */ >-+ hdr.rtm_flags |= RTF_MPLS; >-+ hdr.rtm_mpls = MPLS_OP_PUSH; >-+ hdr.rtm_addrs |= RTA_SRC; >-+ hdr.rtm_msglen += sizeof(mpls); >-+ /* adjust iovec */ >-+ iov[iovcnt].iov_base = &mpls; >-+ iov[iovcnt++].iov_len = sizeof(mpls); >-+ } >-+#endif >-+ >-+#if !defined(__FreeBSD__) /* FreeBSD has no route labeling. */ >- if (kroute->labelid) { >- bzero(&label, sizeof(label)); >- label.sr_len = sizeof(label); >-@@ -1996,11 +2613,11 @@ send_rtmsg(int fd, int action, struct kr >- iov[iovcnt].iov_base = &label; >- iov[iovcnt++].iov_len = sizeof(label); >- } >-+#endif /* !defined(__FreeBSD__) */ >- >- retry: >- if (writev(fd, iov, iovcnt) == -1) { >-- switch (errno) { >-- case ESRCH: >-+ if (errno == ESRCH) { >- if (hdr.rtm_type == RTM_CHANGE) { >- hdr.rtm_type = RTM_ADD; >- goto retry; >-@@ -2009,27 +2626,18 @@ retry: >- inet_ntoa(kroute->prefix), >- kroute->prefixlen); >- return (0); >-- } else { >-- log_warnx("send_rtmsg: action %u, " >-- "prefix %s/%u: %s", hdr.rtm_type, >-- inet_ntoa(kroute->prefix), >-- kroute->prefixlen, strerror(errno)); >-- return (0); >- } >-- break; >-- default: >-- log_warnx("send_rtmsg: action %u, prefix %s/%u: %s", >-- hdr.rtm_type, inet_ntoa(kroute->prefix), >-- kroute->prefixlen, strerror(errno)); >-- return (0); >- } >-+ log_warn("send_rtmsg: action %u, prefix %s/%u", hdr.rtm_type, >-+ inet_ntoa(kroute->prefix), kroute->prefixlen); >-+ return (0); >- } >- >- return (0); >- } >- >- int >--send_rt6msg(int fd, int action, struct kroute6 *kroute) >-+send_rt6msg(int fd, int action, struct ktable *kt, struct kroute6 *kroute) >- { >- struct iovec iov[5]; >- struct rt_msghdr hdr; >-@@ -2037,17 +2645,23 @@ send_rt6msg(int fd, int action, struct k >- struct sockaddr_in6 addr; >- char pad[sizeof(long)]; >- } prefix, nexthop, mask; >-+#if !defined(__FreeBSD__) /* FreeBSD has no route labeling. */ >- struct sockaddr_rtlabel label; >-+#endif /* !defined(__FreeBSD__) */ >- int iovcnt = 0; >- >-- if (kr_state.fib_sync == 0) >-+ if (!kt->fib_sync) >- return (0); >- >- /* initialize header */ >- bzero(&hdr, sizeof(hdr)); >- hdr.rtm_version = RTM_VERSION; >- hdr.rtm_type = action; >-+#if !defined(__FreeBSD__) /* XXX: FreeBSD has no multiple routing tables */ >- hdr.rtm_tableid = kr_state.rtableid; >-+#else >-+ hdr.rtm_flags = RTF_PROTO1; >-+#endif /* !defined(__FreeBSD__) */ >- if (kroute->flags & F_BLACKHOLE) >- hdr.rtm_flags |= RTF_BLACKHOLE; >- if (kroute->flags & F_REJECT) >-@@ -2100,6 +2714,7 @@ send_rt6msg(int fd, int action, struct k >- iov[iovcnt].iov_base = &mask; >- iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6)); >- >-+#if !defined(__FreeBSD__) /* FreeBSD has no route labeling. */ >- if (kroute->labelid) { >- bzero(&label, sizeof(label)); >- label.sr_len = sizeof(label); >-@@ -2112,11 +2727,11 @@ send_rt6msg(int fd, int action, struct k >- iov[iovcnt].iov_base = &label; >- iov[iovcnt++].iov_len = sizeof(label); >- } >-+#endif /* !defined(__FreeBSD__) */ >- >- retry: >- if (writev(fd, iov, iovcnt) == -1) { >-- switch (errno) { >-- case ESRCH: >-+ if (errno == ESRCH) { >- if (hdr.rtm_type == RTM_CHANGE) { >- hdr.rtm_type = RTM_ADD; >- goto retry; >-@@ -2125,31 +2740,26 @@ retry: >- log_in6addr(&kroute->prefix), >- kroute->prefixlen); >- return (0); >-- } else { >-- log_warnx("send_rt6msg: action %u, " >-- "prefix %s/%u: %s", hdr.rtm_type, >-- log_in6addr(&kroute->prefix), >-- kroute->prefixlen, strerror(errno)); >-- return (0); >- } >-- break; >-- default: >-- log_warnx("send_rt6msg: action %u, prefix %s/%u: %s", >-- hdr.rtm_type, log_in6addr(&kroute->prefix), >-- kroute->prefixlen, strerror(errno)); >-- return (0); >- } >-+ log_warn("send_rt6msg: action %u, prefix %s/%u", hdr.rtm_type, >-+ log_in6addr(&kroute->prefix), kroute->prefixlen); >-+ return (0); >- } >- >- return (0); >- } >- >- int >--fetchtable(u_int rtableid, int connected_only) >-+fetchtable(struct ktable *kt) >- { >- size_t len; >-+#if !defined(__FreeBSD__) /* FreeBSD has no table id. */ >- int mib[7]; >-- char *buf, *next, *lim; >-+#else >-+ int mib[6]; >-+#endif >-+ char *buf = NULL, *next, *lim; >- struct rt_msghdr *rtm; >- struct sockaddr *sa, *gw, *rti_info[RTAX_MAX]; >- struct sockaddr_in *sa_in; >-@@ -2163,22 +2773,35 @@ fetchtable(u_int rtableid, int connected >- mib[3] = 0; >- mib[4] = NET_RT_DUMP; >- mib[5] = 0; >-- mib[6] = rtableid; >-+#if !defined(__FreeBSD__) /* FreeBSD has no table id. */ >-+ mib[6] = kt->rtableid; >-+#endif >- >-+#if !defined(__FreeBSD__) /* FreeBSD has no table id. */ >- if (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) { >-- if (rtableid != 0 && errno == EINVAL) /* table nonexistent */ >-+#else >-+ if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) { >-+#endif >-+ if (kt->rtableid != 0 && errno == EINVAL) >-+ /* table nonexistent */ >- return (0); >- log_warn("sysctl"); >- return (-1); >- } >-- if ((buf = malloc(len)) == NULL) { >-- log_warn("fetchtable"); >-- return (-1); >-- } >-- if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) { >-- log_warn("sysctl"); >-- free(buf); >-- return (-1); >-+ if (len > 0) { >-+ if ((buf = malloc(len)) == NULL) { >-+ log_warn("fetchtable"); >-+ return (-1); >-+ } >-+#if !defined(__FreeBSD__) /* FreeBSD has no table id. */ >-+ if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) { >-+#else >-+ if (sysctl(mib, 6, buf, &len, NULL, 0) == -1) { >-+#endif >-+ log_warn("sysctl2"); >-+ free(buf); >-+ return (-1); >-+ } >- } >- >- lim = buf + len; >-@@ -2186,7 +2809,11 @@ fetchtable(u_int rtableid, int connected >- rtm = (struct rt_msghdr *)next; >- if (rtm->rtm_version != RTM_VERSION) >- continue; >-+#if !defined(__FreeBSD__) >- sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); >-+#else >-+ sa = (struct sockaddr *)(next + sizeof(struct rt_msghdr)); >-+#endif >- get_rtaddrs(rtm->rtm_addrs, sa, rti_info); >- >- if ((sa = rti_info[RTAX_DST]) == NULL) >-@@ -2205,7 +2832,11 @@ fetchtable(u_int rtableid, int connected >- } >- >- kr->r.flags = F_KERNEL; >-+#if defined(__FreeBSD__) /* no rtm_priority on FreeBSD */ >-+ kr->r.priority = RTP_BGP; >-+#else >- kr->r.priority = rtm->rtm_priority; >-+#endif >- kr->r.ifindex = rtm->rtm_index; >- kr->r.prefix.s_addr = >- ((struct sockaddr_in *)sa)->sin_addr.s_addr; >-@@ -2223,8 +2854,12 @@ fetchtable(u_int rtableid, int connected >- break; >- kr->r.prefixlen = >- mask2prefixlen(sa_in->sin_addr.s_addr); >-- } else if (rtm->rtm_flags & RTF_HOST) >-+ } else if (rtm->rtm_flags & RTF_HOST) { >- kr->r.prefixlen = 32; >-+#if defined(__FreeBSD__) /* RTF_HOST means connected route */ >-+ kr->r.flags |= F_CONNECTED; >-+#endif >-+ } >- else >- kr->r.prefixlen = >- prefixlen_classful(kr->r.prefix.s_addr); >-@@ -2238,11 +2873,25 @@ fetchtable(u_int rtableid, int connected >- } >- >- kr6->r.flags = F_KERNEL; >-+#if defined(__FreeBSD__) /* no rtm_priority on FreeBSD */ >-+ kr6->r.priority = RTP_BGP; >-+#else >- kr6->r.priority = rtm->rtm_priority; >-+#endif >- kr6->r.ifindex = rtm->rtm_index; >- memcpy(&kr6->r.prefix, >- &((struct sockaddr_in6 *)sa)->sin6_addr, >- sizeof(kr6->r.prefix)); >-+#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER) >-+ if (IN6_IS_ADDR_LINKLOCAL(&kr6->r.prefix)) { >-+ if (((struct sockaddr_in6 *)sa)->sin6_scope_id !=0) >-+ SET_IN6_LINKLOCAL_IFINDEX(kr6->r.prefix, >-+ ((struct sockaddr_in6 *)sa)->sin6_scope_id); >-+ else >-+ SET_IN6_LINKLOCAL_IFINDEX(kr6->r.prefix, >-+ rtm->rtm_index); >-+ } >-+#endif >- >- sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK]; >- if (rtm->rtm_flags & RTF_STATIC) >-@@ -2257,8 +2906,12 @@ fetchtable(u_int rtableid, int connected >- if (sa_in6->sin6_len == 0) >- break; >- kr6->r.prefixlen = mask2prefixlen6(sa_in6); >-- } else if (rtm->rtm_flags & RTF_HOST) >-+ } else if (rtm->rtm_flags & RTF_HOST) { >- kr6->r.prefixlen = 128; >-+#if defined(__FreeBSD__) /* RTF_HOST means connected route */ >-+ kr6->r.flags |= F_CONNECTED; >-+#endif >-+ } >- else >- fatalx("INET6 route without netmask"); >- break; >-@@ -2280,6 +2933,13 @@ fetchtable(u_int rtableid, int connected >- memcpy(&kr6->r.nexthop, >- &((struct sockaddr_in6 *)gw)->sin6_addr, >- sizeof(kr6->r.nexthop)); >-+#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER) >-+ if (IN6_IS_ADDR_LINKLOCAL(&kr6->r.nexthop) && >-+ ((struct sockaddr_in6 *)gw)->sin6_scope_id != 0) { >-+ SET_IN6_LINKLOCAL_IFINDEX(kr6->r.nexthop, >-+ ((struct sockaddr_in6 *)gw)->sin6_scope_id); >-+ } >-+#endif >- break; >- case AF_LINK: >- if (sa->sa_family == AF_INET) >-@@ -2290,23 +2950,28 @@ fetchtable(u_int rtableid, int connected >- } >- >- if (sa->sa_family == AF_INET) { >-+#if !defined(__FreeBSD__) /* no rtm_priority on FreeBSD */ >- if (rtm->rtm_priority == RTP_BGP) { >-- send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r); >-- free(kr); >-- } else if (connected_only && >-- !(kr->r.flags & F_CONNECTED)) >-+#else >-+ /* never delete route */ >-+ if (0) { >-+#endif >-+ send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r); >- free(kr); >-- else >-- kroute_insert(kr); >-+ } else >-+ kroute_insert(kt, kr); >- } else if (sa->sa_family == AF_INET6) { >-+#if !defined(__FreeBSD__) /* no rtm_priority on FreeBSD */ >- if (rtm->rtm_priority == RTP_BGP) { >-- send_rt6msg(kr_state.fd, RTM_DELETE, &kr6->r); >-- free(kr6); >-- } else if (connected_only && >-- !(kr6->r.flags & F_CONNECTED)) >-+#else >-+ /* never delete route */ >-+ if (0) { >-+#endif >-+ send_rt6msg(kr_state.fd, RTM_DELETE, kt, >-+ &kr6->r); >- free(kr6); >-- else >-- kroute6_insert(kr6); >-+ } else >-+ kroute6_insert(kt, kr6); >- } >- } >- free(buf); >-@@ -2327,7 +2992,7 @@ fetchifs(int ifindex) >- mib[0] = CTL_NET; >- mib[1] = AF_ROUTE; >- mib[2] = 0; >-- mib[3] = AF_INET; >-+ mib[3] = AF_INET; /* AF does not matter but AF_INET is shorter */ >- mib[4] = NET_RT_IFLIST; >- mib[5] = ifindex; >- >-@@ -2396,7 +3061,7 @@ dispatch_rtmsg(void) >- struct rt_msghdr *rtm; >- struct if_msghdr ifm; >- struct sockaddr *sa, *rti_info[RTAX_MAX]; >-- int connected_only; >-+ struct ktable *kt; >- >- if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) { >- log_warn("dispatch_rtmsg: read error"); >-@@ -2418,7 +3083,11 @@ dispatch_rtmsg(void) >- case RTM_ADD: >- case RTM_CHANGE: >- case RTM_DELETE: >-+#if !defined(__FreeBSD__) >- sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); >-+#else >-+ sa = (struct sockaddr *)(next + sizeof(struct rt_msghdr)); >-+#endif >- get_rtaddrs(rtm->rtm_addrs, sa, rti_info); >- >- if (rtm->rtm_pid == kr_state.pid) /* cause by us */ >-@@ -2430,16 +3099,14 @@ dispatch_rtmsg(void) >- if (rtm->rtm_flags & RTF_LLINFO) /* arp cache */ >- continue; >- >-- connected_only = 0; >-- if (rtm->rtm_tableid != kr_state.rtableid) { >-- if (rtm->rtm_tableid == 0) >-- connected_only = 1; >-- else >-- continue; >-- } >-+#if !defined(__FreeBSD__) /* FreeBSD has no rtm_tableid. */ >-+ if ((kt = ktable_get(rtm->rtm_tableid)) == NULL) >-+#else >-+ if ((kt = ktable_get(0)) == NULL) >-+#endif >-+ continue; >- >-- if (dispatch_rtmsg_addr(rtm, rti_info, >-- connected_only) == -1) >-+ if (dispatch_rtmsg_addr(rtm, rti_info, kt) == -1) >- return (-1); >- break; >- case RTM_IFINFO: >-@@ -2460,7 +3127,7 @@ dispatch_rtmsg(void) >- >- int >- dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr *rti_info[RTAX_MAX], >-- int connected_only) >-+ struct ktable *kt) >- { >- struct sockaddr *sa; >- struct sockaddr_in *sa_in; >-@@ -2468,7 +3135,7 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt >- struct kroute_node *kr; >- struct kroute6_node *kr6; >- struct bgpd_addr prefix; >-- int flags, oflags, mpath = 0; >-+ int flags, oflags, mpath = 0, changed = 0; >- u_int16_t ifindex; >- u_int8_t prefixlen; >- u_int8_t prio; >-@@ -2494,31 +3161,54 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt >- mpath = 1; >- #endif >- >-+#if !defined(__FreeBSD__) /* no rtm_priority on FreeBSD */ >- prio = rtm->rtm_priority; >-- prefix.af = sa->sa_family; >-- switch (prefix.af) { >-+#else >-+ prio = RTP_BGP; >-+#endif >-+ switch (sa->sa_family) { >- case AF_INET: >-+ prefix.aid = AID_INET; >- prefix.v4.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; >- sa_in = (struct sockaddr_in *)rti_info[RTAX_NETMASK]; >- if (sa_in != NULL) { >- if (sa_in->sin_len != 0) >- prefixlen = mask2prefixlen( >- sa_in->sin_addr.s_addr); >-- } else if (rtm->rtm_flags & RTF_HOST) >-+ } else if (rtm->rtm_flags & RTF_HOST) { >- prefixlen = 32; >-+#if defined(__FreeBSD__) /* RTF_HOST means connected route */ >-+ flags |= F_CONNECTED; >-+#endif >-+ } >- else >- prefixlen = >- prefixlen_classful(prefix.v4.s_addr); >- break; >- case AF_INET6: >-+ prefix.aid = AID_INET6; >- memcpy(&prefix.v6, &((struct sockaddr_in6 *)sa)->sin6_addr, >- sizeof(struct in6_addr)); >-+#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER) >-+ if (IN6_IS_ADDR_LINKLOCAL(&prefix.v6) != 0) { >-+ if (((struct sockaddr_in6 *)sa)->sin6_scope_id !=0) >-+ SET_IN6_LINKLOCAL_IFINDEX(prefix.v6, >-+ ((struct sockaddr_in6 *)sa)->sin6_scope_id); >-+ else >-+ SET_IN6_LINKLOCAL_IFINDEX(prefix.v6, >-+ rtm->rtm_index); >-+ } >-+#endif >- sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK]; >- if (sa_in6 != NULL) { >- if (sa_in6->sin6_len != 0) >- prefixlen = mask2prefixlen6(sa_in6); >-- } else if (rtm->rtm_flags & RTF_HOST) >-+ } else if (rtm->rtm_flags & RTF_HOST) { >- prefixlen = 128; >-+#if defined(__FreeBSD__) /* RTF_HOST means connected route */ >-+ flags |= F_CONNECTED; >-+#endif >-+ } >- else >- fatalx("in6 net addr without netmask"); >- break; >-@@ -2537,10 +3227,10 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt >- } >- >- if (rtm->rtm_type == RTM_DELETE) { >-- switch (prefix.af) { >-- case AF_INET: >-+ switch (prefix.aid) { >-+ case AID_INET: >- sa_in = (struct sockaddr_in *)sa; >-- if ((kr = kroute_find(prefix.v4.s_addr, >-+ if ((kr = kroute_find(kt, prefix.v4.s_addr, >- prefixlen, prio)) == NULL) >- return (0); >- if (!(kr->r.flags & F_KERNEL)) >-@@ -2554,12 +3244,12 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt >- return (0); >- } >- >-- if (kroute_remove(kr) == -1) >-+ if (kroute_remove(kt, kr) == -1) >- return (-1); >- break; >-- case AF_INET6: >-+ case AID_INET6: >- sa_in6 = (struct sockaddr_in6 *)sa; >-- if ((kr6 = kroute6_find(&prefix.v6, prefixlen, >-+ if ((kr6 = kroute6_find(kt, &prefix.v6, prefixlen, >- prio)) == NULL) >- return (0); >- if (!(kr6->r.flags & F_KERNEL)) >-@@ -2574,26 +3264,23 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt >- return (0); >- } >- >-- if (kroute6_remove(kr6) == -1) >-+ if (kroute6_remove(kt, kr6) == -1) >- return (-1); >- break; >- } >- return (0); >- } >- >-- if (connected_only && !(flags & F_CONNECTED)) >-- return (0); >-- >- if (sa == NULL && !(flags & F_CONNECTED)) { >- log_warnx("dispatch_rtmsg no nexthop for %s/%u", >- log_addr(&prefix), prefixlen); >- return (0); >- } >- >-- switch (prefix.af) { >-- case AF_INET: >-+ switch (prefix.aid) { >-+ case AID_INET: >- sa_in = (struct sockaddr_in *)sa; >-- if ((kr = kroute_find(prefix.v4.s_addr, prefixlen, >-+ if ((kr = kroute_find(kt, prefix.v4.s_addr, prefixlen, >- prio)) != NULL) { >- if (kr->r.flags & F_KERNEL) { >- /* get the correct route */ >-@@ -2605,30 +3292,38 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt >- } else if (mpath && rtm->rtm_type == RTM_ADD) >- goto add4; >- >-- if (sa_in != NULL) >-+ if (sa_in != NULL) { >-+ if (kr->r.nexthop.s_addr != >-+ sa_in->sin_addr.s_addr) >-+ changed = 1; >- kr->r.nexthop.s_addr = >- sa_in->sin_addr.s_addr; >-- else >-+ } else { >-+ if (kr->r.nexthop.s_addr != 0) >-+ changed = 1; >- kr->r.nexthop.s_addr = 0; >-+ } >- >- if (kr->r.flags & F_NEXTHOP) >- flags |= F_NEXTHOP; >- oflags = kr->r.flags; >-+ if (flags != oflags) >-+ changed = 1; >- kr->r.flags = flags; >- if ((oflags & F_CONNECTED) && >- !(flags & F_CONNECTED)) { >- kif_kr_remove(kr); >- kr_redistribute(IMSG_NETWORK_REMOVE, >-- &kr->r); >-+ kt, &kr->r); >- } >- if ((flags & F_CONNECTED) && >- !(oflags & F_CONNECTED)) { >- kif_kr_insert(kr); >- kr_redistribute(IMSG_NETWORK_ADD, >-- &kr->r); >-+ kt, &kr->r); >- } >-- if (kr->r.flags & F_NEXTHOP) >-- knexthop_track(kr); >-+ if (kr->r.flags & F_NEXTHOP && changed) >-+ knexthop_track(kt, kr); >- } >- } else if (rtm->rtm_type == RTM_CHANGE) { >- log_warnx("change req for %s/%u: not in table", >-@@ -2651,50 +3346,62 @@ add4: >- kr->r.ifindex = ifindex; >- kr->r.priority = prio; >- >-- kroute_insert(kr); >-+ kroute_insert(kt, kr); >- } >- break; >-- case AF_INET6: >-+ case AID_INET6: >- sa_in6 = (struct sockaddr_in6 *)sa; >-- if ((kr6 = kroute6_find(&prefix.v6, prefixlen, prio)) != NULL) { >-+ if ((kr6 = kroute6_find(kt, &prefix.v6, prefixlen, prio)) != >-+ NULL) { >- if (kr6->r.flags & F_KERNEL) { >- /* get the correct route */ >- if (mpath && rtm->rtm_type == RTM_CHANGE && >- (kr6 = kroute6_matchgw(kr6, sa_in6)) == >- NULL) { >- log_warnx("dispatch_rtmsg[change] " >-- "mpath route not found"); >-+ "IPv6 mpath route not found"); >- return (-1); >- } else if (mpath && rtm->rtm_type == RTM_ADD) >- goto add6; >- >-- if (sa_in6 != NULL) >-+ if (sa_in6 != NULL) { >-+ if (memcmp(&kr6->r.nexthop, >-+ &sa_in6->sin6_addr, >-+ sizeof(struct in6_addr))) >-+ changed = 1; >- memcpy(&kr6->r.nexthop, >- &sa_in6->sin6_addr, >- sizeof(struct in6_addr)); >-- else >-+ } else { >-+ if (memcmp(&kr6->r.nexthop, >-+ &in6addr_any, >-+ sizeof(struct in6_addr))) >-+ changed = 1; >- memcpy(&kr6->r.nexthop, >- &in6addr_any, >- sizeof(struct in6_addr)); >-+ } >- >- if (kr6->r.flags & F_NEXTHOP) >- flags |= F_NEXTHOP; >- oflags = kr6->r.flags; >-+ if (flags != oflags) >-+ changed = 1; >- kr6->r.flags = flags; >- if ((oflags & F_CONNECTED) && >- !(flags & F_CONNECTED)) { >- kif_kr6_remove(kr6); >- kr_redistribute6(IMSG_NETWORK_REMOVE, >-- &kr6->r); >-+ kt, &kr6->r); >- } >- if ((flags & F_CONNECTED) && >- !(oflags & F_CONNECTED)) { >- kif_kr6_insert(kr6); >- kr_redistribute6(IMSG_NETWORK_ADD, >-- &kr6->r); >-+ kt, &kr6->r); >- } >-- if (kr6->r.flags & F_NEXTHOP) >-- knexthop_track(kr6); >-+ if (kr6->r.flags & F_NEXTHOP && changed) >-+ knexthop_track(kt, kr6); >- } >- } else if (rtm->rtm_type == RTM_CHANGE) { >- log_warnx("change req for %s/%u: not in table", >-@@ -2719,8 +3426,12 @@ add6: >- kr6->r.flags = flags; >- kr6->r.ifindex = ifindex; >- kr6->r.priority = prio; >-- >-- kroute6_insert(kr6); >-+#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER) >-+ if (IN6_IS_ADDR_LINKLOCAL(&kr6->r.nexthop)) >-+ SET_IN6_LINKLOCAL_IFINDEX(kr6->r.nexthop, >-+ ifindex); >-+#endif >-+ kroute6_insert(kt, kr6); >- } >- break; >- } > >Property changes on: files/patch-bgpd_kroute.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_log.c >=================================================================== >--- files/patch-bgpd_log.c (revision 500577) >+++ files/patch-bgpd_log.c (nonexistent) >@@ -1,117 +0,0 @@ >-Index: bgpd/log.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/log.c,v >-retrieving revision 1.1.1.5 >-retrieving revision 1.1.1.8 >-diff -u -p -r1.1.1.5 -r1.1.1.8 >---- bgpd/log.c 14 Feb 2010 20:19:57 -0000 1.1.1.5 >-+++ bgpd/log.c 13 Oct 2012 18:22:43 -0000 1.1.1.8 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: log.c,v 1.50 2007/04/23 13:04:24 claudio Exp $ */ >-+/* $OpenBSD: log.c,v 1.55 2011/08/20 19:02:28 sthen Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-@@ -32,6 +32,7 @@ >- #include "log.h" >- >- int debug; >-+int verbose; >- >- void logit(int, const char *, ...); >- >-@@ -42,8 +43,9 @@ log_fmt_peer(const struct peer_config *p >- char *pfmt, *p; >- >- ip = log_addr(&peer->remote_addr); >-- if ((peer->remote_addr.af == AF_INET && peer->remote_masklen != 32) || >-- (peer->remote_addr.af == AF_INET6 && peer->remote_masklen != 128)) { >-+ if ((peer->remote_addr.aid == AID_INET && peer->remote_masklen != 32) || >-+ (peer->remote_addr.aid == AID_INET6 && >-+ peer->remote_masklen != 128)) { >- if (asprintf(&p, "%s/%u", ip, peer->remote_masklen) == -1) >- fatal(NULL); >- } else { >-@@ -77,6 +79,12 @@ log_init(int n_debug) >- } >- >- void >-+log_verbose(int v) >-+{ >-+ verbose = v; >-+} >-+ >-+void >- logit(int pri, const char *fmt, ...) >- { >- va_list ap; >-@@ -193,7 +201,7 @@ log_debug(const char *emsg, ...) >- { >- va_list ap; >- >-- if (debug) { >-+ if (verbose) { >- va_start(ap, emsg); >- vlog(LOG_DEBUG, emsg, ap); >- va_end(ap); >-@@ -250,7 +258,7 @@ log_statechange(struct peer *peer, enum >- >- void >- log_notification(const struct peer *peer, u_int8_t errcode, u_int8_t subcode, >-- u_char *data, u_int16_t datalen) >-+ u_char *data, u_int16_t datalen, const char *dir) >- { >- char *p; >- const char *suberrname = NULL; >-@@ -283,27 +291,31 @@ log_notification(const struct peer *peer >- suberrname = suberr_cease_names[subcode]; >- break; >- case ERR_HOLDTIMEREXPIRED: >-- case ERR_FSM: >- uk = 1; >- break; >-+ case ERR_FSM: >-+ if (subcode >= sizeof(suberr_fsm_names)/sizeof(char *)) >-+ uk = 1; >-+ else >-+ suberrname = suberr_fsm_names[subcode]; >-+ break; >- default: >-- logit(LOG_CRIT, "%s: received notification, unknown errcode " >-- "%u, subcode %u", p, errcode, subcode); >-+ logit(LOG_CRIT, "%s: %s notification, unknown errcode " >-+ "%u, subcode %u", p, dir, errcode, subcode); >- free(p); >- return; >- } >- >- if (uk) >-- logit(LOG_CRIT, >-- "%s: received notification: %s, unknown subcode %u", >-- p, errnames[errcode], subcode); >-+ logit(LOG_CRIT, "%s: %s notification: %s, unknown subcode %u", >-+ p, dir, errnames[errcode], subcode); >- else { >- if (suberrname == NULL) >-- logit(LOG_CRIT, "%s: received notification: %s", >-- p, errnames[errcode]); >-+ logit(LOG_CRIT, "%s: %s notification: %s", p, >-+ dir, errnames[errcode]); >- else >-- logit(LOG_CRIT, "%s: received notification: %s, %s", >-- p, errnames[errcode], suberrname); >-+ logit(LOG_CRIT, "%s: %s notification: %s, %s", >-+ p, dir, errnames[errcode], suberrname); >- } >- free(p); >- } >-@@ -318,6 +330,9 @@ log_conn_attempt(const struct peer *peer >- b = log_sockaddr(sa); >- logit(LOG_INFO, "connection from non-peer %s refused", b); >- } else { >-+ /* only log if there is a chance that the session may come up */ >-+ if (peer->conf.down && peer->state == STATE_IDLE) >-+ return; >- p = log_fmt_peer(&peer->conf); >- logit(LOG_INFO, "Connection attempt from %s while session is " >- "in state %s", p, statenames[peer->state]); > >Property changes on: files/patch-bgpd_log.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_log.h >=================================================================== >--- files/patch-bgpd_log.h (revision 500577) >+++ files/patch-bgpd_log.h (nonexistent) >@@ -1,39 +0,0 @@ >-Index: bgpd/log.h >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/log.h,v >-retrieving revision 1.1.1.2 >-retrieving revision 1.1.1.3 >-diff -u -p -r1.1.1.2 -r1.1.1.3 >---- bgpd/log.h 9 Jul 2009 16:49:54 -0000 1.1.1.2 >-+++ bgpd/log.h 13 Oct 2012 18:22:43 -0000 1.1.1.3 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: log.h,v 1.11 2008/09/11 14:49:58 henning Exp $ */ >-+/* $OpenBSD: log.h,v 1.13 2012/06/10 11:16:08 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-@@ -71,6 +71,13 @@ static const char * const suberr_open_na >- "unsupported capability" >- }; >- >-+static const char * const suberr_fsm_names[] = { >-+ "unspecified error", >-+ "received unexpected message in OpenSent", >-+ "received unexpected message in OpenConfirm", >-+ "received unexpected message in Established" >-+}; >-+ >- static const char * const suberr_update_names[] = { >- "none", >- "attribute list error", >-@@ -109,7 +116,9 @@ static const char * const ctl_res_strerr >- "no such neighbor", >- "permission denied", >- "neighbor does not have this capability", >-- "config file has errors, reload failed" >-+ "config file has errors, reload failed", >-+ "previous reload still running", >-+ "out of memory" >- }; >- >- static const char * const timernames[] = { > >Property changes on: files/patch-bgpd_log.h >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_mrt.c >=================================================================== >--- files/patch-bgpd_mrt.c (revision 500577) >+++ files/patch-bgpd_mrt.c (nonexistent) >@@ -1,864 +0,0 @@ >-Index: bgpd/mrt.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/mrt.c,v >-retrieving revision 1.1.1.7 >-retrieving revision 1.1.1.11 >-diff -u -p -r1.1.1.7 -r1.1.1.11 >---- bgpd/mrt.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 >-+++ bgpd/mrt.c 8 Dec 2012 10:37:09 -0000 1.1.1.11 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: mrt.c,v 1.63 2009/06/29 12:22:16 claudio Exp $ */ >-+/* $OpenBSD: mrt.c,v 1.72 2011/11/06 10:29:05 guenther Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> >-@@ -21,6 +21,7 @@ >- >- #include <errno.h> >- #include <fcntl.h> >-+#include <limits.h> >- #include <stdlib.h> >- #include <string.h> >- #include <time.h> >-@@ -32,20 +33,22 @@ >- >- #include "mrt.h" >- >--int mrt_attr_dump(struct buf *, struct rde_aspath *, struct bgpd_addr *); >-+int mrt_attr_dump(struct ibuf *, struct rde_aspath *, struct bgpd_addr *, int); >- int mrt_dump_entry_mp(struct mrt *, struct prefix *, u_int16_t, >- struct rde_peer*); >- int mrt_dump_entry(struct mrt *, struct prefix *, u_int16_t, struct rde_peer*); >--int mrt_dump_hdr_se(struct buf **, struct peer *, u_int16_t, u_int16_t, >-+int mrt_dump_entry_v2(struct mrt *, struct rib_entry *, u_int32_t); >-+int mrt_dump_peer(struct ibuf *, struct rde_peer *); >-+int mrt_dump_hdr_se(struct ibuf **, struct peer *, u_int16_t, u_int16_t, >- u_int32_t, int); >--int mrt_dump_hdr_rde(struct buf **, u_int16_t type, u_int16_t, u_int32_t); >-+int mrt_dump_hdr_rde(struct ibuf **, u_int16_t type, u_int16_t, u_int32_t); >- int mrt_open(struct mrt *, time_t); >- >- #define DUMP_BYTE(x, b) \ >- do { \ >- u_char t = (b); \ >-- if (buf_add((x), &t, sizeof(t)) == -1) { \ >-- log_warnx("mrt_dump1: buf_add error"); \ >-+ if (ibuf_add((x), &t, sizeof(t)) == -1) { \ >-+ log_warn("mrt_dump1: ibuf_add error"); \ >- goto fail; \ >- } \ >- } while (0) >-@@ -54,8 +57,8 @@ int mrt_open(struct mrt *, time_t); >- do { \ >- u_int16_t t; \ >- t = htons((s)); \ >-- if (buf_add((x), &t, sizeof(t)) == -1) { \ >-- log_warnx("mrt_dump2: buf_add error"); \ >-+ if (ibuf_add((x), &t, sizeof(t)) == -1) { \ >-+ log_warn("mrt_dump2: ibuf_add error"); \ >- goto fail; \ >- } \ >- } while (0) >-@@ -64,8 +67,8 @@ int mrt_open(struct mrt *, time_t); >- do { \ >- u_int32_t t; \ >- t = htonl((l)); \ >-- if (buf_add((x), &t, sizeof(t)) == -1) { \ >-- log_warnx("mrt_dump3: buf_add error"); \ >-+ if (ibuf_add((x), &t, sizeof(t)) == -1) { \ >-+ log_warn("mrt_dump3: ibuf_add error"); \ >- goto fail; \ >- } \ >- } while (0) >-@@ -73,8 +76,8 @@ int mrt_open(struct mrt *, time_t); >- #define DUMP_NLONG(x, l) \ >- do { \ >- u_int32_t t = (l); \ >-- if (buf_add((x), &t, sizeof(t)) == -1) { \ >-- log_warnx("mrt_dump4: buf_add error"); \ >-+ if (ibuf_add((x), &t, sizeof(t)) == -1) { \ >-+ log_warn("mrt_dump4: ibuf_add error"); \ >- goto fail; \ >- } \ >- } while (0) >-@@ -83,55 +86,64 @@ void >- mrt_dump_bgp_msg(struct mrt *mrt, void *pkg, u_int16_t pkglen, >- struct peer *peer) >- { >-- struct buf *buf; >-+ struct ibuf *buf; >- int incoming = 0; >-+ u_int16_t subtype = BGP4MP_MESSAGE; >-+ >-+ if (peer->capa.neg.as4byte) >-+ subtype = BGP4MP_MESSAGE_AS4; >- >- /* get the direction of the message to swap address and AS fields */ >- if (mrt->type == MRT_ALL_IN || mrt->type == MRT_UPDATE_IN) >- incoming = 1; >- >-- if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE, >-+ if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, subtype, >- pkglen, incoming) == -1) >- return; >- >-- if (buf_add(buf, pkg, pkglen) == -1) { >-- log_warnx("mrt_dump_bgp_msg: buf_add error"); >-- buf_free(buf); >-+ if (ibuf_add(buf, pkg, pkglen) == -1) { >-+ log_warn("mrt_dump_bgp_msg: ibuf_add error"); >-+ ibuf_free(buf); >- return; >- } >- >-- buf_close(&mrt->wbuf, buf); >-+ ibuf_close(&mrt->wbuf, buf); >- } >- >- void >- mrt_dump_state(struct mrt *mrt, u_int16_t old_state, u_int16_t new_state, >- struct peer *peer) >- { >-- struct buf *buf; >-+ struct ibuf *buf; >-+ u_int16_t subtype = BGP4MP_STATE_CHANGE; >-+ >-+ if (peer->capa.neg.as4byte) >-+ subtype = BGP4MP_STATE_CHANGE_AS4; >- >-- if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE, >-+ if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, subtype, >- 2 * sizeof(short), 0) == -1) >- return; >- >- DUMP_SHORT(buf, old_state); >- DUMP_SHORT(buf, new_state); >- >-- buf_close(&mrt->wbuf, buf); >-+ ibuf_close(&mrt->wbuf, buf); >- return; >- >- fail: >-- buf_free(buf); >-+ ibuf_free(buf); >- } >- >- int >--mrt_attr_dump(struct buf *buf, struct rde_aspath *a, struct bgpd_addr *nexthop) >-+mrt_attr_dump(struct ibuf *buf, struct rde_aspath *a, struct bgpd_addr *nexthop, >-+ int v2) >- { >- struct attr *oa; >- u_char *pdata; >- u_int32_t tmp; >- int neednewpath = 0; >-- u_int16_t plen; >-- u_int8_t l; >-+ u_int16_t plen, afi; >-+ u_int8_t l, safi; >- >- /* origin */ >- if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ORIGIN, >-@@ -140,12 +152,16 @@ mrt_attr_dump(struct buf *buf, struct rd >- >- /* aspath */ >- pdata = aspath_prepend(a->aspath, rde_local_as(), 0, &plen); >-- pdata = aspath_deflate(pdata, &plen, &neednewpath); >-- if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ASPATH, pdata, plen) == -1) >-+ if (!v2) >-+ pdata = aspath_deflate(pdata, &plen, &neednewpath); >-+ if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ASPATH, pdata, >-+ plen) == -1) { >-+ free(pdata); >- return (-1); >-+ } >- free(pdata); >- >-- if (nexthop) { >-+ if (nexthop && nexthop->aid == AID_INET) { >- /* nexthop, already network byte order */ >- if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_NEXTHOP, >- &nexthop->v4.s_addr, 4) == -1) >-@@ -159,7 +175,7 @@ mrt_attr_dump(struct buf *buf, struct rd >- return (-1); >- } >- >-- /* local preference, only valid for ibgp */ >-+ /* local preference */ >- tmp = htonl(a->lpref); >- if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_LOCALPREF, &tmp, 4) == -1) >- return (-1); >-@@ -173,12 +189,51 @@ mrt_attr_dump(struct buf *buf, struct rd >- return (-1); >- } >- >-+ if (nexthop && nexthop->aid != AID_INET) { >-+ struct ibuf *nhbuf; >-+ >-+ if ((nhbuf = ibuf_dynamic(0, UCHAR_MAX)) == NULL) >-+ return (-1); >-+ if (!v2) { >-+ if (aid2afi(nexthop->aid, &afi, &safi)) >-+ return (-1); >-+ DUMP_SHORT(nhbuf, afi); >-+ DUMP_BYTE(nhbuf, safi); >-+ } >-+ switch (nexthop->aid) { >-+ case AID_INET6: >-+ DUMP_BYTE(nhbuf, sizeof(struct in6_addr)); >-+ if (ibuf_add(nhbuf, &nexthop->v6, >-+ sizeof(struct in6_addr)) == -1) { >-+ } >-+ break; >-+ case AID_VPN_IPv4: >-+ DUMP_BYTE(nhbuf, sizeof(u_int64_t) + >-+ sizeof(struct in_addr)); >-+ DUMP_NLONG(nhbuf, 0); /* set RD to 0 */ >-+ DUMP_NLONG(nhbuf, 0); >-+ DUMP_NLONG(nhbuf, nexthop->v4.s_addr); >-+ break; >-+ } >-+ if (!v2) >-+ DUMP_BYTE(nhbuf, 0); >-+ if (attr_writebuf(buf, ATTR_OPTIONAL, ATTR_MP_REACH_NLRI, >-+ nhbuf->buf, ibuf_size(nhbuf)) == -1) { >-+fail: >-+ ibuf_free(nhbuf); >-+ return (-1); >-+ } >-+ ibuf_free(nhbuf); >-+ } >-+ >- if (neednewpath) { >- pdata = aspath_prepend(a->aspath, rde_local_as(), 0, &plen); >- if (plen != 0) >- if (attr_writebuf(buf, ATTR_OPTIONAL|ATTR_TRANSITIVE, >-- ATTR_AS4_PATH, pdata, plen) == -1) >-+ ATTR_AS4_PATH, pdata, plen) == -1) { >-+ free(pdata); >- return (-1); >-+ } >- free(pdata); >- } >- >-@@ -189,28 +244,26 @@ int >- mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum, >- struct rde_peer *peer) >- { >-- struct buf *buf, *hbuf = NULL, *h2buf = NULL; >-- void *bptr; >-+ struct ibuf *buf, *hbuf = NULL, *h2buf = NULL; >- struct bgpd_addr addr, nexthop, *nh; >- u_int16_t len; >-- u_int8_t p_len; >-- sa_family_t af; >-+ u_int8_t aid; >- >-- if ((buf = buf_dynamic(0, MAX_PKTSIZE)) == NULL) { >-- log_warn("mrt_dump_entry_mp: buf_dynamic"); >-+ if ((buf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) { >-+ log_warn("mrt_dump_entry_mp: ibuf_dynamic"); >- return (-1); >- } >- >-- if (mrt_attr_dump(buf, p->aspath, NULL) == -1) { >-+ if (mrt_attr_dump(buf, p->aspath, NULL, 0) == -1) { >- log_warnx("mrt_dump_entry_mp: mrt_attr_dump error"); >- goto fail; >- } >-- len = buf_size(buf); >-+ len = ibuf_size(buf); >- >-- if ((h2buf = buf_dynamic(MRT_BGP4MP_IPv4_HEADER_SIZE + >-+ if ((h2buf = ibuf_dynamic(MRT_BGP4MP_IPv4_HEADER_SIZE + >- MRT_BGP4MP_IPv4_ENTRY_SIZE, MRT_BGP4MP_IPv6_HEADER_SIZE + >- MRT_BGP4MP_IPv6_ENTRY_SIZE + MRT_BGP4MP_MAX_PREFIXLEN)) == NULL) { >-- log_warn("mrt_dump_entry_mp: buf_dynamic"); >-+ log_warn("mrt_dump_entry_mp: ibuf_dynamic"); >- goto fail; >- } >- >-@@ -219,25 +272,26 @@ mrt_dump_entry_mp(struct mrt *mrt, struc >- DUMP_SHORT(h2buf, /* ifindex */ 0); >- >- /* XXX is this for peer self? */ >-- af = peer->remote_addr.af == 0 ? p->prefix->af : peer->remote_addr.af; >-- switch (af) { >-- case AF_INET: >-+ aid = peer->remote_addr.aid == AID_UNSPEC ? p->prefix->aid : >-+ peer->remote_addr.aid; >-+ switch (aid) { >-+ case AID_INET: >- DUMP_SHORT(h2buf, AFI_IPv4); >- DUMP_NLONG(h2buf, peer->local_v4_addr.v4.s_addr); >- DUMP_NLONG(h2buf, peer->remote_addr.v4.s_addr); >- break; >-- case AF_INET6: >-+ case AID_INET6: >- DUMP_SHORT(h2buf, AFI_IPv6); >-- if (buf_add(h2buf, &peer->local_v6_addr.v6, >-+ if (ibuf_add(h2buf, &peer->local_v6_addr.v6, >- sizeof(struct in6_addr)) == -1 || >-- buf_add(h2buf, &peer->remote_addr.v6, >-+ ibuf_add(h2buf, &peer->remote_addr.v6, >- sizeof(struct in6_addr)) == -1) { >-- log_warnx("mrt_dump_entry_mp: buf_add error"); >-+ log_warn("mrt_dump_entry_mp: ibuf_add error"); >- goto fail; >- } >- break; >- default: >-- log_warnx("king bula found new AF %d in mrt_dump_entry_mp", af); >-+ log_warnx("king bula found new AF in mrt_dump_entry_mp"); >- goto fail; >- } >- >-@@ -247,25 +301,25 @@ mrt_dump_entry_mp(struct mrt *mrt, struc >- >- if (p->aspath->nexthop == NULL) { >- bzero(&nexthop, sizeof(struct bgpd_addr)); >-- nexthop.af = addr.af; >-+ nexthop.aid = addr.aid; >- nh = &nexthop; >- } else >- nh = &p->aspath->nexthop->exit_nexthop; >- >- pt_getaddr(p->prefix, &addr); >-- switch (addr.af) { >-- case AF_INET: >-+ switch (addr.aid) { >-+ case AID_INET: >- DUMP_SHORT(h2buf, AFI_IPv4); /* afi */ >- DUMP_BYTE(h2buf, SAFI_UNICAST); /* safi */ >- DUMP_BYTE(h2buf, 4); /* nhlen */ >- DUMP_NLONG(h2buf, nh->v4.s_addr); /* nexthop */ >- break; >-- case AF_INET6: >-+ case AID_INET6: >- DUMP_SHORT(h2buf, AFI_IPv6); /* afi */ >- DUMP_BYTE(h2buf, SAFI_UNICAST); /* safi */ >- DUMP_BYTE(h2buf, 16); /* nhlen */ >-- if (buf_add(h2buf, &nh->v6, sizeof(struct in6_addr)) == -1) { >-- log_warnx("mrt_dump_entry_mp: buf_add error"); >-+ if (ibuf_add(h2buf, &nh->v6, sizeof(struct in6_addr)) == -1) { >-+ log_warn("mrt_dump_entry_mp: ibuf_add error"); >- goto fail; >- } >- break; >-@@ -274,35 +328,30 @@ mrt_dump_entry_mp(struct mrt *mrt, struc >- goto fail; >- } >- >-- p_len = PREFIX_SIZE(p->prefix->prefixlen); >-- if ((bptr = buf_reserve(h2buf, p_len)) == NULL) { >-- log_warnx("mrt_dump_entry_mp: buf_reserve error"); >-- goto fail; >-- } >-- if (prefix_write(bptr, p_len, &addr, p->prefix->prefixlen) == -1) { >-- log_warnx("mrt_dump_entry_mp: prefix_write error"); >-+ if (prefix_writebuf(h2buf, &addr, p->prefix->prefixlen) == -1) { >-+ log_warn("mrt_dump_entry_mp: prefix_writebuf error"); >- goto fail; >- } >- >- DUMP_SHORT(h2buf, len); >-- len += buf_size(h2buf); >-+ len += ibuf_size(h2buf); >- >- if (mrt_dump_hdr_rde(&hbuf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY, >- len) == -1) >- goto fail; >- >-- buf_close(&mrt->wbuf, hbuf); >-- buf_close(&mrt->wbuf, h2buf); >-- buf_close(&mrt->wbuf, buf); >-+ ibuf_close(&mrt->wbuf, hbuf); >-+ ibuf_close(&mrt->wbuf, h2buf); >-+ ibuf_close(&mrt->wbuf, buf); >- >- return (len + MRT_HEADER_SIZE); >- >- fail: >- if (hbuf) >-- buf_free(hbuf); >-- if (h2buf); >-- buf_free(h2buf); >-- buf_free(buf); >-+ ibuf_free(hbuf); >-+ if (h2buf) >-+ ibuf_free(h2buf); >-+ ibuf_free(buf); >- return (-1); >- } >- >-@@ -310,34 +359,37 @@ int >- mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum, >- struct rde_peer *peer) >- { >-- struct buf *buf, *hbuf; >-+ struct ibuf *buf, *hbuf; >- struct bgpd_addr addr, *nh; >- size_t len; >-+ u_int16_t subtype; >-+ u_int8_t dummy; >- >-- if (p->prefix->af != AF_INET && peer->remote_addr.af == AF_INET) >-- /* only able to dump IPv4 */ >-+ if (p->prefix->aid != peer->remote_addr.aid && >-+ p->prefix->aid != AID_INET && p->prefix->aid != AID_INET6) >-+ /* only able to dump pure IPv4/IPv6 */ >- return (0); >- >-- if ((buf = buf_dynamic(0, MAX_PKTSIZE)) == NULL) { >-- log_warnx("mrt_dump_entry: buf_dynamic"); >-+ if ((buf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) { >-+ log_warn("mrt_dump_entry: ibuf_dynamic"); >- return (-1); >- } >- >- if (p->aspath->nexthop == NULL) { >- bzero(&addr, sizeof(struct bgpd_addr)); >-- addr.af = AF_INET; >-+ addr.aid = p->prefix->aid; >- nh = &addr; >- } else >- nh = &p->aspath->nexthop->exit_nexthop; >-- if (mrt_attr_dump(buf, p->aspath, nh) == -1) { >-+ if (mrt_attr_dump(buf, p->aspath, nh, 0) == -1) { >- log_warnx("mrt_dump_entry: mrt_attr_dump error"); >-- buf_free(buf); >-+ ibuf_free(buf); >- return (-1); >- } >-- len = buf_size(buf); >-- >-- if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP, AFI_IPv4, len) == -1) { >-- buf_free(buf); >-+ len = ibuf_size(buf); >-+ aid2afi(p->prefix->aid, &subtype, &dummy); >-+ if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP, subtype, len) == -1) { >-+ ibuf_free(buf); >- return (-1); >- } >- >-@@ -345,23 +397,241 @@ mrt_dump_entry(struct mrt *mrt, struct p >- DUMP_SHORT(hbuf, snum); >- >- pt_getaddr(p->prefix, &addr); >-- DUMP_NLONG(hbuf, addr.v4.s_addr); >-+ switch (p->prefix->aid) { >-+ case AID_INET: >-+ DUMP_NLONG(hbuf, addr.v4.s_addr); >-+ break; >-+ case AID_INET6: >-+ if (ibuf_add(hbuf, &addr.v6, sizeof(struct in6_addr)) == -1) { >-+ log_warn("mrt_dump_entry: ibuf_add error"); >-+ goto fail; >-+ } >-+ break; >-+ } >- DUMP_BYTE(hbuf, p->prefix->prefixlen); >- >- DUMP_BYTE(hbuf, 1); /* state */ >- DUMP_LONG(hbuf, p->lastchange); /* originated */ >-- DUMP_NLONG(hbuf, peer->remote_addr.v4.s_addr); >-+ switch (p->prefix->aid) { >-+ case AID_INET: >-+ DUMP_NLONG(hbuf, peer->remote_addr.v4.s_addr); >-+ break; >-+ case AID_INET6: >-+ if (ibuf_add(hbuf, &peer->remote_addr.v6, >-+ sizeof(struct in6_addr)) == -1) { >-+ log_warn("mrt_dump_entry: ibuf_add error"); >-+ goto fail; >-+ } >-+ break; >-+ } >- DUMP_SHORT(hbuf, peer->short_as); >- DUMP_SHORT(hbuf, len); >- >-- buf_close(&mrt->wbuf, hbuf); >-- buf_close(&mrt->wbuf, buf); >-+ ibuf_close(&mrt->wbuf, hbuf); >-+ ibuf_close(&mrt->wbuf, buf); >- >- return (len + MRT_HEADER_SIZE); >- >- fail: >-- buf_free(hbuf); >-- buf_free(buf); >-+ ibuf_free(hbuf); >-+ ibuf_free(buf); >-+ return (-1); >-+} >-+ >-+int >-+mrt_dump_entry_v2(struct mrt *mrt, struct rib_entry *re, u_int32_t snum) >-+{ >-+ struct ibuf *buf, *hbuf = NULL; >-+ struct prefix *p; >-+ struct bgpd_addr addr; >-+ size_t len, off; >-+ u_int16_t subtype, nump; >-+ >-+ switch (re->prefix->aid) { >-+ case AID_INET: >-+ subtype = MRT_DUMP_V2_RIB_IPV4_UNICAST; >-+ break; >-+ case AID_INET6: >-+ subtype = MRT_DUMP_V2_RIB_IPV6_UNICAST; >-+ break; >-+ default: >-+ subtype = MRT_DUMP_V2_RIB_GENERIC; >-+ break; >-+ } >-+ >-+ if ((buf = ibuf_dynamic(0, UINT_MAX)) == NULL) { >-+ log_warn("mrt_dump_entry: ibuf_dynamic"); >-+ return (-1); >-+ } >-+ >-+ DUMP_LONG(buf, snum); >-+ pt_getaddr(re->prefix, &addr); >-+ if (subtype == MRT_DUMP_V2_RIB_GENERIC) { >-+ u_int16_t afi; >-+ u_int8_t safi; >-+ >-+ aid2afi(re->prefix->aid, &afi, &safi); >-+ DUMP_SHORT(buf, afi); >-+ DUMP_BYTE(buf, safi); >-+ } >-+ if (prefix_writebuf(buf, &addr, re->prefix->prefixlen) == -1) { >-+ log_warn("mrt_dump_entry_mp: prefix_writebuf error"); >-+ goto fail; >-+ } >-+ >-+ off = ibuf_size(buf); >-+ if (ibuf_reserve(buf, sizeof(nump)) == NULL) { >-+ log_warn("mrt_dump_v2_hdr: ibuf_reserve error"); >-+ goto fail; >-+ } >-+ nump = 0; >-+ LIST_FOREACH(p, &re->prefix_h, rib_l) { >-+ struct bgpd_addr *nh; >-+ struct ibuf *tbuf; >-+ >-+ if (p->aspath->nexthop == NULL) { >-+ bzero(&addr, sizeof(struct bgpd_addr)); >-+ addr.aid = p->prefix->aid; >-+ nh = &addr; >-+ } else >-+ nh = &p->aspath->nexthop->exit_nexthop; >-+ >-+ DUMP_SHORT(buf, p->aspath->peer->mrt_idx); >-+ DUMP_LONG(buf, p->lastchange); /* originated */ >-+ >-+ if ((tbuf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) { >-+ log_warn("mrt_dump_entry_v2: ibuf_dynamic"); >-+ return (-1); >-+ } >-+ if (mrt_attr_dump(tbuf, p->aspath, nh, 1) == -1) { >-+ log_warnx("mrt_dump_entry_v2: mrt_attr_dump error"); >-+ ibuf_free(buf); >-+ return (-1); >-+ } >-+ len = ibuf_size(tbuf); >-+ DUMP_SHORT(buf, (u_int16_t)len); >-+ if (ibuf_add(buf, tbuf->buf, ibuf_size(tbuf)) == -1) { >-+ log_warn("mrt_dump_entry_v2: ibuf_add error"); >-+ ibuf_free(tbuf); >-+ return (-1); >-+ } >-+ ibuf_free(tbuf); >-+ nump++; >-+ } >-+ nump = htons(nump); >-+ memcpy(ibuf_seek(buf, off, sizeof(nump)), &nump, sizeof(nump)); >-+ >-+ len = ibuf_size(buf); >-+ if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP_V2, subtype, len) == -1) { >-+ ibuf_free(buf); >-+ return (-1); >-+ } >-+ >-+ ibuf_close(&mrt->wbuf, hbuf); >-+ ibuf_close(&mrt->wbuf, buf); >-+ >-+ return (0); >-+fail: >-+ if (hbuf) >-+ ibuf_free(hbuf); >-+ ibuf_free(buf); >-+ return (-1); >-+} >-+ >-+int >-+mrt_dump_v2_hdr(struct mrt *mrt, struct bgpd_config *conf, >-+ struct rde_peer_head *ph) >-+{ >-+ struct rde_peer *peer; >-+ struct ibuf *buf, *hbuf = NULL; >-+ size_t len, off; >-+ u_int16_t nlen, nump; >-+ >-+ if ((buf = ibuf_dynamic(0, UINT_MAX)) == NULL) { >-+ log_warn("mrt_dump_v2_hdr: ibuf_dynamic"); >-+ return (-1); >-+ } >-+ >-+ DUMP_NLONG(buf, conf->bgpid); >-+ nlen = strlen(mrt->rib); >-+ if (nlen > 0) >-+ nlen += 1; >-+ DUMP_SHORT(buf, nlen); >-+ if (ibuf_add(buf, mrt->rib, nlen) == -1) { >-+ log_warn("mrt_dump_v2_hdr: ibuf_add error"); >-+ goto fail; >-+ } >-+ >-+ off = ibuf_size(buf); >-+ if (ibuf_reserve(buf, sizeof(nump)) == NULL) { >-+ log_warn("mrt_dump_v2_hdr: ibuf_reserve error"); >-+ goto fail; >-+ } >-+ nump = 0; >-+ LIST_FOREACH(peer, ph, peer_l) { >-+ peer->mrt_idx = nump; >-+ if (mrt_dump_peer(buf, peer) == -1) >-+ goto fail; >-+ nump++; >-+ } >-+ nump = htons(nump); >-+ memcpy(ibuf_seek(buf, off, sizeof(nump)), &nump, sizeof(nump)); >-+ >-+ len = ibuf_size(buf); >-+ if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP_V2, >-+ MRT_DUMP_V2_PEER_INDEX_TABLE, len) == -1) >-+ goto fail; >-+ >-+ ibuf_close(&mrt->wbuf, hbuf); >-+ ibuf_close(&mrt->wbuf, buf); >-+ >-+ return (0); >-+fail: >-+ if (hbuf) >-+ ibuf_free(hbuf); >-+ ibuf_free(buf); >-+ return (-1); >-+} >-+ >-+int >-+mrt_dump_peer(struct ibuf *buf, struct rde_peer *peer) >-+{ >-+ u_int8_t type = 0; >-+ >-+ if (peer->capa.as4byte) >-+ type |= MRT_DUMP_V2_PEER_BIT_A; >-+ if (peer->remote_addr.aid == AID_INET6) >-+ type |= MRT_DUMP_V2_PEER_BIT_I; >-+ >-+ DUMP_BYTE(buf, type); >-+ DUMP_LONG(buf, peer->remote_bgpid); >-+ >-+ switch (peer->remote_addr.aid) { >-+ case AID_INET: >-+ DUMP_NLONG(buf, peer->remote_addr.v4.s_addr); >-+ break; >-+ case AID_INET6: >-+ if (ibuf_add(buf, &peer->remote_addr.v6, >-+ sizeof(struct in6_addr)) == -1) { >-+ log_warn("mrt_dump_peer: ibuf_add error"); >-+ goto fail; >-+ } >-+ break; >-+ case AID_UNSPEC: /* XXX special handling for peer_self? */ >-+ DUMP_NLONG(buf, 0); >-+ break; >-+ default: >-+ log_warnx("king bula found new AF in mrt_dump_entry_mp"); >-+ goto fail; >-+ } >-+ >-+ if (peer->capa.as4byte) >-+ DUMP_LONG(buf, peer->conf.remote_as); >-+ else >-+ DUMP_SHORT(buf, peer->short_as); >-+ >-+ return (0); >-+fail: >- return (-1); >- } >- >-@@ -371,6 +641,11 @@ mrt_dump_upcall(struct rib_entry *re, vo >- struct mrt *mrtbuf = ptr; >- struct prefix *p; >- >-+ if (mrtbuf->type == MRT_TABLE_DUMP_V2) { >-+ mrt_dump_entry_v2(mrtbuf, re, mrtbuf->seqnum++); >-+ return; >-+ } >-+ >- /* >- * dump all prefixes even the inactive ones. That is the way zebra >- * dumps the table so we do the same. If only the active route should >-@@ -387,7 +662,7 @@ mrt_dump_upcall(struct rib_entry *re, vo >- } >- >- void >--mrt_dump_done(void *ptr) >-+mrt_done(void *ptr) >- { >- struct mrt *mrtbuf = ptr; >- >-@@ -395,14 +670,14 @@ mrt_dump_done(void *ptr) >- } >- >- int >--mrt_dump_hdr_se(struct buf ** bp, struct peer *peer, u_int16_t type, >-+mrt_dump_hdr_se(struct ibuf ** bp, struct peer *peer, u_int16_t type, >- u_int16_t subtype, u_int32_t len, int swap) >- { >- time_t now; >- >-- if ((*bp = buf_dynamic(MRT_HEADER_SIZE, MRT_HEADER_SIZE + >-+ if ((*bp = ibuf_dynamic(MRT_HEADER_SIZE, MRT_HEADER_SIZE + >- MRT_BGP4MP_AS4_IPv6_HEADER_SIZE + len)) == NULL) { >-- log_warnx("mrt_dump_hdr_se: buf_open error"); >-+ log_warn("mrt_dump_hdr_se: ibuf_dynamic error"); >- return (-1); >- } >- >-@@ -468,23 +743,23 @@ mrt_dump_hdr_se(struct buf ** bp, struct >- case AF_INET6: >- DUMP_SHORT(*bp, AFI_IPv6); >- if (!swap) >-- if (buf_add(*bp, &((struct sockaddr_in6 *) >-+ if (ibuf_add(*bp, &((struct sockaddr_in6 *) >- &peer->sa_local)->sin6_addr, >- sizeof(struct in6_addr)) == -1) { >-- log_warnx("mrt_dump_hdr_se: buf_add error"); >-+ log_warn("mrt_dump_hdr_se: ibuf_add error"); >- goto fail; >- } >-- if (buf_add(*bp, >-+ if (ibuf_add(*bp, >- &((struct sockaddr_in6 *)&peer->sa_remote)->sin6_addr, >- sizeof(struct in6_addr)) == -1) { >-- log_warnx("mrt_dump_hdr_se: buf_add error"); >-+ log_warn("mrt_dump_hdr_se: ibuf_add error"); >- goto fail; >- } >- if (swap) >-- if (buf_add(*bp, &((struct sockaddr_in6 *) >-+ if (ibuf_add(*bp, &((struct sockaddr_in6 *) >- &peer->sa_local)->sin6_addr, >- sizeof(struct in6_addr)) == -1) { >-- log_warnx("mrt_dump_hdr_se: buf_add error"); >-+ log_warn("mrt_dump_hdr_se: ibuf_add error"); >- goto fail; >- } >- break; >-@@ -493,20 +768,20 @@ mrt_dump_hdr_se(struct buf ** bp, struct >- return (0); >- >- fail: >-- buf_free(*bp); >-+ ibuf_free(*bp); >- return (-1); >- } >- >- int >--mrt_dump_hdr_rde(struct buf **bp, u_int16_t type, u_int16_t subtype, >-+mrt_dump_hdr_rde(struct ibuf **bp, u_int16_t type, u_int16_t subtype, >- u_int32_t len) >- { >- time_t now; >- >-- if ((*bp = buf_dynamic(MRT_HEADER_SIZE, MRT_HEADER_SIZE + >-+ if ((*bp = ibuf_dynamic(MRT_HEADER_SIZE, MRT_HEADER_SIZE + >- MRT_BGP4MP_AS4_IPv6_HEADER_SIZE + MRT_BGP4MP_IPv6_ENTRY_SIZE)) == >- NULL) { >-- log_warnx("mrt_dump_hdr_rde: buf_dynamic error"); >-+ log_warn("mrt_dump_hdr_rde: ibuf_dynamic error"); >- return (-1); >- } >- >-@@ -517,19 +792,28 @@ mrt_dump_hdr_rde(struct buf **bp, u_int1 >- >- switch (type) { >- case MSG_TABLE_DUMP: >-- DUMP_LONG(*bp, MRT_DUMP_HEADER_SIZE + len); >-+ switch (subtype) { >-+ case AFI_IPv4: >-+ len += MRT_DUMP_HEADER_SIZE; >-+ break; >-+ case AFI_IPv6: >-+ len += MRT_DUMP_HEADER_SIZE_V6; >-+ break; >-+ } >-+ DUMP_LONG(*bp, len); >- break; >- case MSG_PROTOCOL_BGP4MP: >-+ case MSG_TABLE_DUMP_V2: >- DUMP_LONG(*bp, len); >- break; >- default: >- log_warnx("mrt_dump_hdr_rde: unsupported type"); >- goto fail; >-- } >-+ } >- return (0); >- >- fail: >-- buf_free(*bp); >-+ ibuf_free(*bp); >- return (-1); >- } >- >-@@ -538,21 +822,22 @@ mrt_write(struct mrt *mrt) >- { >- int r; >- >-- if ((r = buf_write(&mrt->wbuf)) < 0) { >-+ if ((r = ibuf_write(&mrt->wbuf)) < 0) { >- log_warn("mrt dump aborted, mrt_write"); >- mrt_clean(mrt); >-+ mrt_done(mrt); >- } >- } >- >- void >- mrt_clean(struct mrt *mrt) >- { >-- struct buf *b; >-+ struct ibuf *b; >- >- close(mrt->wbuf.fd); >- while ((b = TAILQ_FIRST(&mrt->wbuf.bufs))) { >- TAILQ_REMOVE(&mrt->wbuf.bufs, b, entry); >-- buf_free(b); >-+ ibuf_free(b); >- } >- mrt->wbuf.queued = 0; >- } >-@@ -590,7 +875,8 @@ mrt_open(struct mrt *mrt, time_t now) >- else >- type = IMSG_MRT_REOPEN; >- >-- if (mrt->type == MRT_TABLE_DUMP || mrt->type == MRT_TABLE_DUMP_MP) >-+ if (mrt->type == MRT_TABLE_DUMP || mrt->type == MRT_TABLE_DUMP_MP || >-+ mrt->type == MRT_TABLE_DUMP_V2) >- i = 0; >- >- if (imsg_compose(mrt_imsgbuf[i], type, 0, 0, fd, >-@@ -659,7 +945,9 @@ mrt_handler(struct mrt_head *mrt) >- LIST_FOREACH(m, mrt, entry) { >- if (m->state == MRT_STATE_RUNNING && >- (MRT2MC(m)->ReopenTimerInterval != 0 || >-- m->type == MRT_TABLE_DUMP)) { >-+ m->type == MRT_TABLE_DUMP || >-+ m->type == MRT_TABLE_DUMP_MP || >-+ m->type == MRT_TABLE_DUMP_V2)) { >- if (mrt_open(m, now) == -1) >- continue; >- MRT2MC(m)->ReopenTimer = > >Property changes on: files/patch-bgpd_mrt.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_mrt.h >=================================================================== >--- files/patch-bgpd_mrt.h (revision 500577) >+++ files/patch-bgpd_mrt.h (nonexistent) >@@ -1,287 +0,0 @@ >-Index: bgpd/mrt.h >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/mrt.h,v >-retrieving revision 1.1.1.6 >-retrieving revision 1.1.1.9 >-diff -u -p -r1.1.1.6 -r1.1.1.9 >---- bgpd/mrt.h 14 Feb 2010 20:19:57 -0000 1.1.1.6 >-+++ bgpd/mrt.h 13 Oct 2012 18:22:43 -0000 1.1.1.9 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: mrt.h,v 1.23 2009/06/29 12:22:16 claudio Exp $ */ >-+/* $OpenBSD: mrt.h,v 1.30 2011/09/18 09:31:25 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> >-@@ -18,12 +18,10 @@ >- #ifndef __MRT_H__ >- #define __MRT_H__ >- >--#include "bgpd.h" >-- >- /* >- * MRT binary packet format >- * For more info see: >-- * draft-ietf-grow-mrt-04.txt, "MRT routing information export format" >-+ * draft-ietf-grow-mrt-11.txt, "MRT routing information export format" >- * http://www.quagga.net/docs/docs-multi/Packet-Binary-Dump-Format.html >- */ >- >-@@ -37,11 +35,18 @@ >- * | length | length of packet excluding this header >- * +--------+--------+--------+--------+ >- * >-- * ET types include an additional 32bit microsecond field comming after the >-- * length field. >-+ * ET types include an additional 32bit microsecond field coming after the >-+ * length field. Which is accounted in the length field. >- */ >- #define MRT_HEADER_SIZE 12 >- >-+struct mrt_hdr { >-+ u_int32_t timestamp; >-+ u_int16_t type; >-+ u_int16_t subtype; >-+ u_int32_t length; >-+} __packed; >-+ >- enum MRT_MSG_TYPES { >- MSG_NULL, /* 0 empty msg (deprecated) */ >- MSG_START, /* 1 sender is starting up */ >-@@ -70,13 +75,15 @@ enum MRT_MSG_TYPES { >- * that are normaly saved as MSG_TABLE_DUMP. >- * In most cases this is the format to choose to dump updates et al. >- */ >--enum MRT_BGP4MP_TYPES { >-+enum MRT_BGP4MP_SUBTYPES { >- BGP4MP_STATE_CHANGE, /* state change */ >- BGP4MP_MESSAGE, /* bgp message */ >- BGP4MP_ENTRY, /* table dumps (deprecated) */ >- BGP4MP_SNAPSHOT, /* file name for dump (deprecated) */ >-+ BGP4MP_MESSAGE_AS4, /* same as BGP4MP_MESSAGE with 4byte AS */ >- BGP4MP_STATE_CHANGE_AS4, >-- BGP4MP_MESSAGE_AS4 /* same as BGP4MP_MESSAGE with 4byte AS */ >-+ BGP4MP_MESSAGE_LOCAL, /* same as BGP4MP_MESSAGE but for self */ >-+ BGP4MP_MESSAGE_AS4_LOCAL /* originated updates. Not implemented */ >- }; >- >- /* size of the BGP4MP headers without payload */ >-@@ -104,6 +111,7 @@ enum MRT_BGP4MP_TYPES { >- * >- * The source_ip and dest_ip are dependant of the afi type. For IPv6 source_ip >- * and dest_ip are both 16 bytes long. >-+ * For the AS4 types the source_as and dest_as numbers are both 4 bytes long. >- * >- * Payload of a BGP4MP_STATE_CHANGE packet: >- * >-@@ -155,6 +163,98 @@ enum MRT_BGP4MP_TYPES { >- */ >- >- /* >-+ * New MRT dump format MSG_TABLE_DUMP_V2, the dump is implemented with >-+ * sub-tables for peers and NLRI entries just use the index into the peer >-+ * table. >-+ */ >-+enum MRT_DUMP_V2_SUBTYPES { >-+ MRT_DUMP_V2_PEER_INDEX_TABLE=1, >-+ MRT_DUMP_V2_RIB_IPV4_UNICAST=2, >-+ MRT_DUMP_V2_RIB_IPV4_MULTICAST=3, >-+ MRT_DUMP_V2_RIB_IPV6_UNICAST=4, >-+ MRT_DUMP_V2_RIB_IPV6_MULTICAST=5, >-+ MRT_DUMP_V2_RIB_GENERIC=6 >-+}; >-+ >-+/* >-+ * Format of the MRT_DUMP_V2_PEER_INDEX_TABLE: >-+ * If there is no view_name, view_name_len must be set to 0 >-+ * >-+ * +--------+--------+--------+--------+ >-+ * | collector_bgp_id | >-+ * +--------+--------+--------+--------+ >-+ * | view_name_len | view_name >-+ * +--------+--------+--------+--------+ >-+ * view_name (variable) ... | >-+ * +--------+--------+--------+--------+ >-+ * | peer_count | peer_entries >-+ * +--------+--------+--------+--------+ >-+ * peer_entries (variable) ... >-+ * +--------+--------+--------+--------+ >-+ * >-+ * The format of a peer_entry is the following: >-+ * >-+ * +--------+ >-+ * | type | >-+ * +--------+--------+--------+--------+ >-+ * | peer_bgp_id | >-+ * +--------+--------+--------+--------+ >-+ * | peer_ip_addr (variable) | >-+ * +--------+--------+--------+--------+ >-+ * | peer_as (variable) | >-+ * +--------+--------+--------+--------+ >-+ * >-+ * The message is packed a bit strangely. The type byte defines what size >-+ * the peer addr and peer AS have. >-+ * The position of a peer in the PEER_INDEX_TABLE is used as the index for >-+ * the other messages. >-+ */ >-+#define MRT_DUMP_V2_PEER_BIT_I 0x1 /* set for IPv6 addrs */ >-+#define MRT_DUMP_V2_PEER_BIT_A 0x2 /* set for 32 bits AS number */ >-+ >-+/* >-+ * AFI/SAFI specific RIB Subtypes are special to save a few bytes. >-+ * >-+ * +--------+--------+--------+--------+ >-+ * | seq_num | >-+ * +--------+--------+--------+--------+ >-+ * | plen | prefix (variable) >-+ * +--------+--------+--------+--------+ >-+ * | #entry | rib entries (variable) >-+ * +--------+--------+--------+--------+ >-+ * >-+ * The RIB_GENERIC subtype is needed for the less common AFI/SAFI pairs >-+ * >-+ * +--------+--------+--------+--------+ >-+ * | seq_num | >-+ * +--------+--------+--------+--------+ >-+ * | AFI | SAFI | NLRI >-+ * +--------+--------+--------+--------+ >-+ * NLRI (variable) ... >-+ * +--------+--------+--------+--------+ >-+ * | #entry | rib entries (variable) >-+ * +--------+--------+--------+--------+ >-+ */ >-+ >-+/* >-+ * The RIB entries have the following form. >-+ * >-+ * +--------+--------+ >-+ * | peer index | >-+ * +--------+--------+--------+--------+ >-+ * | originated_time | >-+ * +--------+--------+--------+--------+ >-+ * | attr_len | bgp_attrs >-+ * +--------+--------+--------+--------+ >-+ * bgp_attrs (variable) ... >-+ * +--------+--------+--------+--------+ >-+ * >-+ * Some BGP path attributes need special encoding: >-+ * - the AS_PATH attribute MUST be encoded as 4-Byte AS >-+ * - the MP_REACH_NLRI only consists of the nexthop len and nexthop address >-+ */ >-+ >-+/* >- * Format for routing table dumps in "old" mrt format. >- * Type MSG_TABLE_DUMP and subtype is AFI_IPv4 (1) for IPv4 and AFI_IPv6 (2) >- * for IPv6. In the IPv6 case prefix and peer_ip are both 16 bytes long. >-@@ -182,8 +282,14 @@ enum MRT_BGP4MP_TYPES { >- * The status field is unused and should be set to 1. >- */ >- >-+enum MRT_DUMP_SUBTYPES { >-+ MRT_DUMP_AFI_IP=1, >-+ MRT_DUMP_AFI_IPv6=2 >-+}; >-+ >- /* size of the dump header until attr_len */ >- #define MRT_DUMP_HEADER_SIZE 22 >-+#define MRT_DUMP_HEADER_SIZE_V6 46 >- >- /* >- * OLD MRT message headers. These structs are here for completion but >-@@ -192,7 +298,7 @@ enum MRT_BGP4MP_TYPES { >- * Only for bgp messages (type 5, 9 and 10) >- * Nota bene for bgp dumps MSG_PROTOCOL_BGP4MP should be used. >- */ >--enum MRT_BGP_TYPES { >-+enum MRT_BGP_SUBTYPES { >- MSG_BGP_NULL, >- MSG_BGP_UPDATE, /* raw update packet (contains both withdraws >- and announcements) */ >-@@ -221,10 +327,8 @@ enum MRT_BGP_TYPES { >- * >- * For IPv6 the type is MSG_PROTOCOL_BGP4PLUS and the subtype remains >- * MSG_BGP_UPDATE. The source_ip and dest_ip are again extended to 16 bytes. >-- */ >-- >--/* >-- * For subtype MSG_BGP_STATECHANGE (for all BGP types or just for the >-+ * >-+ * For subtype MSG_BGP_STATE_CHANGE (for all BGP types or just for the >- * MSG_PROTOCOL_BGP4PLUS case? Unclear.) >- * >- * +--------+--------+--------+--------+ >-@@ -235,7 +339,7 @@ enum MRT_BGP_TYPES { >- * | new_state | >- * +--------+--------+ >- * >-- * State are defined in RFC 1771. >-+ * States are defined in RFC 1771/4271. >- */ >- >- /* >-@@ -251,66 +355,4 @@ enum MRT_BGP_TYPES { >- * terminated ... | 0 | >- * +--------+--------+--------+ >- */ >-- >--#define MRT_FILE_LEN 512 >--enum mrt_type { >-- MRT_NONE, >-- MRT_TABLE_DUMP, >-- MRT_TABLE_DUMP_MP, >-- MRT_ALL_IN, >-- MRT_ALL_OUT, >-- MRT_UPDATE_IN, >-- MRT_UPDATE_OUT >--}; >-- >--enum mrt_state { >-- MRT_STATE_RUNNING, >-- MRT_STATE_OPEN, >-- MRT_STATE_REOPEN, >-- MRT_STATE_REMOVE >--}; >-- >--struct mrt { >-- char rib[PEER_DESCR_LEN]; >-- struct msgbuf wbuf; >-- LIST_ENTRY(mrt) entry; >-- u_int32_t peer_id; >-- u_int32_t group_id; >-- enum mrt_type type; >-- enum mrt_state state; >-- u_int16_t seqnum; >--}; >-- >--struct mrt_config { >-- struct mrt conf; >-- char name[MRT_FILE_LEN]; /* base file name */ >-- char file[MRT_FILE_LEN]; /* actual file name */ >-- time_t ReopenTimer; >-- time_t ReopenTimerInterval; >--}; >-- >--#define MRT2MC(x) ((struct mrt_config *)(x)) >--#define MRT_MAX_TIMEOUT 7200 >-- >--struct peer; >--struct prefix; >--struct rib_entry; >-- >--/* prototypes */ >--void mrt_dump_bgp_msg(struct mrt *, void *, u_int16_t, >-- struct peer *); >--void mrt_dump_state(struct mrt *, u_int16_t, u_int16_t, >-- struct peer *); >--void mrt_clear_seq(void); >--void mrt_dump_upcall(struct rib_entry *, void *); >--void mrt_dump_done(void *); >--void mrt_write(struct mrt *); >--void mrt_clean(struct mrt *); >--void mrt_init(struct imsgbuf *, struct imsgbuf *); >--int mrt_timeout(struct mrt_head *); >--void mrt_reconfigure(struct mrt_head *); >--void mrt_handler(struct mrt_head *); >--struct mrt *mrt_get(struct mrt_head *, struct mrt *); >--int mrt_mergeconfig(struct mrt_head *, struct mrt_head *); >-- >- #endif > >Property changes on: files/patch-bgpd_mrt.h >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_name2id.c >=================================================================== >--- files/patch-bgpd_name2id.c (revision 500577) >+++ files/patch-bgpd_name2id.c (nonexistent) >@@ -1,14 +0,0 @@ >-Index: bgpd/name2id.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/name2id.c,v >-retrieving revision 1.1.1.2 >-retrieving revision 1.1.1.3 >-diff -u -p -r1.1.1.2 -r1.1.1.3 >---- bgpd/name2id.c 9 Jul 2009 16:49:54 -0000 1.1.1.2 >-+++ bgpd/name2id.c 13 Oct 2012 18:22:43 -0000 1.1.1.3 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: name2id.c,v 1.9 2009/06/04 04:46:42 claudio Exp $ */ >-+/* $OpenBSD: name2id.c,v 1.8 2009/05/17 12:25:15 claudio Exp $ */ >- >- /* >- * Copyright (c) 2004, 2005 Henning Brauer <henning@openbsd.org> > >Property changes on: files/patch-bgpd_name2id.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_parse.y >=================================================================== >--- files/patch-bgpd_parse.y (revision 500577) >+++ files/patch-bgpd_parse.y (nonexistent) >@@ -1,1626 +0,0 @@ >-Index: bgpd/parse.y >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/parse.y,v >-retrieving revision 1.1.1.8 >-retrieving revision 1.12 >-diff -u -p -r1.1.1.8 -r1.12 >---- bgpd/parse.y 14 Feb 2010 20:19:57 -0000 1.1.1.8 >-+++ bgpd/parse.y 8 Dec 2012 20:17:59 -0000 1.12 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: parse.y,v 1.231 2009/06/06 01:10:29 claudio Exp $ */ >-+/* $OpenBSD: parse.y,v 1.264 2012/09/23 09:39:17 claudio Exp $ */ >- >- /* >- * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> >-@@ -25,7 +25,10 @@ >- #include <sys/stat.h> >- #include <netinet/in.h> >- #include <arpa/inet.h> >-- >-+#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */ >-+#include <netmpls/mpls.h> >-+#endif >-+ >- #include <ctype.h> >- #include <err.h> >- #include <unistd.h> >-@@ -33,6 +36,9 @@ >- #include <limits.h> >- #include <stdarg.h> >- #include <stdio.h> >-+#if defined(__FreeBSD__) >-+#include <stdlib.h> >-+#endif >- #include <string.h> >- #include <syslog.h> >- >-@@ -74,10 +80,12 @@ char *symget(const char *); >- >- static struct bgpd_config *conf; >- static struct mrt_head *mrtconf; >--static struct network_head *netconf; >-+static struct network_head *netconf, *gnetconf; >- static struct peer *peer_l, *peer_l_old; >- static struct peer *curpeer; >- static struct peer *curgroup; >-+static struct rdomain *currdom; >-+static struct rdomain_head *rdom_l; >- static struct filter_head *filter_l; >- static struct filter_head *peerfilter_l; >- static struct filter_head *groupfilter_l; >-@@ -105,7 +113,7 @@ struct filter_match_l { >- struct filter_match m; >- struct filter_prefix_l *prefix_l; >- struct filter_as_l *as_l; >-- sa_family_t af; >-+ u_int8_t aid; >- } fmopts; >- >- struct peer *alloc_peer(void); >-@@ -113,8 +121,8 @@ struct peer *new_peer(void); >- struct peer *new_group(void); >- int add_mrtconfig(enum mrt_type, char *, time_t, struct peer *, >- char *); >--int add_rib(char *, u_int16_t); >--int find_rib(char *); >-+int add_rib(char *, u_int, u_int16_t); >-+struct rde_rib *find_rib(char *); >- int get_id(struct peer *); >- int expand_rule(struct filter_rule *, struct filter_peers_l *, >- struct filter_match_l *, struct filter_set_head *); >-@@ -123,12 +131,14 @@ int neighbor_consistent(struct peer *) >- int merge_filterset(struct filter_set_head *, struct filter_set *); >- void copy_filterset(struct filter_set_head *, >- struct filter_set_head *); >--void move_filterset(struct filter_set_head *, >-- struct filter_set_head *); >- struct filter_rule *get_rule(enum action_types); >- >- int getcommunity(char *); >--int parsecommunity(char *, int *, int *); >-+int parsecommunity(struct filter_community *, char *); >-+int parsesubtype(char *); >-+int parseextvalue(char *, u_int32_t *); >-+int parseextcommunity(struct filter_extcommunity *, char *, >-+ char *); >- >- typedef struct { >- union { >-@@ -159,29 +169,33 @@ typedef struct { >- %} >- >- %token AS ROUTERID HOLDTIME YMIN LISTEN ON FIBUPDATE RTABLE >-+%token RDOMAIN RD EXPORTTRGT IMPORTTRGT >- %token RDE RIB EVALUATE IGNORE COMPARE >- %token GROUP NEIGHBOR NETWORK >--%token REMOTEAS DESCR LOCALADDR MULTIHOP PASSIVE MAXPREFIX RESTART >--%token ANNOUNCE DEMOTE CONNECTRETRY >--%token ENFORCE NEIGHBORAS CAPABILITIES REFLECTOR DEPEND DOWN SOFTRECONFIG >--%token DUMP IN OUT >-+%token REMOTEAS DESCR LLIFACE LOCALADDR MULTIHOP PASSIVE MAXPREFIX RESTART >-+%token ANNOUNCE CAPABILITIES REFRESH AS4BYTE CONNECTRETRY >-+%token DEMOTE ENFORCE NEIGHBORAS REFLECTOR DEPEND DOWN SOFTRECONFIG >-+%token DUMP IN OUT SOCKET RESTRICTED >- %token LOG ROUTECOLL TRANSPARENT >- %token TCP MD5SIG PASSWORD KEY TTLSECURITY >- %token ALLOW DENY MATCH >- %token QUICK >- %token FROM TO ANY >- %token CONNECTED STATIC >--%token PREFIX PREFIXLEN SOURCEAS TRANSITAS PEERAS COMMUNITY DELETE >-+%token COMMUNITY EXTCOMMUNITY >-+%token PREFIX PREFIXLEN SOURCEAS TRANSITAS PEERAS DELETE MAXASLEN MAXASSEQ >- %token SET LOCALPREF MED METRIC NEXTHOP REJECT BLACKHOLE NOMODIFY SELF >--%token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL >-+%token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL ORIGIN >- %token ERROR INCLUDE >- %token IPSEC ESP AH SPI IKE >- %token IPV4 IPV6 >- %token QUALIFY VIA >-+%token NE LE GE XRANGE >- %token <v.string> STRING >- %token <v.number> NUMBER >--%type <v.number> asnumber as4number optnumber yesno inout >--%type <v.number> espah family restart >-+%type <v.number> asnumber as4number optnumber >-+%type <v.number> espah family restart origincode nettype >-+%type <v.number> yesno inout restricted >- %type <v.string> string filter_rib >- %type <v.addr> address >- %type <v.prefix> prefix addrspec >-@@ -204,6 +218,7 @@ grammar : /* empty */ >- | grammar include '\n' >- | grammar conf_main '\n' >- | grammar varset '\n' >-+ | grammar rdomain '\n' >- | grammar neighbor '\n' >- | grammar group '\n' >- | grammar filterrule '\n' >-@@ -211,8 +226,12 @@ grammar : /* empty */ >- ; >- >- asnumber : NUMBER { >-- if ($1 < 0 || $1 >= ASNUM_MAX) { >-- yyerror("AS too big: max %u", ASNUM_MAX - 1); >-+ /* >-+ * Accroding to iana 65535 and 4294967295 are reserved >-+ * but enforcing this is not duty of the parser. >-+ */ >-+ if ($1 < 0 || $1 > UINT_MAX) { >-+ yyerror("AS too big: max %u", UINT_MAX); >- YYERROR; >- } >- } >-@@ -274,6 +293,8 @@ yesno : STRING { >- else if (!strcmp($1, "no")) >- $$ = 0; >- else { >-+ yyerror("syntax error, " >-+ "either yes or no expected"); >- free($1); >- YYERROR; >- } >-@@ -318,7 +339,7 @@ conf_main : AS as4number { >- conf->short_as = $3; >- } >- | ROUTERID address { >-- if ($2.af != AF_INET) { >-+ if ($2.aid != AID_INET) { >- yyerror("router-id must be an IPv4 address"); >- YYERROR; >- } >-@@ -342,42 +363,25 @@ conf_main : AS as4number { >- } >- | LISTEN ON address { >- struct listen_addr *la; >-- struct sockaddr_in *in; >-- struct sockaddr_in6 *in6; >- >- if ((la = calloc(1, sizeof(struct listen_addr))) == >- NULL) >- fatal("parse conf_main listen on calloc"); >- >- la->fd = -1; >-- la->sa.ss_family = $3.af; >-- switch ($3.af) { >-- case AF_INET: >-- la->sa.ss_len = sizeof(struct sockaddr_in); >-- in = (struct sockaddr_in *)&la->sa; >-- in->sin_addr.s_addr = $3.v4.s_addr; >-- in->sin_port = htons(BGP_PORT); >-- break; >-- case AF_INET6: >-- la->sa.ss_len = sizeof(struct sockaddr_in6); >-- in6 = (struct sockaddr_in6 *)&la->sa; >-- memcpy(&in6->sin6_addr, &$3.v6, >-- sizeof(in6->sin6_addr)); >-- in6->sin6_port = htons(BGP_PORT); >-- break; >-- default: >-- yyerror("king bula does not like family %u", >-- $3.af); >-- YYERROR; >-- } >-- >-+ memcpy(&la->sa, addr2sa(&$3, BGP_PORT), sizeof(la->sa)); >- TAILQ_INSERT_TAIL(listen_addrs, la, entry); >- } >- | FIBUPDATE yesno { >-+ struct rde_rib *rr; >-+ rr = find_rib("Loc-RIB"); >-+ if (rr == NULL) >-+ fatalx("RTABLE can not find the main RIB!"); >-+ >- if ($2 == 0) >-- conf->flags |= BGPD_FLAG_NO_FIB_UPDATE; >-+ rr->flags |= F_RIB_NOFIBSYNC; >- else >-- conf->flags &= ~BGPD_FLAG_NO_FIB_UPDATE; >-+ rr->flags &= ~F_RIB_NOFIBSYNC; >- } >- | ROUTECOLL yesno { >- if ($2 == 1) >-@@ -386,7 +390,7 @@ conf_main : AS as4number { >- conf->flags &= ~BGPD_FLAG_NO_EVALUATE; >- } >- | RDE RIB STRING { >-- if (add_rib($3, F_RIB_NOFIB)) { >-+ if (add_rib($3, 0, F_RIB_NOFIB)) { >- free($3); >- YYERROR; >- } >-@@ -395,9 +399,27 @@ conf_main : AS as4number { >- | RDE RIB STRING yesno EVALUATE { >- if ($4) { >- free($3); >-+ yyerror("bad rde rib definition"); >- YYERROR; >- } >-- if (!add_rib($3, F_RIB_NOEVALUATE)) { >-+ if (add_rib($3, 0, F_RIB_NOFIB | F_RIB_NOEVALUATE)) { >-+ free($3); >-+ YYERROR; >-+ } >-+ free($3); >-+ } >-+ | RDE RIB STRING RTABLE NUMBER { >-+ if (add_rib($3, $5, 0)) { >-+ free($3); >-+ YYERROR; >-+ } >-+ free($3); >-+ } >-+ | RDE RIB STRING RTABLE NUMBER FIBUPDATE yesno { >-+ int flags = 0; >-+ if ($7 == 0) >-+ flags = F_RIB_NOFIBSYNC; >-+ if (add_rib($3, $5, flags)) { >- free($3); >- YYERROR; >- } >-@@ -418,59 +440,7 @@ conf_main : AS as4number { >- } >- free($2); >- } >-- | NETWORK prefix filter_set { >-- struct network *n; >-- >-- if ((n = calloc(1, sizeof(struct network))) == NULL) >-- fatal("new_network"); >-- memcpy(&n->net.prefix, &$2.prefix, >-- sizeof(n->net.prefix)); >-- n->net.prefixlen = $2.len; >-- move_filterset($3, &n->net.attrset); >-- free($3); >-- >-- TAILQ_INSERT_TAIL(netconf, n, entry); >-- } >-- | NETWORK family STATIC filter_set { >-- if ($2 == AFI_IPv4) { >-- conf->flags |= BGPD_FLAG_REDIST_STATIC; >-- move_filterset($4, &conf->staticset); >-- } else if ($2 == AFI_IPv6) { >-- conf->flags |= BGPD_FLAG_REDIST6_STATIC; >-- move_filterset($4, &conf->staticset6); >-- } else { >-- yyerror("unknown family"); >-- free($4); >-- YYERROR; >-- } >-- free($4); >-- } >-- | NETWORK family CONNECTED filter_set { >-- if ($2 == AFI_IPv4) { >-- conf->flags |= BGPD_FLAG_REDIST_CONNECTED; >-- move_filterset($4, &conf->connectset); >-- } else if ($2 == AFI_IPv6) { >-- conf->flags |= BGPD_FLAG_REDIST6_CONNECTED; >-- move_filterset($4, &conf->connectset6); >-- } else { >-- yyerror("unknown family"); >-- free($4); >-- YYERROR; >-- } >-- free($4); >-- } >-- | NETWORK STATIC filter_set { >-- /* keep for compatibility till after next release */ >-- conf->flags |= BGPD_FLAG_REDIST_STATIC; >-- move_filterset($3, &conf->staticset); >-- free($3); >-- } >-- | NETWORK CONNECTED filter_set { >-- /* keep for compatibility till after next release */ >-- conf->flags |= BGPD_FLAG_REDIST_CONNECTED; >-- move_filterset($3, &conf->connectset); >-- free($3); >-- } >-+ | network >- | DUMP STRING STRING optnumber { >- int action; >- >-@@ -484,6 +454,8 @@ conf_main : AS as4number { >- action = MRT_TABLE_DUMP; >- else if (!strcmp($2, "table-mp")) >- action = MRT_TABLE_DUMP_MP; >-+ else if (!strcmp($2, "table-v2")) >-+ action = MRT_TABLE_DUMP_V2; >- else { >- yyerror("unknown mrt dump type"); >- free($2); >-@@ -511,6 +483,8 @@ conf_main : AS as4number { >- action = MRT_TABLE_DUMP; >- else if (!strcmp($4, "table-mp")) >- action = MRT_TABLE_DUMP_MP; >-+ else if (!strcmp($4, "table-v2")) >-+ action = MRT_TABLE_DUMP_V2; >- else { >- yyerror("unknown mrt dump type"); >- free($3); >-@@ -575,11 +549,20 @@ conf_main : AS as4number { >- free($4); >- } >- | RTABLE NUMBER { >-- if ($2 > RT_TABLEID_MAX || $2 < 0) { >-- yyerror("invalid rtable id"); >-+#if defined(__FreeBSD__) /* FreeBSD does not support RTABLE */ >-+ yyerror("rtable id not supported in FreeBSD, yet"); >-+ YYERROR; >-+#else >-+ struct rde_rib *rr; >-+ if (ktable_exists($2, NULL) != 1) { >-+ yyerror("rtable id %lld does not exist", $2); >- YYERROR; >- } >-- conf->rtableid = $2; >-+ rr = find_rib("Loc-RIB"); >-+ if (rr == NULL) >-+ fatalx("RTABLE can not find the main RIB!"); >-+ rr->rtableid = $2; >-+#endif /* defined(__FreeBSD__) */ >- } >- | CONNECTRETRY NUMBER { >- if ($2 > USHRT_MAX || $2 < 1) { >-@@ -588,6 +571,15 @@ conf_main : AS as4number { >- } >- conf->connectretry = $2; >- } >-+ | SOCKET STRING restricted { >-+ if ($3) { >-+ free(conf->rcsock); >-+ conf->rcsock = $2; >-+ } else { >-+ free(conf->csock); >-+ conf->csock = $2; >-+ } >-+ } >- ; >- >- mrtdump : DUMP STRING inout STRING optnumber { >-@@ -620,10 +612,47 @@ mrtdump : DUMP STRING inout STRING optn >- } >- ; >- >-+network : NETWORK prefix filter_set { >-+ struct network *n; >-+ >-+ if ((n = calloc(1, sizeof(struct network))) == NULL) >-+ fatal("new_network"); >-+ memcpy(&n->net.prefix, &$2.prefix, >-+ sizeof(n->net.prefix)); >-+ n->net.prefixlen = $2.len; >-+ filterset_move($3, &n->net.attrset); >-+ free($3); >-+ >-+ TAILQ_INSERT_TAIL(netconf, n, entry); >-+ } >-+ | NETWORK family nettype filter_set { >-+ struct network *n; >-+ >-+ if ((n = calloc(1, sizeof(struct network))) == NULL) >-+ fatal("new_network"); >-+ if (afi2aid($2, SAFI_UNICAST, &n->net.prefix.aid) == >-+ -1) { >-+ yyerror("unknown family"); >-+ filterset_free($4); >-+ free($4); >-+ YYERROR; >-+ } >-+ n->net.type = $3 ? NETWORK_STATIC : NETWORK_CONNECTED; >-+ filterset_move($4, &n->net.attrset); >-+ free($4); >-+ >-+ TAILQ_INSERT_TAIL(netconf, n, entry); >-+ } >-+ ; >-+ >- inout : IN { $$ = 1; } >- | OUT { $$ = 0; } >- ; >- >-+restricted : RESTRICTED { $$ = 1; } >-+ | /* nothing */ { $$ = 0; } >-+ ; >-+ >- address : STRING { >- u_int8_t len; >- >-@@ -635,11 +664,11 @@ address : STRING { >- } >- free($1); >- >-- if (($$.af == AF_INET && len != 32) || >-- ($$.af == AF_INET6 && len != 128)) { >-+ if (($$.aid == AID_INET && len != 32) || >-+ ($$.aid == AID_INET6 && len != 128)) { >- /* unreachable */ >- yyerror("got prefixlen %u, expected %u", >-- len, $$.af == AF_INET ? 32 : 128); >-+ len, $$.aid == AID_INET ? 32 : 128); >- YYERROR; >- } >- } >-@@ -653,7 +682,7 @@ prefix : STRING '/' NUMBER { >- free($1); >- YYERROR; >- } >-- if (asprintf(&s, "%s/%lld", $1, $3) == -1) >-+ if (asprintf(&s, "%s/%lld", $1, (long long int)$3) == -1) >- fatal(NULL); >- free($1); >- >-@@ -672,7 +701,7 @@ prefix : STRING '/' NUMBER { >- yyerror("bad prefix %lld/%lld", $1, $3); >- YYERROR; >- } >-- if (asprintf(&s, "%lld/%lld", $1, $3) == -1) >-+ if (asprintf(&s, "%lld/%lld", (long long int)$1, (long long int)$3) == -1) >- fatal(NULL); >- >- if (!host(s, &$$.prefix, &$$.len)) { >-@@ -686,7 +715,7 @@ prefix : STRING '/' NUMBER { >- >- addrspec : address { >- memcpy(&$$.prefix, &$1, sizeof(struct bgpd_addr)); >-- if ($$.prefix.af == AF_INET) >-+ if ($$.prefix.aid == AID_INET) >- $$.len = 32; >- else >- $$.len = 128; >-@@ -705,14 +734,150 @@ optnumber : /* empty */ { $$ = 0; } >- | NUMBER >- ; >- >-+rdomain : RDOMAIN NUMBER optnl '{' optnl { >-+ if (ktable_exists($2, NULL) != 1) { >-+ yyerror("rdomain %lld does not exist", $2); >-+ YYERROR; >-+ } >-+ if (!(currdom = calloc(1, sizeof(struct rdomain)))) >-+ fatal(NULL); >-+ currdom->rtableid = $2; >-+ TAILQ_INIT(&currdom->import); >-+ TAILQ_INIT(&currdom->export); >-+ TAILQ_INIT(&currdom->net_l); >-+ netconf = &currdom->net_l; >-+ } >-+ rdomainopts_l '}' { >-+ /* insert into list */ >-+ SIMPLEQ_INSERT_TAIL(rdom_l, currdom, entry); >-+ currdom = NULL; >-+ netconf = gnetconf; >-+ } >-+ >-+rdomainopts_l : rdomainopts_l rdomainoptsl >-+ | rdomainoptsl >-+ ; >-+ >-+rdomainoptsl : rdomainopts nl >-+ ; >-+ >-+rdomainopts : RD STRING { >-+ struct filter_extcommunity ext; >-+ u_int64_t rd; >-+ >-+ if (parseextcommunity(&ext, "rt", $2) == -1) { >-+ free($2); >-+ YYERROR; >-+ } >-+ free($2); >-+ /* >-+ * RD is almost encode like an ext-community, >-+ * but only almost so convert here. >-+ */ >-+ if (community_ext_conv(&ext, 0, &rd)) { >-+ yyerror("bad encoding of rd"); >-+ YYERROR; >-+ } >-+ rd = betoh64(rd) & 0xffffffffffffULL; >-+ switch (ext.type) { >-+ case EXT_COMMUNITY_TWO_AS: >-+ rd |= (0ULL << 48); >-+ break; >-+ case EXT_COMMUNITY_IPV4: >-+ rd |= (1ULL << 48); >-+ break; >-+ case EXT_COMMUNITY_FOUR_AS: >-+ rd |= (2ULL << 48); >-+ break; >-+ default: >-+ yyerror("bad encoding of rd"); >-+ YYERROR; >-+ } >-+ currdom->rd = htobe64(rd); >-+ } >-+ | EXPORTTRGT STRING STRING { >-+ struct filter_set *set; >-+ >-+ if ((set = calloc(1, sizeof(struct filter_set))) == >-+ NULL) >-+ fatal(NULL); >-+ set->type = ACTION_SET_EXT_COMMUNITY; >-+ if (parseextcommunity(&set->action.ext_community, >-+ $2, $3) == -1) { >-+ free($3); >-+ free($2); >-+ free(set); >-+ YYERROR; >-+ } >-+ free($3); >-+ free($2); >-+ TAILQ_INSERT_TAIL(&currdom->export, set, entry); >-+ } >-+ | IMPORTTRGT STRING STRING { >-+ struct filter_set *set; >-+ >-+ if ((set = calloc(1, sizeof(struct filter_set))) == >-+ NULL) >-+ fatal(NULL); >-+ set->type = ACTION_SET_EXT_COMMUNITY; >-+ if (parseextcommunity(&set->action.ext_community, >-+ $2, $3) == -1) { >-+ free($3); >-+ free($2); >-+ free(set); >-+ YYERROR; >-+ } >-+ free($3); >-+ free($2); >-+ TAILQ_INSERT_TAIL(&currdom->import, set, entry); >-+ } >-+ | DESCR string { >-+ if (strlcpy(currdom->descr, $2, >-+ sizeof(currdom->descr)) >= >-+ sizeof(currdom->descr)) { >-+ yyerror("descr \"%s\" too long: max %u", >-+ $2, sizeof(currdom->descr) - 1); >-+ free($2); >-+ YYERROR; >-+ } >-+ free($2); >-+ } >-+ | FIBUPDATE yesno { >-+ if ($2 == 0) >-+ currdom->flags |= F_RIB_NOFIBSYNC; >-+ else >-+ currdom->flags &= ~F_RIB_NOFIBSYNC; >-+ } >-+ | network >-+ | DEPEND ON STRING { >-+ /* XXX this is a hack */ >-+ if (if_nametoindex($3) == 0) { >-+ yyerror("interface %s does not exist", $3); >-+ free($3); >-+ YYERROR; >-+ } >-+ strlcpy(currdom->ifmpe, $3, IFNAMSIZ); >-+ free($3); >-+ if (get_mpe_label(currdom)) { >-+ yyerror("failed to get mpls label from %s", >-+ currdom->ifmpe); >-+ YYERROR; >-+ } >-+ } >-+ ; >-+ >- neighbor : { curpeer = new_peer(); } >- NEIGHBOR addrspec { >- memcpy(&curpeer->conf.remote_addr, &$3.prefix, >- sizeof(curpeer->conf.remote_addr)); >- curpeer->conf.remote_masklen = $3.len; >-- if (($3.prefix.af == AF_INET && $3.len != 32) || >-- ($3.prefix.af == AF_INET6 && $3.len != 128)) >-+ if (($3.prefix.aid == AID_INET && $3.len != 32) || >-+ ($3.prefix.aid == AID_INET6 && $3.len != 128)) >- curpeer->conf.template = 1; >-+ if (curpeer->conf.capabilities.mp[ >-+ curpeer->conf.remote_addr.aid] == -1) >-+ curpeer->conf.capabilities.mp[ >-+ curpeer->conf.remote_addr.aid] = 1; >- if (get_id(curpeer)) { >- yyerror("get_id failed"); >- YYERROR; >-@@ -802,6 +967,17 @@ peeropts : REMOTEAS as4number { >- } >- free($2); >- } >-+ | LLIFACE string { >-+ if (strlcpy(curpeer->conf.lliface, $2, >-+ sizeof(curpeer->conf.lliface)) >= >-+ sizeof(curpeer->conf.lliface)) { >-+ yyerror("lliface \"%s\" too long: max %u", >-+ $2, sizeof(curpeer->conf.lliface) - 1); >-+ free($2); >-+ YYERROR; >-+ } >-+ free($2); >-+ } >- | LOCALADDR address { >- memcpy(&curpeer->conf.local_addr, &$2, >- sizeof(curpeer->conf.local_addr)); >-@@ -852,13 +1028,17 @@ peeropts : REMOTEAS as4number { >- curpeer->conf.min_holdtime = $3; >- } >- | ANNOUNCE family STRING { >-- u_int8_t safi; >-+ u_int8_t aid, safi; >-+ int8_t val = 1; >- >-- if (!strcmp($3, "none")) >-- safi = SAFI_NONE; >-- else if (!strcmp($3, "unicast")) >-+ if (!strcmp($3, "none")) { >- safi = SAFI_UNICAST; >-- else { >-+ val = 0; >-+ } else if (!strcmp($3, "unicast")) { >-+ safi = SAFI_UNICAST; >-+ } else if (!strcmp($3, "vpn")) { >-+ safi = SAFI_MPLSVPN; >-+ } else { >- yyerror("unknown/unsupported SAFI \"%s\"", >- $3); >- free($3); >-@@ -866,25 +1046,31 @@ peeropts : REMOTEAS as4number { >- } >- free($3); >- >-- switch ($2) { >-- case AFI_IPv4: >-- curpeer->conf.capabilities.mp_v4 = safi; >-- break; >-- case AFI_IPv6: >-- curpeer->conf.capabilities.mp_v6 = safi; >-- break; >-- default: >-- fatal("king bula sees borked AFI"); >-+ if (afi2aid($2, safi, &aid) == -1) { >-+ yyerror("unknown AFI/SAFI pair"); >-+ YYERROR; >- } >-+ curpeer->conf.capabilities.mp[aid] = val; >- } >- | ANNOUNCE CAPABILITIES yesno { >- curpeer->conf.announce_capa = $3; >- } >-+ | ANNOUNCE REFRESH yesno { >-+ curpeer->conf.capabilities.refresh = $3; >-+ } >-+ | ANNOUNCE RESTART yesno { >-+ curpeer->conf.capabilities.grestart.restart = $3; >-+ } >-+ | ANNOUNCE AS4BYTE yesno { >-+ curpeer->conf.capabilities.as4byte = $3; >-+ } >- | ANNOUNCE SELF { >- curpeer->conf.announce_type = ANNOUNCE_SELF; >- } >- | ANNOUNCE STRING { >-- if (!strcmp($2, "none")) >-+ if (!strcmp($2, "self")) >-+ curpeer->conf.announce_type = ANNOUNCE_SELF; >-+ else if (!strcmp($2, "none")) >- curpeer->conf.announce_type = ANNOUNCE_NONE; >- else if (!strcmp($2, "all")) >- curpeer->conf.announce_type = ANNOUNCE_ALL; >-@@ -1083,7 +1269,7 @@ peeropts : REMOTEAS as4number { >- curpeer->conf.reflector_client = 1; >- } >- | REFLECTOR address { >-- if ($2.af != AF_INET) { >-+ if ($2.aid != AID_INET) { >- yyerror("route reflector cluster-id must be " >- "an IPv4 address"); >- YYERROR; >-@@ -1157,6 +1343,10 @@ family : IPV4 { $$ = AFI_IPv4; } >- | IPV6 { $$ = AFI_IPv6; } >- ; >- >-+nettype : STATIC { $$ = 1; }, >-+ | CONNECTED { $$ = 0; } >-+ ; >-+ >- espah : ESP { $$ = 1; } >- | AH { $$ = 0; } >- ; >-@@ -1336,12 +1526,12 @@ filter_prefix_l : filter_prefix { $$ >- ; >- >- filter_prefix : prefix { >-- if (fmopts.af && fmopts.af != $1.prefix.af) { >-+ if (fmopts.aid && fmopts.aid != $1.prefix.aid) { >- yyerror("rules with mixed address families " >- "are not allowed"); >- YYERROR; >- } else >-- fmopts.af = $1.prefix.af; >-+ fmopts.aid = $1.prefix.aid; >- if (($$ = calloc(1, sizeof(struct filter_prefix_l))) == >- NULL) >- fatal(NULL); >-@@ -1410,6 +1600,12 @@ filter_as : as4number { >- fatal(NULL); >- $$->a.as = $1; >- } >-+ | NEIGHBORAS { >-+ if (($$ = calloc(1, sizeof(struct filter_as_l))) == >-+ NULL) >-+ fatal(NULL); >-+ $$->a.flags = AS_FLAG_NEIGHBORAS; >-+ } >- ; >- >- filter_match_h : /* empty */ { >-@@ -1437,18 +1633,18 @@ filter_elm : filter_prefix_h { >- fmopts.prefix_l = $1; >- } >- | PREFIXLEN prefixlenop { >-- if (fmopts.af == 0) { >-+ if (fmopts.aid == 0) { >- yyerror("address family needs to be specified " >- "before \"prefixlen\""); >- YYERROR; >- } >-- if (fmopts.m.prefixlen.af) { >-+ if (fmopts.m.prefixlen.aid) { >- yyerror("\"prefixlen\" already specified"); >- YYERROR; >- } >- memcpy(&fmopts.m.prefixlen, &$2, >- sizeof(fmopts.m.prefixlen)); >-- fmopts.m.prefixlen.af = fmopts.af; >-+ fmopts.m.prefixlen.aid = fmopts.aid; >- } >- | filter_as_h { >- if (fmopts.as_l != NULL) { >-@@ -1457,32 +1653,93 @@ filter_elm : filter_prefix_h { >- } >- fmopts.as_l = $1; >- } >-+ | MAXASLEN NUMBER { >-+ if (fmopts.m.aslen.type != ASLEN_NONE) { >-+ yyerror("AS length filters already specified"); >-+ YYERROR; >-+ } >-+ if ($2 < 0 || $2 > UINT_MAX) { >-+ yyerror("bad max-as-len %lld", $2); >-+ YYERROR; >-+ } >-+ fmopts.m.aslen.type = ASLEN_MAX; >-+ fmopts.m.aslen.aslen = $2; >-+ } >-+ | MAXASSEQ NUMBER { >-+ if (fmopts.m.aslen.type != ASLEN_NONE) { >-+ yyerror("AS length filters already specified"); >-+ YYERROR; >-+ } >-+ if ($2 < 0 || $2 > UINT_MAX) { >-+ yyerror("bad max-as-seq %lld", $2); >-+ YYERROR; >-+ } >-+ fmopts.m.aslen.type = ASLEN_SEQ; >-+ fmopts.m.aslen.aslen = $2; >-+ } >- | COMMUNITY STRING { >- if (fmopts.m.community.as != COMMUNITY_UNSET) { >- yyerror("\"community\" already specified"); >- free($2); >- YYERROR; >- } >-- if (parsecommunity($2, &fmopts.m.community.as, >-- &fmopts.m.community.type) == -1) { >-+ if (parsecommunity(&fmopts.m.community, $2) == -1) { >- free($2); >- YYERROR; >- } >- free($2); >- } >-+ | EXTCOMMUNITY STRING STRING { >-+ if (fmopts.m.ext_community.flags & >-+ EXT_COMMUNITY_FLAG_VALID) { >-+ yyerror("\"ext-community\" already specified"); >-+ free($2); >-+ free($3); >-+ YYERROR; >-+ } >-+ >-+ if (parseextcommunity(&fmopts.m.ext_community, >-+ $2, $3) == -1) { >-+ free($2); >-+ free($3); >-+ YYERROR; >-+ } >-+ free($2); >-+ free($3); >-+ } >- | IPV4 { >-- if (fmopts.af) { >-+ if (fmopts.aid) { >- yyerror("address family already specified"); >- YYERROR; >- } >-- fmopts.af = AF_INET; >-+ fmopts.aid = AID_INET; >- } >- | IPV6 { >-- if (fmopts.af) { >-+ if (fmopts.aid) { >- yyerror("address family already specified"); >- YYERROR; >- } >-- fmopts.af = AF_INET6; >-+ fmopts.aid = AID_INET6; >-+ } >-+ | NEXTHOP address { >-+ if (fmopts.m.nexthop.flags) { >-+ yyerror("nexthop already specified"); >-+ YYERROR; >-+ } >-+ if (fmopts.aid && fmopts.aid != $2.aid) { >-+ yyerror("nexthop address family doesn't match " >-+ "rule address family"); >-+ YYERROR; >-+ } >-+ fmopts.m.nexthop.addr = $2; >-+ fmopts.m.nexthop.flags = FILTER_NEXTHOP_ADDR; >-+ } >-+ | NEXTHOP NEIGHBOR { >-+ if (fmopts.m.nexthop.flags) { >-+ yyerror("nexthop already specified"); >-+ YYERROR; >-+ } >-+ fmopts.m.nexthop.flags = FILTER_NEXTHOP_NEIGHBOR; >- } >- ; >- >-@@ -1588,7 +1845,7 @@ filter_set_opt : LOCALPREF NUMBER { >- } >- if (($$ = calloc(1, sizeof(struct filter_set))) == NULL) >- fatal(NULL); >-- if ($2 > 0) { >-+ if ($2 >= 0) { >- $$->type = ACTION_SET_MED; >- $$->action.metric = $2; >- } else { >-@@ -1623,7 +1880,7 @@ filter_set_opt : LOCALPREF NUMBER { >- } >- if (($$ = calloc(1, sizeof(struct filter_set))) == NULL) >- fatal(NULL); >-- if ($2 > 0) { >-+ if ($2 >= 0) { >- $$->type = ACTION_SET_MED; >- $$->action.metric = $2; >- } else { >-@@ -1782,8 +2039,7 @@ filter_set_opt : LOCALPREF NUMBER { >- else >- $$->type = ACTION_SET_COMMUNITY; >- >-- if (parsecommunity($3, &$$->action.community.as, >-- &$$->action.community.type) == -1) { >-+ if (parsecommunity(&$$->action.community, $3) == -1) { >- free($3); >- free($$); >- YYERROR; >-@@ -1796,40 +2052,62 @@ filter_set_opt : LOCALPREF NUMBER { >- free($$); >- YYERROR; >- } >-- /* Don't allow setting of unknown well-known types */ >-- if ($$->action.community.as == COMMUNITY_WELLKNOWN) { >-- switch ($$->action.community.type) { >-- case COMMUNITY_NO_EXPORT: >-- case COMMUNITY_NO_ADVERTISE: >-- case COMMUNITY_NO_EXPSUBCONFED: >-- case COMMUNITY_NO_PEER: >-- /* valid */ >-- break; >-- default: >-- /* unknown */ >-- yyerror("Invalid well-known community"); >-- free($$); >-- YYERROR; >-- break; >-- } >-+ } >-+ | EXTCOMMUNITY delete STRING STRING { >-+ if (($$ = calloc(1, sizeof(struct filter_set))) == NULL) >-+ fatal(NULL); >-+ if ($2) >-+ $$->type = ACTION_DEL_EXT_COMMUNITY; >-+ else >-+ $$->type = ACTION_SET_EXT_COMMUNITY; >-+ >-+ if (parseextcommunity(&$$->action.ext_community, >-+ $3, $4) == -1) { >-+ free($3); >-+ free($4); >-+ free($$); >-+ YYERROR; >- } >-+ free($3); >-+ free($4); >-+ } >-+ | ORIGIN origincode { >-+ if (($$ = calloc(1, sizeof(struct filter_set))) == NULL) >-+ fatal(NULL); >-+ $$->type = ACTION_SET_ORIGIN; >-+ $$->action.origin = $2; >- } >- ; >- >-+origincode : string { >-+ if (!strcmp($1, "egp")) >-+ $$ = ORIGIN_EGP; >-+ else if (!strcmp($1, "igp")) >-+ $$ = ORIGIN_IGP; >-+ else if (!strcmp($1, "incomplete")) >-+ $$ = ORIGIN_INCOMPLETE; >-+ else { >-+ yyerror("unknown origin \"%s\"", $1); >-+ free($1); >-+ YYERROR; >-+ } >-+ free($1); >-+ }; >-+ >- comma : "," >- | /* empty */ >- ; >- >- unaryop : '=' { $$ = OP_EQ; } >-- | '!' '=' { $$ = OP_NE; } >-- | '<' '=' { $$ = OP_LE; } >-+ | NE { $$ = OP_NE; } >-+ | LE { $$ = OP_LE; } >- | '<' { $$ = OP_LT; } >-- | '>' '=' { $$ = OP_GE; } >-+ | GE { $$ = OP_GE; } >- | '>' { $$ = OP_GT; } >- ; >- >- binaryop : '-' { $$ = OP_RANGE; } >-- | '>' '<' { $$ = OP_XRANGE; } >-+ | XRANGE { $$ = OP_XRANGE; } >- ; >- >- %% >-@@ -1873,6 +2151,7 @@ lookup(char *s) >- { "allow", ALLOW}, >- { "announce", ANNOUNCE}, >- { "any", ANY}, >-+ { "as-4byte", AS4BYTE }, >- { "blackhole", BLACKHOLE}, >- { "capabilities", CAPABILITIES}, >- { "community", COMMUNITY}, >-@@ -1889,16 +2168,22 @@ lookup(char *s) >- { "enforce", ENFORCE}, >- { "esp", ESP}, >- { "evaluate", EVALUATE}, >-+ { "export-target", EXPORTTRGT}, >-+ { "ext-community", EXTCOMMUNITY}, >- { "fib-update", FIBUPDATE}, >- { "from", FROM}, >- { "group", GROUP}, >- { "holdtime", HOLDTIME}, >- { "ignore", IGNORE}, >- { "ike", IKE}, >-+ { "import-target", IMPORTTRGT}, >- { "in", IN}, >- { "include", INCLUDE}, >- { "inet", IPV4}, >- { "inet6", IPV6}, >-+#if defined(IPV6_LINKLOCAL_PEER) >-+ { "interface", LLIFACE}, >-+#endif >- { "ipsec", IPSEC}, >- { "key", KEY}, >- { "listen", LISTEN}, >-@@ -1906,6 +2191,8 @@ lookup(char *s) >- { "localpref", LOCALPREF}, >- { "log", LOG}, >- { "match", MATCH}, >-+ { "max-as-len", MAXASLEN}, >-+ { "max-as-seq", MAXASSEQ}, >- { "max-prefix", MAXPREFIX}, >- { "md5sig", MD5SIG}, >- { "med", MED}, >-@@ -1918,6 +2205,7 @@ lookup(char *s) >- { "nexthop", NEXTHOP}, >- { "no-modify", NOMODIFY}, >- { "on", ON}, >-+ { "origin", ORIGIN}, >- { "out", OUT}, >- { "passive", PASSIVE}, >- { "password", PASSWORD}, >-@@ -1929,10 +2217,14 @@ lookup(char *s) >- { "prepend-self", PREPEND_SELF}, >- { "qualify", QUALIFY}, >- { "quick", QUICK}, >-+ { "rd", RD}, >- { "rde", RDE}, >-+ { "rdomain", RDOMAIN}, >-+ { "refresh", REFRESH }, >- { "reject", REJECT}, >- { "remote-as", REMOTEAS}, >- { "restart", RESTART}, >-+ { "restricted", RESTRICTED}, >- { "rib", RIB}, >- { "route-collector", ROUTECOLL}, >- { "route-reflector", REFLECTOR}, >-@@ -1941,6 +2233,7 @@ lookup(char *s) >- { "rtlabel", RTLABEL}, >- { "self", SELF}, >- { "set", SET}, >-+ { "socket", SOCKET }, >- { "softreconfig", SOFTRECONFIG}, >- { "source-as", SOURCEAS}, >- { "spi", SPI}, >-@@ -2117,9 +2410,10 @@ top: >- return (0); >- if (next == quotec || c == ' ' || c == '\t') >- c = next; >-- else if (next == '\n') >-+ else if (next == '\n') { >-+ file->lineno++; >- continue; >-- else >-+ } else >- lungetc(next); >- } else if (c == quotec) { >- *p = '\0'; >-@@ -2135,6 +2429,26 @@ top: >- if (yylval.v.string == NULL) >- fatal("yylex: strdup"); >- return (STRING); >-+ case '!': >-+ next = lgetc(0); >-+ if (next == '=') >-+ return (NE); >-+ lungetc(next); >-+ break; >-+ case '<': >-+ next = lgetc(0); >-+ if (next == '=') >-+ return (LE); >-+ lungetc(next); >-+ break; >-+ case '>': >-+ next = lgetc(0); >-+ if (next == '<') >-+ return (XRANGE); >-+ else if (next == '=') >-+ return (GE); >-+ lungetc(next); >-+ break; >- } >- >- #define allowed_to_end_number(x) \ >-@@ -2274,18 +2588,21 @@ popfile(void) >- int >- parse_config(char *filename, struct bgpd_config *xconf, >- struct mrt_head *xmconf, struct peer **xpeers, struct network_head *nc, >-- struct filter_head *xfilter_l) >-+ struct filter_head *xfilter_l, struct rdomain_head *xrdom_l) >- { >- struct sym *sym, *next; >- struct peer *p, *pnext; >- struct listen_addr *la; >- struct network *n; >- struct filter_rule *r; >-+ struct rde_rib *rr; >-+ struct rdomain *rd; >- int errors = 0; >- >- if ((conf = calloc(1, sizeof(struct bgpd_config))) == NULL) >- fatal(NULL); >- conf->opts = xconf->opts; >-+ conf->csock = strdup(SOCKET_NAME); >- >- if ((file = pushfile(filename, 1)) == NULL) { >- free(conf); >-@@ -2316,13 +2633,15 @@ parse_config(char *filename, struct bgpd >- id = 1; >- >- /* network list is always empty in the parent */ >-- netconf = nc; >-+ gnetconf = netconf = nc; >- TAILQ_INIT(netconf); >- /* init the empty filter list for later */ >- TAILQ_INIT(xfilter_l); >-+ SIMPLEQ_INIT(xrdom_l); >-+ rdom_l = xrdom_l; >- >-- add_rib("Adj-RIB-In", F_RIB_NOEVALUATE); >-- add_rib("Loc-RIB", 0); >-+ add_rib("Adj-RIB-In", 0, F_RIB_NOFIB | F_RIB_NOEVALUATE); >-+ add_rib("Loc-RIB", 0, 0); >- >- yyparse(); >- errors = file->errors; >-@@ -2344,6 +2663,9 @@ parse_config(char *filename, struct bgpd >- >- if (errors) { >- /* XXX more leaks in this case */ >-+ free(conf->csock); >-+ free(conf->rcsock); >-+ >- while ((la = TAILQ_FIRST(listen_addrs)) != NULL) { >- TAILQ_REMOVE(listen_addrs, la, entry); >- free(la); >-@@ -2357,23 +2679,44 @@ parse_config(char *filename, struct bgpd >- >- while ((n = TAILQ_FIRST(netconf)) != NULL) { >- TAILQ_REMOVE(netconf, n, entry); >-+ filterset_free(&n->net.attrset); >- free(n); >- } >- >- while ((r = TAILQ_FIRST(filter_l)) != NULL) { >- TAILQ_REMOVE(filter_l, r, entry); >-+ filterset_free(&r->set); >- free(r); >- } >- >- while ((r = TAILQ_FIRST(peerfilter_l)) != NULL) { >- TAILQ_REMOVE(peerfilter_l, r, entry); >-+ filterset_free(&r->set); >- free(r); >- } >- >- while ((r = TAILQ_FIRST(groupfilter_l)) != NULL) { >- TAILQ_REMOVE(groupfilter_l, r, entry); >-+ filterset_free(&r->set); >- free(r); >- } >-+ while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) { >-+ SIMPLEQ_REMOVE_HEAD(&ribnames, entry); >-+ free(rr); >-+ } >-+ while ((rd = SIMPLEQ_FIRST(rdom_l)) != NULL) { >-+ SIMPLEQ_REMOVE_HEAD(rdom_l, entry); >-+ filterset_free(&rd->export); >-+ filterset_free(&rd->import); >-+ >-+ while ((n = TAILQ_FIRST(&rd->net_l)) != NULL) { >-+ TAILQ_REMOVE(&rd->net_l, n, entry); >-+ filterset_free(&n->net.attrset); >-+ free(n); >-+ } >-+ >-+ free(rd); >-+ } >- } else { >- errors += merge_config(xconf, conf, peer_l, listen_addrs); >- errors += mrt_mergeconfig(xmconf, mrtconf); >-@@ -2505,27 +2848,27 @@ getcommunity(char *s) >- } >- >- int >--parsecommunity(char *s, int *as, int *type) >-+parsecommunity(struct filter_community *c, char *s) >- { >- char *p; >-- int i; >-+ int i, as; >- >- /* Well-known communities */ >- if (strcasecmp(s, "NO_EXPORT") == 0) { >-- *as = COMMUNITY_WELLKNOWN; >-- *type = COMMUNITY_NO_EXPORT; >-+ c->as = COMMUNITY_WELLKNOWN; >-+ c->type = COMMUNITY_NO_EXPORT; >- return (0); >- } else if (strcasecmp(s, "NO_ADVERTISE") == 0) { >-- *as = COMMUNITY_WELLKNOWN; >-- *type = COMMUNITY_NO_ADVERTISE; >-+ c->as = COMMUNITY_WELLKNOWN; >-+ c->type = COMMUNITY_NO_ADVERTISE; >- return (0); >- } else if (strcasecmp(s, "NO_EXPORT_SUBCONFED") == 0) { >-- *as = COMMUNITY_WELLKNOWN; >-- *type = COMMUNITY_NO_EXPSUBCONFED; >-+ c->as = COMMUNITY_WELLKNOWN; >-+ c->type = COMMUNITY_NO_EXPSUBCONFED; >- return (0); >- } else if (strcasecmp(s, "NO_PEER") == 0) { >-- *as = COMMUNITY_WELLKNOWN; >-- *type = COMMUNITY_NO_PEER; >-+ c->as = COMMUNITY_WELLKNOWN; >-+ c->type = COMMUNITY_NO_PEER; >- return (0); >- } >- >-@@ -2537,23 +2880,176 @@ parsecommunity(char *s, int *as, int *ty >- >- if ((i = getcommunity(s)) == COMMUNITY_ERROR) >- return (-1); >-- if (i == USHRT_MAX) { >-+ if (i == COMMUNITY_WELLKNOWN) { >- yyerror("Bad community AS number"); >- return (-1); >- } >-- *as = i; >-+ as = i; >- >- if ((i = getcommunity(p)) == COMMUNITY_ERROR) >- return (-1); >-- *type = i; >-+ c->as = as; >-+ c->type = i; >- >- return (0); >- } >- >-+int >-+parsesubtype(char *type) >-+{ >-+ /* this has to be sorted always */ >-+ static const struct keywords keywords[] = { >-+ { "bdc", EXT_COMMUNITY_BGP_COLLECT }, >-+ { "odi", EXT_COMMUNITY_OSPF_DOM_ID }, >-+ { "ori", EXT_COMMUNITY_OSPF_RTR_ID }, >-+ { "ort", EXT_COMMUNITY_OSPF_RTR_TYPE }, >-+ { "rt", EXT_COMMUNITY_ROUTE_TGT }, >-+ { "soo", EXT_CUMMUNITY_ROUTE_ORIG } >-+ }; >-+ const struct keywords *p; >-+ >-+ p = bsearch(type, keywords, sizeof(keywords)/sizeof(keywords[0]), >-+ sizeof(keywords[0]), kw_cmp); >-+ >-+ if (p) >-+ return (p->k_val); >-+ else >-+ return (-1); >-+} >-+ >-+int >-+parseextvalue(char *s, u_int32_t *v) >-+{ >-+ const char *errstr; >-+ char *p; >-+ struct in_addr ip; >-+ u_int32_t uvalh = 0, uval; >-+ >-+ if ((p = strchr(s, '.')) == NULL) { >-+ /* AS_PLAIN number (4 or 2 byte) */ >-+ uval = strtonum(s, 0, UINT_MAX, &errstr); >-+ if (errstr) { >-+ yyerror("Bad ext-community %s is %s", s, errstr); >-+ return (-1); >-+ } >-+ *v = uval; >-+ if (uval > USHRT_MAX) >-+ return (EXT_COMMUNITY_FOUR_AS); >-+ else >-+ return (EXT_COMMUNITY_TWO_AS); >-+ } else if (strchr(p + 1, '.') == NULL) { >-+ /* AS_DOT number (4-byte) */ >-+ *p++ = '\0'; >-+ uvalh = strtonum(s, 0, USHRT_MAX, &errstr); >-+ if (errstr) { >-+ yyerror("Bad ext-community %s is %s", s, errstr); >-+ return (-1); >-+ } >-+ uval = strtonum(p, 0, USHRT_MAX, &errstr); >-+ if (errstr) { >-+ yyerror("Bad ext-community %s is %s", p, errstr); >-+ return (-1); >-+ } >-+ *v = uval | (uvalh << 16); >-+ return (EXT_COMMUNITY_FOUR_AS); >-+ } else { >-+ /* more then one dot -> IP address */ >-+ if (inet_aton(s, &ip) == 0) { >-+ yyerror("Bad ext-community %s not parseable", s); >-+ return (-1); >-+ } >-+ *v = ip.s_addr; >-+ return (EXT_COMMUNITY_IPV4); >-+ } >-+ return (-1); >-+} >-+ >-+int >-+parseextcommunity(struct filter_extcommunity *c, char *t, char *s) >-+{ >-+ const struct ext_comm_pairs iana[] = IANA_EXT_COMMUNITIES; >-+ const char *errstr; >-+ u_int64_t ullval = 0; >-+ u_int32_t uval; >-+ char *p, *ep; >-+ unsigned int i; >-+ int type, subtype; >-+ >-+ if ((subtype = parsesubtype(t)) == -1) { >-+ yyerror("Bad ext-community unknown type"); >-+ return (-1); >-+ } >-+ >-+ if ((p = strchr(s, ':')) == NULL) { >-+ type = EXT_COMMUNITY_OPAQUE, >-+ errno = 0; >-+ ullval = strtoull(s, &ep, 0); >-+ if (s[0] == '\0' || *ep != '\0') { >-+ yyerror("Bad ext-community bad value"); >-+ return (-1); >-+ } >-+ if (errno == ERANGE && ullval > EXT_COMMUNITY_OPAQUE_MAX) { >-+ yyerror("Bad ext-community value to big"); >-+ return (-1); >-+ } >-+ c->data.ext_opaq = ullval; >-+ } else { >-+ *p++ = '\0'; >-+ if ((type = parseextvalue(s, &uval)) == -1) >-+ return (-1); >-+ switch (type) { >-+ case EXT_COMMUNITY_TWO_AS: >-+ ullval = strtonum(p, 0, UINT_MAX, &errstr); >-+ break; >-+ case EXT_COMMUNITY_IPV4: >-+ case EXT_COMMUNITY_FOUR_AS: >-+ ullval = strtonum(p, 0, USHRT_MAX, &errstr); >-+ break; >-+ default: >-+ fatalx("parseextcommunity: unexpected result"); >-+ } >-+ if (errstr) { >-+ yyerror("Bad ext-community %s is %s", p, >-+ errstr); >-+ return (-1); >-+ } >-+ switch (type) { >-+ case EXT_COMMUNITY_TWO_AS: >-+ c->data.ext_as.as = uval; >-+ c->data.ext_as.val = ullval; >-+ break; >-+ case EXT_COMMUNITY_IPV4: >-+ c->data.ext_ip.addr.s_addr = uval; >-+ c->data.ext_ip.val = ullval; >-+ break; >-+ case EXT_COMMUNITY_FOUR_AS: >-+ c->data.ext_as4.as4 = uval; >-+ c->data.ext_as4.val = ullval; >-+ break; >-+ } >-+ } >-+ c->type = type; >-+ c->subtype = subtype; >-+ >-+ /* verify type/subtype combo */ >-+ for (i = 0; i < sizeof(iana)/sizeof(iana[0]); i++) { >-+ if (iana[i].type == type && iana[i].subtype == subtype) { >-+ if (iana[i].transitive) >-+ c->type |= EXT_COMMUNITY_TRANSITIVE; >-+ c->flags |= EXT_COMMUNITY_FLAG_VALID; >-+ return (0); >-+ } >-+ } >-+ >-+ yyerror("Bad ext-community bad format for type"); >-+ return (-1); >-+} >-+ >- struct peer * >- alloc_peer(void) >- { >- struct peer *p; >-+ u_int8_t i; >- >- if ((p = calloc(1, sizeof(struct peer))) == NULL) >- fatal("new_peer"); >-@@ -2564,11 +3060,11 @@ alloc_peer(void) >- p->conf.distance = 1; >- p->conf.announce_type = ANNOUNCE_UNDEF; >- p->conf.announce_capa = 1; >-- p->conf.capabilities.mp_v4 = SAFI_UNICAST; >-- p->conf.capabilities.mp_v6 = SAFI_NONE; >-+ for (i = 0; i < AID_MAX; i++) >-+ p->conf.capabilities.mp[i] = -1; >- p->conf.capabilities.refresh = 1; >-- p->conf.capabilities.restart = 0; >-- p->conf.capabilities.as4byte = 0; >-+ p->conf.capabilities.grestart.restart = 1; >-+ p->conf.capabilities.as4byte = 1; >- p->conf.local_as = conf->as; >- p->conf.local_short_as = conf->short_as; >- p->conf.softreconfig_in = 1; >-@@ -2592,6 +3088,9 @@ new_peer(void) >- if (strlcpy(p->conf.descr, curgroup->conf.descr, >- sizeof(p->conf.descr)) >= sizeof(p->conf.descr)) >- fatalx("new_peer descr strlcpy"); >-+ if (strlcpy(p->conf.lliface, curgroup->conf.lliface, >-+ sizeof(p->conf.lliface)) >= sizeof(p->conf.lliface)) >-+ fatalx("new_peer lliface strlcpy"); >- p->conf.groupid = curgroup->conf.id; >- p->conf.local_as = curgroup->conf.local_as; >- p->conf.local_short_as = curgroup->conf.local_short_as; >-@@ -2674,39 +3173,52 @@ add_mrtconfig(enum mrt_type type, char * >- } >- >- int >--add_rib(char *name, u_int16_t flags) >-+add_rib(char *name, u_int rtableid, u_int16_t flags) >- { >- struct rde_rib *rr; >-+ u_int rdom; >- >-- if (find_rib(name)) { >-- yyerror("rib \"%s\" allready exists.", name); >-- return (-1); >-- } >-- >-- if ((rr = calloc(1, sizeof(*rr))) == NULL) { >-- log_warn("add_rib"); >-- return (-1); >-+ if ((rr = find_rib(name)) == NULL) { >-+ if ((rr = calloc(1, sizeof(*rr))) == NULL) { >-+ log_warn("add_rib"); >-+ return (-1); >-+ } >- } >- if (strlcpy(rr->name, name, sizeof(rr->name)) >= sizeof(rr->name)) { >- yyerror("rib name \"%s\" too long: max %u", >- name, sizeof(rr->name) - 1); >-+ free(rr); >- return (-1); >- } >- rr->flags |= flags; >-+ if ((rr->flags & F_RIB_HASNOFIB) == 0) { >-+ if (ktable_exists(rtableid, &rdom) != 1) { >-+ yyerror("rtable id %lld does not exist", rtableid); >-+ free(rr); >-+ return (-1); >-+ } >-+ if (rdom != 0) { >-+ yyerror("rtable %lld does not belong to rdomain 0", >-+ rtableid); >-+ free(rr); >-+ return (-1); >-+ } >-+ rr->rtableid = rtableid; >-+ } >- SIMPLEQ_INSERT_TAIL(&ribnames, rr, entry); >- return (0); >- } >- >--int >-+struct rde_rib * >- find_rib(char *name) >- { >- struct rde_rib *rr; >- >- SIMPLEQ_FOREACH(rr, &ribnames, entry) { >- if (!strcmp(rr->name, name)) >-- return (1); >-+ return (rr); >- } >-- return (0); >-+ return (NULL); >- } >- >- int >-@@ -2715,7 +3227,7 @@ get_id(struct peer *newpeer) >- struct peer *p; >- >- for (p = peer_l_old; p != NULL; p = p->next) >-- if (newpeer->conf.remote_addr.af) { >-+ if (newpeer->conf.remote_addr.aid) { >- if (!memcmp(&p->conf.remote_addr, >- &newpeer->conf.remote_addr, >- sizeof(p->conf.remote_addr))) { >-@@ -2856,9 +3368,11 @@ str2key(char *s, char *dest, size_t max_ >- int >- neighbor_consistent(struct peer *p) >- { >-+ u_int8_t i; >-+ >- /* local-address and peer's address: same address family */ >-- if (p->conf.local_addr.af && >-- p->conf.local_addr.af != p->conf.remote_addr.af) { >-+ if (p->conf.local_addr.aid && >-+ p->conf.local_addr.aid != p->conf.remote_addr.aid) { >- yyerror("local-address and neighbor address " >- "must be of the same address family"); >- return (-1); >-@@ -2869,7 +3383,7 @@ neighbor_consistent(struct peer *p) >- p->conf.auth.method == AUTH_IPSEC_IKE_AH || >- p->conf.auth.method == AUTH_IPSEC_MANUAL_ESP || >- p->conf.auth.method == AUTH_IPSEC_MANUAL_AH) && >-- !p->conf.local_addr.af) { >-+ !p->conf.local_addr.aid) { >- yyerror("neighbors with any form of IPsec configured " >- "need local-address to be specified"); >- return (-1); >-@@ -2889,18 +3403,14 @@ neighbor_consistent(struct peer *p) >- return (-1); >- } >- >-- /* for testing: enable 4-byte AS number capability if necessary */ >-- if (conf->as > USHRT_MAX || p->conf.remote_as > USHRT_MAX) >-- p->conf.capabilities.as4byte = 1; >-- >- /* set default values if they where undefined */ >- p->conf.ebgp = (p->conf.remote_as != conf->as); >- if (p->conf.announce_type == ANNOUNCE_UNDEF) >-- p->conf.announce_type = p->conf.ebgp == 0 ? >-- ANNOUNCE_ALL : ANNOUNCE_SELF; >-+ p->conf.announce_type = p->conf.ebgp ? >-+ ANNOUNCE_SELF : ANNOUNCE_ALL; >- if (p->conf.enforce_as == ENFORCE_AS_UNDEF) >-- p->conf.enforce_as = p->conf.ebgp == 0 ? >-- ENFORCE_AS_OFF : ENFORCE_AS_ON; >-+ p->conf.enforce_as = p->conf.ebgp ? >-+ ENFORCE_AS_ON : ENFORCE_AS_OFF; >- >- /* EBGP neighbors are not allowed in route reflector clusters */ >- if (p->conf.reflector_client && p->conf.ebgp) { >-@@ -2909,6 +3419,11 @@ neighbor_consistent(struct peer *p) >- return (-1); >- } >- >-+ /* the default MP capability is NONE */ >-+ for (i = 0; i < AID_MAX; i++) >-+ if (p->conf.capabilities.mp[i] == -1) >-+ p->conf.capabilities.mp[i] = 0; >-+ >- return (0); >- } >- >-@@ -2927,6 +3442,11 @@ merge_filterset(struct filter_set_head * >- yyerror("community is already set"); >- else if (s->type == ACTION_DEL_COMMUNITY) >- yyerror("community will already be deleted"); >-+ else if (s->type == ACTION_SET_EXT_COMMUNITY) >-+ yyerror("ext-community is already set"); >-+ else if (s->type == ACTION_DEL_EXT_COMMUNITY) >-+ yyerror( >-+ "ext-community will already be deleted"); >- else >- yyerror("redefining set parameter %s", >- filterset_name(s->type)); >-@@ -2953,9 +3473,18 @@ merge_filterset(struct filter_set_head * >- return (0); >- } >- break; >-+ case ACTION_SET_EXT_COMMUNITY: >-+ case ACTION_DEL_EXT_COMMUNITY: >-+ if (memcmp(&s->action.ext_community, >-+ &t->action.ext_community, >-+ sizeof(s->action.ext_community)) < 0) { >-+ TAILQ_INSERT_BEFORE(t, s, entry); >-+ return (0); >-+ } >-+ break; >- case ACTION_SET_NEXTHOP: >-- if (s->action.nexthop.af < >-- t->action.nexthop.af) { >-+ if (s->action.nexthop.aid < >-+ t->action.nexthop.aid) { >- TAILQ_INSERT_BEFORE(t, s, entry); >- return (0); >- } >-@@ -2985,22 +3514,6 @@ copy_filterset(struct filter_set_head *s >- } >- } >- >--void >--move_filterset(struct filter_set_head *source, struct filter_set_head *dest) >--{ >-- struct filter_set *s; >-- >-- TAILQ_INIT(dest); >-- >-- if (source == NULL) >-- return; >-- >-- while ((s = TAILQ_FIRST(source)) != NULL) { >-- TAILQ_REMOVE(source, s, entry); >-- TAILQ_INSERT_TAIL(dest, s, entry); >-- } >--} >-- >- struct filter_rule * >- get_rule(enum action_types type) >- { > >Property changes on: files/patch-bgpd_parse.y >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_pfkey.c >=================================================================== >--- files/patch-bgpd_pfkey.c (revision 500577) >+++ files/patch-bgpd_pfkey.c (nonexistent) >@@ -1,471 +0,0 @@ >-diff -ur bgpd.orig/pfkey.c bgpd/pfkey.c >---- bgpd.orig/pfkey.c 2013-03-15 12:07:16.000000000 +0000 >-+++ bgpd/pfkey.c 2013-03-15 12:07:47.000000000 +0000 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: pfkey.c,v 1.37 2009/04/21 15:25:52 henning Exp $ */ >-+/* $OpenBSD: pfkey.c,v 1.40 2009/12/14 17:38:18 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-@@ -21,7 +21,7 @@ >- #include <sys/socket.h> >- #include <sys/uio.h> >- #include <net/pfkeyv2.h> >--#include <netinet/ip_ipsp.h> >-+//#include <netinet/ip_ipsp.h> >- #include <ctype.h> >- #include <errno.h> >- #include <limits.h> >-@@ -65,15 +65,15 @@ >- { >- struct sadb_msg smsg; >- struct sadb_sa sa; >-- struct sadb_address sa_src, sa_dst, sa_peer, sa_smask, sa_dmask; >-+ struct sadb_address sa_src, sa_dst; >- struct sadb_key sa_akey, sa_ekey; >- struct sadb_spirange sa_spirange; >-- struct sadb_protocol sa_flowtype, sa_protocol; >- struct iovec iov[IOV_CNT]; >- ssize_t n; >- int len = 0; >- int iov_cnt; >-- struct sockaddr_storage ssrc, sdst, speer, smask, dmask; >-+ struct sockaddr_storage ssrc, sdst, smask, dmask; >-+ struct sockaddr *saptr; >- >- if (!pid) >- pid = getpid(); >-@@ -81,22 +81,17 @@ >- /* we need clean sockaddr... no ports set */ >- bzero(&ssrc, sizeof(ssrc)); >- bzero(&smask, sizeof(smask)); >-- switch (src->af) { >-- case AF_INET: >-- ((struct sockaddr_in *)&ssrc)->sin_addr = src->v4; >-- ssrc.ss_len = sizeof(struct sockaddr_in); >-- ssrc.ss_family = AF_INET; >-+ if ((saptr = addr2sa(src, 0))) >-+ memcpy(&ssrc, saptr, sizeof(ssrc)); >-+ switch (src->aid) { >-+ case AID_INET: >- memset(&((struct sockaddr_in *)&smask)->sin_addr, 0xff, 32/8); >- break; >-- case AF_INET6: >-- memcpy(&((struct sockaddr_in6 *)&ssrc)->sin6_addr, >-- &src->v6, sizeof(struct in6_addr)); >-- ssrc.ss_len = sizeof(struct sockaddr_in6); >-- ssrc.ss_family = AF_INET6; >-+ case AID_INET6: >- memset(&((struct sockaddr_in6 *)&smask)->sin6_addr, 0xff, >- 128/8); >- break; >-- case 0: >-+ case AID_UNSPEC: >- ssrc.ss_len = sizeof(struct sockaddr); >- break; >- default: >-@@ -107,22 +102,17 @@ >- >- bzero(&sdst, sizeof(sdst)); >- bzero(&dmask, sizeof(dmask)); >-- switch (dst->af) { >-- case AF_INET: >-- ((struct sockaddr_in *)&sdst)->sin_addr = dst->v4; >-- sdst.ss_len = sizeof(struct sockaddr_in); >-- sdst.ss_family = AF_INET; >-+ if ((saptr = addr2sa(dst, 0))) >-+ memcpy(&sdst, saptr, sizeof(sdst)); >-+ switch (dst->aid) { >-+ case AID_INET: >- memset(&((struct sockaddr_in *)&dmask)->sin_addr, 0xff, 32/8); >- break; >-- case AF_INET6: >-- memcpy(&((struct sockaddr_in6 *)&sdst)->sin6_addr, >-- &dst->v6, sizeof(struct in6_addr)); >-- sdst.ss_len = sizeof(struct sockaddr_in6); >-- sdst.ss_family = AF_INET6; >-+ case AID_INET6: >- memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr, 0xff, >- 128/8); >- break; >-- case 0: >-+ case AID_UNSPEC: >- sdst.ss_len = sizeof(struct sockaddr); >- break; >- default: >-@@ -135,7 +125,7 @@ >- smsg.sadb_msg_version = PF_KEY_V2; >- smsg.sadb_msg_seq = ++sadb_msg_seq; >- smsg.sadb_msg_pid = pid; >-- smsg.sadb_msg_len = sizeof(smsg) / 8; >-+ smsg.sadb_msg_len = PFKEY_UNIT64(sizeof(smsg)); >- smsg.sadb_msg_type = mtype; >- smsg.sadb_msg_satype = satype; >- >-@@ -143,7 +133,7 @@ >- case SADB_GETSPI: >- bzero(&sa_spirange, sizeof(sa_spirange)); >- sa_spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE; >-- sa_spirange.sadb_spirange_len = sizeof(sa_spirange) / 8; >-+ sa_spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(sa_spirange)); >- sa_spirange.sadb_spirange_min = 0x100; >- sa_spirange.sadb_spirange_max = 0xffffffff; >- sa_spirange.sadb_spirange_reserved = 0; >-@@ -153,11 +143,12 @@ >- case SADB_DELETE: >- bzero(&sa, sizeof(sa)); >- sa.sadb_sa_exttype = SADB_EXT_SA; >-- sa.sadb_sa_len = sizeof(sa) / 8; >-+ sa.sadb_sa_len = PFKEY_UNIT64(sizeof(sa)); >- sa.sadb_sa_replay = 0; >- sa.sadb_sa_spi = spi; >- sa.sadb_sa_state = SADB_SASTATE_MATURE; >- break; >-+#if 0 >- case SADB_X_ADDFLOW: >- case SADB_X_DELFLOW: >- bzero(&sa_flowtype, sizeof(sa_flowtype)); >-@@ -172,35 +163,37 @@ >- sa_protocol.sadb_protocol_direction = 0; >- sa_protocol.sadb_protocol_proto = 6; >- break; >-+#endif >- } >- >- bzero(&sa_src, sizeof(sa_src)); >- sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; >-- sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)) / 8; >-+ sa_src.sadb_address_len = PFKEY_UNIT64(sizeof(sa_src) + ROUNDUP(ssrc.ss_len)); >- >- bzero(&sa_dst, sizeof(sa_dst)); >- sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST; >-- sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)) / 8; >-+ sa_dst.sadb_address_len = PFKEY_UNIT64(sizeof(sa_dst) + ROUNDUP(sdst.ss_len)); >- >- sa.sadb_sa_auth = aalg; >-- sa.sadb_sa_encrypt = SADB_X_EALG_AES; /* XXX */ >-+ sa.sadb_sa_encrypt = ealg; /* XXX */ >- >- switch (mtype) { >- case SADB_ADD: >- case SADB_UPDATE: >- bzero(&sa_akey, sizeof(sa_akey)); >- sa_akey.sadb_key_exttype = SADB_EXT_KEY_AUTH; >-- sa_akey.sadb_key_len = (sizeof(sa_akey) + >-- ((alen + 7) / 8) * 8) / 8; >-+ sa_akey.sadb_key_len = PFKEY_UNIT64(sizeof(sa_akey) + >-+ (PFKEY_ALIGN8(alen))); >- sa_akey.sadb_key_bits = 8 * alen; >- >- bzero(&sa_ekey, sizeof(sa_ekey)); >- sa_ekey.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; >-- sa_ekey.sadb_key_len = (sizeof(sa_ekey) + >-- ((elen + 7) / 8) * 8) / 8; >-+ sa_ekey.sadb_key_len = PFKEY_UNIT64(sizeof(sa_ekey) + >-+ (PFKEY_ALIGN8(elen))); >- sa_ekey.sadb_key_bits = 8 * elen; >- >- break; >-+#if 0 >- case SADB_X_ADDFLOW: >- case SADB_X_DELFLOW: >- /* sa_peer always points to the remote machine */ >-@@ -220,8 +213,8 @@ >- sa_dst.sadb_address_exttype = SADB_X_EXT_DST_FLOW; >- >- bzero(&smask, sizeof(smask)); >-- switch (src->af) { >-- case AF_INET: >-+ switch (src->aid) { >-+ case AID_INET: >- smask.ss_len = sizeof(struct sockaddr_in); >- smask.ss_family = AF_INET; >- memset(&((struct sockaddr_in *)&smask)->sin_addr, >-@@ -233,7 +226,7 @@ >- htons(0xffff); >- } >- break; >-- case AF_INET6: >-+ case AID_INET6: >- smask.ss_len = sizeof(struct sockaddr_in6); >- smask.ss_family = AF_INET6; >- memset(&((struct sockaddr_in6 *)&smask)->sin6_addr, >-@@ -247,8 +240,8 @@ >- break; >- } >- bzero(&dmask, sizeof(dmask)); >-- switch (dst->af) { >-- case AF_INET: >-+ switch (dst->aid) { >-+ case AID_INET: >- dmask.ss_len = sizeof(struct sockaddr_in); >- dmask.ss_family = AF_INET; >- memset(&((struct sockaddr_in *)&dmask)->sin_addr, >-@@ -260,7 +253,7 @@ >- htons(0xffff); >- } >- break; >-- case AF_INET6: >-+ case AID_INET6: >- dmask.ss_len = sizeof(struct sockaddr_in6); >- dmask.ss_family = AF_INET6; >- memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr, >-@@ -284,6 +277,7 @@ >- sa_dmask.sadb_address_len = >- (sizeof(sa_dmask) + ROUNDUP(dmask.ss_len)) / 8; >- break; >-+#endif >- } >- >- iov_cnt = 0; >-@@ -310,6 +304,7 @@ >- smsg.sadb_msg_len += sa_spirange.sadb_spirange_len; >- iov_cnt++; >- break; >-+#if 0 >- case SADB_X_ADDFLOW: >- /* sa_peer always points to the remote machine */ >- iov[iov_cnt].iov_base = &sa_peer; >-@@ -351,6 +346,7 @@ >- smsg.sadb_msg_len += sa_dmask.sadb_address_len; >- iov_cnt++; >- break; >-+#endif >- } >- >- /* dest addr */ >-@@ -380,7 +376,7 @@ >- iov[iov_cnt].iov_len = sizeof(sa_akey); >- iov_cnt++; >- iov[iov_cnt].iov_base = akey; >-- iov[iov_cnt].iov_len = ((alen + 7) / 8) * 8; >-+ iov[iov_cnt].iov_len = PFKEY_ALIGN8(alen); >- smsg.sadb_msg_len += sa_akey.sadb_key_len; >- iov_cnt++; >- } >-@@ -390,14 +386,14 @@ >- iov[iov_cnt].iov_len = sizeof(sa_ekey); >- iov_cnt++; >- iov[iov_cnt].iov_base = ekey; >-- iov[iov_cnt].iov_len = ((elen + 7) / 8) * 8; >-+ iov[iov_cnt].iov_len = PFKEY_ALIGN8(elen); >- smsg.sadb_msg_len += sa_ekey.sadb_key_len; >- iov_cnt++; >- } >- break; >- } >- >-- len = smsg.sadb_msg_len * 8; >-+ len = PFKEY_UNUNIT64(smsg.sadb_msg_len); >- do { >- n = writev(sd, iov, iov_cnt); >- } while (n == -1 && (errno == EAGAIN || errno == EINTR)); >-@@ -411,6 +407,33 @@ >- } >- >- int >-+pfkey_read(int sd, struct sadb_msg *h) >-+{ >-+ struct sadb_msg hdr; >-+ >-+ if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) { >-+ log_warn("pfkey peek"); >-+ return (-1); >-+ } >-+ >-+ /* XXX: Only one message can be outstanding. */ >-+ if (hdr.sadb_msg_seq == sadb_msg_seq && >-+ hdr.sadb_msg_pid == pid) { >-+ if (h) >-+ bcopy(&hdr, h, sizeof(hdr)); >-+ return (0); >-+ } >-+ >-+ /* not ours, discard */ >-+ if (read(sd, &hdr, sizeof(hdr)) == -1) { >-+ log_warn("pfkey read"); >-+ return (-1); >-+ } >-+ >-+ return (1); >-+} >-+ >-+int >- pfkey_reply(int sd, u_int32_t *spip) >- { >- struct sadb_msg hdr, *msg; >-@@ -418,27 +441,17 @@ >- struct sadb_sa *sa; >- u_int8_t *data; >- ssize_t len; >-+ int rv; >- >-- for (;;) { >-- if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) { >-- log_warn("pfkey peek"); >-- return (-1); >-- } >-- >-- if (hdr.sadb_msg_seq == sadb_msg_seq && >-- hdr.sadb_msg_pid == pid) >-- break; >-- >-- /* not ours, discard */ >-- if (read(sd, &hdr, sizeof(hdr)) == -1) { >-- log_warn("pfkey read"); >-+ do { >-+ rv = pfkey_read(sd, &hdr); >-+ if (rv == -1) >- return (-1); >-- } >-- } >-+ } while (rv); >- >- if (hdr.sadb_msg_errno != 0) { >- errno = hdr.sadb_msg_errno; >-- if (errno == ESRCH) >-+ if (errno == ESRCH || errno == EEXIST) >- return (0); >- else { >- log_warn("pfkey"); >-@@ -486,13 +499,8 @@ >- pfkey_sa_add(struct bgpd_addr *src, struct bgpd_addr *dst, u_int8_t keylen, >- char *key, u_int32_t *spi) >- { >-- if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_GETSPI, 0, >-- src, dst, 0, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0) >-- return (-1); >-- if (pfkey_reply(fd, spi) < 0) >-- return (-1); >-- if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_UPDATE, 0, >-- src, dst, *spi, 0, keylen, key, 0, 0, NULL, 0, 0) < 0) >-+ if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_ADD, 0, >-+ src, dst, *spi, SADB_X_AALG_TCP_MD5, keylen, key, SADB_EALG_NONE, 0, NULL, 0, 0) < 0) >- return (-1); >- if (pfkey_reply(fd, NULL) < 0) >- return (-1); >-@@ -503,7 +511,7 @@ >- pfkey_sa_remove(struct bgpd_addr *src, struct bgpd_addr *dst, u_int32_t *spi) >- { >- if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_DELETE, 0, >-- src, dst, *spi, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0) >-+ src, dst, *spi, SADB_X_AALG_TCP_MD5, 0, NULL, 0, 0, NULL, 0, 0) < 0) >- return (-1); >- if (pfkey_reply(fd, NULL) < 0) >- return (-1); >-@@ -511,37 +519,37 @@ >- return (0); >- } >- >-+#define TCP_SIG_SPI 0x1000 >- int >- pfkey_md5sig_establish(struct peer *p) >- { >- sleep(1); >- >-- if (!p->auth.spi_out) >-- if (pfkey_sa_add(&p->auth.local_addr, &p->conf.remote_addr, >-- p->conf.auth.md5key_len, p->conf.auth.md5key, >-- &p->auth.spi_out) == -1) >-- return (-1); >-- if (!p->auth.spi_in) >-- if (pfkey_sa_add(&p->conf.remote_addr, &p->auth.local_addr, >-- p->conf.auth.md5key_len, p->conf.auth.md5key, >-- &p->auth.spi_in) == -1) >-- return (-1); >-+ p->auth.spi_out = htonl(TCP_SIG_SPI); >-+ if (pfkey_sa_add(&p->auth.local_addr, &p->conf.remote_addr, >-+ p->conf.auth.md5key_len, p->conf.auth.md5key, >-+ &p->auth.spi_out) == -1) >-+ return (-1); >-+ p->auth.spi_in = htonl(TCP_SIG_SPI); >-+ if (pfkey_sa_add(&p->conf.remote_addr, &p->auth.local_addr, >-+ p->conf.auth.md5key_len, p->conf.auth.md5key, >-+ &p->auth.spi_out) == -1) >-+ return (-1); >- >- p->auth.established = 1; >- return (0); >- } >-+#undef TCP_SIG_SPI >- >- int >- pfkey_md5sig_remove(struct peer *p) >- { >-- if (p->auth.spi_out) >-- if (pfkey_sa_remove(&p->auth.local_addr, &p->conf.remote_addr, >-- &p->auth.spi_out) == -1) >-- return (-1); >-- if (p->auth.spi_in) >-- if (pfkey_sa_remove(&p->conf.remote_addr, &p->auth.local_addr, >-- &p->auth.spi_in) == -1) >-- return (-1); >-+ if (pfkey_sa_remove(&p->auth.local_addr, &p->conf.remote_addr, >-+ &p->auth.spi_out) == -1) >-+ return (-1); >-+ if (pfkey_sa_remove(&p->conf.remote_addr, &p->auth.local_addr, >-+ &p->auth.spi_in) == -1) >-+ return (-1); >- >- p->auth.established = 0; >- return (0); >-@@ -550,6 +558,7 @@ >- int >- pfkey_ipsec_establish(struct peer *p) >- { >-+#if 0 >- uint8_t satype = SADB_SATYPE_ESP; >- >- switch (p->auth.method) { >-@@ -621,6 +630,9 @@ >- >- p->auth.established = 1; >- return (0); >-+#else >-+ return (-1); >-+#endif >- } >- >- int >-@@ -660,6 +672,7 @@ >- break; >- } >- >-+#if 0 >- if (pfkey_flow(fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT, >- &p->auth.local_addr, &p->conf.remote_addr, 0, BGP_PORT) < 0) >- return (-1); >-@@ -681,6 +694,7 @@ >- if (pfkey_flow(fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN, >- &p->conf.remote_addr, &p->auth.local_addr, BGP_PORT, 0) < 0) >- return (-1); >-+#endif >- if (pfkey_reply(fd, NULL) < 0) >- return (-1); >- >-@@ -715,9 +729,7 @@ >- int >- pfkey_remove(struct peer *p) >- { >-- if (!p->auth.established) >-- return (0); >-- else if (p->auth.method == AUTH_MD5SIG) >-+ if (p->auth.method == AUTH_MD5SIG) >- return (pfkey_md5sig_remove(p)); >- else >- return (pfkey_ipsec_remove(p)); >-@@ -730,11 +742,9 @@ >- if (errno == EPROTONOSUPPORT) { >- log_warnx("PF_KEY not available, disabling ipsec"); >- sysdep->no_pfkey = 1; >-- return (0); >-- } else { >-- log_warn("PF_KEY socket"); >- return (-1); >-- } >-+ } else >-+ fatal("pfkey setup failed"); >- } >-- return (0); >-+ return (fd); >- } > >Property changes on: files/patch-bgpd_pfkey.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_pftable.c >=================================================================== >--- files/patch-bgpd_pftable.c (revision 500577) >+++ files/patch-bgpd_pftable.c (nonexistent) >@@ -1,17 +0,0 @@ >-Index: bgpd/pftable.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/pftable.c,v >-retrieving revision 1.1.1.5 >-retrieving revision 1.1.1.7 >-diff -u -p -r1.1.1.5 -r1.1.1.7 >---- bgpd/pftable.c 14 Feb 2010 20:19:57 -0000 1.1.1.5 >-+++ bgpd/pftable.c 13 Oct 2012 18:22:44 -0000 1.1.1.7 >-@@ -214,7 +214,7 @@ pftable_add_work(const char *table, stru >- >- bzero(pfa, sizeof(*pfa)); >- memcpy(&pfa->pfra_u, &addr->ba, (len + 7U) / 8); >-- pfa->pfra_af = addr->af; >-+ pfa->pfra_af = aid2af(addr->aid); >- pfa->pfra_net = len; >- >- pft->naddrs++; > >Property changes on: files/patch-bgpd_pftable.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_printconf.c >=================================================================== >--- files/patch-bgpd_printconf.c (revision 500577) >+++ files/patch-bgpd_printconf.c (nonexistent) >@@ -1,439 +0,0 @@ >-Index: bgpd/printconf.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/printconf.c,v >-retrieving revision 1.1.1.7 >-retrieving revision 1.11 >-diff -u -p -r1.1.1.7 -r1.11 >---- bgpd/printconf.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 >-+++ bgpd/printconf.c 16 May 2014 00:36:26 -0000 1.11 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: printconf.c,v 1.70 2009/06/06 01:10:29 claudio Exp $ */ >-+/* $OpenBSD: printconf.c,v 1.88 2012/09/23 09:39:18 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-@@ -16,9 +16,13 @@ >- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >- */ >- >-+#include <limits.h> >- #include <stdio.h> >- #include <stdlib.h> >- #include <string.h> >-+#if defined(__FreeBSD__) /* limits.h */ >-+#include <limits.h> >-+#endif >- >- #include "bgpd.h" >- #include "mrt.h" >-@@ -27,14 +31,19 @@ >- >- void print_op(enum comp_ops); >- void print_community(int, int); >-+void print_extcommunity(struct filter_extcommunity *); >-+void print_origin(u_int8_t); >- void print_set(struct filter_set_head *); >- void print_mainconf(struct bgpd_config *); >-+void print_rdomain_targets(struct filter_set_head *, const char *); >-+void print_rdomain(struct rdomain *); >-+const char *print_af(u_int8_t); >- void print_network(struct network_config *); >- void print_peer(struct peer_config *, struct bgpd_config *, >- const char *); >- const char *print_auth_alg(u_int8_t); >- const char *print_enc_alg(u_int8_t); >--const char *print_safi(u_int8_t); >-+void print_announce(struct peer_config *, const char *); >- void print_rule(struct peer *, struct filter_rule *); >- const char * mrt_type(enum mrt_type); >- void print_mrt(u_int32_t, u_int32_t, const char *, const char *); >-@@ -94,6 +103,45 @@ print_community(int as, int type) >- } >- >- void >-+print_extcommunity(struct filter_extcommunity *c) >-+{ >-+ switch (c->type & EXT_COMMUNITY_VALUE) { >-+ case EXT_COMMUNITY_TWO_AS: >-+ printf("%s %i:%i ", log_ext_subtype(c->subtype), >-+ c->data.ext_as.as, c->data.ext_as.val); >-+ break; >-+ case EXT_COMMUNITY_IPV4: >-+ printf("%s %s:%i ", log_ext_subtype(c->subtype), >-+ inet_ntoa(c->data.ext_ip.addr), c->data.ext_ip.val); >-+ break; >-+ case EXT_COMMUNITY_FOUR_AS: >-+ printf("%s %s:%i ", log_ext_subtype(c->subtype), >-+ log_as(c->data.ext_as4.as4), c->data.ext_as.val); >-+ break; >-+ case EXT_COMMUNITY_OPAQUE: >-+ printf("%s 0x%llx ", log_ext_subtype(c->subtype), >-+ (long long unsigned int)c->data.ext_opaq); >-+ break; >-+ default: >-+ printf("0x%x 0x%llx ", c->type, (long long unsigned int)c->data.ext_opaq); >-+ break; >-+ } >-+} >-+ >-+void >-+print_origin(u_int8_t o) >-+{ >-+ if (o == ORIGIN_IGP) >-+ printf("igp "); >-+ else if (o == ORIGIN_EGP) >-+ printf("egp "); >-+ else if (o == ORIGIN_INCOMPLETE) >-+ printf("incomplete "); >-+ else >-+ printf("%u ", o); >-+} >-+ >-+void >- print_set(struct filter_set_head *set) >- { >- struct filter_set *s; >-@@ -161,11 +209,23 @@ print_set(struct filter_set_head *set) >- case ACTION_RTLABEL: >- printf("rtlabel %s ", s->action.rtlabel); >- break; >-+ case ACTION_SET_ORIGIN: >-+ printf("origin "); >-+ print_origin(s->action.origin); >-+ break; >- case ACTION_RTLABEL_ID: >- case ACTION_PFTABLE_ID: >- /* not possible */ >- printf("king bula saiz: config broken"); >- break; >-+ case ACTION_SET_EXT_COMMUNITY: >-+ printf("ext-community "); >-+ print_extcommunity(&s->action.ext_community); >-+ break; >-+ case ACTION_DEL_EXT_COMMUNITY: >-+ printf("ext-community delete "); >-+ print_extcommunity(&s->action.ext_community); >-+ break; >- } >- } >- printf("}"); >-@@ -182,6 +242,10 @@ print_mainconf(struct bgpd_config *conf) >- printf(" %u", conf->short_as); >- ina.s_addr = conf->bgpid; >- printf("\nrouter-id %s\n", inet_ntoa(ina)); >-+ >-+ printf("socket \"%s\"\n", conf->csock); >-+ if (conf->rcsock) >-+ printf("socket \"%s\" restricted\n", conf->rcsock); >- if (conf->holdtime) >- printf("holdtime %u\n", conf->holdtime); >- if (conf->min_holdtime) >-@@ -189,11 +253,6 @@ print_mainconf(struct bgpd_config *conf) >- if (conf->connectretry) >- printf("connect-retry %u\n", conf->connectretry); >- >-- if (conf->flags & BGPD_FLAG_NO_FIB_UPDATE) >-- printf("fib-update no\n"); >-- else >-- printf("fib-update yes\n"); >-- >- if (conf->flags & BGPD_FLAG_NO_EVALUATE) >- printf("route-collector yes\n"); >- >-@@ -214,43 +273,67 @@ print_mainconf(struct bgpd_config *conf) >- printf("nexthop qualify via bgp\n"); >- if (conf->flags & BGPD_FLAG_NEXTHOP_DEFAULT) >- printf("nexthop qualify via default\n"); >-+} >- >-- if (conf->flags & BGPD_FLAG_REDIST_CONNECTED) { >-- printf("network inet connected"); >-- if (!TAILQ_EMPTY(&conf->connectset)) >-- printf(" "); >-- print_set(&conf->connectset); >-- printf("\n"); >-- } >-- if (conf->flags & BGPD_FLAG_REDIST_STATIC) { >-- printf("network inet static"); >-- if (!TAILQ_EMPTY(&conf->staticset)) >-- printf(" "); >-- print_set(&conf->staticset); >-- printf("\n"); >-- } >-- if (conf->flags & BGPD_FLAG_REDIST6_CONNECTED) { >-- printf("network inet6 connected"); >-- if (!TAILQ_EMPTY(&conf->connectset6)) >-- printf(" "); >-- print_set(&conf->connectset6); >-- printf("\n"); >-- } >-- if (conf->flags & BGPD_FLAG_REDIST_STATIC) { >-- printf("network inet6 static"); >-- if (!TAILQ_EMPTY(&conf->staticset6)) >-- printf(" "); >-- print_set(&conf->staticset6); >-+void >-+print_rdomain_targets(struct filter_set_head *set, const char *tgt) >-+{ >-+ struct filter_set *s; >-+ TAILQ_FOREACH(s, set, entry) { >-+ printf("\t%s ", tgt); >-+ print_extcommunity(&s->action.ext_community); >- printf("\n"); >- } >-- if (conf->rtableid) >-- printf("rtable %u\n", conf->rtableid); >-+} >-+ >-+void >-+print_rdomain(struct rdomain *r) >-+{ >-+ printf("rdomain %u {\n", r->rtableid); >-+ printf("\tdescr \"%s\"\n", r->descr); >-+ if (r->flags & F_RIB_NOFIBSYNC) >-+ printf("\tfib-update no\n"); >-+ else >-+ printf("\tfib-update yes\n"); >-+ printf("\tdepend on %s\n", r->ifmpe); >-+ >-+ printf("\n\t%s\n", log_rd(r->rd)); >-+ >-+ print_rdomain_targets(&r->export, "export-target"); >-+ print_rdomain_targets(&r->import, "import-target"); >-+ >-+ printf("}\n"); >-+} >-+ >-+const char * >-+print_af(u_int8_t aid) >-+{ >-+ /* >-+ * Hack around the fact that aid2str() will return "IPv4 unicast" >-+ * for AID_INET. AID_INET and AID_INET6 need special handling and >-+ * the other AID should never end up here (at least for now). >-+ */ >-+ if (aid == AID_INET) >-+ return ("inet"); >-+ if (aid == AID_INET6) >-+ return ("inet6"); >-+ return (aid2str(aid)); >- } >- >- void >- print_network(struct network_config *n) >- { >-- printf("network %s/%u", log_addr(&n->prefix), n->prefixlen); >-+ switch (n->type) { >-+ case NETWORK_STATIC: >-+ printf("network %s static", print_af(n->prefix.aid)); >-+ break; >-+ case NETWORK_CONNECTED: >-+ printf("network %s connected", print_af(n->prefix.aid)); >-+ break; >-+ default: >-+ printf("network %s/%u", log_addr(&n->prefix), n->prefixlen); >-+ break; >-+ } >- if (!TAILQ_EMPTY(&n->attrset)) >- printf(" "); >- print_set(&n->attrset); >-@@ -263,8 +346,8 @@ print_peer(struct peer_config *p, struct >- char *method; >- struct in_addr ina; >- >-- if ((p->remote_addr.af == AF_INET && p->remote_masklen != 32) || >-- (p->remote_addr.af == AF_INET6 && p->remote_masklen != 128)) >-+ if ((p->remote_addr.aid == AID_INET && p->remote_masklen != 32) || >-+ (p->remote_addr.aid == AID_INET6 && p->remote_masklen != 128)) >- printf("%sneighbor %s/%u {\n", c, log_addr(&p->remote_addr), >- p->remote_masklen); >- else >-@@ -281,7 +364,7 @@ print_peer(struct peer_config *p, struct >- printf("%s\tmultihop %u\n", c, p->distance); >- if (p->passive) >- printf("%s\tpassive\n", c); >-- if (p->local_addr.af) >-+ if (p->local_addr.aid) >- printf("%s\tlocal-address %s\n", c, log_addr(&p->local_addr)); >- if (p->max_prefix) { >- printf("%s\tmax-prefix %u", c, p->max_prefix); >-@@ -295,6 +378,12 @@ print_peer(struct peer_config *p, struct >- printf("%s\tholdtime min %u\n", c, p->min_holdtime); >- if (p->announce_capa == 0) >- printf("%s\tannounce capabilities no\n", c); >-+ if (p->capabilities.refresh == 0) >-+ printf("%s\tannounce refresh no\n", c); >-+ if (p->capabilities.grestart.restart == 0) >-+ printf("%s\tannounce restart no\n", c); >-+ if (p->capabilities.as4byte == 0) >-+ printf("%s\tannounce as4byte no\n", c); >- if (p->announce_type == ANNOUNCE_SELF) >- printf("%s\tannounce self\n", c); >- else if (p->announce_type == ANNOUNCE_NONE) >-@@ -324,6 +413,10 @@ print_peer(struct peer_config *p, struct >- printf("%s\tdepend on \"%s\"\n", c, p->if_depend); >- if (p->flags & PEERFLAG_TRANS_AS) >- printf("%s\ttransparent-as yes\n", c); >-+#if defined(IPV6_LINKLOCAL_PEER) >-+ if (p->lliface[0]) >-+ printf("%s\tinterface %s\n", c, p->lliface); >-+#endif >- >- if (p->auth.method == AUTH_MD5SIG) >- printf("%s\ttcp md5sig\n", c); >-@@ -354,8 +447,7 @@ print_peer(struct peer_config *p, struct >- if (p->ttlsec) >- printf("%s\tttl-security yes\n", c); >- >-- printf("%s\tannounce IPv4 %s\n", c, print_safi(p->capabilities.mp_v4)); >-- printf("%s\tannounce IPv6 %s\n", c, print_safi(p->capabilities.mp_v6)); >-+ print_announce(p, c); >- >- if (p->softreconfig_in == 1) >- printf("%s\tsoftreconfig in yes\n", c); >-@@ -399,17 +491,14 @@ print_enc_alg(u_int8_t alg) >- } >- } >- >--const char * >--print_safi(u_int8_t safi) >-+void >-+print_announce(struct peer_config *p, const char *c) >- { >-- switch (safi) { >-- case SAFI_NONE: >-- return ("none"); >-- case SAFI_UNICAST: >-- return ("unicast"); >-- default: >-- return ("?"); >-- } >-+ u_int8_t aid; >-+ >-+ for (aid = 0; aid < AID_MAX; aid++) >-+ if (p->capabilities.mp[aid]) >-+ printf("%s\tannounce %s\n", c, aid2str(aid)); >- } >- >- void >-@@ -455,14 +544,14 @@ print_rule(struct peer *peer_l, struct f >- } else >- printf("any "); >- >-- if (r->match.prefix.addr.af) >-+ if (r->match.prefix.addr.aid) >- printf("prefix %s/%u ", log_addr(&r->match.prefix.addr), >- r->match.prefix.len); >- >-- if (r->match.prefix.addr.af == 0 && r->match.prefixlen.af) { >-- if (r->match.prefixlen.af == AF_INET) >-+ if (r->match.prefix.addr.aid == 0 && r->match.prefixlen.aid) { >-+ if (r->match.prefixlen.aid == AID_INET) >- printf("inet "); >-- if (r->match.prefixlen.af == AF_INET6) >-+ if (r->match.prefixlen.aid == AID_INET6) >- printf("inet6 "); >- } >- >-@@ -479,6 +568,13 @@ print_rule(struct peer *peer_l, struct f >- } >- } >- >-+ if (r->match.nexthop.flags) { >-+ if (r->match.nexthop.flags == FILTER_NEXTHOP_NEIGHBOR) >-+ printf("nexthop neighbor "); >-+ else >-+ printf("nexthop %s ", log_addr(&r->match.nexthop.addr)); >-+ } >-+ >- if (r->match.as.type) { >- if (r->match.as.type == AS_ALL) >- printf("AS %s ", log_as(r->match.as.as)); >-@@ -492,11 +588,20 @@ print_rule(struct peer *peer_l, struct f >- printf("unfluffy-as %s ", log_as(r->match.as.as)); >- } >- >-+ if (r->match.aslen.type) { >-+ printf("%s %u ", r->match.aslen.type == ASLEN_MAX ? >-+ "max-as-len" : "max-as-seq", r->match.aslen.aslen); >-+ } >-+ >- if (r->match.community.as != COMMUNITY_UNSET) { >- printf("community "); >- print_community(r->match.community.as, >- r->match.community.type); >- } >-+ if (r->match.ext_community.flags & EXT_COMMUNITY_FLAG_VALID) { >-+ printf("ext-community "); >-+ print_extcommunity(&r->match.ext_community); >-+ } >- >- print_set(&r->set); >- >-@@ -513,6 +618,8 @@ mrt_type(enum mrt_type t) >- return "table"; >- case MRT_TABLE_DUMP_MP: >- return "table-mp"; >-+ case MRT_TABLE_DUMP_V2: >-+ return "table-v2"; >- case MRT_ALL_IN: >- return "all in"; >- case MRT_ALL_OUT: >-@@ -541,12 +648,12 @@ print_mrt(u_int32_t pid, u_int32_t gid, >- printf("%s%sdump ", prep, prep2); >- if (m->rib[0]) >- printf("rib %s ", m->rib); >-+ printf("%s \"%s\"", mrt_type(m->type), >-+ MRT2MC(m)->name); >- if (MRT2MC(m)->ReopenTimerInterval == 0) >-- printf("%s %s\n", mrt_type(m->type), >-- MRT2MC(m)->name); >-+ printf("\n"); >- else >-- printf("%s %s %d\n", mrt_type(m->type), >-- MRT2MC(m)->name, >-+ printf(" %ld\n", >- MRT2MC(m)->ReopenTimerInterval); >- } >- } >-@@ -612,26 +719,34 @@ peer_compare(const void *aa, const void >- void >- print_config(struct bgpd_config *conf, struct rib_names *rib_l, >- struct network_head *net_l, struct peer *peer_l, >-- struct filter_head *rules_l, struct mrt_head *mrt_l) >-+ struct filter_head *rules_l, struct mrt_head *mrt_l, >-+ struct rdomain_head *rdom_l) >- { >- struct filter_rule *r; >- struct network *n; >- struct rde_rib *rr; >-+ struct rdomain *rd; >- >- xmrt_l = mrt_l; >-- printf("\n"); >- print_mainconf(conf); >- printf("\n"); >-+ TAILQ_FOREACH(n, net_l, entry) >-+ print_network(&n->net); >-+ printf("\n"); >-+ SIMPLEQ_FOREACH(rd, rdom_l, entry) >-+ print_rdomain(rd); >-+ printf("\n"); >- SIMPLEQ_FOREACH(rr, rib_l, entry) { >- if (rr->flags & F_RIB_NOEVALUATE) >- printf("rde rib %s no evaluate\n", rr->name); >-- else >-+ else if (rr->flags & F_RIB_NOFIB) >- printf("rde rib %s\n", rr->name); >-+ else >-+ printf("rde rib %s rtable %u fib-update %s\n", rr->name, >-+ rr->rtableid, rr->flags & F_RIB_NOFIBSYNC ? >-+ "no" : "yes"); >- } >- printf("\n"); >-- TAILQ_FOREACH(n, net_l, entry) >-- print_network(&n->net); >-- printf("\n"); >- print_mrt(0, 0, "", ""); >- printf("\n"); >- print_groups(conf, peer_l); > >Property changes on: files/patch-bgpd_printconf.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_rde.c >=================================================================== >--- files/patch-bgpd_rde.c (revision 500577) >+++ files/patch-bgpd_rde.c (nonexistent) >@@ -1,2614 +0,0 @@ >-Index: bgpd/rde.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde.c,v >-retrieving revision 1.1.1.8 >-retrieving revision 1.12 >-diff -u -p -r1.1.1.8 -r1.12 >---- bgpd/rde.c 14 Feb 2010 20:19:57 -0000 1.1.1.8 >-+++ bgpd/rde.c 16 May 2014 00:36:26 -0000 1.12 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: rde.c,v 1.264 2009/06/29 12:22:16 claudio Exp $ */ >-+/* $OpenBSD: rde.c,v 1.320 2012/09/18 09:45:51 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-@@ -18,10 +18,11 @@ >- >- #include <sys/types.h> >- #include <sys/socket.h> >-+#include <sys/time.h> >-+#include <sys/resource.h> >- >- #include <errno.h> >- #include <ifaddrs.h> >--#include <limits.h> >- #include <pwd.h> >- #include <poll.h> >- #include <signal.h> >-@@ -50,13 +51,18 @@ void rde_update_withdraw(struct rde_pe >- u_int8_t); >- int rde_attr_parse(u_char *, u_int16_t, struct rde_peer *, >- struct rde_aspath *, struct mpattr *); >-+int rde_attr_add(struct rde_aspath *, u_char *, u_int16_t); >- u_int8_t rde_attr_missing(struct rde_aspath *, int, u_int16_t); >--int rde_get_mp_nexthop(u_char *, u_int16_t, u_int16_t, >-- struct rde_aspath *); >-+int rde_get_mp_nexthop(u_char *, u_int16_t, u_int8_t, >-+ struct rde_aspath *, struct rde_peer *); >-+int rde_update_extract_prefix(u_char *, u_int16_t, void *, >-+ u_int8_t, u_int8_t); >- int rde_update_get_prefix(u_char *, u_int16_t, struct bgpd_addr *, >- u_int8_t *); >- int rde_update_get_prefix6(u_char *, u_int16_t, struct bgpd_addr *, >- u_int8_t *); >-+int rde_update_get_vpn4(u_char *, u_int16_t, struct bgpd_addr *, >-+ u_int8_t *); >- void rde_update_err(struct rde_peer *, u_int8_t , u_int8_t, >- void *, u_int16_t); >- void rde_update_log(const char *, u_int16_t, >-@@ -78,11 +84,15 @@ void rde_dump_ctx_new(struct ctl_show_ >- void rde_dump_mrt_new(struct mrt *, pid_t, int); >- void rde_dump_done(void *); >- >-+int rde_rdomain_import(struct rde_aspath *, struct rdomain *); >- void rde_up_dump_upcall(struct rib_entry *, void *); >- void rde_softreconfig_out(struct rib_entry *, void *); >- void rde_softreconfig_in(struct rib_entry *, void *); >-+void rde_softreconfig_load(struct rib_entry *, void *); >-+void rde_softreconfig_load_peer(struct rib_entry *, void *); >-+void rde_softreconfig_unload_peer(struct rib_entry *, void *); >- void rde_update_queue_runner(void); >--void rde_update6_queue_runner(void); >-+void rde_update6_queue_runner(u_int8_t); >- >- void peer_init(u_int32_t); >- void peer_shutdown(void); >-@@ -91,10 +101,12 @@ struct rde_peer *peer_add(u_int32_t, str >- struct rde_peer *peer_get(u_int32_t); >- void peer_up(u_int32_t, struct session_up *); >- void peer_down(u_int32_t); >--void peer_dump(u_int32_t, u_int16_t, u_int8_t); >--void peer_send_eor(struct rde_peer *, u_int16_t, u_int16_t); >-+void peer_flush(struct rde_peer *, u_int8_t); >-+void peer_stale(u_int32_t, u_int8_t); >-+void peer_recv_eor(struct rde_peer *, u_int8_t); >-+void peer_dump(u_int32_t, u_int8_t); >-+void peer_send_eor(struct rde_peer *, u_int8_t); >- >--void network_init(struct network_head *); >- void network_add(struct network_config *, int); >- void network_delete(struct network_config *, int); >- void network_dump_upcall(struct rib_entry *, void *); >-@@ -108,6 +120,7 @@ time_t reloadtime; >- struct rde_peer_head peerlist; >- struct rde_peer *peerself; >- struct filter_head *rules_l, *newrules; >-+struct rdomain_head *rdomains_l, *newdomains; >- struct imsgbuf *ibuf_se; >- struct imsgbuf *ibuf_se_ctl; >- struct imsgbuf *ibuf_main; >-@@ -120,11 +133,12 @@ struct rde_dump_ctx { >- }; >- >- struct rde_mrt_ctx { >-- struct mrt mrt; >-- struct rib_context ribctx; >-+ struct mrt mrt; >-+ struct rib_context ribctx; >-+ LIST_ENTRY(rde_mrt_ctx) entry; >- }; >- >--struct mrt_head rde_mrts = LIST_HEAD_INITIALIZER(rde_mrts); >-+LIST_HEAD(, rde_mrt_ctx) rde_mrts = LIST_HEAD_INITIALIZER(rde_mrts); >- u_int rde_mrt_cnt; >- >- void >-@@ -144,24 +158,17 @@ u_int32_t attrhashsize = 512; >- u_int32_t nexthophashsize = 64; >- >- pid_t >--rde_main(struct bgpd_config *config, struct peer *peer_l, >-- struct network_head *net_l, struct filter_head *rules, >-- struct mrt_head *mrt_l, struct rib_names *rib_n, int pipe_m2r[2], >-- int pipe_s2r[2], int pipe_m2s[2], int pipe_s2rctl[2], int debug) >-+rde_main(int pipe_m2r[2], int pipe_s2r[2], int pipe_m2s[2], int pipe_s2rctl[2], >-+ int debug) >- { >- pid_t pid; >- struct passwd *pw; >-- struct peer *p; >-- struct listen_addr *la; >- struct pollfd *pfd = NULL; >-- struct filter_rule *f; >-- struct filter_set *set; >-- struct nexthop *nh; >-- struct rde_rib *rr; >-- struct mrt *mrt, *xmrt; >-+ struct rde_mrt_ctx *mctx, *xmctx; >- void *newp; >- u_int pfd_elms = 0, i, j; >- int timeout; >-+ u_int8_t aid; >- >- switch (pid = fork()) { >- case -1: >-@@ -172,8 +179,6 @@ rde_main(struct bgpd_config *config, str >- return (pid); >- } >- >-- conf = config; >-- >- if ((pw = getpwnam(BGPD_USER)) == NULL) >- fatal("getpwnam"); >- >-@@ -194,6 +199,8 @@ rde_main(struct bgpd_config *config, str >- signal(SIGINT, rde_sighdlr); >- signal(SIGPIPE, SIG_IGN); >- signal(SIGHUP, SIG_IGN); >-+ signal(SIGALRM, SIG_IGN); >-+ signal(SIGUSR1, SIG_IGN); >- >- close(pipe_s2r[0]); >- close(pipe_s2rctl[0]); >-@@ -210,50 +217,25 @@ rde_main(struct bgpd_config *config, str >- imsg_init(ibuf_se_ctl, pipe_s2rctl[1]); >- imsg_init(ibuf_main, pipe_m2r[1]); >- >-- /* peer list, mrt list and listener list are not used in the RDE */ >-- while ((p = peer_l) != NULL) { >-- peer_l = p->next; >-- free(p); >-- } >-- >-- while ((mrt = LIST_FIRST(mrt_l)) != NULL) { >-- LIST_REMOVE(mrt, entry); >-- free(mrt); >-- } >-- >-- while ((la = TAILQ_FIRST(config->listen_addrs)) != NULL) { >-- TAILQ_REMOVE(config->listen_addrs, la, entry); >-- close(la->fd); >-- free(la); >-- } >-- free(config->listen_addrs); >-- >- pt_init(); >-- while ((rr = SIMPLEQ_FIRST(&ribnames))) { >-- SIMPLEQ_REMOVE_HEAD(&ribnames, entry); >-- rib_new(-1, rr->name, rr->flags); >-- free(rr); >-- } >- path_init(pathhashsize); >- aspath_init(pathhashsize); >- attr_init(attrhashsize); >- nexthop_init(nexthophashsize); >- peer_init(peerhashsize); >-- rules_l = rules; >-- network_init(net_l); >- >-+ rules_l = calloc(1, sizeof(struct filter_head)); >-+ if (rules_l == NULL) >-+ fatal(NULL); >-+ TAILQ_INIT(rules_l); >-+ rdomains_l = calloc(1, sizeof(struct rdomain_head)); >-+ if (rdomains_l == NULL) >-+ fatal(NULL); >-+ SIMPLEQ_INIT(rdomains_l); >-+ if ((conf = calloc(1, sizeof(struct bgpd_config))) == NULL) >-+ fatal(NULL); >- log_info("route decision engine ready"); >- >-- TAILQ_FOREACH(f, rules, entry) { >-- f->peer.ribid = rib_find(f->rib); >-- TAILQ_FOREACH(set, &f->set, entry) { >-- if (set->type == ACTION_SET_NEXTHOP) { >-- nh = nexthop_get(&set->action.nexthop); >-- nh->refcnt++; >-- } >-- } >-- } >-- >- while (rde_quit == 0) { >- if (pfd_elms < PFD_PIPE_COUNT + rde_mrt_cnt) { >- if ((newp = realloc(pfd, sizeof(struct pollfd) * >-@@ -287,11 +269,18 @@ rde_main(struct bgpd_config *config, str >- timeout = 0; >- >- i = PFD_PIPE_COUNT; >-- LIST_FOREACH(mrt, &rde_mrts, entry) { >-- if (mrt->wbuf.queued) { >-- pfd[i].fd = mrt->wbuf.fd; >-+ for (mctx = LIST_FIRST(&rde_mrts); mctx != 0; mctx = xmctx) { >-+ xmctx = LIST_NEXT(mctx, entry); >-+ if (mctx->mrt.wbuf.queued) { >-+ pfd[i].fd = mctx->mrt.wbuf.fd; >- pfd[i].events = POLLOUT; >- i++; >-+ } else if (mctx->mrt.state == MRT_STATE_REMOVE) { >-+ close(mctx->mrt.wbuf.fd); >-+ LIST_REMOVE(&mctx->ribctx, entry); >-+ LIST_REMOVE(mctx, entry); >-+ free(mctx); >-+ rde_mrt_cnt--; >- } >- } >- >-@@ -325,24 +314,17 @@ rde_main(struct bgpd_config *config, str >- if (pfd[PFD_PIPE_SESSION_CTL].revents & POLLIN) >- rde_dispatch_imsg_session(ibuf_se_ctl); >- >-- for (j = PFD_PIPE_COUNT, mrt = LIST_FIRST(&rde_mrts); >-- j < i && mrt != 0; j++) { >-- xmrt = LIST_NEXT(mrt, entry); >-- if (pfd[j].fd == mrt->wbuf.fd && >-+ for (j = PFD_PIPE_COUNT, mctx = LIST_FIRST(&rde_mrts); >-+ j < i && mctx != 0; j++) { >-+ if (pfd[j].fd == mctx->mrt.wbuf.fd && >- pfd[j].revents & POLLOUT) >-- mrt_write(mrt); >-- if (mrt->wbuf.queued == 0 && >-- mrt->state == MRT_STATE_REMOVE) { >-- close(mrt->wbuf.fd); >-- LIST_REMOVE(mrt, entry); >-- free(mrt); >-- rde_mrt_cnt--; >-- } >-- mrt = xmrt; >-+ mrt_write(&mctx->mrt); >-+ mctx = LIST_NEXT(mctx, entry); >- } >- >- rde_update_queue_runner(); >-- rde_update6_queue_runner(); >-+ for (aid = AID_INET6; aid < AID_MAX; aid++) >-+ rde_update6_queue_runner(aid); >- if (ibuf_se_ctl->w.queued <= 0) >- rib_dump_runner(); >- } >-@@ -351,11 +333,12 @@ rde_main(struct bgpd_config *config, str >- if (debug) >- rde_shutdown(); >- >-- while ((mrt = LIST_FIRST(&rde_mrts)) != NULL) { >-- msgbuf_clear(&mrt->wbuf); >-- close(mrt->wbuf.fd); >-- LIST_REMOVE(mrt, entry); >-- free(mrt); >-+ while ((mctx = LIST_FIRST(&rde_mrts)) != NULL) { >-+ msgbuf_clear(&mctx->mrt.wbuf); >-+ close(mctx->mrt.wbuf.fd); >-+ LIST_REMOVE(&mctx->ribctx, entry); >-+ LIST_REMOVE(mctx, entry); >-+ free(mctx); >- } >- >- msgbuf_clear(&ibuf_se->w); >-@@ -378,13 +361,18 @@ rde_dispatch_imsg_session(struct imsgbuf >- struct imsg imsg; >- struct peer p; >- struct peer_config pconf; >-- struct rrefresh r; >-- struct rde_peer *peer; >- struct session_up sup; >-+ struct ctl_show_rib csr; >- struct ctl_show_rib_request req; >-+ struct rde_peer *peer; >-+ struct rde_aspath *asp; >- struct filter_set *s; >- struct nexthop *nh; >-- int n; >-+ u_int8_t *asdata; >-+ ssize_t n; >-+ int verbose; >-+ u_int16_t len; >-+ u_int8_t aid; >- >- if ((n = imsg_read(ibuf)) == -1) >- fatal("rde_dispatch_imsg_session: imsg_read error"); >-@@ -422,13 +410,56 @@ rde_dispatch_imsg_session(struct imsgbuf >- case IMSG_SESSION_DOWN: >- peer_down(imsg.hdr.peerid); >- break; >-+ case IMSG_SESSION_STALE: >-+ if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(aid)) { >-+ log_warnx("rde_dispatch: wrong imsg len"); >-+ break; >-+ } >-+ memcpy(&aid, imsg.data, sizeof(aid)); >-+ if (aid >= AID_MAX) >-+ fatalx("IMSG_SESSION_STALE: bad AID"); >-+ peer_stale(imsg.hdr.peerid, aid); >-+ break; >-+ case IMSG_SESSION_FLUSH: >-+ if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(aid)) { >-+ log_warnx("rde_dispatch: wrong imsg len"); >-+ break; >-+ } >-+ memcpy(&aid, imsg.data, sizeof(aid)); >-+ if (aid >= AID_MAX) >-+ fatalx("IMSG_SESSION_FLUSH: bad AID"); >-+ if ((peer = peer_get(imsg.hdr.peerid)) == NULL) { >-+ log_warnx("rde_dispatch: unknown peer id %d", >-+ imsg.hdr.peerid); >-+ break; >-+ } >-+ peer_flush(peer, aid); >-+ break; >-+ case IMSG_SESSION_RESTARTED: >-+ if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(aid)) { >-+ log_warnx("rde_dispatch: wrong imsg len"); >-+ break; >-+ } >-+ memcpy(&aid, imsg.data, sizeof(aid)); >-+ if (aid >= AID_MAX) >-+ fatalx("IMSG_SESSION_RESTARTED: bad AID"); >-+ if ((peer = peer_get(imsg.hdr.peerid)) == NULL) { >-+ log_warnx("rde_dispatch: unknown peer id %d", >-+ imsg.hdr.peerid); >-+ break; >-+ } >-+ if (peer->staletime[aid]) >-+ peer_flush(peer, aid); >-+ break; >- case IMSG_REFRESH: >-- if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(r)) { >-+ if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(aid)) { >- log_warnx("rde_dispatch: wrong imsg len"); >- break; >- } >-- memcpy(&r, imsg.data, sizeof(r)); >-- peer_dump(imsg.hdr.peerid, r.afi, r.safi); >-+ memcpy(&aid, imsg.data, sizeof(aid)); >-+ if (aid >= AID_MAX) >-+ fatalx("IMSG_REFRESH: bad AID"); >-+ peer_dump(imsg.hdr.peerid, aid); >- break; >- case IMSG_NETWORK_ADD: >- if (imsg.hdr.len - IMSG_HEADER_SIZE != >-@@ -440,23 +471,68 @@ rde_dispatch_imsg_session(struct imsgbuf >- TAILQ_INIT(&netconf_s.attrset); >- session_set = &netconf_s.attrset; >- break; >-+ case IMSG_NETWORK_ASPATH: >-+ if (imsg.hdr.len - IMSG_HEADER_SIZE < >-+ sizeof(struct ctl_show_rib)) { >-+ log_warnx("rde_dispatch: wrong imsg len"); >-+ bzero(&netconf_s, sizeof(netconf_s)); >-+ break; >-+ } >-+ asdata = imsg.data; >-+ asdata += sizeof(struct ctl_show_rib); >-+ memcpy(&csr, imsg.data, sizeof(csr)); >-+ if (csr.aspath_len + sizeof(csr) > imsg.hdr.len - >-+ IMSG_HEADER_SIZE) { >-+ log_warnx("rde_dispatch: wrong aspath len"); >-+ bzero(&netconf_s, sizeof(netconf_s)); >-+ break; >-+ } >-+ asp = path_get(); >-+ asp->lpref = csr.local_pref; >-+ asp->med = csr.med; >-+ asp->weight = csr.weight; >-+ asp->flags = csr.flags; >-+ asp->origin = csr.origin; >-+ asp->flags |= F_PREFIX_ANNOUNCED | F_ANN_DYNAMIC; >-+ asp->aspath = aspath_get(asdata, csr.aspath_len); >-+ netconf_s.asp = asp; >-+ break; >-+ case IMSG_NETWORK_ATTR: >-+ if (imsg.hdr.len <= IMSG_HEADER_SIZE) { >-+ log_warnx("rde_dispatch: wrong imsg len"); >-+ break; >-+ } >-+ /* parse path attributes */ >-+ len = imsg.hdr.len - IMSG_HEADER_SIZE; >-+ asp = netconf_s.asp; >-+ if (rde_attr_add(asp, imsg.data, len) == -1) { >-+ log_warnx("rde_dispatch: bad network " >-+ "attribute"); >-+ path_put(asp); >-+ bzero(&netconf_s, sizeof(netconf_s)); >-+ break; >-+ } >-+ break; >- case IMSG_NETWORK_DONE: >- if (imsg.hdr.len != IMSG_HEADER_SIZE) { >- log_warnx("rde_dispatch: wrong imsg len"); >- break; >- } >- session_set = NULL; >-- switch (netconf_s.prefix.af) { >-- case AF_INET: >-+ switch (netconf_s.prefix.aid) { >-+ case AID_INET: >- if (netconf_s.prefixlen > 32) >- goto badnet; >- network_add(&netconf_s, 0); >- break; >-- case AF_INET6: >-+ case AID_INET6: >- if (netconf_s.prefixlen > 128) >- goto badnet; >- network_add(&netconf_s, 0); >- break; >-+ case 0: >-+ /* something failed beforehands */ >-+ break; >- default: >- badnet: >- log_warnx("rde_dispatch: bad network"); >-@@ -528,10 +604,14 @@ badnet: >- peer->prefix_rcvd_update; >- p.stats.prefix_rcvd_withdraw = >- peer->prefix_rcvd_withdraw; >-+ p.stats.prefix_rcvd_eor = >-+ peer->prefix_rcvd_eor; >- p.stats.prefix_sent_update = >- peer->prefix_sent_update; >- p.stats.prefix_sent_withdraw = >- peer->prefix_sent_withdraw; >-+ p.stats.prefix_sent_eor = >-+ peer->prefix_sent_eor; >- } >- imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NEIGHBOR, 0, >- imsg.hdr.pid, -1, &p, sizeof(struct peer)); >-@@ -544,6 +624,11 @@ badnet: >- imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_RIB_MEM, 0, >- imsg.hdr.pid, -1, &rdemem, sizeof(rdemem)); >- break; >-+ case IMSG_CTL_LOG_VERBOSE: >-+ /* already checked by SE */ >-+ memcpy(&verbose, imsg.data, sizeof(verbose)); >-+ log_verbose(verbose); >-+ break; >- default: >- break; >- } >-@@ -554,14 +639,17 @@ badnet: >- void >- rde_dispatch_imsg_parent(struct imsgbuf *ibuf) >- { >-+ static struct rdomain *rd; >- struct imsg imsg; >- struct mrt xmrt; >- struct rde_rib rn; >- struct rde_peer *peer; >-+ struct peer_config *pconf; >- struct filter_rule *r; >- struct filter_set *s; >- struct nexthop *nh; >-- int n, fd, reconf_in = 0, reconf_out = 0; >-+ int n, fd, reconf_in = 0, reconf_out = 0, >-+ reconf_rib = 0; >- u_int16_t rid; >- >- if ((n = imsg_read(ibuf)) == -1) >-@@ -576,20 +664,12 @@ rde_dispatch_imsg_parent(struct imsgbuf >- break; >- >- switch (imsg.hdr.type) { >-- case IMSG_RECONF_CONF: >-- reloadtime = time(NULL); >-- newrules = calloc(1, sizeof(struct filter_head)); >-- if (newrules == NULL) >-- fatal(NULL); >-- TAILQ_INIT(newrules); >-- if ((nconf = malloc(sizeof(struct bgpd_config))) == >-- NULL) >-- fatal(NULL); >-- memcpy(nconf, imsg.data, sizeof(struct bgpd_config)); >-- for (rid = 0; rid < rib_size; rid++) >-- ribs[rid].state = RIB_DELETE; >-- break; >- case IMSG_NETWORK_ADD: >-+ if (imsg.hdr.len - IMSG_HEADER_SIZE != >-+ sizeof(struct network_config)) { >-+ log_warnx("rde_dispatch: wrong imsg len"); >-+ break; >-+ } >- memcpy(&netconf_p, imsg.data, sizeof(netconf_p)); >- TAILQ_INIT(&netconf_p.attrset); >- parent_set = &netconf_p.attrset; >-@@ -608,6 +688,26 @@ rde_dispatch_imsg_parent(struct imsgbuf >- TAILQ_INIT(&netconf_p.attrset); >- network_delete(&netconf_p, 1); >- break; >-+ case IMSG_RECONF_CONF: >-+ if (imsg.hdr.len - IMSG_HEADER_SIZE != >-+ sizeof(struct bgpd_config)) >-+ fatalx("IMSG_RECONF_CONF bad len"); >-+ reloadtime = time(NULL); >-+ newrules = calloc(1, sizeof(struct filter_head)); >-+ if (newrules == NULL) >-+ fatal(NULL); >-+ TAILQ_INIT(newrules); >-+ newdomains = calloc(1, sizeof(struct rdomain_head)); >-+ if (newdomains == NULL) >-+ fatal(NULL); >-+ SIMPLEQ_INIT(newdomains); >-+ if ((nconf = malloc(sizeof(struct bgpd_config))) == >-+ NULL) >-+ fatal(NULL); >-+ memcpy(nconf, imsg.data, sizeof(struct bgpd_config)); >-+ for (rid = 0; rid < rib_size; rid++) >-+ ribs[rid].state = RECONF_DELETE; >-+ break; >- case IMSG_RECONF_RIB: >- if (imsg.hdr.len - IMSG_HEADER_SIZE != >- sizeof(struct rde_rib)) >-@@ -615,9 +715,26 @@ rde_dispatch_imsg_parent(struct imsgbuf >- memcpy(&rn, imsg.data, sizeof(rn)); >- rid = rib_find(rn.name); >- if (rid == RIB_FAILED) >-- rib_new(-1, rn.name, rn.flags); >-- else >-- ribs[rid].state = RIB_ACTIVE; >-+ rib_new(rn.name, rn.rtableid, rn.flags); >-+ else if (ribs[rid].rtableid != rn.rtableid || >-+ (ribs[rid].flags & F_RIB_HASNOFIB) != >-+ (rn.flags & F_RIB_HASNOFIB)) { >-+ /* Big hammer in the F_RIB_NOFIB case but >-+ * not often enough used to optimise it more. */ >-+ rib_free(&ribs[rid]); >-+ rib_new(rn.name, rn.rtableid, rn.flags); >-+ } else >-+ ribs[rid].state = RECONF_KEEP; >-+ break; >-+ case IMSG_RECONF_PEER: >-+ if (imsg.hdr.len - IMSG_HEADER_SIZE != >-+ sizeof(struct peer_config)) >-+ fatalx("IMSG_RECONF_PEER bad len"); >-+ if ((peer = peer_get(imsg.hdr.peerid)) == NULL) >-+ break; >-+ pconf = imsg.data; >-+ strlcpy(peer->conf.rib, pconf->rib, >-+ sizeof(peer->conf.rib)); >- break; >- case IMSG_RECONF_FILTER: >- if (imsg.hdr.len - IMSG_HEADER_SIZE != >-@@ -631,12 +748,42 @@ rde_dispatch_imsg_parent(struct imsgbuf >- parent_set = &r->set; >- TAILQ_INSERT_TAIL(newrules, r, entry); >- break; >-+ case IMSG_RECONF_RDOMAIN: >-+ if (imsg.hdr.len - IMSG_HEADER_SIZE != >-+ sizeof(struct rdomain)) >-+ fatalx("IMSG_RECONF_RDOMAIN bad len"); >-+ if ((rd = malloc(sizeof(struct rdomain))) == NULL) >-+ fatal(NULL); >-+ memcpy(rd, imsg.data, sizeof(struct rdomain)); >-+ TAILQ_INIT(&rd->import); >-+ TAILQ_INIT(&rd->export); >-+ SIMPLEQ_INSERT_TAIL(newdomains, rd, entry); >-+ break; >-+ case IMSG_RECONF_RDOMAIN_EXPORT: >-+ if (rd == NULL) { >-+ log_warnx("rde_dispatch_imsg_parent: " >-+ "IMSG_RECONF_RDOMAIN_EXPORT unexpected"); >-+ break; >-+ } >-+ parent_set = &rd->export; >-+ break; >-+ case IMSG_RECONF_RDOMAIN_IMPORT: >-+ if (rd == NULL) { >-+ log_warnx("rde_dispatch_imsg_parent: " >-+ "IMSG_RECONF_RDOMAIN_IMPORT unexpected"); >-+ break; >-+ } >-+ parent_set = &rd->import; >-+ break; >-+ case IMSG_RECONF_RDOMAIN_DONE: >-+ parent_set = NULL; >-+ break; >- case IMSG_RECONF_DONE: >- if (nconf == NULL) >- fatalx("got IMSG_RECONF_DONE but no config"); >- if ((nconf->flags & BGPD_FLAG_NO_EVALUATE) >- != (conf->flags & BGPD_FLAG_NO_EVALUATE)) { >-- log_warnx( "change to/from route-collector " >-+ log_warnx("change to/from route-collector " >- "mode ignored"); >- if (conf->flags & BGPD_FLAG_NO_EVALUATE) >- nconf->flags |= BGPD_FLAG_NO_EVALUATE; >-@@ -644,10 +791,27 @@ rde_dispatch_imsg_parent(struct imsgbuf >- nconf->flags &= ~BGPD_FLAG_NO_EVALUATE; >- } >- memcpy(conf, nconf, sizeof(struct bgpd_config)); >-+ conf->listen_addrs = NULL; >-+ conf->csock = NULL; >-+ conf->rcsock = NULL; >- free(nconf); >- nconf = NULL; >- parent_set = NULL; >-- prefix_network_clean(peerself, reloadtime, 0); >-+ /* sync peerself with conf */ >-+ peerself->remote_bgpid = ntohl(conf->bgpid); >-+ peerself->conf.local_as = conf->as; >-+ peerself->conf.remote_as = conf->as; >-+ peerself->short_as = conf->short_as; >-+ >-+ /* apply new set of rdomain, sync will be done later */ >-+ while ((rd = SIMPLEQ_FIRST(rdomains_l)) != NULL) { >-+ SIMPLEQ_REMOVE_HEAD(rdomains_l, entry); >-+ filterset_free(&rd->import); >-+ filterset_free(&rd->export); >-+ free(rd); >-+ } >-+ free(rdomains_l); >-+ rdomains_l = newdomains; >- >- /* check if filter changed */ >- LIST_FOREACH(peer, &peerlist, peer_l) { >-@@ -655,30 +819,59 @@ rde_dispatch_imsg_parent(struct imsgbuf >- continue; >- peer->reconf_out = 0; >- peer->reconf_in = 0; >-- if (peer->conf.softreconfig_out && >-- !rde_filter_equal(rules_l, newrules, peer, >-- DIR_OUT)) { >-- peer->reconf_out = 1; >-- reconf_out = 1; >-- } >-+ peer->reconf_rib = 0; >- if (peer->conf.softreconfig_in && >- !rde_filter_equal(rules_l, newrules, peer, >- DIR_IN)) { >- peer->reconf_in = 1; >- reconf_in = 1; >- } >-+ if (peer->ribid != rib_find(peer->conf.rib)) { >-+ rib_dump(&ribs[peer->ribid], >-+ rde_softreconfig_unload_peer, peer, >-+ AID_UNSPEC); >-+ peer->ribid = rib_find(peer->conf.rib); >-+ peer->reconf_rib = 1; >-+ reconf_rib = 1; >-+ continue; >-+ } >-+ if (peer->conf.softreconfig_out && >-+ !rde_filter_equal(rules_l, newrules, peer, >-+ DIR_OUT)) { >-+ peer->reconf_out = 1; >-+ reconf_out = 1; >-+ } >- } >-- /* XXX this needs rework anyway */ >-- /* sync local-RIB first */ >-+ /* bring ribs in sync before softreconfig dance */ >-+ for (rid = 0; rid < rib_size; rid++) { >-+ if (ribs[rid].state == RECONF_DELETE) >-+ rib_free(&ribs[rid]); >-+ else if (ribs[rid].state == RECONF_REINIT) >-+ rib_dump(&ribs[0], >-+ rde_softreconfig_load, &ribs[rid], >-+ AID_UNSPEC); >-+ } >-+ /* sync local-RIBs first */ >- if (reconf_in) >- rib_dump(&ribs[0], rde_softreconfig_in, NULL, >-- AF_UNSPEC); >-+ AID_UNSPEC); >- /* then sync peers */ >- if (reconf_out) { >- int i; >-- for (i = 1; i < rib_size; i++) >-+ for (i = 1; i < rib_size; i++) { >-+ if (ribs[i].state == RECONF_REINIT) >-+ /* already synced by _load */ >-+ continue; >- rib_dump(&ribs[i], rde_softreconfig_out, >-- NULL, AF_UNSPEC); >-+ NULL, AID_UNSPEC); >-+ } >-+ } >-+ if (reconf_rib) { >-+ LIST_FOREACH(peer, &peerlist, peer_l) { >-+ rib_dump(&ribs[peer->ribid], >-+ rde_softreconfig_load_peer, >-+ peer, AID_UNSPEC); >-+ } >- } >- >- while ((r = TAILQ_FIRST(rules_l)) != NULL) { >-@@ -688,16 +881,18 @@ rde_dispatch_imsg_parent(struct imsgbuf >- } >- free(rules_l); >- rules_l = newrules; >-- for (rid = 0; rid < rib_size; rid++) { >-- if (ribs[rid].state == RIB_DELETE) >-- rib_free(&ribs[rid]); >-- } >-+ >- log_info("RDE reconfigured"); >-+ imsg_compose(ibuf_main, IMSG_RECONF_DONE, 0, 0, >-+ -1, NULL, 0); >- break; >- case IMSG_NEXTHOP_UPDATE: >- nexthop_update(imsg.data); >- break; >- case IMSG_FILTER_SET: >-+ if (imsg.hdr.len > IMSG_HEADER_SIZE + >-+ sizeof(struct filter_set)) >-+ fatalx("IMSG_RECONF_CONF bad len"); >- if (parent_set == NULL) { >- log_warnx("rde_dispatch_imsg_parent: " >- "IMSG_FILTER_SET unexpected"); >-@@ -725,7 +920,8 @@ rde_dispatch_imsg_parent(struct imsgbuf >- log_warnx("expected to receive fd for mrt dump " >- "but didn't receive any"); >- else if (xmrt.type == MRT_TABLE_DUMP || >-- xmrt.type == MRT_TABLE_DUMP_MP) { >-+ xmrt.type == MRT_TABLE_DUMP_MP || >-+ xmrt.type == MRT_TABLE_DUMP_V2) { >- rde_dump_mrt_new(&xmrt, imsg.hdr.pid, fd); >- } else >- close(fd); >-@@ -744,6 +940,8 @@ rde_dispatch_imsg_parent(struct imsgbuf >- int >- rde_update_dispatch(struct imsg *imsg) >- { >-+ struct bgpd_addr prefix; >-+ struct mpattr mpa; >- struct rde_peer *peer; >- struct rde_aspath *asp = NULL; >- u_char *p, *mpp = NULL; >-@@ -752,9 +950,8 @@ rde_update_dispatch(struct imsg *imsg) >- u_int16_t withdrawn_len; >- u_int16_t attrpath_len; >- u_int16_t nlri_len; >-- u_int8_t prefixlen, safi, subtype; >-- struct bgpd_addr prefix; >-- struct mpattr mpa; >-+ u_int8_t aid, prefixlen, safi, subtype; >-+ u_int32_t fas; >- >- peer = peer_get(imsg->hdr.peerid); >- if (peer == NULL) /* unknown peer, cannot happen */ >-@@ -810,26 +1007,21 @@ rde_update_dispatch(struct imsg *imsg) >- goto done; >- } >- >-- /* >-- * if either ATTR_AS4_AGGREGATOR or ATTR_AS4_PATH is present >-- * try to fixup the attributes. >-- * XXX do not fixup if F_ATTR_LOOP is set. >-- */ >-- if (asp->flags & F_ATTR_AS4BYTE_NEW && >-- !(asp->flags & F_ATTR_LOOP)) >-- rde_as4byte_fixup(peer, asp); >-+ rde_as4byte_fixup(peer, asp); >- >- /* enforce remote AS if requested */ >- if (asp->flags & F_ATTR_ASPATH && >-- peer->conf.enforce_as == ENFORCE_AS_ON) >-- if (peer->conf.remote_as != >-- aspath_neighbor(asp->aspath)) { >-- log_peer_warnx(&peer->conf, "bad path, " >-- "enforce remote-as enabled"); >-- rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH, >-+ peer->conf.enforce_as == ENFORCE_AS_ON) { >-+ fas = aspath_neighbor(asp->aspath); >-+ if (peer->conf.remote_as != fas) { >-+ log_peer_warnx(&peer->conf, "bad path, " >-+ "starting with %s, " >-+ "enforce neighbor-as enabled", log_as(fas)); >-+ rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH, >- NULL, 0); >-- goto done; >-+ goto done; >- } >-+ } >- >- rde_reflector(peer, asp); >- } >-@@ -860,9 +1052,9 @@ rde_update_dispatch(struct imsg *imsg) >- p += pos; >- len -= pos; >- >-- if (peer->capa_received.mp_v4 == SAFI_NONE && >-- peer->capa_received.mp_v6 != SAFI_NONE) { >-- log_peer_warnx(&peer->conf, "bad AFI, IPv4 disabled"); >-+ if (peer->capa.mp[AID_INET] == 0) { >-+ log_peer_warnx(&peer->conf, >-+ "bad withdraw, %s disabled", aid2str(AID_INET)); >- rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, >- NULL, 0); >- goto done; >-@@ -879,6 +1071,10 @@ rde_update_dispatch(struct imsg *imsg) >- ERR_UPD_ATTRLIST, NULL, 0); >- return (-1); >- } >-+ if (withdrawn_len == 0) { >-+ /* EoR marker */ >-+ peer_recv_eor(peer, AID_INET); >-+ } >- return (0); >- } >- >-@@ -892,15 +1088,30 @@ rde_update_dispatch(struct imsg *imsg) >- afi = ntohs(afi); >- safi = *mpp++; >- mplen--; >-- switch (afi) { >-- case AFI_IPv6: >-- if (peer->capa_received.mp_v6 == SAFI_NONE) { >-- log_peer_warnx(&peer->conf, "bad AFI, " >-- "IPv6 disabled"); >-- rde_update_err(peer, ERR_UPDATE, >-- ERR_UPD_OPTATTR, NULL, 0); >-- goto done; >-- } >-+ >-+ if (afi2aid(afi, safi, &aid) == -1) { >-+ log_peer_warnx(&peer->conf, >-+ "bad AFI/SAFI pair in withdraw"); >-+ rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, >-+ NULL, 0); >-+ goto done; >-+ } >-+ >-+ if (peer->capa.mp[aid] == 0) { >-+ log_peer_warnx(&peer->conf, >-+ "bad withdraw, %s disabled", aid2str(aid)); >-+ rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, >-+ NULL, 0); >-+ goto done; >-+ } >-+ >-+ if ((asp->flags & ~F_ATTR_MP_UNREACH) == 0 && mplen == 0) { >-+ /* EoR marker */ >-+ peer_recv_eor(peer, aid); >-+ } >-+ >-+ switch (aid) { >-+ case AID_INET6: >- while (mplen > 0) { >- if ((pos = rde_update_get_prefix6(mpp, mplen, >- &prefix, &prefixlen)) == -1) { >-@@ -926,6 +1137,32 @@ rde_update_dispatch(struct imsg *imsg) >- rde_update_withdraw(peer, &prefix, prefixlen); >- } >- break; >-+ case AID_VPN_IPv4: >-+ while (mplen > 0) { >-+ if ((pos = rde_update_get_vpn4(mpp, mplen, >-+ &prefix, &prefixlen)) == -1) { >-+ log_peer_warnx(&peer->conf, >-+ "bad VPNv4 withdraw prefix"); >-+ rde_update_err(peer, ERR_UPDATE, >-+ ERR_UPD_OPTATTR, >-+ mpa.unreach, mpa.unreach_len); >-+ goto done; >-+ } >-+ if (prefixlen > 32) { >-+ log_peer_warnx(&peer->conf, >-+ "bad VPNv4 withdraw prefix"); >-+ rde_update_err(peer, ERR_UPDATE, >-+ ERR_UPD_OPTATTR, >-+ mpa.unreach, mpa.unreach_len); >-+ goto done; >-+ } >-+ >-+ mpp += pos; >-+ mplen -= pos; >-+ >-+ rde_update_withdraw(peer, &prefix, prefixlen); >-+ } >-+ break; >- default: >- /* silently ignore unsupported multiprotocol AF */ >- break; >-@@ -963,9 +1200,9 @@ rde_update_dispatch(struct imsg *imsg) >- p += pos; >- nlri_len -= pos; >- >-- if (peer->capa_received.mp_v4 == SAFI_NONE && >-- peer->capa_received.mp_v6 != SAFI_NONE) { >-- log_peer_warnx(&peer->conf, "bad AFI, IPv4 disabled"); >-+ if (peer->capa.mp[AID_INET] == 0) { >-+ log_peer_warnx(&peer->conf, >-+ "bad update, %s disabled", aid2str(AID_INET)); >- rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, >- NULL, 0); >- goto done; >-@@ -995,6 +1232,22 @@ rde_update_dispatch(struct imsg *imsg) >- safi = *mpp++; >- mplen--; >- >-+ if (afi2aid(afi, safi, &aid) == -1) { >-+ log_peer_warnx(&peer->conf, >-+ "bad AFI/SAFI pair in update"); >-+ rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, >-+ NULL, 0); >-+ goto done; >-+ } >-+ >-+ if (peer->capa.mp[aid] == 0) { >-+ log_peer_warnx(&peer->conf, >-+ "bad update, %s disabled", aid2str(aid)); >-+ rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, >-+ NULL, 0); >-+ goto done; >-+ } >-+ >- /* >- * this works because asp is not linked. >- * But first unlock the previously locked nexthop. >-@@ -1004,8 +1257,8 @@ rde_update_dispatch(struct imsg *imsg) >- (void)nexthop_delete(asp->nexthop); >- asp->nexthop = NULL; >- } >-- if ((pos = rde_get_mp_nexthop(mpp, mplen, afi, asp)) == -1) { >-- log_peer_warnx(&peer->conf, "bad IPv6 nlri prefix"); >-+ if ((pos = rde_get_mp_nexthop(mpp, mplen, aid, asp, peer)) == -1) { >-+ log_peer_warnx(&peer->conf, "bad nlri prefix"); >- rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, >- mpa.reach, mpa.reach_len); >- goto done; >-@@ -1013,16 +1266,8 @@ rde_update_dispatch(struct imsg *imsg) >- mpp += pos; >- mplen -= pos; >- >-- switch (afi) { >-- case AFI_IPv6: >-- if (peer->capa_received.mp_v6 == SAFI_NONE) { >-- log_peer_warnx(&peer->conf, "bad AFI, " >-- "IPv6 disabled"); >-- rde_update_err(peer, ERR_UPDATE, >-- ERR_UPD_OPTATTR, NULL, 0); >-- goto done; >-- } >-- >-+ switch (aid) { >-+ case AID_INET6: >- while (mplen > 0) { >- if ((pos = rde_update_get_prefix6(mpp, mplen, >- &prefix, &prefixlen)) == -1) { >-@@ -1058,6 +1303,42 @@ rde_update_dispatch(struct imsg *imsg) >- >- } >- break; >-+ case AID_VPN_IPv4: >-+ while (mplen > 0) { >-+ if ((pos = rde_update_get_vpn4(mpp, mplen, >-+ &prefix, &prefixlen)) == -1) { >-+ log_peer_warnx(&peer->conf, >-+ "bad VPNv4 nlri prefix"); >-+ rde_update_err(peer, ERR_UPDATE, >-+ ERR_UPD_OPTATTR, >-+ mpa.reach, mpa.reach_len); >-+ goto done; >-+ } >-+ if (prefixlen > 32) { >-+ rde_update_err(peer, ERR_UPDATE, >-+ ERR_UPD_OPTATTR, >-+ mpa.reach, mpa.reach_len); >-+ goto done; >-+ } >-+ >-+ mpp += pos; >-+ mplen -= pos; >-+ >-+ rde_update_update(peer, asp, &prefix, >-+ prefixlen); >-+ >-+ /* max prefix checker */ >-+ if (peer->conf.max_prefix && >-+ peer->prefix_cnt >= peer->conf.max_prefix) { >-+ log_peer_warnx(&peer->conf, >-+ "prefix limit reached"); >-+ rde_update_err(peer, ERR_CEASE, >-+ ERR_CEASE_MAX_PREFIX, NULL, 0); >-+ goto done; >-+ } >-+ >-+ } >-+ break; >- default: >- /* silently ignore unsupported multiprotocol AF */ >- break; >-@@ -1085,7 +1366,8 @@ rde_update_update(struct rde_peer *peer, >- struct bgpd_addr *prefix, u_int8_t prefixlen) >- { >- struct rde_aspath *fasp; >-- int r = 0; >-+ enum filter_actions action; >-+ int r = 0, f = 0; >- u_int16_t i; >- >- peer->prefix_rcvd_update++; >-@@ -1095,18 +1377,24 @@ rde_update_update(struct rde_peer *peer, >- >- for (i = 1; i < rib_size; i++) { >- /* input filter */ >-- if (rde_filter(i, &fasp, rules_l, peer, asp, prefix, prefixlen, >-- peer, DIR_IN) == ACTION_DENY) >-- goto done; >-+ action = rde_filter(i, &fasp, rules_l, peer, asp, prefix, >-+ prefixlen, peer, DIR_IN); >- >- if (fasp == NULL) >- fasp = asp; >- >-- rde_update_log("update", i, peer, &fasp->nexthop->exit_nexthop, >-- prefix, prefixlen); >-- r += path_update(&ribs[i], peer, fasp, prefix, prefixlen); >-+ if (action == ACTION_ALLOW) { >-+ rde_update_log("update", i, peer, >-+ &fasp->nexthop->exit_nexthop, prefix, prefixlen); >-+ r += path_update(&ribs[i], peer, fasp, prefix, >-+ prefixlen); >-+ } else if (prefix_remove(&ribs[i], peer, prefix, prefixlen, >-+ 0)) { >-+ rde_update_log("filtered withdraw", i, peer, >-+ NULL, prefix, prefixlen); >-+ f++; >-+ } >- >--done: >- /* free modified aspath */ >- if (fasp != asp) >- path_put(fasp); >-@@ -1114,6 +1402,8 @@ done: >- >- if (r) >- peer->prefix_cnt++; >-+ else if (f) >-+ peer->prefix_cnt--; >- } >- >- void >-@@ -1152,7 +1442,7 @@ rde_update_withdraw(struct rde_peer *pee >- } while (0) >- >- #define CHECK_FLAGS(s, t, m) \ >-- (((s) & ~(ATTR_EXTLEN | (m))) == (t)) >-+ (((s) & ~(ATTR_DEFMASK | (m))) == (t)) >- >- int >- rde_attr_parse(u_char *p, u_int16_t len, struct rde_peer *peer, >-@@ -1161,6 +1451,7 @@ rde_attr_parse(u_char *p, u_int16_t len, >- struct bgpd_addr nexthop; >- u_char *op = p, *npath; >- u_int32_t tmp32; >-+ int err; >- u_int16_t attr_len, nlen; >- u_int16_t plen = 0; >- u_int8_t flags; >-@@ -1195,6 +1486,7 @@ bad_len: >- switch (type) { >- case ATTR_UNDEF: >- /* ignore and drop path attributes with a type code of 0 */ >-+ plen += attr_len; >- break; >- case ATTR_ORIGIN: >- if (attr_len != 1) >-@@ -1220,7 +1512,17 @@ bad_flags: >- case ATTR_ASPATH: >- if (!CHECK_FLAGS(flags, ATTR_WELL_KNOWN, 0)) >- goto bad_flags; >-- if (aspath_verify(p, attr_len, rde_as4byte(peer)) != 0) { >-+ err = aspath_verify(p, attr_len, rde_as4byte(peer)); >-+ if (err == AS_ERR_SOFT) { >-+ /* >-+ * soft errors like unexpected segment types are >-+ * not considered fatal and the path is just >-+ * marked invalid. >-+ */ >-+ a->flags |= F_ATTR_PARSE_ERR; >-+ log_peer_warnx(&peer->conf, "bad ASPATH, " >-+ "path invalidated and prefix withdrawn"); >-+ } else if (err != 0) { >- rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH, >- NULL, 0); >- return (-1); >-@@ -1248,7 +1550,7 @@ bad_flags: >- a->flags |= F_ATTR_NEXTHOP; >- >- bzero(&nexthop, sizeof(nexthop)); >-- nexthop.af = AF_INET; >-+ nexthop.aid = AID_INET; >- UPD_READ(&nexthop.v4.s_addr, p, plen, 4); >- /* >- * Check if the nexthop is a valid IP address. We consider >-@@ -1305,9 +1607,21 @@ bad_flags: >- goto optattr; >- case ATTR_AGGREGATOR: >- if ((!rde_as4byte(peer) && attr_len != 6) || >-- (rde_as4byte(peer) && attr_len != 8)) >-- goto bad_len; >-- if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, 0)) >-+ (rde_as4byte(peer) && attr_len != 8)) { >-+ /* >-+ * ignore attribute in case of error as per >-+ * draft-ietf-idr-optional-transitive-00.txt >-+ * but only if partial bit is set >-+ */ >-+ if ((flags & ATTR_PARTIAL) == 0) >-+ goto bad_len; >-+ log_peer_warnx(&peer->conf, "bad AGGREGATOR, " >-+ "partial attribute ignored"); >-+ plen += attr_len; >-+ break; >-+ } >-+ if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, >-+ ATTR_PARTIAL)) >- goto bad_flags; >- if (!rde_as4byte(peer)) { >- /* need to inflate aggregator AS to 4-byte */ >-@@ -1323,8 +1637,35 @@ bad_flags: >- /* 4-byte ready server take the default route */ >- goto optattr; >- case ATTR_COMMUNITIES: >-- if ((attr_len & 0x3) != 0) >-- goto bad_len; >-+ if (attr_len % 4 != 0) { >-+ /* >-+ * mark update as bad and withdraw all routes as per >-+ * draft-ietf-idr-optional-transitive-00.txt >-+ * but only if partial bit is set >-+ */ >-+ if ((flags & ATTR_PARTIAL) == 0) >-+ goto bad_len; >-+ a->flags |= F_ATTR_PARSE_ERR; >-+ log_peer_warnx(&peer->conf, "bad COMMUNITIES, " >-+ "path invalidated and prefix withdrawn"); >-+ } >-+ if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, >-+ ATTR_PARTIAL)) >-+ goto bad_flags; >-+ goto optattr; >-+ case ATTR_EXT_COMMUNITIES: >-+ if (attr_len % 8 != 0) { >-+ /* >-+ * mark update as bad and withdraw all routes as per >-+ * draft-ietf-idr-optional-transitive-00.txt >-+ * but only if partial bit is set >-+ */ >-+ if ((flags & ATTR_PARTIAL) == 0) >-+ goto bad_len; >-+ a->flags |= F_ATTR_PARSE_ERR; >-+ log_peer_warnx(&peer->conf, "bad EXT_COMMUNITIES, " >-+ "path invalidated and prefix withdrawn"); >-+ } >- if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, >- ATTR_PARTIAL)) >- goto bad_flags; >-@@ -1336,7 +1677,7 @@ bad_flags: >- goto bad_flags; >- goto optattr; >- case ATTR_CLUSTER_LIST: >-- if ((attr_len & 0x3) != 0) >-+ if (attr_len % 4 != 0) >- goto bad_len; >- if (!CHECK_FLAGS(flags, ATTR_OPTIONAL, 0)) >- goto bad_flags; >-@@ -1370,8 +1711,15 @@ bad_flags: >- plen += attr_len; >- break; >- case ATTR_AS4_AGGREGATOR: >-- if (attr_len != 8) >-- goto bad_len; >-+ if (attr_len != 8) { >-+ /* see ATTR_AGGREGATOR ... */ >-+ if ((flags & ATTR_PARTIAL) == 0) >-+ goto bad_len; >-+ log_peer_warnx(&peer->conf, "bad AS4_AGGREGATOR, " >-+ "partial attribute ignored"); >-+ plen += attr_len; >-+ break; >-+ } >- if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, >- ATTR_PARTIAL)) >- goto bad_flags; >-@@ -1381,20 +1729,31 @@ bad_flags: >- if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, >- ATTR_PARTIAL)) >- goto bad_flags; >-- if (aspath_verify(p, attr_len, 1) != 0) { >-+ if ((err = aspath_verify(p, attr_len, 1)) != 0) { >- /* >- * XXX RFC does not specify how to handle errors. >- * XXX Instead of dropping the session because of a >-- * XXX bad path just mark the full update as not >-- * XXX loop-free the update is no longer eligible and >-- * XXX will not be considered for routing or >-- * XXX redistribution. Something better is needed. >-+ * XXX bad path just mark the full update as having >-+ * XXX a parse error which makes the update no longer >-+ * XXX eligible and will not be considered for routing >-+ * XXX or redistribution. >-+ * XXX We follow draft-ietf-idr-optional-transitive >-+ * XXX by looking at the partial bit. >-+ * XXX Consider soft errors similar to a partial attr. >- */ >-- a->flags |= F_ATTR_LOOP; >-- goto optattr; >-- } >-- a->flags |= F_ATTR_AS4BYTE_NEW; >-- goto optattr; >-+ if (flags & ATTR_PARTIAL || err == AS_ERR_SOFT) { >-+ a->flags |= F_ATTR_PARSE_ERR; >-+ log_peer_warnx(&peer->conf, "bad AS4_PATH, " >-+ "path invalidated and prefix withdrawn"); >-+ goto optattr; >-+ } else { >-+ rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH, >-+ NULL, 0); >-+ return (-1); >-+ } >-+ } >-+ a->flags |= F_ATTR_AS4BYTE_NEW; >-+ goto optattr; >- default: >- if ((flags & ATTR_OPTIONAL) == 0) { >- rde_update_err(peer, ERR_UPDATE, ERR_UPD_UNKNWN_WK_ATTR, >-@@ -1415,6 +1774,42 @@ bad_list: >- >- return (plen); >- } >-+ >-+int >-+rde_attr_add(struct rde_aspath *a, u_char *p, u_int16_t len) >-+{ >-+ u_int16_t attr_len; >-+ u_int16_t plen = 0; >-+ u_int8_t flags; >-+ u_int8_t type; >-+ u_int8_t tmp8; >-+ >-+ if (a == NULL) /* no aspath, nothing to do */ >-+ return (0); >-+ if (len < 3) >-+ return (-1); >-+ >-+ UPD_READ(&flags, p, plen, 1); >-+ UPD_READ(&type, p, plen, 1); >-+ >-+ if (flags & ATTR_EXTLEN) { >-+ if (len - plen < 2) >-+ return (-1); >-+ UPD_READ(&attr_len, p, plen, 2); >-+ attr_len = ntohs(attr_len); >-+ } else { >-+ UPD_READ(&tmp8, p, plen, 1); >-+ attr_len = tmp8; >-+ } >-+ >-+ if (len - plen < attr_len) >-+ return (-1); >-+ >-+ if (attr_optadd(a, flags, type, p, attr_len) == -1) >-+ return (-1); >-+ return (0); >-+} >-+ >- #undef UPD_READ >- #undef CHECK_FLAGS >- >-@@ -1440,8 +1835,8 @@ rde_attr_missing(struct rde_aspath *a, i >- } >- >- int >--rde_get_mp_nexthop(u_char *data, u_int16_t len, u_int16_t afi, >-- struct rde_aspath *asp) >-+rde_get_mp_nexthop(u_char *data, u_int16_t len, u_int8_t aid, >-+ struct rde_aspath *asp, struct rde_peer *peer) >- { >- struct bgpd_addr nexthop; >- u_int8_t totlen, nhlen; >-@@ -1457,8 +1852,9 @@ rde_get_mp_nexthop(u_char *data, u_int16 >- return (-1); >- >- bzero(&nexthop, sizeof(nexthop)); >-- switch (afi) { >-- case AFI_IPv6: >-+ nexthop.aid = aid; >-+ switch (aid) { >-+ case AID_INET6: >- /* >- * RFC2545 describes that there may be a link-local >- * address carried in nexthop. Yikes! >-@@ -1471,72 +1867,144 @@ rde_get_mp_nexthop(u_char *data, u_int16 >- log_warnx("bad multiprotocol nexthop, bad size"); >- return (-1); >- } >-- nexthop.af = AF_INET6; >- memcpy(&nexthop.v6.s6_addr, data, 16); >-- asp->nexthop = nexthop_get(&nexthop); >-+#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER) >-+ if (IN6_IS_ADDR_LINKLOCAL(&nexthop.v6) && >-+ peer->conf.lliface[0]) { >-+ int ifindex; >-+ >-+ ifindex = if_nametoindex(peer->conf.lliface); >-+ if (ifindex != 0) { >-+ SET_IN6_LINKLOCAL_IFINDEX(nexthop.v6, ifindex); >-+ nexthop.scope_id = ifindex; >-+ } else >-+ log_warnx("bad interface: %s", peer->conf.lliface); >-+ } >-+#endif >-+ break; >-+ case AID_VPN_IPv4: >- /* >-- * lock the nexthop because it is not yet linked else >-- * withdraws may remove this nexthop which in turn would >-- * cause a use after free error. >-+ * Neither RFC4364 nor RFC3107 specify the format of the >-+ * nexthop in an explicit way. The quality of RFC went down >-+ * the toilet the larger the number got. >-+ * RFC4364 is very confusing about VPN-IPv4 address and the >-+ * VPN-IPv4 prefix that carries also a MPLS label. >-+ * So the nexthop is a 12-byte address with a 64bit RD and >-+ * an IPv4 address following. In the nexthop case the RD can >-+ * be ignored. >-+ * Since the nexthop has to be in the main IPv4 table just >-+ * create an AID_INET nexthop. So we don't need to handle >-+ * AID_VPN_IPv4 in nexthop and kroute. >- */ >-- asp->nexthop->refcnt++; >-- >-- /* ignore reserved (old SNPA) field as per RFC 4760 */ >-- totlen += nhlen + 1; >-- data += nhlen + 1; >-- >-- return (totlen); >-- default: >-- log_warnx("bad multiprotocol nexthop, bad AF"); >-+ if (nhlen != 12) { >-+ log_warnx("bad multiprotocol nexthop, bad size"); >-+ return (-1); >-+ } >-+ data += sizeof(u_int64_t); >-+ nexthop.aid = AID_INET; >-+ memcpy(&nexthop.v4, data, sizeof(nexthop.v4)); >- break; >-+ default: >-+ log_warnx("bad multiprotocol nexthop, bad AID"); >-+ return (-1); >- } >- >-- return (-1); >-+ asp->nexthop = nexthop_get(&nexthop); >-+ /* >-+ * lock the nexthop because it is not yet linked else >-+ * withdraws may remove this nexthop which in turn would >-+ * cause a use after free error. >-+ */ >-+ asp->nexthop->refcnt++; >-+ >-+ /* ignore reserved (old SNPA) field as per RFC4760 */ >-+ totlen += nhlen + 1; >-+ data += nhlen + 1; >-+ >-+ return (totlen); >-+} >-+ >-+int >-+rde_update_extract_prefix(u_char *p, u_int16_t len, void *va, >-+ u_int8_t pfxlen, u_int8_t max) >-+{ >-+ static u_char addrmask[] = { >-+ 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; >-+ u_char *a = va; >-+ int i; >-+ u_int16_t plen = 0; >-+ >-+ for (i = 0; pfxlen && i < max; i++) { >-+ if (len <= plen) >-+ return (-1); >-+ if (pfxlen < 8) { >-+ a[i] = *p++ & addrmask[pfxlen]; >-+ plen++; >-+ break; >-+ } else { >-+ a[i] = *p++; >-+ plen++; >-+ pfxlen -= 8; >-+ } >-+ } >-+ return (plen); >- } >- >- int >- rde_update_get_prefix(u_char *p, u_int16_t len, struct bgpd_addr *prefix, >- u_int8_t *prefixlen) >- { >-- int i; >-- u_int8_t pfxlen; >-- u_int16_t plen; >-- union { >-- struct in_addr a32; >-- u_int8_t a8[4]; >-- } addr; >-+ u_int8_t pfxlen; >-+ int plen; >- >- if (len < 1) >- return (-1); >- >-- memcpy(&pfxlen, p, 1); >-- p += 1; >-- plen = 1; >-+ pfxlen = *p++; >-+ len--; >- >- bzero(prefix, sizeof(struct bgpd_addr)); >-- addr.a32.s_addr = 0; >-- for (i = 0; i <= 3; i++) { >-- if (pfxlen > i * 8) { >-- if (len - plen < 1) >-- return (-1); >-- memcpy(&addr.a8[i], p++, 1); >-- plen++; >-- } >-- } >-- prefix->af = AF_INET; >-- prefix->v4.s_addr = addr.a32.s_addr; >-+ prefix->aid = AID_INET; >- *prefixlen = pfxlen; >- >-- return (plen); >-+ if ((plen = rde_update_extract_prefix(p, len, &prefix->v4, pfxlen, >-+ sizeof(prefix->v4))) == -1) >-+ return (-1); >-+ >-+ return (plen + 1); /* pfxlen needs to be added */ >- } >- >- int >- rde_update_get_prefix6(u_char *p, u_int16_t len, struct bgpd_addr *prefix, >- u_int8_t *prefixlen) >- { >-- int i; >-+ int plen; >- u_int8_t pfxlen; >-- u_int16_t plen; >-+ >-+ if (len < 1) >-+ return (-1); >-+ >-+ pfxlen = *p++; >-+ len--; >-+ >-+ bzero(prefix, sizeof(struct bgpd_addr)); >-+ prefix->aid = AID_INET6; >-+ *prefixlen = pfxlen; >-+ >-+ if ((plen = rde_update_extract_prefix(p, len, &prefix->v6, pfxlen, >-+ sizeof(prefix->v6))) == -1) >-+ return (-1); >-+ >-+ return (plen + 1); /* pfxlen needs to be added */ >-+} >-+ >-+int >-+rde_update_get_vpn4(u_char *p, u_int16_t len, struct bgpd_addr *prefix, >-+ u_int8_t *prefixlen) >-+{ >-+ int rv, done = 0; >-+ u_int8_t pfxlen; >-+ u_int16_t plen; >- >- if (len < 1) >- return (-1); >-@@ -1546,25 +2014,50 @@ rde_update_get_prefix6(u_char *p, u_int1 >- plen = 1; >- >- bzero(prefix, sizeof(struct bgpd_addr)); >-- for (i = 0; i <= 15; i++) { >-- if (pfxlen > i * 8) { >-- if (len - plen < 1) >-- return (-1); >-- memcpy(&prefix->v6.s6_addr[i], p++, 1); >-- plen++; >-- } >-- } >-- prefix->af = AF_INET6; >-+ >-+ /* label stack */ >-+ do { >-+ if (len - plen < 3 || pfxlen < 3 * 8) >-+ return (-1); >-+ if (prefix->vpn4.labellen + 3U > >-+ sizeof(prefix->vpn4.labelstack)) >-+ return (-1); >-+ prefix->vpn4.labelstack[prefix->vpn4.labellen++] = *p++; >-+ prefix->vpn4.labelstack[prefix->vpn4.labellen++] = *p++; >-+ prefix->vpn4.labelstack[prefix->vpn4.labellen] = *p++; >-+ if (prefix->vpn4.labelstack[prefix->vpn4.labellen] & >-+ BGP_MPLS_BOS) >-+ done = 1; >-+ prefix->vpn4.labellen++; >-+ plen += 3; >-+ pfxlen -= 3 * 8; >-+ } while (!done); >-+ >-+ /* RD */ >-+ if (len - plen < (int)sizeof(u_int64_t) || >-+ pfxlen < sizeof(u_int64_t) * 8) >-+ return (-1); >-+ memcpy(&prefix->vpn4.rd, p, sizeof(u_int64_t)); >-+ pfxlen -= sizeof(u_int64_t) * 8; >-+ p += sizeof(u_int64_t); >-+ plen += sizeof(u_int64_t); >-+ >-+ /* prefix */ >-+ prefix->aid = AID_VPN_IPv4; >- *prefixlen = pfxlen; >- >-- return (plen); >-+ if ((rv = rde_update_extract_prefix(p, len, &prefix->vpn4.addr, >-+ pfxlen, sizeof(prefix->vpn4.addr))) == -1) >-+ return (-1); >-+ >-+ return (plen + rv); >- } >- >- void >- rde_update_err(struct rde_peer *peer, u_int8_t error, u_int8_t suberr, >- void *data, u_int16_t size) >- { >-- struct buf *wbuf; >-+ struct ibuf *wbuf; >- >- if ((wbuf = imsg_create(ibuf_se, IMSG_UPDATE_ERR, peer->conf.id, 0, >- size + sizeof(error) + sizeof(suberr))) == NULL) >-@@ -1616,16 +2109,30 @@ rde_as4byte_fixup(struct rde_peer *peer, >- struct attr *nasp, *naggr, *oaggr; >- u_int32_t as; >- >-+ /* >-+ * if either ATTR_AS4_AGGREGATOR or ATTR_AS4_PATH is present >-+ * try to fixup the attributes. >-+ * Do not fixup if F_ATTR_PARSE_ERR is set. >-+ */ >-+ if (!(a->flags & F_ATTR_AS4BYTE_NEW) || a->flags & F_ATTR_PARSE_ERR) >-+ return; >-+ >- /* first get the attributes */ >- nasp = attr_optget(a, ATTR_AS4_PATH); >- naggr = attr_optget(a, ATTR_AS4_AGGREGATOR); >- >- if (rde_as4byte(peer)) { >- /* NEW session using 4-byte ASNs */ >-- if (nasp) >-+ if (nasp) { >-+ log_peer_warnx(&peer->conf, "uses 4-byte ASN " >-+ "but sent AS4_PATH attribute."); >- attr_free(a, nasp); >-- if (naggr) >-+ } >-+ if (naggr) { >-+ log_peer_warnx(&peer->conf, "uses 4-byte ASN " >-+ "but sent AS4_AGGREGATOR attribute."); >- attr_free(a, naggr); >-+ } >- return; >- } >- /* OLD session using 2-byte ASNs */ >-@@ -1669,6 +2176,10 @@ rde_reflector(struct rde_peer *peer, str >- u_int16_t len; >- u_int32_t id; >- >-+ /* do not consider updates with parse errors */ >-+ if (asp->flags & F_ATTR_PARSE_ERR) >-+ return; >-+ >- /* check for originator id if eq router_id drop */ >- if ((a = attr_optget(asp, ATTR_ORIGINATOR_ID)) != NULL) { >- if (memcmp(&conf->bgpid, a->data, sizeof(conf->bgpid)) == 0) { >-@@ -1677,10 +2188,10 @@ rde_reflector(struct rde_peer *peer, str >- return; >- } >- } else if (conf->flags & BGPD_FLAG_REFLECTOR) { >-- if (peer->conf.ebgp == 0) >-- id = htonl(peer->remote_bgpid); >-- else >-+ if (peer->conf.ebgp) >- id = conf->bgpid; >-+ else >-+ id = htonl(peer->remote_bgpid); >- if (attr_optadd(asp, ATTR_OPTIONAL, ATTR_ORIGINATOR_ID, >- &id, sizeof(u_int32_t)) == -1) >- fatalx("attr_optadd failed but impossible"); >-@@ -1724,17 +2235,17 @@ void >- rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags) >- { >- struct ctl_show_rib rib; >-- struct buf *wbuf; >-+ struct ibuf *wbuf; >- struct attr *a; >- void *bp; >-+ time_t staletime; >- u_int8_t l; >- >- bzero(&rib, sizeof(rib)); >- rib.lastchange = p->lastchange; >- rib.local_pref = asp->lpref; >- rib.med = asp->med; >-- rib.prefix_cnt = asp->prefix_cnt; >-- rib.active_cnt = asp->active_cnt; >-+ rib.weight = asp->weight; >- strlcpy(rib.descr, asp->peer->conf.descr, sizeof(rib.descr)); >- memcpy(&rib.remote_addr, &asp->peer->remote_addr, >- sizeof(rib.remote_addr)); >-@@ -1748,23 +2259,26 @@ rde_dump_rib_as(struct prefix *p, struct >- /* announced network may have a NULL nexthop */ >- bzero(&rib.true_nexthop, sizeof(rib.true_nexthop)); >- bzero(&rib.exit_nexthop, sizeof(rib.exit_nexthop)); >-- rib.true_nexthop.af = p->prefix->af; >-- rib.exit_nexthop.af = p->prefix->af; >-+ rib.true_nexthop.aid = p->prefix->aid; >-+ rib.exit_nexthop.aid = p->prefix->aid; >- } >- pt_getaddr(p->prefix, &rib.prefix); >- rib.prefixlen = p->prefix->prefixlen; >- rib.origin = asp->origin; >- rib.flags = 0; >- if (p->rib->active == p) >-- rib.flags |= F_RIB_ACTIVE; >-- if (asp->peer->conf.ebgp == 0) >-- rib.flags |= F_RIB_INTERNAL; >-+ rib.flags |= F_PREF_ACTIVE; >-+ if (!asp->peer->conf.ebgp) >-+ rib.flags |= F_PREF_INTERNAL; >- if (asp->flags & F_PREFIX_ANNOUNCED) >-- rib.flags |= F_RIB_ANNOUNCE; >-+ rib.flags |= F_PREF_ANNOUNCE; >- if (asp->nexthop == NULL || asp->nexthop->state == NEXTHOP_REACH) >-- rib.flags |= F_RIB_ELIGIBLE; >-+ rib.flags |= F_PREF_ELIGIBLE; >- if (asp->flags & F_ATTR_LOOP) >-- rib.flags &= ~F_RIB_ELIGIBLE; >-+ rib.flags &= ~F_PREF_ELIGIBLE; >-+ staletime = asp->peer->staletime[p->prefix->aid]; >-+ if (staletime && p->lastchange <= staletime) >-+ rib.flags |= F_PREF_STALE; >- rib.aspath_len = aspath_length(asp->aspath); >- >- if ((wbuf = imsg_create(ibuf_se_ctl, IMSG_CTL_SHOW_RIB, 0, pid, >-@@ -1784,13 +2298,13 @@ rde_dump_rib_as(struct prefix *p, struct >- IMSG_CTL_SHOW_RIB_ATTR, 0, pid, >- attr_optlen(a))) == NULL) >- return; >-- if ((bp = buf_reserve(wbuf, attr_optlen(a))) == NULL) { >-- buf_free(wbuf); >-+ if ((bp = ibuf_reserve(wbuf, attr_optlen(a))) == NULL) { >-+ ibuf_free(wbuf); >- return; >- } >- if (attr_write(bp, attr_optlen(a), a->flags, >- a->type, a->data, a->len) == -1) { >-- buf_free(wbuf); >-+ ibuf_free(wbuf); >- return; >- } >- imsg_close(ibuf_se_ctl, wbuf); >-@@ -1828,17 +2342,20 @@ rde_dump_filter(struct prefix *p, struct >- { >- struct rde_peer *peer; >- >-- if (req->flags & F_CTL_ADJ_IN || >-+ if (req->flags & F_CTL_ADJ_IN || >- !(req->flags & (F_CTL_ADJ_IN|F_CTL_ADJ_OUT))) { >- if (req->peerid && req->peerid != p->aspath->peer->conf.id) >- return; >-- if (req->type == IMSG_CTL_SHOW_RIB_AS && >-- !aspath_match(p->aspath->aspath, req->as.type, req->as.as)) >-+ if (req->type == IMSG_CTL_SHOW_RIB_AS && >-+ !aspath_match(p->aspath->aspath->data, >-+ p->aspath->aspath->len, req->as.type, req->as.as)) >- return; >- if (req->type == IMSG_CTL_SHOW_RIB_COMMUNITY && >-- !rde_filter_community(p->aspath, req->community.as, >-+ !community_match(p->aspath, req->community.as, >- req->community.type)) >- return; >-+ if ((req->flags & F_CTL_ACTIVE) && p->rib->active != p) >-+ return; >- rde_dump_rib_as(p, p->aspath, req->pid, req->flags); >- } else if (req->flags & F_CTL_ADJ_OUT) { >- if (p->rib->active != p) >-@@ -1872,7 +2389,7 @@ rde_dump_prefix_upcall(struct rib_entry >- >- pt = re->prefix; >- pt_getaddr(pt, &addr); >-- if (addr.af != ctx->req.prefix.af) >-+ if (addr.aid != ctx->req.prefix.aid) >- return; >- if (ctx->req.prefixlen > pt->prefixlen) >- return; >-@@ -1889,6 +2406,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req >- struct rib_entry *re; >- u_int error; >- u_int16_t id; >-+ u_int8_t hostplen = 0; >- >- if ((ctx = calloc(1, sizeof(*ctx))) == NULL) { >- log_warn("rde_dump_ctx_new"); >-@@ -1902,6 +2420,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req >- error = CTL_RES_NOSUCHPEER; >- imsg_compose(ibuf_se_ctl, IMSG_CTL_RESULT, 0, pid, -1, &error, >- sizeof(error)); >-+ free(ctx); >- return; >- } >- >-@@ -1924,7 +2443,18 @@ rde_dump_ctx_new(struct ctl_show_rib_req >- ctx->ribctx.ctx_upcall = rde_dump_prefix_upcall; >- break; >- } >-- if (req->prefixlen == 32) >-+ switch (req->prefix.aid) { >-+ case AID_INET: >-+ case AID_VPN_IPv4: >-+ hostplen = 32; >-+ break; >-+ case AID_INET6: >-+ hostplen = 128; >-+ break; >-+ default: >-+ fatalx("rde_dump_ctx_new: unknown af"); >-+ } >-+ if (req->prefixlen == hostplen) >- re = rib_lookup(&ribs[id], &req->prefix); >- else >- re = rib_get(&ribs[id], &req->prefix, req->prefixlen); >-@@ -1937,7 +2467,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req >- } >- ctx->ribctx.ctx_done = rde_dump_done; >- ctx->ribctx.ctx_arg = ctx; >-- ctx->ribctx.ctx_af = ctx->req.af; >-+ ctx->ribctx.ctx_aid = ctx->req.aid; >- rib_dump_r(&ctx->ribctx); >- } >- >-@@ -1971,13 +2501,17 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t >- free(ctx); >- return; >- } >-+ >-+ if (ctx->mrt.type == MRT_TABLE_DUMP_V2) >-+ mrt_dump_v2_hdr(&ctx->mrt, conf, &peerlist); >-+ >- ctx->ribctx.ctx_count = RDE_RUNNER_ROUNDS; >- ctx->ribctx.ctx_rib = &ribs[id]; >- ctx->ribctx.ctx_upcall = mrt_dump_upcall; >-- ctx->ribctx.ctx_done = mrt_dump_done; >-+ ctx->ribctx.ctx_done = mrt_done; >- ctx->ribctx.ctx_arg = &ctx->mrt; >-- ctx->ribctx.ctx_af = AF_UNSPEC; >-- LIST_INSERT_HEAD(&rde_mrts, &ctx->mrt, entry); >-+ ctx->ribctx.ctx_aid = AID_UNSPEC; >-+ LIST_INSERT_HEAD(&rde_mrts, ctx, entry); >- rde_mrt_cnt++; >- rib_dump_r(&ctx->ribctx); >- } >-@@ -1985,13 +2519,25 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t >- /* >- * kroute specific functions >- */ >-+int >-+rde_rdomain_import(struct rde_aspath *asp, struct rdomain *rd) >-+{ >-+ struct filter_set *s; >-+ >-+ TAILQ_FOREACH(s, &rd->import, entry) { >-+ if (community_ext_match(asp, &s->action.ext_community, 0)) >-+ return (1); >-+ } >-+ return (0); >-+} >-+ >- void >--rde_send_kroute(struct prefix *new, struct prefix *old) >-+rde_send_kroute(struct prefix *new, struct prefix *old, u_int16_t ribid) >- { >-- struct kroute_label kl; >-- struct kroute6_label kl6; >-+ struct kroute_full kr; >- struct bgpd_addr addr; >- struct prefix *p; >-+ struct rdomain *rd; >- enum imsg_type type; >- >- /* >-@@ -2011,43 +2557,43 @@ rde_send_kroute(struct prefix *new, stru >- } >- >- pt_getaddr(p->prefix, &addr); >-- switch (addr.af) { >-- case AF_INET: >-- bzero(&kl, sizeof(kl)); >-- kl.kr.prefix.s_addr = addr.v4.s_addr; >-- kl.kr.prefixlen = p->prefix->prefixlen; >-- if (p->aspath->flags & F_NEXTHOP_REJECT) >-- kl.kr.flags |= F_REJECT; >-- if (p->aspath->flags & F_NEXTHOP_BLACKHOLE) >-- kl.kr.flags |= F_BLACKHOLE; >-- if (type == IMSG_KROUTE_CHANGE) >-- kl.kr.nexthop.s_addr = >-- p->aspath->nexthop->true_nexthop.v4.s_addr; >-- strlcpy(kl.label, rtlabel_id2name(p->aspath->rtlabelid), >-- sizeof(kl.label)); >-- if (imsg_compose(ibuf_main, type, 0, 0, -1, &kl, >-- sizeof(kl)) == -1) >-- fatal("imsg_compose error"); >-+ bzero(&kr, sizeof(kr)); >-+ memcpy(&kr.prefix, &addr, sizeof(kr.prefix)); >-+ kr.prefixlen = p->prefix->prefixlen; >-+ if (p->aspath->flags & F_NEXTHOP_REJECT) >-+ kr.flags |= F_REJECT; >-+ if (p->aspath->flags & F_NEXTHOP_BLACKHOLE) >-+ kr.flags |= F_BLACKHOLE; >-+ if (type == IMSG_KROUTE_CHANGE) >-+ memcpy(&kr.nexthop, &p->aspath->nexthop->true_nexthop, >-+ sizeof(kr.nexthop)); >-+ strlcpy(kr.label, rtlabel_id2name(p->aspath->rtlabelid), >-+ sizeof(kr.label)); >-+ >-+ switch (addr.aid) { >-+ case AID_VPN_IPv4: >-+ if (ribid != 1) >-+ /* not Loc-RIB, no update for VPNs */ >-+ break; >-+ >-+ SIMPLEQ_FOREACH(rd, rdomains_l, entry) { >-+ if (!rde_rdomain_import(p->aspath, rd)) >-+ continue; >-+ /* must send exit_nexthop so that correct MPLS tunnel >-+ * is chosen >-+ */ >-+ if (type == IMSG_KROUTE_CHANGE) >-+ memcpy(&kr.nexthop, >-+ &p->aspath->nexthop->exit_nexthop, >-+ sizeof(kr.nexthop)); >-+ if (imsg_compose(ibuf_main, type, rd->rtableid, 0, -1, >-+ &kr, sizeof(kr)) == -1) >-+ fatal("imsg_compose error"); >-+ } >- break; >-- case AF_INET6: >-- bzero(&kl6, sizeof(kl6)); >-- memcpy(&kl6.kr.prefix, &addr.v6, sizeof(struct in6_addr)); >-- kl6.kr.prefixlen = p->prefix->prefixlen; >-- if (p->aspath->flags & F_NEXTHOP_REJECT) >-- kl6.kr.flags |= F_REJECT; >-- if (p->aspath->flags & F_NEXTHOP_BLACKHOLE) >-- kl6.kr.flags |= F_BLACKHOLE; >-- if (type == IMSG_KROUTE_CHANGE) { >-- type = IMSG_KROUTE6_CHANGE; >-- memcpy(&kl6.kr.nexthop, >-- &p->aspath->nexthop->true_nexthop.v6, >-- sizeof(struct in6_addr)); >-- } else >-- type = IMSG_KROUTE6_DELETE; >-- strlcpy(kl6.label, rtlabel_id2name(p->aspath->rtlabelid), >-- sizeof(kl6.label)); >-- if (imsg_compose(ibuf_main, type, 0, 0, -1, &kl6, >-- sizeof(kl6)) == -1) >-+ default: >-+ if (imsg_compose(ibuf_main, type, ribs[ribid].rtableid, 0, -1, >-+ &kr, sizeof(kr)) == -1) >- fatal("imsg_compose error"); >- break; >- } >-@@ -2098,7 +2644,6 @@ rde_send_pftable_commit(void) >- void >- rde_send_nexthop(struct bgpd_addr *next, int valid) >- { >-- size_t size; >- int type; >- >- if (valid) >-@@ -2106,8 +2651,6 @@ rde_send_nexthop(struct bgpd_addr *next, >- else >- type = IMSG_NEXTHOP_REMOVE; >- >-- size = sizeof(struct bgpd_addr); >-- >- if (imsg_compose(ibuf_main, type, 0, 0, -1, next, >- sizeof(struct bgpd_addr)) == -1) >- fatal("imsg_compose error"); >-@@ -2201,6 +2744,10 @@ rde_softreconfig_in(struct rib_entry *re >- continue; >- >- for (i = 1; i < rib_size; i++) { >-+ /* only active ribs need a softreconfig rerun */ >-+ if (ribs[i].state != RECONF_KEEP) >-+ continue; >-+ >- /* check if prefix changed */ >- oa = rde_filter(i, &oasp, rules_l, peer, asp, &addr, >- pt->prefixlen, peer, DIR_IN); >-@@ -2228,7 +2775,7 @@ rde_softreconfig_in(struct rib_entry *re >- if (path_compare(nasp, oasp) == 0) >- goto done; >- /* send update */ >-- path_update(&ribs[1], peer, nasp, &addr, >-+ path_update(&ribs[i], peer, nasp, &addr, >- pt->prefixlen); >- } >- >-@@ -2241,6 +2788,104 @@ done: >- } >- } >- >-+void >-+rde_softreconfig_load(struct rib_entry *re, void *ptr) >-+{ >-+ struct rib *rib = ptr; >-+ struct prefix *p, *np; >-+ struct pt_entry *pt; >-+ struct rde_peer *peer; >-+ struct rde_aspath *asp, *nasp; >-+ enum filter_actions action; >-+ struct bgpd_addr addr; >-+ >-+ pt = re->prefix; >-+ pt_getaddr(pt, &addr); >-+ for (p = LIST_FIRST(&re->prefix_h); p != NULL; p = np) { >-+ np = LIST_NEXT(p, rib_l); >-+ >-+ /* store aspath as prefix may change till we're done */ >-+ asp = p->aspath; >-+ peer = asp->peer; >-+ >-+ action = rde_filter(rib->id, &nasp, newrules, peer, asp, &addr, >-+ pt->prefixlen, peer, DIR_IN); >-+ nasp = nasp != NULL ? nasp : asp; >-+ >-+ if (action == ACTION_ALLOW) { >-+ /* update Local-RIB */ >-+ path_update(rib, peer, nasp, &addr, pt->prefixlen); >-+ } >-+ >-+ if (nasp != asp) >-+ path_put(nasp); >-+ } >-+} >-+ >-+void >-+rde_softreconfig_load_peer(struct rib_entry *re, void *ptr) >-+{ >-+ struct rde_peer *peer = ptr; >-+ struct prefix *p = re->active; >-+ struct pt_entry *pt; >-+ struct rde_aspath *nasp; >-+ enum filter_actions na; >-+ struct bgpd_addr addr; >-+ >-+ pt = re->prefix; >-+ pt_getaddr(pt, &addr); >-+ >-+ /* check if prefix was announced */ >-+ if (up_test_update(peer, p) != 1) >-+ return; >-+ >-+ na = rde_filter(re->ribid, &nasp, newrules, peer, p->aspath, >-+ &addr, pt->prefixlen, p->aspath->peer, DIR_OUT); >-+ nasp = nasp != NULL ? nasp : p->aspath; >-+ >-+ if (na == ACTION_DENY) >-+ /* nothing todo */ >-+ goto done; >-+ >-+ /* send update */ >-+ up_generate(peer, nasp, &addr, pt->prefixlen); >-+done: >-+ if (nasp != p->aspath) >-+ path_put(nasp); >-+} >-+ >-+void >-+rde_softreconfig_unload_peer(struct rib_entry *re, void *ptr) >-+{ >-+ struct rde_peer *peer = ptr; >-+ struct prefix *p = re->active; >-+ struct pt_entry *pt; >-+ struct rde_aspath *oasp; >-+ enum filter_actions oa; >-+ struct bgpd_addr addr; >-+ >-+ pt = re->prefix; >-+ pt_getaddr(pt, &addr); >-+ >-+ /* check if prefix was announced */ >-+ if (up_test_update(peer, p) != 1) >-+ return; >-+ >-+ oa = rde_filter(re->ribid, &oasp, rules_l, peer, p->aspath, >-+ &addr, pt->prefixlen, p->aspath->peer, DIR_OUT); >-+ oasp = oasp != NULL ? oasp : p->aspath; >-+ >-+ if (oa == ACTION_DENY) >-+ /* nothing todo */ >-+ goto done; >-+ >-+ /* send withdraw */ >-+ up_generate(peer, NULL, &addr, pt->prefixlen); >-+done: >-+ if (oasp != p->aspath) >-+ path_put(oasp); >-+} >-+ >- /* >- * update specific functions >- */ >-@@ -2252,7 +2897,7 @@ rde_up_dump_upcall(struct rib_entry *re, >- struct rde_peer *peer = ptr; >- >- if (re->ribid != peer->ribid) >-- fatalx("King Bula: monsterous evil horror."); >-+ fatalx("King Bula: monstrous evil horror."); >- if (re->active == NULL) >- return; >- up_generate_updates(rules_l, peer, re->active, NULL); >-@@ -2265,7 +2910,7 @@ rde_generate_updates(u_int16_t ribid, st >- >- /* >- * If old is != NULL we know it was active and should be removed. >-- * If new is != NULL we know it is reachable and then we should >-+ * If new is != NULL we know it is reachable and then we should >- * generate an update. >- */ >- if (old == NULL && new == NULL) >-@@ -2286,7 +2931,7 @@ void >- rde_update_queue_runner(void) >- { >- struct rde_peer *peer; >-- int r, sent, max = RDE_RUNNER_ROUNDS; >-+ int r, sent, max = RDE_RUNNER_ROUNDS, eor = 0; >- u_int16_t len, wd_len, wpos; >- >- len = sizeof(queue_buf) - MSGSIZE_HEADER; >-@@ -2300,7 +2945,7 @@ rde_update_queue_runner(void) >- /* first withdraws */ >- wpos = 2; /* reserve space for the length field */ >- r = up_dump_prefix(queue_buf + wpos, len - wpos - 2, >-- &peer->withdraws, peer); >-+ &peer->withdraws[AID_INET], peer); >- wd_len = r; >- /* write withdraws length filed */ >- wd_len = htons(wd_len); >-@@ -2310,31 +2955,49 @@ rde_update_queue_runner(void) >- /* now bgp path attributes */ >- r = up_dump_attrnlri(queue_buf + wpos, len - wpos, >- peer); >-- wpos += r; >-- >-- if (wpos == 4) >-- /* >-- * No packet to send. The 4 bytes are the >-- * needed withdraw and path attribute length. >-- */ >-- continue; >-+ switch (r) { >-+ case -1: >-+ eor = 1; >-+ if (wd_len == 0) { >-+ /* no withdraws queued just send EoR */ >-+ peer_send_eor(peer, AID_INET); >-+ continue; >-+ } >-+ break; >-+ case 2: >-+ if (wd_len == 0) { >-+ /* >-+ * No packet to send. No withdraws and >-+ * no path attributes. Skip. >-+ */ >-+ continue; >-+ } >-+ /* FALLTHROUGH */ >-+ default: >-+ wpos += r; >-+ break; >-+ } >- >- /* finally send message to SE */ >- if (imsg_compose(ibuf_se, IMSG_UPDATE, peer->conf.id, >- 0, -1, queue_buf, wpos) == -1) >- fatal("imsg_compose error"); >- sent++; >-+ if (eor) { >-+ eor = 0; >-+ peer_send_eor(peer, AID_INET); >-+ } >- } >- max -= sent; >- } while (sent != 0 && max > 0); >- } >- >- void >--rde_update6_queue_runner(void) >-+rde_update6_queue_runner(u_int8_t aid) >- { >- struct rde_peer *peer; >- u_char *b; >-- int sent, max = RDE_RUNNER_ROUNDS / 2; >-+ int r, sent, max = RDE_RUNNER_ROUNDS / 2; >- u_int16_t len; >- >- /* first withdraws ... */ >-@@ -2346,7 +3009,7 @@ rde_update6_queue_runner(void) >- if (peer->state != PEER_UP) >- continue; >- len = sizeof(queue_buf) - MSGSIZE_HEADER; >-- b = up_dump_mp_unreach(queue_buf, &len, peer); >-+ b = up_dump_mp_unreach(queue_buf, &len, peer, aid); >- >- if (b == NULL) >- continue; >-@@ -2369,10 +3032,18 @@ rde_update6_queue_runner(void) >- if (peer->state != PEER_UP) >- continue; >- len = sizeof(queue_buf) - MSGSIZE_HEADER; >-- b = up_dump_mp_reach(queue_buf, &len, peer); >-- >-- if (b == NULL) >-+ r = up_dump_mp_reach(queue_buf, &len, peer, aid); >-+ switch (r) { >-+ case -2: >-+ continue; >-+ case -1: >-+ peer_send_eor(peer, aid); >- continue; >-+ default: >-+ b = queue_buf + r; >-+ break; >-+ } >-+ >- /* finally send message to SE */ >- if (imsg_compose(ibuf_se, IMSG_UPDATE, peer->conf.id, >- 0, -1, b, len) == -1) >-@@ -2411,7 +3082,7 @@ rde_decisionflags(void) >- int >- rde_as4byte(struct rde_peer *peer) >- { >-- return (peer->capa_announced.as4byte && peer->capa_received.as4byte); >-+ return (peer->capa.as4byte); >- } >- >- /* >-@@ -2429,7 +3100,6 @@ void >- peer_init(u_int32_t hashsize) >- { >- struct peer_config pc; >-- struct in_addr id; >- u_int32_t hs, i; >- >- for (hs = 1; hs < hashsize; hs <<= 1) >-@@ -2445,17 +3115,13 @@ peer_init(u_int32_t hashsize) >- peertable.peer_hashmask = hs - 1; >- >- bzero(&pc, sizeof(pc)); >-- pc.remote_as = conf->as; >-- id.s_addr = conf->bgpid; >-- snprintf(pc.descr, sizeof(pc.descr), "LOCAL: ID %s", inet_ntoa(id)); >-+ snprintf(pc.descr, sizeof(pc.descr), "LOCAL"); >- >- peerself = peer_add(0, &pc); >- if (peerself == NULL) >- fatalx("peer_init add self"); >- >- peerself->state = PEER_UP; >-- peerself->remote_bgpid = ntohl(conf->bgpid); >-- peerself->short_as = conf->short_as; >- } >- >- void >-@@ -2534,14 +3200,10 @@ peer_localaddrs(struct rde_peer *peer, s >- if (ifa->ifa_addr->sa_family == >- match->ifa_addr->sa_family) >- ifa = match; >-- peer->local_v4_addr.af = AF_INET; >-- peer->local_v4_addr.v4.s_addr = >-- ((struct sockaddr_in *)ifa->ifa_addr)-> >-- sin_addr.s_addr; >-+ sa2addr(ifa->ifa_addr, &peer->local_v4_addr); >- break; >- } >- } >-- >- for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { >- if (ifa->ifa_addr->sa_family == AF_INET6 && >- strcmp(ifa->ifa_name, match->ifa_name) == 0) { >-@@ -2559,13 +3221,7 @@ peer_localaddrs(struct rde_peer *peer, s >- &((struct sockaddr_in6 *)ifa-> >- ifa_addr)->sin6_addr)) >- continue; >-- peer->local_v6_addr.af = AF_INET6; >-- memcpy(&peer->local_v6_addr.v6, >-- &((struct sockaddr_in6 *)ifa->ifa_addr)-> >-- sin6_addr, sizeof(struct in6_addr)); >-- peer->local_v6_addr.scope_id = >-- ((struct sockaddr_in6 *)ifa->ifa_addr)-> >-- sin6_scope_id; >-+ sa2addr(ifa->ifa_addr, &peer->local_v6_addr); >- break; >- } >- } >-@@ -2577,23 +3233,22 @@ void >- peer_up(u_int32_t id, struct session_up *sup) >- { >- struct rde_peer *peer; >-+ u_int8_t i; >- >- peer = peer_get(id); >- if (peer == NULL) { >-- log_warnx("peer_up: peer id %d already exists", id); >-+ log_warnx("peer_up: unknown peer id %d", id); >- return; >- } >- >-- if (peer->state != PEER_DOWN && peer->state != PEER_NONE) >-+ if (peer->state != PEER_DOWN && peer->state != PEER_NONE && >-+ peer->state != PEER_UP) >- fatalx("peer_up: bad state"); >- peer->remote_bgpid = ntohl(sup->remote_bgpid); >- peer->short_as = sup->short_as; >- memcpy(&peer->remote_addr, &sup->remote_addr, >- sizeof(peer->remote_addr)); >-- memcpy(&peer->capa_announced, &sup->capa_announced, >-- sizeof(peer->capa_announced)); >-- memcpy(&peer->capa_received, &sup->capa_received, >-- sizeof(peer->capa_received)); >-+ memcpy(&peer->capa, &sup->capa, sizeof(peer->capa)); >- >- peer_localaddrs(peer, &sup->local_addr); >- >-@@ -2607,7 +3262,10 @@ peer_up(u_int32_t id, struct session_up >- */ >- return; >- >-- peer_dump(id, AFI_ALL, SAFI_ALL); >-+ for (i = 0; i < AID_MAX; i++) { >-+ if (peer->capa.mp[i] == 1) >-+ peer_dump(id, i); >-+ } >- } >- >- void >-@@ -2641,43 +3299,90 @@ peer_down(u_int32_t id) >- free(peer); >- } >- >-+/* >-+ * Flush all routes older then staletime. If staletime is 0 all routes will >-+ * be flushed. >-+ */ >-+void >-+peer_flush(struct rde_peer *peer, u_int8_t aid) >-+{ >-+ struct rde_aspath *asp, *nasp; >-+ >-+ /* walk through per peer RIB list and remove all stale prefixes. */ >-+ for (asp = LIST_FIRST(&peer->path_h); asp != NULL; asp = nasp) { >-+ nasp = LIST_NEXT(asp, peer_l); >-+ path_remove_stale(asp, aid); >-+ } >-+ >-+ /* Deletions are performed in path_remove() */ >-+ rde_send_pftable_commit(); >-+ >-+ /* flushed no need to keep staletime */ >-+ peer->staletime[aid] = 0; >-+} >-+ >- void >--peer_dump(u_int32_t id, u_int16_t afi, u_int8_t safi) >-+peer_stale(u_int32_t id, u_int8_t aid) >- { >- struct rde_peer *peer; >-+ time_t now; >- >- peer = peer_get(id); >- if (peer == NULL) { >-- log_warnx("peer_down: unknown peer id %d", id); >-+ log_warnx("peer_stale: unknown peer id %d", id); >- return; >- } >- >-- if (afi == AFI_ALL || afi == AFI_IPv4) >-- if (safi == SAFI_ALL || safi == SAFI_UNICAST) { >-- if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE) >-- up_generate_default(rules_l, peer, AF_INET); >-- else >-- rib_dump(&ribs[peer->ribid], rde_up_dump_upcall, >-- peer, AF_INET); >-- } >-- if (afi == AFI_ALL || afi == AFI_IPv6) >-- if (safi == SAFI_ALL || safi == SAFI_UNICAST) { >-- if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE) >-- up_generate_default(rules_l, peer, AF_INET6); >-- else >-- rib_dump(&ribs[peer->ribid], rde_up_dump_upcall, >-- peer, AF_INET6); >-- } >-+ if (peer->staletime[aid]) >-+ peer_flush(peer, aid); >-+ peer->staletime[aid] = now = time(NULL); >- >-- if (peer->capa_received.restart && peer->capa_announced.restart) >-- peer_send_eor(peer, afi, safi); >-+ /* make sure new prefixes start on a higher timestamp */ >-+ do { >-+ sleep(1); >-+ } while (now >= time(NULL)); >- } >- >--/* End-of-RIB marker, draft-ietf-idr-restart-13.txt */ >- void >--peer_send_eor(struct rde_peer *peer, u_int16_t afi, u_int16_t safi) >-+peer_dump(u_int32_t id, u_int8_t aid) >- { >-- if (afi == AFI_IPv4 && safi == SAFI_UNICAST) { >-+ struct rde_peer *peer; >-+ >-+ peer = peer_get(id); >-+ if (peer == NULL) { >-+ log_warnx("peer_dump: unknown peer id %d", id); >-+ return; >-+ } >-+ >-+ if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE) >-+ up_generate_default(rules_l, peer, aid); >-+ else >-+ rib_dump(&ribs[peer->ribid], rde_up_dump_upcall, peer, aid); >-+ if (peer->capa.grestart.restart) >-+ up_generate_marker(peer, aid); >-+} >-+ >-+/* End-of-RIB marker, RFC 4724 */ >-+void >-+peer_recv_eor(struct rde_peer *peer, u_int8_t aid) >-+{ >-+ peer->prefix_rcvd_eor++; >-+ >-+ /* First notify SE to remove possible race with the timeout. */ >-+ if (imsg_compose(ibuf_se, IMSG_SESSION_RESTARTED, peer->conf.id, >-+ 0, -1, &aid, sizeof(aid)) == -1) >-+ fatal("imsg_compose error"); >-+} >-+ >-+void >-+peer_send_eor(struct rde_peer *peer, u_int8_t aid) >-+{ >-+ u_int16_t afi; >-+ u_int8_t safi; >-+ >-+ peer->prefix_sent_eor++; >-+ >-+ if (aid == AID_INET) { >- u_char null[4]; >- >- bzero(&null, 4); >-@@ -2688,6 +3393,9 @@ peer_send_eor(struct rde_peer *peer, u_i >- u_int16_t i; >- u_char buf[10]; >- >-+ if (aid2afi(aid, &afi, &safi) == -1) >-+ fatalx("peer_send_eor: bad AID"); >-+ >- i = 0; /* v4 withdrawn len */ >- bcopy(&i, &buf[0], sizeof(i)); >- i = htons(6); /* path attr len */ >-@@ -2709,39 +3417,61 @@ peer_send_eor(struct rde_peer *peer, u_i >- * network announcement stuff >- */ >- void >--network_init(struct network_head *net_l) >--{ >-- struct network *n; >-- >-- reloadtime = time(NULL); >-- >-- while ((n = TAILQ_FIRST(net_l)) != NULL) { >-- TAILQ_REMOVE(net_l, n, entry); >-- network_add(&n->net, 1); >-- free(n); >-- } >--} >-- >--void >- network_add(struct network_config *nc, int flagstatic) >- { >-+ struct rdomain *rd; >- struct rde_aspath *asp; >-+ struct filter_set_head *vpnset = NULL; >-+ in_addr_t prefix4; >- u_int16_t i; >- >-- asp = path_get(); >-- asp->aspath = aspath_get(NULL, 0); >-- asp->origin = ORIGIN_IGP; >-- asp->flags = F_ATTR_ORIGIN | F_ATTR_ASPATH | >-- F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED; >-- /* the nexthop is unset unless a default set overrides it */ >-+ if (nc->rtableid) { >-+ SIMPLEQ_FOREACH(rd, rdomains_l, entry) { >-+ if (rd->rtableid != nc->rtableid) >-+ continue; >-+ switch (nc->prefix.aid) { >-+ case AID_INET: >-+ prefix4 = nc->prefix.v4.s_addr; >-+ bzero(&nc->prefix, sizeof(nc->prefix)); >-+ nc->prefix.aid = AID_VPN_IPv4; >-+ nc->prefix.vpn4.rd = rd->rd; >-+ nc->prefix.vpn4.addr.s_addr = prefix4; >-+ nc->prefix.vpn4.labellen = 3; >-+ nc->prefix.vpn4.labelstack[0] = >-+ (rd->label >> 12) & 0xff; >-+ nc->prefix.vpn4.labelstack[1] = >-+ (rd->label >> 4) & 0xff; >-+ nc->prefix.vpn4.labelstack[2] = >-+ (rd->label << 4) & 0xf0; >-+ nc->prefix.vpn4.labelstack[2] |= BGP_MPLS_BOS; >-+ vpnset = &rd->export; >-+ break; >-+ default: >-+ log_warnx("unable to VPNize prefix"); >-+ filterset_free(&nc->attrset); >-+ return; >-+ } >-+ } >-+ } >-+ >-+ if (nc->type == NETWORK_MRTCLONE) { >-+ asp = nc->asp; >-+ } else { >-+ asp = path_get(); >-+ asp->aspath = aspath_get(NULL, 0); >-+ asp->origin = ORIGIN_IGP; >-+ asp->flags = F_ATTR_ORIGIN | F_ATTR_ASPATH | >-+ F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED; >-+ /* the nexthop is unset unless a default set overrides it */ >-+ } >- if (!flagstatic) >- asp->flags |= F_ANN_DYNAMIC; >-- >-- rde_apply_set(asp, &nc->attrset, nc->prefix.af, peerself, peerself); >-+ rde_apply_set(asp, &nc->attrset, nc->prefix.aid, peerself, peerself); >-+ if (vpnset) >-+ rde_apply_set(asp, vpnset, nc->prefix.aid, peerself, peerself); >- for (i = 1; i < rib_size; i++) >- path_update(&ribs[i], peerself, asp, &nc->prefix, >- nc->prefixlen); >-- >- path_put(asp); >- filterset_free(&nc->attrset); >- } >-@@ -2749,12 +3479,41 @@ network_add(struct network_config *nc, i >- void >- network_delete(struct network_config *nc, int flagstatic) >- { >-- u_int32_t flags = F_PREFIX_ANNOUNCED; >-- u_int32_t i; >-+ struct rdomain *rd; >-+ in_addr_t prefix4; >-+ u_int32_t flags = F_PREFIX_ANNOUNCED; >-+ u_int32_t i; >- >- if (!flagstatic) >- flags |= F_ANN_DYNAMIC; >- >-+ if (nc->rtableid) { >-+ SIMPLEQ_FOREACH(rd, rdomains_l, entry) { >-+ if (rd->rtableid != nc->rtableid) >-+ continue; >-+ switch (nc->prefix.aid) { >-+ case AID_INET: >-+ prefix4 = nc->prefix.v4.s_addr; >-+ bzero(&nc->prefix, sizeof(nc->prefix)); >-+ nc->prefix.aid = AID_VPN_IPv4; >-+ nc->prefix.vpn4.rd = rd->rd; >-+ nc->prefix.vpn4.addr.s_addr = prefix4; >-+ nc->prefix.vpn4.labellen = 3; >-+ nc->prefix.vpn4.labelstack[0] = >-+ (rd->label >> 12) & 0xff; >-+ nc->prefix.vpn4.labelstack[1] = >-+ (rd->label >> 4) & 0xff; >-+ nc->prefix.vpn4.labelstack[2] = >-+ (rd->label << 4) & 0xf0; >-+ nc->prefix.vpn4.labelstack[2] |= BGP_MPLS_BOS; >-+ break; >-+ default: >-+ log_warnx("unable to VPNize prefix"); >-+ return; >-+ } >-+ } >-+ } >-+ >- for (i = rib_size - 1; i > 0; i--) >- prefix_remove(&ribs[i], peerself, &nc->prefix, nc->prefixlen, >- flags); >-@@ -2764,38 +3523,31 @@ void >- network_dump_upcall(struct rib_entry *re, void *ptr) >- { >- struct prefix *p; >-- struct kroute k; >-- struct kroute6 k6; >-+ struct kroute_full k; >- struct bgpd_addr addr; >- struct rde_dump_ctx *ctx = ptr; >- >- LIST_FOREACH(p, &re->prefix_h, rib_l) { >- if (!(p->aspath->flags & F_PREFIX_ANNOUNCED)) >- continue; >-- if (p->prefix->af == AF_INET) { >-- bzero(&k, sizeof(k)); >-- pt_getaddr(p->prefix, &addr); >-- k.prefix.s_addr = addr.v4.s_addr; >-- k.prefixlen = p->prefix->prefixlen; >-- if (p->aspath->peer == peerself) >-- k.flags = F_KERNEL; >-- if (imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NETWORK, 0, >-- ctx->req.pid, -1, &k, sizeof(k)) == -1) >-- log_warnx("network_dump_upcall: " >-- "imsg_compose error"); >-- } >-- if (p->prefix->af == AF_INET6) { >-- bzero(&k6, sizeof(k6)); >-- pt_getaddr(p->prefix, &addr); >-- memcpy(&k6.prefix, &addr.v6, sizeof(k6.prefix)); >-- k6.prefixlen = p->prefix->prefixlen; >-- if (p->aspath->peer == peerself) >-- k6.flags = F_KERNEL; >-- if (imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NETWORK6, 0, >-- ctx->req.pid, -1, &k6, sizeof(k6)) == -1) >-- log_warnx("network_dump_upcall: " >-- "imsg_compose error"); >-- } >-+ pt_getaddr(p->prefix, &addr); >-+ >-+ bzero(&k, sizeof(k)); >-+ memcpy(&k.prefix, &addr, sizeof(k.prefix)); >-+ if (p->aspath->nexthop == NULL || >-+ p->aspath->nexthop->state != NEXTHOP_REACH) >-+ k.nexthop.aid = k.prefix.aid; >-+ else >-+ memcpy(&k.nexthop, &p->aspath->nexthop->true_nexthop, >-+ sizeof(k.nexthop)); >-+ k.prefixlen = p->prefix->prefixlen; >-+ k.flags = F_KERNEL; >-+ if ((p->aspath->flags & F_ANN_DYNAMIC) == 0) >-+ k.flags = F_STATIC; >-+ if (imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NETWORK, 0, >-+ ctx->req.pid, -1, &k, sizeof(k)) == -1) >-+ log_warnx("network_dump_upcall: " >-+ "imsg_compose error"); >- } >- } >- >-@@ -2841,10 +3593,10 @@ sa_cmp(struct bgpd_addr *a, struct socka >- struct sockaddr_in *in_b; >- struct sockaddr_in6 *in6_b; >- >-- if (a->af != b->sa_family) >-+ if (aid2af(a->aid) != b->sa_family) >- return (1); >- >-- switch (a->af) { >-+ switch (b->sa_family) { >- case AF_INET: >- in_b = (struct sockaddr_in *)b; >- if (a->v4.s_addr != in_b->sin_addr.s_addr) >-@@ -2855,10 +3607,11 @@ sa_cmp(struct bgpd_addr *a, struct socka >- #ifdef __KAME__ >- /* directly stolen from sbin/ifconfig/ifconfig.c */ >- if (IN6_IS_ADDR_LINKLOCAL(&in6_b->sin6_addr)) { >-- in6_b->sin6_scope_id = >-- ntohs(*(u_int16_t *)&in6_b->sin6_addr.s6_addr[2]); >-- in6_b->sin6_addr.s6_addr[2] = >-- in6_b->sin6_addr.s6_addr[3] = 0; >-+ if (in6_b->sin6_scope_id == 0) { >-+ in6_b->sin6_scope_id = >-+ IN6_LINKLOCAL_IFINDEX(in6_b->sin6_addr); >-+ } >-+ SET_IN6_LINKLOCAL_IFINDEX(in6_b->sin6_addr, 0); >- } >- #endif >- if (bcmp(&a->v6, &in6_b->sin6_addr, > >Property changes on: files/patch-bgpd_rde.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_rde.h >=================================================================== >--- files/patch-bgpd_rde.h (revision 500577) >+++ files/patch-bgpd_rde.h (nonexistent) >@@ -1,361 +0,0 @@ >-Index: bgpd/rde.h >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde.h,v >-retrieving revision 1.1.1.8 >-retrieving revision 1.1.1.13 >-diff -u -p -r1.1.1.8 -r1.1.1.13 >---- bgpd/rde.h 14 Feb 2010 20:19:57 -0000 1.1.1.8 >-+++ bgpd/rde.h 8 Dec 2012 10:37:09 -0000 1.1.1.13 >-@@ -1,8 +1,8 @@ >--/* $OpenBSD: rde.h,v 1.120 2009/06/06 01:10:29 claudio Exp $ */ >-+/* $OpenBSD: rde.h,v 1.144 2012/09/12 05:56:22 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and >-- * Andre Oppermann <oppermann@pipeline.ch> >-+ * Andre Oppermann <oppermann@networx.ch> >- * >- * Permission to use, copy, modify, and distribute this software for any >- * purpose with or without fee is hereby granted, provided that the above >-@@ -56,16 +56,16 @@ struct rde_peer { >- struct bgpd_addr local_v6_addr; >- struct uptree_prefix up_prefix; >- struct uptree_attr up_attrs; >-- struct uplist_attr updates; >-- struct uplist_prefix withdraws; >-- struct uplist_attr updates6; >-- struct uplist_prefix withdraws6; >-- struct capabilities capa_announced; >-- struct capabilities capa_received; >-+ struct uplist_attr updates[AID_MAX]; >-+ struct uplist_prefix withdraws[AID_MAX]; >-+ struct capabilities capa; >-+ time_t staletime[AID_MAX]; >- u_int64_t prefix_rcvd_update; >- u_int64_t prefix_rcvd_withdraw; >-+ u_int64_t prefix_rcvd_eor; >- u_int64_t prefix_sent_update; >- u_int64_t prefix_sent_withdraw; >-+ u_int64_t prefix_sent_eor; >- u_int32_t prefix_cnt; /* # of prefixes */ >- u_int32_t remote_bgpid; /* host byte order! */ >- u_int32_t up_pcnt; >-@@ -75,12 +75,16 @@ struct rde_peer { >- enum peer_state state; >- u_int16_t ribid; >- u_int16_t short_as; >-+ u_int16_t mrt_idx; >- u_int8_t reconf_in; /* in filter changed */ >- u_int8_t reconf_out; /* out filter changed */ >-+ u_int8_t reconf_rib; /* rib changed */ >- }; >- >- #define AS_SET 1 >- #define AS_SEQUENCE 2 >-+#define AS_CONFED_SEQUENCE 3 >-+#define AS_CONFED_SET 4 >- #define ASPATH_HEADER_SIZE (sizeof(struct aspath) - sizeof(u_char)) >- >- LIST_HEAD(aspath_list, aspath); >-@@ -117,6 +121,9 @@ enum attrtypes { >- #define ATTR_PARTIAL 0x20 >- #define ATTR_TRANSITIVE 0x40 >- #define ATTR_OPTIONAL 0x80 >-+#define ATTR_RESERVED 0x0f >-+/* by default mask the reserved bits and the ext len bit */ >-+#define ATTR_DEFMASK (ATTR_RESERVED | ATTR_EXTLEN) >- >- /* default attribute flags for well known attributes */ >- #define ATTR_WELL_KNOWN ATTR_TRANSITIVE >-@@ -163,6 +170,8 @@ LIST_HEAD(prefix_head, prefix); >- #define F_NEXTHOP_REJECT 0x02000 >- #define F_NEXTHOP_BLACKHOLE 0x04000 >- #define F_NEXTHOP_NOMODIFY 0x08000 >-+#define F_NEXTHOP_MASK 0x0f000 >-+#define F_ATTR_PARSE_ERR 0x10000 >- #define F_ATTR_LINKED 0x20000 >- >- >-@@ -220,14 +229,14 @@ struct nexthop { >- /* generic entry without address specific part */ >- struct pt_entry { >- RB_ENTRY(pt_entry) pt_e; >-- sa_family_t af; >-+ u_int8_t aid; >- u_int8_t prefixlen; >- u_int16_t refcnt; >- }; >- >- struct pt_entry4 { >- RB_ENTRY(pt_entry) pt_e; >-- sa_family_t af; >-+ u_int8_t aid; >- u_int8_t prefixlen; >- u_int16_t refcnt; >- struct in_addr prefix4; >-@@ -235,12 +244,25 @@ struct pt_entry4 { >- >- struct pt_entry6 { >- RB_ENTRY(pt_entry) pt_e; >-- sa_family_t af; >-+ u_int8_t aid; >- u_int8_t prefixlen; >- u_int16_t refcnt; >- struct in6_addr prefix6; >- }; >- >-+struct pt_entry_vpn4 { >-+ RB_ENTRY(pt_entry) pt_e; >-+ u_int8_t aid; >-+ u_int8_t prefixlen; >-+ u_int16_t refcnt; >-+ struct in_addr prefix4; >-+ u_int64_t rd; >-+ u_int8_t labelstack[21]; >-+ u_int8_t labellen; >-+ u_int8_t pad1; >-+ u_int8_t pad2; >-+}; >-+ >- struct rib_context { >- LIST_ENTRY(rib_context) entry; >- struct rib_entry *ctx_re; >-@@ -250,7 +272,7 @@ struct rib_context { >- void (*ctx_wait)(void *); >- void *ctx_arg; >- unsigned int ctx_count; >-- sa_family_t ctx_af; >-+ u_int8_t ctx_aid; >- }; >- >- struct rib_entry { >-@@ -262,23 +284,15 @@ struct rib_entry { >- u_int16_t flags; >- }; >- >--enum rib_state { >-- RIB_NONE, >-- RIB_ACTIVE, >-- RIB_DELETE >--}; >-- >- struct rib { >- char name[PEER_DESCR_LEN]; >- struct rib_tree rib; >-- enum rib_state state; >-+ u_int rtableid; >- u_int16_t flags; >- u_int16_t id; >-+ enum reconf_action state; >- }; >- >--#define F_RIB_ENTRYLOCK 0x0001 >--#define F_RIB_NOEVALUATE 0x0002 >--#define F_RIB_NOFIB 0x0004 >- #define RIB_FAILED 0xffff >- >- struct prefix { >-@@ -292,8 +306,14 @@ struct prefix { >- extern struct rde_memstats rdemem; >- >- /* prototypes */ >-+/* mrt.c */ >-+int mrt_dump_v2_hdr(struct mrt *, struct bgpd_config *, >-+ struct rde_peer_head *); >-+void mrt_dump_upcall(struct rib_entry *, void *); >-+void mrt_done(void *); >-+ >- /* rde.c */ >--void rde_send_kroute(struct prefix *, struct prefix *); >-+void rde_send_kroute(struct prefix *, struct prefix *, u_int16_t); >- void rde_send_nexthop(struct bgpd_addr *, int); >- void rde_send_pftable(u_int16_t, struct bgpd_addr *, >- u_int8_t, int); >-@@ -309,7 +329,7 @@ int rde_as4byte(struct rde_peer *); >- /* rde_attr.c */ >- int attr_write(void *, u_int16_t, u_int8_t, u_int8_t, void *, >- u_int16_t); >--int attr_writebuf(struct buf *, u_int8_t, u_int8_t, void *, >-+int attr_writebuf(struct ibuf *, u_int8_t, u_int8_t, void *, >- u_int16_t); >- void attr_init(u_int32_t); >- void attr_shutdown(void); >-@@ -327,6 +347,7 @@ int aspath_verify(void *, u_int16_t, i >- #define AS_ERR_LEN -1 >- #define AS_ERR_TYPE -2 >- #define AS_ERR_BAD -3 >-+#define AS_ERR_SOFT -4 >- void aspath_init(u_int32_t); >- void aspath_shutdown(void); >- struct aspath *aspath_get(void *, u_int16_t); >-@@ -341,22 +362,66 @@ u_int32_t aspath_neighbor(struct aspath >- int aspath_loopfree(struct aspath *, u_int32_t); >- int aspath_compare(struct aspath *, struct aspath *); >- u_char *aspath_prepend(struct aspath *, u_int32_t, int, u_int16_t *); >--int aspath_match(struct aspath *, enum as_spec, u_int32_t); >--int community_match(void *, u_int16_t, int, int); >-+int aspath_lenmatch(struct aspath *, enum aslen_spec, u_int); >-+int community_match(struct rde_aspath *, int, int); >- int community_set(struct rde_aspath *, int, int); >- void community_delete(struct rde_aspath *, int, int); >-+int community_ext_match(struct rde_aspath *, >-+ struct filter_extcommunity *, u_int16_t); >-+int community_ext_set(struct rde_aspath *, >-+ struct filter_extcommunity *, u_int16_t); >-+void community_ext_delete(struct rde_aspath *, >-+ struct filter_extcommunity *, u_int16_t); >-+int community_ext_conv(struct filter_extcommunity *, u_int16_t, >-+ u_int64_t *); >-+ >-+/* rde_decide.c */ >-+void prefix_evaluate(struct prefix *, struct rib_entry *); >-+ >-+/* rde_filter.c */ >-+enum filter_actions rde_filter(u_int16_t, struct rde_aspath **, >-+ struct filter_head *, struct rde_peer *, >-+ struct rde_aspath *, struct bgpd_addr *, u_int8_t, >-+ struct rde_peer *, enum directions); >-+void rde_apply_set(struct rde_aspath *, struct filter_set_head *, >-+ u_int8_t, struct rde_peer *, struct rde_peer *); >-+int rde_filter_equal(struct filter_head *, struct filter_head *, >-+ struct rde_peer *, enum directions); >-+ >-+/* rde_prefix.c */ >-+#define pt_empty(pt) ((pt)->refcnt == 0) >-+#define pt_ref(pt) do { \ >-+ ++(pt)->refcnt; \ >-+ if ((pt)->refcnt == 0) \ >-+ fatalx("pt_ref: overflow"); \ >-+} while(0) >-+#define pt_unref(pt) do { \ >-+ if ((pt)->refcnt == 0) \ >-+ fatalx("pt_unref: underflow"); \ >-+ --(pt)->refcnt; \ >-+} while(0) >-+ >-+void pt_init(void); >-+void pt_shutdown(void); >-+void pt_getaddr(struct pt_entry *, struct bgpd_addr *); >-+struct pt_entry *pt_fill(struct bgpd_addr *, int); >-+struct pt_entry *pt_get(struct bgpd_addr *, int); >-+struct pt_entry *pt_add(struct bgpd_addr *, int); >-+void pt_remove(struct pt_entry *); >-+struct pt_entry *pt_lookup(struct bgpd_addr *); >-+int pt_prefix_cmp(const struct pt_entry *, const struct pt_entry *); >- >- /* rde_rib.c */ >- extern u_int16_t rib_size; >- extern struct rib *ribs; >- >--u_int16_t rib_new(int, char *, u_int16_t); >-+u_int16_t rib_new(char *, u_int, u_int16_t); >- u_int16_t rib_find(char *); >- void rib_free(struct rib *); >- struct rib_entry *rib_get(struct rib *, struct bgpd_addr *, int); >- struct rib_entry *rib_lookup(struct rib *, struct bgpd_addr *); >- void rib_dump(struct rib *, void (*)(struct rib_entry *, void *), >-- void *, sa_family_t); >-+ void *, u_int8_t); >- void rib_dump_r(struct rib_context *); >- void rib_dump_runner(void); >- int rib_dump_pending(void); >-@@ -368,6 +433,7 @@ int path_update(struct rib *, struct r >- int path_compare(struct rde_aspath *, struct rde_aspath *); >- struct rde_aspath *path_lookup(struct rde_aspath *, struct rde_peer *); >- void path_remove(struct rde_aspath *); >-+void path_remove_stale(struct rde_aspath *, u_int8_t); >- void path_destroy(struct rde_aspath *); >- int path_empty(struct rde_aspath *); >- struct rde_aspath *path_copy(struct rde_aspath *); >-@@ -375,8 +441,6 @@ struct rde_aspath *path_get(void); >- void path_put(struct rde_aspath *); >- >- #define PREFIX_SIZE(x) (((x) + 7) / 8 + 1) >--int prefix_compare(const struct bgpd_addr *, >-- const struct bgpd_addr *, int); >- struct prefix *prefix_get(struct rib *, struct rde_peer *, >- struct bgpd_addr *, int, u_int32_t); >- int prefix_add(struct rib *, struct rde_aspath *, >-@@ -385,6 +449,7 @@ void prefix_move(struct rde_aspath *, >- int prefix_remove(struct rib *, struct rde_peer *, >- struct bgpd_addr *, int, u_int32_t); >- int prefix_write(u_char *, int, struct bgpd_addr *, u_int8_t); >-+int prefix_writebuf(struct ibuf *, struct bgpd_addr *, u_int8_t); >- struct prefix *prefix_bypeer(struct rib_entry *, struct rde_peer *, >- u_int32_t); >- void prefix_updateall(struct rde_aspath *, enum nexthop_state, >-@@ -395,7 +460,7 @@ void prefix_network_clean(struct rde_p >- void nexthop_init(u_int32_t); >- void nexthop_shutdown(void); >- void nexthop_modify(struct rde_aspath *, struct bgpd_addr *, >-- enum action_types, sa_family_t); >-+ enum action_types, u_int8_t); >- void nexthop_link(struct rde_aspath *); >- void nexthop_unlink(struct rde_aspath *); >- int nexthop_delete(struct nexthop *); >-@@ -403,9 +468,6 @@ void nexthop_update(struct kroute_next >- struct nexthop *nexthop_get(struct bgpd_addr *); >- int nexthop_compare(struct nexthop *, struct nexthop *); >- >--/* rde_decide.c */ >--void prefix_evaluate(struct prefix *, struct rib_entry *); >-- >- /* rde_update.c */ >- void up_init(struct rde_peer *); >- void up_down(struct rde_peer *); >-@@ -415,49 +477,14 @@ int up_generate(struct rde_peer *, str >- void up_generate_updates(struct filter_head *, struct rde_peer *, >- struct prefix *, struct prefix *); >- void up_generate_default(struct filter_head *, struct rde_peer *, >-- sa_family_t); >-+ u_int8_t); >-+int up_generate_marker(struct rde_peer *, u_int8_t); >- int up_dump_prefix(u_char *, int, struct uplist_prefix *, >- struct rde_peer *); >- int up_dump_attrnlri(u_char *, int, struct rde_peer *); >--u_char *up_dump_mp_unreach(u_char *, u_int16_t *, struct rde_peer *); >--u_char *up_dump_mp_reach(u_char *, u_int16_t *, struct rde_peer *); >-- >--/* rde_prefix.c */ >--#define pt_empty(pt) ((pt)->refcnt == 0) >--#define pt_ref(pt) do { \ >-- ++(pt)->refcnt; \ >-- if ((pt)->refcnt == 0) \ >-- fatalx("pt_ref: overflow"); \ >--} while(0) >--#define pt_unref(pt) do { \ >-- if ((pt)->refcnt == 0) \ >-- fatalx("pt_unref: underflow"); \ >-- --(pt)->refcnt; \ >--} while(0) >-- >--void pt_init(void); >--void pt_shutdown(void); >--void pt_getaddr(struct pt_entry *, struct bgpd_addr *); >--struct pt_entry *pt_fill(struct bgpd_addr *, int); >--struct pt_entry *pt_get(struct bgpd_addr *, int); >--struct pt_entry *pt_add(struct bgpd_addr *, int); >--void pt_remove(struct pt_entry *); >--struct pt_entry *pt_lookup(struct bgpd_addr *); >--int pt_prefix_cmp(const struct pt_entry *, const struct pt_entry *); >-- >-- >--/* rde_filter.c */ >--enum filter_actions rde_filter(u_int16_t, struct rde_aspath **, >-- struct filter_head *, struct rde_peer *, >-- struct rde_aspath *, struct bgpd_addr *, u_int8_t, >-- struct rde_peer *, enum directions); >--void rde_apply_set(struct rde_aspath *, struct filter_set_head *, >-- sa_family_t, struct rde_peer *, struct rde_peer *); >--int rde_filter_community(struct rde_aspath *, int, int); >--int rde_filter_equal(struct filter_head *, struct filter_head *, >-- struct rde_peer *, enum directions); >-- >--/* util.c */ >--u_int32_t aspath_extract(const void *, int); >-+u_char *up_dump_mp_unreach(u_char *, u_int16_t *, struct rde_peer *, >-+ u_int8_t); >-+int up_dump_mp_reach(u_char *, u_int16_t *, struct rde_peer *, >-+ u_int8_t); >- >- #endif /* __RDE_H__ */ > >Property changes on: files/patch-bgpd_rde.h >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_rde_attr.c >=================================================================== >--- files/patch-bgpd_rde_attr.c (revision 500577) >+++ files/patch-bgpd_rde_attr.c (nonexistent) >@@ -1,562 +0,0 @@ >-Index: bgpd/rde_attr.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_attr.c,v >-retrieving revision 1.1.1.6 >-retrieving revision 1.7 >-diff -u -p -r1.1.1.6 -r1.7 >---- bgpd/rde_attr.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 >-+++ bgpd/rde_attr.c 13 Oct 2012 18:36:00 -0000 1.7 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: rde_attr.c,v 1.79 2009/03/19 06:52:59 claudio Exp $ */ >-+/* $OpenBSD: rde_attr.c,v 1.90 2012/04/12 17:27:20 claudio Exp $ */ >- >- /* >- * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> >-@@ -17,14 +17,22 @@ >- */ >- >- #include <sys/types.h> >-+#if defined(__FreeBSD__) /* sys/hash.h */ >-+#include "hash.h" >-+#else >- #include <sys/hash.h> >-+#endif /* defined(__FreeBSD__) */ >- #include <sys/queue.h> >- >- #include <netinet/in.h> >- >-+#include <limits.h> >- #include <stdlib.h> >- #include <stdio.h> >- #include <string.h> >-+#if defined(__FreeBSD__) /* limits.h */ >-+#include <limits.h> >-+#endif /* defined(__FreeBSD__) */ >- >- #include "bgpd.h" >- #include "rde.h" >-@@ -36,12 +44,12 @@ attr_write(void *p, u_int16_t p_len, u_i >- u_char *b = p; >- u_int16_t tmp, tot_len = 2; /* attribute header (without len) */ >- >-+ flags &= ~ATTR_DEFMASK; >- if (data_len > 255) { >- tot_len += 2 + data_len; >- flags |= ATTR_EXTLEN; >- } else { >- tot_len += 1 + data_len; >-- flags &= ~ATTR_EXTLEN; >- } >- >- if (tot_len > p_len) >-@@ -63,26 +71,26 @@ attr_write(void *p, u_int16_t p_len, u_i >- } >- >- int >--attr_writebuf(struct buf *buf, u_int8_t flags, u_int8_t type, void *data, >-+attr_writebuf(struct ibuf *buf, u_int8_t flags, u_int8_t type, void *data, >- u_int16_t data_len) >- { >- u_char hdr[4]; >- >-+ flags &= ~ATTR_DEFMASK; >- if (data_len > 255) { >- flags |= ATTR_EXTLEN; >- hdr[2] = (data_len >> 8) & 0xff; >- hdr[3] = data_len & 0xff; >- } else { >-- flags &= ~ATTR_EXTLEN; >- hdr[2] = data_len & 0xff; >- } >- >- hdr[0] = flags; >- hdr[1] = type; >- >-- if (buf_add(buf, hdr, flags & ATTR_EXTLEN ? 4 : 3) == -1) >-+ if (ibuf_add(buf, hdr, flags & ATTR_EXTLEN ? 4 : 3) == -1) >- return (-1); >-- if (buf_add(buf, data, data_len) == -1) >-+ if (ibuf_add(buf, data, data_len) == -1) >- return (-1); >- return (0); >- } >-@@ -146,8 +154,11 @@ attr_optadd(struct rde_aspath *asp, u_in >- for (l = 0; l < asp->others_len; l++) { >- if (asp->others[l] == NULL) >- break; >-- if (type == asp->others[l]->type) >-+ if (type == asp->others[l]->type) { >-+ if (a->refcnt == 0) >-+ attr_put(a); >- return (-1); >-+ } >- } >- >- /* add attribute to the table but first bump refcnt */ >-@@ -318,6 +329,7 @@ attr_alloc(u_int8_t flags, u_int8_t type >- fatal("attr_optadd"); >- rdemem.attr_cnt++; >- >-+ flags &= ~ATTR_DEFMASK; /* normalize mask */ >- a->flags = flags; >- a->hash = hash32_buf(&flags, sizeof(flags), HASHINIT); >- a->type = type; >-@@ -347,6 +359,7 @@ attr_lookup(u_int8_t flags, u_int8_t typ >- struct attr *a; >- u_int32_t hash; >- >-+ flags &= ~ATTR_DEFMASK; /* normalize mask */ >- hash = hash32_buf(&flags, sizeof(flags), HASHINIT); >- hash = hash32_buf(&type, sizeof(type), hash); >- hash = hash32_buf(&len, sizeof(len), hash); >-@@ -405,6 +418,7 @@ aspath_verify(void *data, u_int16_t len, >- u_int8_t *seg = data; >- u_int16_t seg_size, as_size = 2; >- u_int8_t seg_len, seg_type; >-+ int err = 0; >- >- if (len & 1) >- /* odd length aspath are invalid */ >-@@ -419,7 +433,15 @@ aspath_verify(void *data, u_int16_t len, >- seg_type = seg[0]; >- seg_len = seg[1]; >- >-- if (seg_type != AS_SET && seg_type != AS_SEQUENCE) >-+ /* >-+ * BGP confederations should not show up but consider them >-+ * as a soft error which invalidates the path but keeps the >-+ * bgp session running. >-+ */ >-+ if (seg_type == AS_CONFED_SEQUENCE || seg_type == AS_CONFED_SET) >-+ err = AS_ERR_SOFT; >-+ if (seg_type != AS_SET && seg_type != AS_SEQUENCE && >-+ seg_type != AS_CONFED_SEQUENCE && seg_type != AS_CONFED_SET) >- return (AS_ERR_TYPE); >- >- seg_size = 2 + as_size * seg_len; >-@@ -431,7 +453,7 @@ aspath_verify(void *data, u_int16_t len, >- /* empty aspath segments are not allowed */ >- return (AS_ERR_BAD); >- } >-- return (0); /* aspath is valid but probably not loop free */ >-+ return (err); /* aspath is valid but probably not loop free */ >- } >- >- void >-@@ -762,15 +784,9 @@ aspath_countcopy(struct aspath *aspath, >- u_int32_t >- aspath_neighbor(struct aspath *aspath) >- { >-- /* >-- * Empty aspath is OK -- internal as route. >-- * But what is the neighbor? For now let's return 0. >-- * That should not break anything. >-- */ >-- >-+ /* Empty aspath is OK -- internal AS route. */ >- if (aspath->len == 0) >-- return (0); >-- >-+ return (rde_local_as()); >- return (aspath_extract(aspath->data, 0)); >- } >- >-@@ -910,76 +926,63 @@ aspath_prepend(struct aspath *asp, u_int >- return (p); >- } >- >--/* we need to be able to search more than one as */ >- int >--aspath_match(struct aspath *a, enum as_spec type, u_int32_t as) >-+aspath_lenmatch(struct aspath *a, enum aslen_spec type, u_int aslen) >- { >- u_int8_t *seg; >-- int final; >-+ u_int32_t as, lastas = 0; >-+ u_int count = 0; >- u_int16_t len, seg_size; >- u_int8_t i, seg_type, seg_len; >- >-- if (type == AS_EMPTY) { >-- if (a->len == 0) >-+ if (type == ASLEN_MAX) { >-+ if (aslen < aspath_count(a->data, a->len)) >- return (1); >- else >- return (0); >- } >- >-- final = 0; >-+ /* type == ASLEN_SEQ */ >- seg = a->data; >- for (len = a->len; len > 0; len -= seg_size, seg += seg_size) { >- seg_type = seg[0]; >- seg_len = seg[1]; >- seg_size = 2 + sizeof(u_int32_t) * seg_len; >- >-- final = (len == seg_size); >-- >-- /* just check the first (leftmost) AS */ >-- if (type == AS_PEER) { >-- if (as == aspath_extract(seg, 0)) >-- return (1); >-- else >-- return (0); >-- } >-- /* just check the final (rightmost) AS */ >-- if (type == AS_SOURCE) { >-- /* not yet in the final segment */ >-- if (!final) >-- continue; >-- >-- if (as == aspath_extract(seg, seg_len - 1)) >-- return (1); >-- else >-- return (0); >-- } >-- >-- /* AS_TRANSIT or AS_ALL */ >- for (i = 0; i < seg_len; i++) { >-- if (as == aspath_extract(seg, i)) { >-- /* >-- * the source (rightmost) AS is excluded from >-- * AS_TRANSIT matches. >-- */ >-- if (final && i == seg_len - 1 && >-- type == AS_TRANSIT) >-- return (0); >-- return (1); >-- } >-+ /* what should we do with AS_SET? */ >-+ as = aspath_extract(seg, i); >-+ if (as == lastas) { >-+ if (aslen < ++count) >-+ return (1); >-+ } else >-+ count = 1; >-+ lastas = as; >- } >- } >- return (0); >- } >- >-+/* >-+ * Functions handling communities and extended communities. >-+ */ >-+ >-+int community_ext_matchone(struct filter_extcommunity *, u_int16_t, u_int64_t); >-+ >- int >--community_match(void *data, u_int16_t len, int as, int type) >-+community_match(struct rde_aspath *asp, int as, int type) >- { >-- u_int8_t *p = data; >-- u_int16_t eas, etype; >-+ struct attr *a; >-+ u_int8_t *p; >-+ u_int16_t eas, etype, len; >- >-- len >>= 2; /* divide by four */ >-+ a = attr_optget(asp, ATTR_COMMUNITIES); >-+ if (a == NULL) >-+ /* no communities, no match */ >-+ return (0); >- >-- for (; len > 0; len--) { >-+ p = a->data; >-+ for (len = a->len / 4; len > 0; len--) { >- eas = *p++; >- eas <<= 8; >- eas |= *p++; >-@@ -1000,7 +1003,6 @@ community_set(struct rde_aspath *asp, in >- u_int8_t *p = NULL; >- unsigned int i, ncommunities = 0; >- u_int8_t f = ATTR_OPTIONAL|ATTR_TRANSITIVE; >-- u_int8_t t = ATTR_COMMUNITIES; >- >- attr = attr_optget(asp, ATTR_COMMUNITIES); >- if (attr != NULL) { >-@@ -1017,7 +1019,7 @@ community_set(struct rde_aspath *asp, in >- p += 4; >- } >- >-- if (ncommunities++ >= 0x3fff) >-+ if (ncommunities++ >= USHRT_MAX / 4) >- /* overflow */ >- return (0); >- >-@@ -1032,11 +1034,10 @@ community_set(struct rde_aspath *asp, in >- if (attr != NULL) { >- memcpy(p + 4, attr->data, attr->len); >- f = attr->flags; >-- t = attr->type; >- attr_free(asp, attr); >- } >- >-- attr_optadd(asp, f, t, p, ncommunities << 2); >-+ attr_optadd(asp, f, ATTR_COMMUNITIES, p, ncommunities << 2); >- >- free(p); >- return (1); >-@@ -1049,7 +1050,7 @@ community_delete(struct rde_aspath *asp, >- u_int8_t *p, *n; >- u_int16_t l, len = 0; >- u_int16_t eas, etype; >-- u_int8_t f, t; >-+ u_int8_t f; >- >- attr = attr_optget(asp, ATTR_COMMUNITIES); >- if (attr == NULL) >-@@ -1100,10 +1101,250 @@ community_delete(struct rde_aspath *asp, >- } >- >- f = attr->flags; >-- t = attr->type; >- >- attr_free(asp, attr); >-- attr_optadd(asp, f, t, n, len); >-+ attr_optadd(asp, f, ATTR_COMMUNITIES, n, len); >- free(n); >- } >- >-+int >-+community_ext_match(struct rde_aspath *asp, struct filter_extcommunity *c, >-+ u_int16_t neighas) >-+{ >-+ struct attr *attr; >-+ u_int8_t *p; >-+ u_int64_t ec; >-+ u_int16_t len; >-+ >-+ attr = attr_optget(asp, ATTR_EXT_COMMUNITIES); >-+ if (attr == NULL) >-+ /* no communities, no match */ >-+ return (0); >-+ >-+ p = attr->data; >-+ for (len = attr->len / sizeof(ec); len > 0; len--) { >-+ memcpy(&ec, p, sizeof(ec)); >-+ if (community_ext_matchone(c, neighas, ec)) >-+ return (1); >-+ p += sizeof(ec); >-+ } >-+ >-+ return (0); >-+} >-+ >-+int >-+community_ext_set(struct rde_aspath *asp, struct filter_extcommunity *c, >-+ u_int16_t neighas) >-+{ >-+ struct attr *attr; >-+ u_int8_t *p = NULL; >-+ u_int64_t community; >-+ unsigned int i, ncommunities = 0; >-+ u_int8_t f = ATTR_OPTIONAL|ATTR_TRANSITIVE; >-+ >-+ if (community_ext_conv(c, neighas, &community)) >-+ return (0); >-+ >-+ attr = attr_optget(asp, ATTR_EXT_COMMUNITIES); >-+ if (attr != NULL) { >-+ p = attr->data; >-+ ncommunities = attr->len / sizeof(community); >-+ } >-+ >-+ /* first check if the community is not already set */ >-+ for (i = 0; i < ncommunities; i++) { >-+ if (memcmp(&community, p, sizeof(community)) == 0) >-+ /* already present, nothing todo */ >-+ return (1); >-+ p += sizeof(community); >-+ } >-+ >-+ if (ncommunities++ >= USHRT_MAX / sizeof(community)) >-+ /* overflow */ >-+ return (0); >-+ >-+ if ((p = malloc(ncommunities * sizeof(community))) == NULL) >-+ fatal("community_ext_set"); >-+ >-+ memcpy(p, &community, sizeof(community)); >-+ if (attr != NULL) { >-+ memcpy(p + sizeof(community), attr->data, attr->len); >-+ f = attr->flags; >-+ attr_free(asp, attr); >-+ } >-+ >-+ attr_optadd(asp, f, ATTR_EXT_COMMUNITIES, p, >-+ ncommunities * sizeof(community)); >-+ >-+ free(p); >-+ return (1); >-+} >-+ >-+void >-+community_ext_delete(struct rde_aspath *asp, struct filter_extcommunity *c, >-+ u_int16_t neighas) >-+{ >-+ struct attr *attr; >-+ u_int8_t *p, *n; >-+ u_int64_t community; >-+ u_int16_t l, len = 0; >-+ u_int8_t f; >-+ >-+ if (community_ext_conv(c, neighas, &community)) >-+ return; >-+ >-+ attr = attr_optget(asp, ATTR_EXT_COMMUNITIES); >-+ if (attr == NULL) >-+ /* no attr nothing to do */ >-+ return; >-+ >-+ p = attr->data; >-+ for (l = 0; l < attr->len; l += sizeof(community)) { >-+ if (memcmp(&community, p + l, sizeof(community)) == 0) >-+ /* match */ >-+ continue; >-+ len += sizeof(community); >-+ } >-+ >-+ if (len == 0) { >-+ attr_free(asp, attr); >-+ return; >-+ } >-+ >-+ if ((n = malloc(len)) == NULL) >-+ fatal("community_delete"); >-+ >-+ p = attr->data; >-+ for (l = 0; l < len && p < attr->data + attr->len; >-+ p += sizeof(community)) { >-+ if (memcmp(&community, p, sizeof(community)) == 0) >-+ /* match */ >-+ continue; >-+ memcpy(n + l, p, sizeof(community)); >-+ l += sizeof(community); >-+ } >-+ >-+ f = attr->flags; >-+ >-+ attr_free(asp, attr); >-+ attr_optadd(asp, f, ATTR_EXT_COMMUNITIES, n, len); >-+ free(n); >-+} >-+ >-+int >-+community_ext_conv(struct filter_extcommunity *c, u_int16_t neighas, >-+ u_int64_t *community) >-+{ >-+ u_int64_t com; >-+ u_int32_t ip; >-+ >-+ com = (u_int64_t)c->type << 56; >-+ switch (c->type & EXT_COMMUNITY_VALUE) { >-+ case EXT_COMMUNITY_TWO_AS: >-+ com |= (u_int64_t)c->subtype << 48; >-+ com |= (u_int64_t)c->data.ext_as.as << 32; >-+ com |= c->data.ext_as.val; >-+ break; >-+ case EXT_COMMUNITY_IPV4: >-+ com |= (u_int64_t)c->subtype << 48; >-+ ip = ntohl(c->data.ext_ip.addr.s_addr); >-+ com |= (u_int64_t)ip << 16; >-+ com |= c->data.ext_ip.val; >-+ break; >-+ case EXT_COMMUNITY_FOUR_AS: >-+ com |= (u_int64_t)c->subtype << 48; >-+ com |= (u_int64_t)c->data.ext_as4.as4 << 16; >-+ com |= c->data.ext_as4.val; >-+ break; >-+ case EXT_COMMUNITY_OPAQUE: >-+ com |= (u_int64_t)c->subtype << 48; >-+ com |= c->data.ext_opaq & EXT_COMMUNITY_OPAQUE_MAX; >-+ break; >-+ default: >-+ com |= c->data.ext_opaq & 0xffffffffffffffULL; >-+ break; >-+ } >-+ >-+ *community = htobe64(com); >-+ >-+ return (0); >-+} >-+ >-+int >-+community_ext_matchone(struct filter_extcommunity *c, u_int16_t neighas, >-+ u_int64_t community) >-+{ >-+ u_int64_t com, mask; >-+ u_int32_t ip; >-+ >-+ community = betoh64(community); >-+ >-+ com = (u_int64_t)c->type << 56; >-+ mask = 0xffULL << 56; >-+ if ((com & mask) != (community & mask)) >-+ return (0); >-+ >-+ switch (c->type & EXT_COMMUNITY_VALUE) { >-+ case EXT_COMMUNITY_TWO_AS: >-+ case EXT_COMMUNITY_IPV4: >-+ case EXT_COMMUNITY_FOUR_AS: >-+ case EXT_COMMUNITY_OPAQUE: >-+ com = (u_int64_t)c->subtype << 48; >-+ mask = 0xffULL << 48; >-+ if ((com & mask) != (community & mask)) >-+ return (0); >-+ break; >-+ default: >-+ com = c->data.ext_opaq & 0xffffffffffffffULL; >-+ mask = 0xffffffffffffffULL; >-+ if ((com & mask) == (community & mask)) >-+ return (1); >-+ return (0); >-+ } >-+ >-+ >-+ switch (c->type & EXT_COMMUNITY_VALUE) { >-+ case EXT_COMMUNITY_TWO_AS: >-+ com = (u_int64_t)c->data.ext_as.as << 32; >-+ mask = 0xffffULL << 32; >-+ if ((com & mask) != (community & mask)) >-+ return (0); >-+ >-+ com = c->data.ext_as.val; >-+ mask = 0xffffffffULL; >-+ if ((com & mask) == (community & mask)) >-+ return (1); >-+ break; >-+ case EXT_COMMUNITY_IPV4: >-+ ip = ntohl(c->data.ext_ip.addr.s_addr); >-+ com = (u_int64_t)ip << 16; >-+ mask = 0xffffffff0000ULL; >-+ if ((com & mask) != (community & mask)) >-+ return (0); >-+ >-+ com = c->data.ext_ip.val; >-+ mask = 0xffff; >-+ if ((com & mask) == (community & mask)) >-+ return (1); >-+ break; >-+ case EXT_COMMUNITY_FOUR_AS: >-+ com = (u_int64_t)c->data.ext_as4.as4 << 16; >-+ mask = 0xffffffffULL << 16; >-+ if ((com & mask) != (community & mask)) >-+ return (0); >-+ >-+ com = c->data.ext_as4.val; >-+ mask = 0xffff; >-+ if ((com & mask) == (community & mask)) >-+ return (1); >-+ break; >-+ case EXT_COMMUNITY_OPAQUE: >-+ com = c->data.ext_opaq & EXT_COMMUNITY_OPAQUE_MAX; >-+ mask = EXT_COMMUNITY_OPAQUE_MAX; >-+ if ((com & mask) == (community & mask)) >-+ return (1); >-+ break; >-+ } >-+ >-+ return (0); >-+} > >Property changes on: files/patch-bgpd_rde_attr.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_rde_decide.c >=================================================================== >--- files/patch-bgpd_rde_decide.c (revision 500577) >+++ files/patch-bgpd_rde_decide.c (nonexistent) >@@ -1,133 +0,0 @@ >-Index: bgpd/rde_decide.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_decide.c,v >-retrieving revision 1.1.1.6 >-retrieving revision 1.4 >-diff -u -p -r1.1.1.6 -r1.4 >---- bgpd/rde_decide.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 >-+++ bgpd/rde_decide.c 13 Oct 2012 18:36:00 -0000 1.4 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: rde_decide.c,v 1.58 2009/06/29 14:10:13 claudio Exp $ */ >-+/* $OpenBSD: rde_decide.c,v 1.61 2012/04/12 17:31:05 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> >-@@ -109,6 +109,9 @@ int >- prefix_cmp(struct prefix *p1, struct prefix *p2) >- { >- struct rde_aspath *asp1, *asp2; >-+ struct attr *a; >-+ u_int32_t p1id, p2id; >-+ int p1cnt, p2cnt; >- >- if (p1 == NULL) >- return (-1); >-@@ -118,6 +121,12 @@ prefix_cmp(struct prefix *p1, struct pre >- asp1 = p1->aspath; >- asp2 = p2->aspath; >- >-+ /* pathes with errors are not eligible */ >-+ if (asp1->flags & F_ATTR_PARSE_ERR) >-+ return (-1); >-+ if (asp2->flags & F_ATTR_PARSE_ERR) >-+ return (1); >-+ >- /* only loop free pathes are eligible */ >- if (asp1->flags & F_ATTR_LOOP) >- return (-1); >-@@ -130,7 +139,7 @@ prefix_cmp(struct prefix *p1, struct pre >- if (asp1->nexthop != NULL && asp1->nexthop->state != NEXTHOP_REACH) >- return (-1); >- >-- /* 2. preference of prefix, bigger is better */ >-+ /* 2. local preference of prefix, bigger is better */ >- if ((asp1->lpref - asp2->lpref) != 0) >- return (asp1->lpref - asp2->lpref); >- >-@@ -154,10 +163,10 @@ prefix_cmp(struct prefix *p1, struct pre >- * It is absolutely important that the ebgp value in peer_config.ebgp >- * is bigger than all other ones (IBGP, confederations) >- */ >-- if ((asp1->peer->conf.ebgp - asp2->peer->conf.ebgp) != 0) { >-- if (asp1->peer->conf.ebgp == 1) /* p1 is EBGP other is lower */ >-+ if (asp1->peer->conf.ebgp != asp2->peer->conf.ebgp) { >-+ if (asp1->peer->conf.ebgp) /* p1 is EBGP other is lower */ >- return 1; >-- else if (asp2->peer->conf.ebgp == 1) /* p2 is EBGP */ >-+ else if (asp2->peer->conf.ebgp) /* p2 is EBGP */ >- return -1; >- } >- >-@@ -181,13 +190,30 @@ prefix_cmp(struct prefix *p1, struct pre >- if ((p2->lastchange - p1->lastchange) != 0) >- return (p2->lastchange - p1->lastchange); >- >-- /* 10. lowest BGP Id wins */ >-- if ((p2->aspath->peer->remote_bgpid - >-- p1->aspath->peer->remote_bgpid) != 0) >-- return (p2->aspath->peer->remote_bgpid - >-- p1->aspath->peer->remote_bgpid); >-+ /* 10. lowest BGP Id wins, use ORIGINATOR_ID if present */ >-+ if ((a = attr_optget(asp1, ATTR_ORIGINATOR_ID)) != NULL) { >-+ memcpy(&p1id, a->data, sizeof(p1id)); >-+ p1id = ntohl(p1id); >-+ } else >-+ p1id = asp1->peer->remote_bgpid; >-+ if ((a = attr_optget(asp2, ATTR_ORIGINATOR_ID)) != NULL) { >-+ memcpy(&p2id, a->data, sizeof(p2id)); >-+ p2id = ntohl(p2id); >-+ } else >-+ p2id = asp2->peer->remote_bgpid; >-+ if ((p2id - p1id) != 0) >-+ return (p2id - p1id); >-+ >-+ /* 11. compare CLUSTER_LIST length, shorter is better */ >-+ p1cnt = p2cnt = 0; >-+ if ((a = attr_optget(asp1, ATTR_CLUSTER_LIST)) != NULL) >-+ p1cnt = a->len / sizeof(u_int32_t); >-+ if ((a = attr_optget(asp2, ATTR_CLUSTER_LIST)) != NULL) >-+ p2cnt = a->len / sizeof(u_int32_t); >-+ if ((p2cnt - p1cnt) != 0) >-+ return (p2cnt - p1cnt); >- >-- /* 11. lowest peer address wins (IPv4 is better than IPv6) */ >-+ /* 12. lowest peer address wins (IPv4 is better than IPv6) */ >- if (memcmp(&p1->aspath->peer->remote_addr, >- &p2->aspath->peer->remote_addr, >- sizeof(p1->aspath->peer->remote_addr)) != 0) >-@@ -195,7 +221,7 @@ prefix_cmp(struct prefix *p1, struct pre >- &p2->aspath->peer->remote_addr, >- sizeof(p1->aspath->peer->remote_addr))); >- >-- /* 12. for announced prefixes prefer dynamic routes */ >-+ /* 13. for announced prefixes prefer dynamic routes */ >- if ((asp1->flags & F_ANN_DYNAMIC) != (asp2->flags & F_ANN_DYNAMIC)) { >- if (asp1->flags & F_ANN_DYNAMIC) >- return (1); >-@@ -204,7 +230,7 @@ prefix_cmp(struct prefix *p1, struct pre >- } >- >- fatalx("Uh, oh a politician in the decision process"); >-- /* NOTREACHED */ >-+ return(0); /* NOTREACHED */ >- } >- >- /* >-@@ -245,7 +271,7 @@ prefix_evaluate(struct prefix *p, struct >- } >- >- xp = LIST_FIRST(&re->prefix_h); >-- if (xp == NULL || xp->aspath->flags & F_ATTR_LOOP || >-+ if (xp == NULL || xp->aspath->flags & (F_ATTR_LOOP|F_ATTR_PARSE_ERR) || >- (xp->aspath->nexthop != NULL && >- xp->aspath->nexthop->state != NEXTHOP_REACH)) >- /* xp is ineligible */ >-@@ -263,7 +289,7 @@ prefix_evaluate(struct prefix *p, struct >- */ >- rde_generate_updates(re->ribid, xp, re->active); >- if ((re->flags & F_RIB_NOFIB) == 0) >-- rde_send_kroute(xp, re->active); >-+ rde_send_kroute(xp, re->active, re->ribid); >- >- re->active = xp; >- if (xp != NULL) > >Property changes on: files/patch-bgpd_rde_decide.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_rde_filter.c >=================================================================== >--- files/patch-bgpd_rde_filter.c (revision 500577) >+++ files/patch-bgpd_rde_filter.c (nonexistent) >@@ -1,297 +0,0 @@ >-Index: bgpd/rde_filter.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_filter.c,v >-retrieving revision 1.1.1.7 >-retrieving revision 1.9 >-diff -u -p -r1.1.1.7 -r1.9 >---- bgpd/rde_filter.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 >-+++ bgpd/rde_filter.c 8 Dec 2012 20:17:59 -0000 1.9 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: rde_filter.c,v 1.56 2009/06/06 01:10:29 claudio Exp $ */ >-+/* $OpenBSD: rde_filter.c,v 1.67 2011/09/20 21:19:06 claudio Exp $ */ >- >- /* >- * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> >-@@ -26,7 +26,7 @@ >- #include "rde.h" >- >- int rde_filter_match(struct filter_rule *, struct rde_aspath *, >-- struct bgpd_addr *, u_int8_t, struct rde_peer *); >-+ struct bgpd_addr *, u_int8_t, struct rde_peer *, struct rde_peer *); >- int filterset_equal(struct filter_set_head *, struct filter_set_head *); >- >- enum filter_actions >-@@ -40,6 +40,13 @@ rde_filter(u_int16_t ribid, struct rde_a >- if (new != NULL) >- *new = NULL; >- >-+ if (asp->flags & F_ATTR_PARSE_ERR) >-+ /* >-+ * don't try to filter bad updates just deny them >-+ * so they act as implicit withdraws >-+ */ >-+ return (ACTION_DENY); >-+ >- TAILQ_FOREACH(f, rules, entry) { >- if (dir != f->dir) >- continue; >-@@ -51,7 +58,7 @@ rde_filter(u_int16_t ribid, struct rde_a >- if (f->peer.peerid != 0 && >- f->peer.peerid != peer->conf.id) >- continue; >-- if (rde_filter_match(f, asp, prefix, prefixlen, peer)) { >-+ if (rde_filter_match(f, asp, prefix, prefixlen, peer, from)) { >- if (asp != NULL && new != NULL) { >- /* asp may get modified so create a copy */ >- if (*new == NULL) { >-@@ -59,7 +66,7 @@ rde_filter(u_int16_t ribid, struct rde_a >- /* ... and use the copy from now on */ >- asp = *new; >- } >-- rde_apply_set(asp, &f->set, prefix->af, >-+ rde_apply_set(asp, &f->set, prefix->aid, >- from, peer); >- } >- if (f->action != ACTION_NONE) >-@@ -73,7 +80,7 @@ rde_filter(u_int16_t ribid, struct rde_a >- >- void >- rde_apply_set(struct rde_aspath *asp, struct filter_set_head *sh, >-- sa_family_t af, struct rde_peer *from, struct rde_peer *peer) >-+ u_int8_t aid, struct rde_peer *from, struct rde_peer *peer) >- { >- struct filter_set *set; >- u_char *np; >-@@ -167,7 +174,7 @@ rde_apply_set(struct rde_aspath *asp, st >- case ACTION_SET_NEXTHOP_NOMODIFY: >- case ACTION_SET_NEXTHOP_SELF: >- nexthop_modify(asp, &set->action.nexthop, set->type, >-- af); >-+ aid); >- break; >- case ACTION_SET_COMMUNITY: >- switch (set->action.community.as) { >-@@ -243,19 +250,42 @@ rde_apply_set(struct rde_aspath *asp, st >- asp->rtlabelid = set->action.id; >- rtlabel_ref(asp->rtlabelid); >- break; >-+ case ACTION_SET_ORIGIN: >-+ asp->origin = set->action.origin; >-+ break; >-+ case ACTION_SET_EXT_COMMUNITY: >-+ community_ext_set(asp, &set->action.ext_community, >-+ peer->conf.remote_as); >-+ break; >-+ case ACTION_DEL_EXT_COMMUNITY: >-+ community_ext_delete(asp, &set->action.ext_community, >-+ peer->conf.remote_as); >-+ break; >- } >- } >- } >- >- int >- rde_filter_match(struct filter_rule *f, struct rde_aspath *asp, >-- struct bgpd_addr *prefix, u_int8_t plen, struct rde_peer *peer) >-+ struct bgpd_addr *prefix, u_int8_t plen, struct rde_peer *peer, >-+ struct rde_peer *from) >- { >-- int as, type; >-+ u_int32_t pas; >-+ int cas, type; >- >-- if (asp != NULL && f->match.as.type != AS_NONE) >-- if (aspath_match(asp->aspath, f->match.as.type, >-- f->match.as.as) == 0) >-+ if (asp != NULL && f->match.as.type != AS_NONE) { >-+ if (f->match.as.flags & AS_FLAG_NEIGHBORAS) >-+ pas = peer->conf.remote_as; >-+ else >-+ pas = f->match.as.as; >-+ if (aspath_match(asp->aspath->data, asp->aspath->len, >-+ f->match.as.type, pas) == 0) >-+ return (0); >-+ } >-+ >-+ if (asp != NULL && f->match.aslen.type != ASLEN_NONE) >-+ if (aspath_lenmatch(asp->aspath, f->match.aslen.type, >-+ f->match.aslen.aslen) == 0) >- return (0); >- >- if (asp != NULL && f->match.community.as != COMMUNITY_UNSET) { >-@@ -263,10 +293,10 @@ rde_filter_match(struct filter_rule *f, >- case COMMUNITY_ERROR: >- fatalx("rde_apply_set bad community string"); >- case COMMUNITY_NEIGHBOR_AS: >-- as = peer->conf.remote_as; >-+ cas = peer->conf.remote_as; >- break; >- default: >-- as = f->match.community.as; >-+ cas = f->match.community.as; >- break; >- } >- >-@@ -281,12 +311,17 @@ rde_filter_match(struct filter_rule *f, >- break; >- } >- >-- if (rde_filter_community(asp, as, type) == 0) >-+ if (community_match(asp, cas, type) == 0) >- return (0); >- } >-+ if (asp != NULL && >-+ (f->match.ext_community.flags & EXT_COMMUNITY_FLAG_VALID)) >-+ if (community_ext_match(asp, &f->match.ext_community, >-+ peer->conf.remote_as) == 0) >-+ return (0); >- >-- if (f->match.prefix.addr.af != 0) { >-- if (f->match.prefix.addr.af != prefix->af) >-+ if (f->match.prefix.addr.aid != 0) { >-+ if (f->match.prefix.addr.aid != prefix->aid) >- /* don't use IPv4 rules for IPv6 and vice versa */ >- return (0); >- >-@@ -322,7 +357,7 @@ rde_filter_match(struct filter_rule *f, >- } else if (f->match.prefixlen.op != OP_NONE) { >- /* only prefixlen without a prefix */ >- >-- if (f->match.prefixlen.af != prefix->af) >-+ if (f->match.prefixlen.aid != prefix->aid) >- /* don't use IPv4 rules for IPv6 and vice versa */ >- return (0); >- >-@@ -350,25 +385,40 @@ rde_filter_match(struct filter_rule *f, >- } >- /* NOTREACHED */ >- } >-+ if (f->match.nexthop.flags != 0) { >-+ struct bgpd_addr *nexthop, *cmpaddr; >-+ if (asp->nexthop == NULL) >-+ /* no nexthop, skip */ >-+ return (0); >-+ nexthop = &asp->nexthop->exit_nexthop; >-+ if (f->match.nexthop.flags == FILTER_NEXTHOP_ADDR) >-+ cmpaddr = &f->match.nexthop.addr; >-+ else >-+ cmpaddr = &from->remote_addr; >-+ if (cmpaddr->aid != nexthop->aid) >-+ /* don't use IPv4 rules for IPv6 and vice versa */ >-+ return (0); >-+ >-+ switch (cmpaddr->aid) { >-+ case AID_INET: >-+ if (cmpaddr->v4.s_addr != nexthop->v4.s_addr) >-+ return (0); >-+ break; >-+ case AID_INET6: >-+ if (memcmp(&cmpaddr->v6, &nexthop->v6, >-+ sizeof(struct in6_addr))) >-+ return (0); >-+ break; >-+ default: >-+ fatalx("King Bula lost in address space"); >-+ } >-+ } >- >- /* matched somewhen or is anymatch rule */ >- return (1); >- } >- >- int >--rde_filter_community(struct rde_aspath *asp, int as, int type) >--{ >-- struct attr *a; >-- >-- a = attr_optget(asp, ATTR_COMMUNITIES); >-- if (a == NULL) >-- /* no communities, no match */ >-- return (0); >-- >-- return (community_match(a->data, a->len, as, type)); >--} >-- >--int >- rde_filter_equal(struct filter_head *a, struct filter_head *b, >- struct rde_peer *peer, enum directions dir) >- { >-@@ -476,6 +526,12 @@ filterset_cmp(struct filter_set *a, stru >- return (a->action.community.type - b->action.community.type); >- } >- >-+ if (a->type == ACTION_SET_EXT_COMMUNITY || >-+ a->type == ACTION_DEL_EXT_COMMUNITY) { /* a->type == b->type */ >-+ return (memcmp(&a->action.ext_community, >-+ &b->action.ext_community, sizeof(a->action.ext_community))); >-+ } >-+ >- if (a->type == ACTION_SET_NEXTHOP && b->type == ACTION_SET_NEXTHOP) { >- /* >- * This is the only interesting case, all others are considered >-@@ -483,13 +539,29 @@ filterset_cmp(struct filter_set *a, stru >- * reject it at the same time. Allow one IPv4 and one IPv6 >- * per filter set or only one of the other nexthop modifiers. >- */ >-- return (a->action.nexthop.af - b->action.nexthop.af); >-+ return (a->action.nexthop.aid - b->action.nexthop.aid); >- } >- >- /* equal */ >- return (0); >- } >- >-+void >-+filterset_move(struct filter_set_head *source, struct filter_set_head *dest) >-+{ >-+ struct filter_set *s; >-+ >-+ TAILQ_INIT(dest); >-+ >-+ if (source == NULL) >-+ return; >-+ >-+ while ((s = TAILQ_FIRST(source)) != NULL) { >-+ TAILQ_REMOVE(source, s, entry); >-+ TAILQ_INSERT_TAIL(dest, s, entry); >-+ } >-+} >-+ >- int >- filterset_equal(struct filter_set_head *ah, struct filter_set_head *bh) >- { >-@@ -574,6 +646,19 @@ filterset_equal(struct filter_set_head * >- if (strcmp(as, bs) == 0) >- continue; >- break; >-+ case ACTION_SET_ORIGIN: >-+ if (a->type == b->type && >-+ a->action.origin == b->action.origin) >-+ continue; >-+ break; >-+ case ACTION_SET_EXT_COMMUNITY: >-+ case ACTION_DEL_EXT_COMMUNITY: >-+ if (a->type == b->type && memcmp( >-+ &a->action.ext_community, >-+ &b->action.ext_community, >-+ sizeof(a->action.ext_community)) == 0) >-+ continue; >-+ break; >- } >- /* compare failed */ >- return (0); >-@@ -616,7 +701,14 @@ filterset_name(enum action_types type) >- case ACTION_RTLABEL: >- case ACTION_RTLABEL_ID: >- return ("rtlabel"); >-+ case ACTION_SET_ORIGIN: >-+ return ("origin"); >-+ case ACTION_SET_EXT_COMMUNITY: >-+ return ("ext-community"); >-+ case ACTION_DEL_EXT_COMMUNITY: >-+ return ("ext-community delete"); >- } >- >- fatalx("filterset_name: got lost"); >-+ return (NULL); /* NOT REACHED */ >- } > >Property changes on: files/patch-bgpd_rde_filter.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_rde_prefix.c >=================================================================== >--- files/patch-bgpd_rde_prefix.c (revision 500577) >+++ files/patch-bgpd_rde_prefix.c (nonexistent) >@@ -1,301 +0,0 @@ >-Index: bgpd/rde_prefix.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_prefix.c,v >-retrieving revision 1.1.1.6 >-retrieving revision 1.6 >-diff -u -p -r1.1.1.6 -r1.6 >---- bgpd/rde_prefix.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 >-+++ bgpd/rde_prefix.c 13 Oct 2012 18:36:00 -0000 1.6 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: rde_prefix.c,v 1.29 2009/05/30 18:27:17 claudio Exp $ */ >-+/* $OpenBSD: rde_prefix.c,v 1.31 2010/01/13 06:02:37 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> >-@@ -38,15 +38,16 @@ >- * pt_lookup: lookup a IP in the prefix table. Mainly for "show ip bgp". >- * pt_empty: returns true if there is no bgp prefix linked to the pt_entry. >- * pt_init: initialize prefix table. >-- * pt_alloc?: allocate a AF specific pt_entry. Internal function. >-+ * pt_alloc: allocate a AF specific pt_entry. Internal function. >- * pt_free: free a pt_entry. Internal function. >- */ >- >- /* internal prototypes */ >--static struct pt_entry4 *pt_alloc4(void); >--static struct pt_entry6 *pt_alloc6(void); >-+static struct pt_entry *pt_alloc(struct pt_entry *); >- static void pt_free(struct pt_entry *); >- >-+size_t pt_sizes[AID_MAX] = AID_PTSIZE; >-+ >- RB_HEAD(pt_tree, pt_entry); >- RB_PROTOTYPE(pt_tree, pt_entry, pt_e, pt_prefix_cmp); >- RB_GENERATE(pt_tree, pt_entry, pt_e, pt_prefix_cmp); >-@@ -70,17 +71,24 @@ void >- pt_getaddr(struct pt_entry *pte, struct bgpd_addr *addr) >- { >- bzero(addr, sizeof(struct bgpd_addr)); >-- switch (pte->af) { >-- case AF_INET: >-- addr->af = pte->af; >-+ addr->aid = pte->aid; >-+ switch (addr->aid) { >-+ case AID_INET: >- addr->v4 = ((struct pt_entry4 *)pte)->prefix4; >- break; >-- case AF_INET6: >-- addr->af = pte->af; >-+ case AID_INET6: >- memcpy(&addr->v6, &((struct pt_entry6 *)pte)->prefix6, >- sizeof(addr->v6)); >- /* XXX scope_id ??? */ >- break; >-+ case AID_VPN_IPv4: >-+ addr->vpn4.addr = ((struct pt_entry_vpn4 *)pte)->prefix4; >-+ addr->vpn4.rd = ((struct pt_entry_vpn4 *)pte)->rd; >-+ addr->vpn4.labellen = ((struct pt_entry_vpn4 *)pte)->labellen; >-+ memcpy(addr->vpn4.labelstack, >-+ ((struct pt_entry_vpn4 *)pte)->labelstack, >-+ addr->vpn4.labellen); >-+ break; >- default: >- fatalx("pt_getaddr: unknown af"); >- } >-@@ -89,33 +97,49 @@ pt_getaddr(struct pt_entry *pte, struct >- struct pt_entry * >- pt_fill(struct bgpd_addr *prefix, int prefixlen) >- { >-- static struct pt_entry4 pte4; >-- static struct pt_entry6 pte6; >-- in_addr_t addr_hbo; >-+ static struct pt_entry4 pte4; >-+ static struct pt_entry6 pte6; >-+ static struct pt_entry_vpn4 pte_vpn4; >-+ in_addr_t addr_hbo; >- >-- switch (prefix->af) { >-- case AF_INET: >-+ switch (prefix->aid) { >-+ case AID_INET: >- bzero(&pte4, sizeof(pte4)); >-+ pte4.aid = prefix->aid; >- if (prefixlen > 32) >-- fatalx("pt_get: bad IPv4 prefixlen"); >-- pte4.af = AF_INET; >-+ fatalx("pt_fill: bad IPv4 prefixlen"); >- addr_hbo = ntohl(prefix->v4.s_addr); >- pte4.prefix4.s_addr = htonl(addr_hbo & >- prefixlen2mask(prefixlen)); >- pte4.prefixlen = prefixlen; >- return ((struct pt_entry *)&pte4); >-- case AF_INET6: >-+ case AID_INET6: >- bzero(&pte6, sizeof(pte6)); >-+ pte6.aid = prefix->aid; >- if (prefixlen > 128) >- fatalx("pt_get: bad IPv6 prefixlen"); >-- pte6.af = AF_INET6; >- pte6.prefixlen = prefixlen; >- inet6applymask(&pte6.prefix6, &prefix->v6, prefixlen); >- return ((struct pt_entry *)&pte6); >-+ case AID_VPN_IPv4: >-+ bzero(&pte_vpn4, sizeof(pte_vpn4)); >-+ pte_vpn4.aid = prefix->aid; >-+ if (prefixlen > 32) >-+ fatalx("pt_fill: bad IPv4 prefixlen"); >-+ addr_hbo = ntohl(prefix->vpn4.addr.s_addr); >-+ pte_vpn4.prefix4.s_addr = htonl(addr_hbo & >-+ prefixlen2mask(prefixlen)); >-+ pte_vpn4.prefixlen = prefixlen; >-+ pte_vpn4.rd = prefix->vpn4.rd; >-+ pte_vpn4.labellen = prefix->vpn4.labellen; >-+ memcpy(pte_vpn4.labelstack, prefix->vpn4.labelstack, >-+ prefix->vpn4.labellen); >-+ return ((struct pt_entry *)&pte_vpn4); >- default: >-- log_warnx("pt_get: unknown af"); >-- return (NULL); >-+ fatalx("pt_fill: unknown af"); >- } >-+ /* NOT REACHED */ >-+ return (NULL); >- } >- >- struct pt_entry * >-@@ -131,39 +155,12 @@ struct pt_entry * >- pt_add(struct bgpd_addr *prefix, int prefixlen) >- { >- struct pt_entry *p = NULL; >-- struct pt_entry4 *p4; >-- struct pt_entry6 *p6; >-- in_addr_t addr_hbo; >-- >-- switch (prefix->af) { >-- case AF_INET: >-- p4 = pt_alloc4(); >-- if (prefixlen > 32) >-- fatalx("pt_add: bad IPv4 prefixlen"); >-- p4->af = AF_INET; >-- p4->prefixlen = prefixlen; >-- addr_hbo = ntohl(prefix->v4.s_addr); >-- p4->prefix4.s_addr = htonl(addr_hbo & >-- prefixlen2mask(prefixlen)); >-- p = (struct pt_entry *)p4; >-- break; >-- case AF_INET6: >-- p6 = pt_alloc6(); >-- if (prefixlen > 128) >-- fatalx("pt_add: bad IPv6 prefixlen"); >-- p6->af = AF_INET6; >-- p6->prefixlen = prefixlen; >-- inet6applymask(&p6->prefix6, &prefix->v6, prefixlen); >-- p = (struct pt_entry *)p6; >-- break; >-- default: >-- fatalx("pt_add: unknown af"); >-- } >- >-- if (RB_INSERT(pt_tree, &pttable, p) != NULL) { >-- log_warnx("pt_add: insert failed"); >-- return (NULL); >-- } >-+ p = pt_fill(prefix, prefixlen); >-+ p = pt_alloc(p); >-+ >-+ if (RB_INSERT(pt_tree, &pttable, p) != NULL) >-+ fatalx("pt_add: insert failed"); >- >- return (p); >- } >-@@ -183,13 +180,14 @@ struct pt_entry * >- pt_lookup(struct bgpd_addr *addr) >- { >- struct pt_entry *p; >-- int i; >-+ int i = 0; >- >-- switch (addr->af) { >-- case AF_INET: >-+ switch (addr->aid) { >-+ case AID_INET: >-+ case AID_VPN_IPv4: >- i = 32; >- break; >-- case AF_INET6: >-+ case AID_INET6: >- i = 128; >- break; >- default: >-@@ -206,17 +204,18 @@ pt_lookup(struct bgpd_addr *addr) >- int >- pt_prefix_cmp(const struct pt_entry *a, const struct pt_entry *b) >- { >-- const struct pt_entry4 *a4, *b4; >-- const struct pt_entry6 *a6, *b6; >-- int i; >-+ const struct pt_entry4 *a4, *b4; >-+ const struct pt_entry6 *a6, *b6; >-+ const struct pt_entry_vpn4 *va4, *vb4; >-+ int i; >- >-- if (a->af > b->af) >-+ if (a->aid > b->aid) >- return (1); >-- if (a->af < b->af) >-+ if (a->aid < b->aid) >- return (-1); >- >-- switch (a->af) { >-- case AF_INET: >-+ switch (a->aid) { >-+ case AID_INET: >- a4 = (const struct pt_entry4 *)a; >- b4 = (const struct pt_entry4 *)b; >- if (ntohl(a4->prefix4.s_addr) > ntohl(b4->prefix4.s_addr)) >-@@ -228,7 +227,7 @@ pt_prefix_cmp(const struct pt_entry *a, >- if (a4->prefixlen < b4->prefixlen) >- return (-1); >- return (0); >-- case AF_INET6: >-+ case AID_INET6: >- a6 = (const struct pt_entry6 *)a; >- b6 = (const struct pt_entry6 *)b; >- >-@@ -242,49 +241,49 @@ pt_prefix_cmp(const struct pt_entry *a, >- if (a6->prefixlen > b6->prefixlen) >- return (1); >- return (0); >-+ case AID_VPN_IPv4: >-+ va4 = (const struct pt_entry_vpn4 *)a; >-+ vb4 = (const struct pt_entry_vpn4 *)b; >-+ if (ntohl(va4->prefix4.s_addr) > ntohl(vb4->prefix4.s_addr)) >-+ return (1); >-+ if (ntohl(va4->prefix4.s_addr) < ntohl(vb4->prefix4.s_addr)) >-+ return (-1); >-+ if (va4->prefixlen > vb4->prefixlen) >-+ return (1); >-+ if (va4->prefixlen < vb4->prefixlen) >-+ return (-1); >-+ if (betoh64(va4->rd) > betoh64(vb4->rd)) >-+ return (1); >-+ if (betoh64(va4->rd) < betoh64(vb4->rd)) >-+ return (-1); >-+ return (0); >- default: >- fatalx("pt_prefix_cmp: unknown af"); >- } >- return (-1); >- } >- >--/* returns a zeroed pt_entry function may not return on fail */ >--static struct pt_entry4 * >--pt_alloc4(void) >-+/* >-+ * Returns a pt_entry cloned from the one passed in. >-+ * Function may not return on failure. >-+ */ >-+static struct pt_entry * >-+pt_alloc(struct pt_entry *op) >- { >-- struct pt_entry4 *p; >-+ struct pt_entry *p; >- >-- p = calloc(1, sizeof(*p)); >-+ p = malloc(pt_sizes[op->aid]); >- if (p == NULL) >- fatal("pt_alloc"); >-- rdemem.pt4_cnt++; >-- return (p); >--} >-+ rdemem.pt_cnt[op->aid]++; >-+ memcpy(p, op, pt_sizes[op->aid]); >- >--static struct pt_entry6 * >--pt_alloc6(void) >--{ >-- struct pt_entry6 *p; >-- >-- p = calloc(1, sizeof(*p)); >-- if (p == NULL) >-- fatal("pt_alloc"); >-- rdemem.pt6_cnt++; >- return (p); >- } >- >- static void >- pt_free(struct pt_entry *pte) >- { >-- switch (pte->af) { >-- case AF_INET: >-- rdemem.pt4_cnt--; >-- break; >-- case AF_INET6: >-- rdemem.pt6_cnt--; >-- break; >-- default: >-- break; >-- } >-+ rdemem.pt_cnt[pte->aid]--; >- free(pte); >- } > >Property changes on: files/patch-bgpd_rde_prefix.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_rde_rib.c >=================================================================== >--- files/patch-bgpd_rde_rib.c (revision 500577) >+++ files/patch-bgpd_rde_rib.c (nonexistent) >@@ -1,513 +0,0 @@ >-Index: bgpd/rde_rib.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_rib.c,v >-retrieving revision 1.1.1.7 >-retrieving revision 1.8 >-diff -u -p -r1.1.1.7 -r1.8 >---- bgpd/rde_rib.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 >-+++ bgpd/rde_rib.c 13 Oct 2012 18:36:00 -0000 1.8 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: rde_rib.c,v 1.116 2009/06/29 14:13:48 claudio Exp $ */ >-+/* $OpenBSD: rde_rib.c,v 1.133 2012/07/01 11:55:13 sthen Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> >-@@ -18,7 +18,11 @@ >- >- #include <sys/types.h> >- #include <sys/queue.h> >-+#if defined(__FreeBSD__) /* sys/hash.h */ >-+#include "hash.h" >-+#else >- #include <sys/hash.h> >-+#endif /* defined(__FreeBSD__) */ >- >- #include <stdlib.h> >- #include <string.h> >-@@ -50,16 +54,15 @@ RB_GENERATE(rib_tree, rib_entry, rib_e, >- >- /* RIB specific functions */ >- u_int16_t >--rib_new(int id, char *name, u_int16_t flags) >-+rib_new(char *name, u_int rtableid, u_int16_t flags) >- { >- struct rib *xribs; >- size_t newsize; >-+ u_int16_t id; >- >-- if (id < 0) { >-- for (id = 0; id < rib_size; id++) { >-- if (*ribs[id].name == '\0') >-- break; >-- } >-+ for (id = 0; id < rib_size; id++) { >-+ if (*ribs[id].name == '\0') >-+ break; >- } >- >- if (id == RIB_FAILED) >-@@ -78,9 +81,10 @@ rib_new(int id, char *name, u_int16_t fl >- bzero(&ribs[id], sizeof(struct rib)); >- strlcpy(ribs[id].name, name, sizeof(ribs[id].name)); >- RB_INIT(&ribs[id].rib); >-- ribs[id].state = RIB_ACTIVE; >-+ ribs[id].state = RECONF_REINIT; >- ribs[id].id = id; >- ribs[id].flags = flags; >-+ ribs[id].rtableid = rtableid; >- >- return (id); >- } >-@@ -173,15 +177,16 @@ rib_lookup(struct rib *rib, struct bgpd_ >- struct rib_entry *re; >- int i; >- >-- switch (addr->af) { >-- case AF_INET: >-+ switch (addr->aid) { >-+ case AID_INET: >-+ case AID_VPN_IPv4: >- for (i = 32; i >= 0; i--) { >- re = rib_get(rib, addr, i); >- if (re != NULL) >- return (re); >- } >- break; >-- case AF_INET6: >-+ case AID_INET6: >- for (i = 128; i >= 0; i--) { >- re = rib_get(rib, addr, i); >- if (re != NULL) >-@@ -215,6 +220,7 @@ rib_add(struct rib *rib, struct bgpd_add >- >- if (RB_INSERT(rib_tree, &rib->rib, re) != NULL) { >- log_warnx("rib_add: insert failed"); >-+ free(re); >- return (NULL); >- } >- >-@@ -254,7 +260,7 @@ rib_empty(struct rib_entry *re) >- >- void >- rib_dump(struct rib *rib, void (*upcall)(struct rib_entry *, void *), >-- void *arg, sa_family_t af) >-+ void *arg, u_int8_t aid) >- { >- struct rib_context *ctx; >- >-@@ -263,7 +269,7 @@ rib_dump(struct rib *rib, void (*upcall) >- ctx->ctx_rib = rib; >- ctx->ctx_upcall = upcall; >- ctx->ctx_arg = arg; >-- ctx->ctx_af = af; >-+ ctx->ctx_aid = aid; >- rib_dump_r(ctx); >- } >- >-@@ -280,7 +286,8 @@ rib_dump_r(struct rib_context *ctx) >- re = rib_restart(ctx); >- >- for (i = 0; re != NULL; re = RB_NEXT(rib_tree, unused, re)) { >-- if (ctx->ctx_af != AF_UNSPEC && ctx->ctx_af != re->prefix->af) >-+ if (ctx->ctx_aid != AID_UNSPEC && >-+ ctx->ctx_aid != re->prefix->aid) >- continue; >- if (ctx->ctx_count && i++ >= ctx->ctx_count && >- (re->flags & F_RIB_ENTRYLOCK) == 0) { >-@@ -308,7 +315,7 @@ rib_restart(struct rib_context *ctx) >- re->flags &= ~F_RIB_ENTRYLOCK; >- >- /* find first non empty element */ >-- while (rib_empty(re)) >-+ while (re && rib_empty(re)) >- re = RB_NEXT(rib_tree, unused, re); >- >- /* free the previously locked rib element if empty */ >-@@ -502,6 +509,36 @@ path_remove(struct rde_aspath *asp) >- } >- } >- >-+/* remove all stale routes or if staletime is 0 remove all routes for >-+ a specified AID. */ >-+void >-+path_remove_stale(struct rde_aspath *asp, u_int8_t aid) >-+{ >-+ struct prefix *p, *np; >-+ time_t staletime; >-+ >-+ staletime = asp->peer->staletime[aid]; >-+ for (p = LIST_FIRST(&asp->prefix_h); p != NULL; p = np) { >-+ np = LIST_NEXT(p, path_l); >-+ if (p->prefix->aid != aid) >-+ continue; >-+ >-+ if (staletime && p->lastchange > staletime) >-+ continue; >-+ >-+ if (asp->pftableid) { >-+ struct bgpd_addr addr; >-+ >-+ pt_getaddr(p->prefix, &addr); >-+ /* Commit is done in peer_flush() */ >-+ rde_send_pftable(p->aspath->pftableid, &addr, >-+ p->prefix->prefixlen, 1); >-+ } >-+ prefix_destroy(p); >-+ } >-+} >-+ >-+ >- /* this function is only called by prefix_remove and path_remove */ >- void >- path_destroy(struct rde_aspath *asp) >-@@ -624,48 +661,6 @@ static void prefix_link(struct prefix >- struct rde_aspath *); >- static void prefix_unlink(struct prefix *); >- >--int >--prefix_compare(const struct bgpd_addr *a, const struct bgpd_addr *b, >-- int prefixlen) >--{ >-- in_addr_t mask, aa, ba; >-- int i; >-- u_int8_t m; >-- >-- if (a->af != b->af) >-- return (a->af - b->af); >-- >-- switch (a->af) { >-- case AF_INET: >-- if (prefixlen > 32) >-- fatalx("prefix_cmp: bad IPv4 prefixlen"); >-- mask = htonl(prefixlen2mask(prefixlen)); >-- aa = ntohl(a->v4.s_addr & mask); >-- ba = ntohl(b->v4.s_addr & mask); >-- if (aa != ba) >-- return (aa - ba); >-- return (0); >-- case AF_INET6: >-- if (prefixlen > 128) >-- fatalx("prefix_cmp: bad IPv6 prefixlen"); >-- for (i = 0; i < prefixlen / 8; i++) >-- if (a->v6.s6_addr[i] != b->v6.s6_addr[i]) >-- return (a->v6.s6_addr[i] - b->v6.s6_addr[i]); >-- i = prefixlen % 8; >-- if (i) { >-- m = 0xff00 >> i; >-- if ((a->v6.s6_addr[prefixlen / 8] & m) != >-- (b->v6.s6_addr[prefixlen / 8] & m)) >-- return ((a->v6.s6_addr[prefixlen / 8] & m) - >-- (b->v6.s6_addr[prefixlen / 8] & m)); >-- } >-- return (0); >-- default: >-- fatalx("prefix_cmp: unknown af"); >-- } >-- return (-1); >--} >-- >- /* >- * search for specified prefix of a peer. Returns NULL if not found. >- */ >-@@ -806,16 +801,58 @@ prefix_write(u_char *buf, int len, struc >- { >- int totlen; >- >-- if (prefix->af != AF_INET && prefix->af != AF_INET6) >-+ switch (prefix->aid) { >-+ case AID_INET: >-+ case AID_INET6: >-+ totlen = PREFIX_SIZE(plen); >-+ >-+ if (totlen > len) >-+ return (-1); >-+ *buf++ = plen; >-+ memcpy(buf, &prefix->ba, totlen - 1); >-+ return (totlen); >-+ case AID_VPN_IPv4: >-+ totlen = PREFIX_SIZE(plen) + sizeof(prefix->vpn4.rd) + >-+ prefix->vpn4.labellen; >-+ plen += (sizeof(prefix->vpn4.rd) + prefix->vpn4.labellen) * 8; >-+ >-+ if (totlen > len) >-+ return (-1); >-+ *buf++ = plen; >-+ memcpy(buf, &prefix->vpn4.labelstack, prefix->vpn4.labellen); >-+ buf += prefix->vpn4.labellen; >-+ memcpy(buf, &prefix->vpn4.rd, sizeof(prefix->vpn4.rd)); >-+ buf += sizeof(prefix->vpn4.rd); >-+ memcpy(buf, &prefix->vpn4.addr, PREFIX_SIZE(plen) - 1); >-+ return (totlen); >-+ default: >- return (-1); >-+ } >-+} >- >-- totlen = PREFIX_SIZE(plen); >-+int >-+prefix_writebuf(struct ibuf *buf, struct bgpd_addr *prefix, u_int8_t plen) >-+{ >-+ int totlen; >-+ void *bptr; >- >-- if (totlen > len) >-+ switch (prefix->aid) { >-+ case AID_INET: >-+ case AID_INET6: >-+ totlen = PREFIX_SIZE(plen); >-+ break; >-+ case AID_VPN_IPv4: >-+ totlen = PREFIX_SIZE(plen) + sizeof(prefix->vpn4.rd) + >-+ prefix->vpn4.labellen; >-+ default: >- return (-1); >-- *buf++ = plen; >-- memcpy(buf, &prefix->ba, totlen - 1); >-- return (totlen); >-+ } >-+ >-+ if ((bptr = ibuf_reserve(buf, totlen)) == NULL) >-+ return (-1); >-+ if (prefix_write(bptr, totlen, prefix, plen) == -1) >-+ return (-1); >-+ return (0); >- } >- >- /* >-@@ -861,7 +898,7 @@ prefix_updateall(struct rde_aspath *asp, >- */ >- if ((p->rib->flags & F_RIB_NOFIB) == 0 && >- p == p->rib->active) >-- rde_send_kroute(p, NULL); >-+ rde_send_kroute(p, NULL, p->rib->ribid); >- continue; >- } >- >-@@ -871,7 +908,7 @@ prefix_updateall(struct rde_aspath *asp, >- * If the prefix is the active one remove it first, >- * this has to be done because we can not detect when >- * the active prefix changes its state. In this case >-- * we know that this is a withdrawl and so the second >-+ * we know that this is a withdrawal and so the second >- * prefix_evaluate() will generate no update because >- * the nexthop is unreachable or ineligible. >- */ >-@@ -885,16 +922,12 @@ prefix_updateall(struct rde_aspath *asp, >- void >- prefix_destroy(struct prefix *p) >- { >-- struct rib_entry *re; >- struct rde_aspath *asp; >- >-- re = p->rib; >- asp = p->aspath; >- prefix_unlink(p); >- prefix_free(p); >- >-- if (rib_empty(re)) >-- rib_remove(re); >- if (path_empty(asp)) >- path_destroy(asp); >- } >-@@ -907,21 +940,16 @@ prefix_network_clean(struct rde_peer *pe >- { >- struct rde_aspath *asp, *xasp; >- struct prefix *p, *xp; >-- struct pt_entry *pte; >- >- for (asp = LIST_FIRST(&peer->path_h); asp != NULL; asp = xasp) { >- xasp = LIST_NEXT(asp, peer_l); >-- if ((asp->flags & F_ANN_DYNAMIC) == flags) >-+ if ((asp->flags & F_ANN_DYNAMIC) != flags) >- continue; >- for (p = LIST_FIRST(&asp->prefix_h); p != NULL; p = xp) { >- xp = LIST_NEXT(p, path_l); >- if (reloadtime > p->lastchange) { >-- pte = p->prefix; >- prefix_unlink(p); >- prefix_free(p); >-- >-- if (pt_empty(pte)) >-- pt_remove(pte); >- } >- } >- if (path_empty(asp)) >-@@ -954,11 +982,11 @@ prefix_link(struct prefix *pref, struct >- static void >- prefix_unlink(struct prefix *pref) >- { >-- if (pref->rib) { >-- /* make route decision */ >-- LIST_REMOVE(pref, rib_l); >-- prefix_evaluate(NULL, pref->rib); >-- } >-+ struct rib_entry *re = pref->rib; >-+ >-+ /* make route decision */ >-+ LIST_REMOVE(pref, rib_l); >-+ prefix_evaluate(NULL, re); >- >- LIST_REMOVE(pref, path_l); >- PREFIX_COUNT(pref->aspath, -1); >-@@ -966,6 +994,8 @@ prefix_unlink(struct prefix *pref) >- pt_unref(pref->prefix); >- if (pt_empty(pref->prefix)) >- pt_remove(pref->prefix); >-+ if (rib_empty(re)) >-+ rib_remove(re); >- >- /* destroy all references to other objects */ >- pref->aspath = NULL; >-@@ -973,8 +1003,8 @@ prefix_unlink(struct prefix *pref) >- pref->rib = NULL; >- >- /* >-- * It's the caller's duty to remove empty aspath respectively pt_entry >-- * structures. Also freeing the unlinked prefix is the caller's duty. >-+ * It's the caller's duty to remove empty aspath structures. >-+ * Also freeing the unlinked prefix is the caller's duty. >- */ >- } >- >-@@ -1070,10 +1100,6 @@ nexthop_update(struct kroute_nexthop *ms >- return; >- } >- >-- if (nexthop_delete(nh)) >-- /* nexthop no longer used */ >-- return; >-- >- oldstate = nh->state; >- if (msg->valid) >- nh->state = NEXTHOP_REACH; >-@@ -1088,21 +1114,13 @@ nexthop_update(struct kroute_nexthop *ms >- memcpy(&nh->true_nexthop, &msg->gateway, >- sizeof(nh->true_nexthop)); >- >-- switch (msg->nexthop.af) { >-- case AF_INET: >-- nh->nexthop_netlen = msg->kr.kr4.prefixlen; >-- nh->nexthop_net.af = AF_INET; >-- nh->nexthop_net.v4.s_addr = msg->kr.kr4.prefix.s_addr; >-- break; >-- case AF_INET6: >-- nh->nexthop_netlen = msg->kr.kr6.prefixlen; >-- nh->nexthop_net.af = AF_INET6; >-- memcpy(&nh->nexthop_net.v6, &msg->kr.kr6.prefix, >-- sizeof(struct in6_addr)); >-- break; >-- default: >-- fatalx("nexthop_update: unknown af"); >-- } >-+ memcpy(&nh->nexthop_net, &msg->net, >-+ sizeof(nh->nexthop_net)); >-+ nh->nexthop_netlen = msg->netlen; >-+ >-+ if (nexthop_delete(nh)) >-+ /* nexthop no longer used */ >-+ return; >- >- if (rde_noevaluate()) >- /* >-@@ -1118,35 +1136,38 @@ nexthop_update(struct kroute_nexthop *ms >- >- void >- nexthop_modify(struct rde_aspath *asp, struct bgpd_addr *nexthop, >-- enum action_types type, sa_family_t af) >-+ enum action_types type, u_int8_t aid) >- { >- struct nexthop *nh; >- >-- if (type == ACTION_SET_NEXTHOP_REJECT) { >-- asp->flags |= F_NEXTHOP_REJECT; >-+ if (type == ACTION_SET_NEXTHOP && aid != nexthop->aid) >- return; >-- } >-- if (type == ACTION_SET_NEXTHOP_BLACKHOLE) { >-+ >-+ asp->flags &= ~F_NEXTHOP_MASK; >-+ switch (type) { >-+ case ACTION_SET_NEXTHOP_REJECT: >-+ asp->flags |= F_NEXTHOP_REJECT; >-+ break; >-+ case ACTION_SET_NEXTHOP_BLACKHOLE: >- asp->flags |= F_NEXTHOP_BLACKHOLE; >-- return; >-- } >-- if (type == ACTION_SET_NEXTHOP_NOMODIFY) { >-+ break; >-+ case ACTION_SET_NEXTHOP_NOMODIFY: >- asp->flags |= F_NEXTHOP_NOMODIFY; >-- return; >-- } >-- if (type == ACTION_SET_NEXTHOP_SELF) { >-+ break; >-+ case ACTION_SET_NEXTHOP_SELF: >- asp->flags |= F_NEXTHOP_SELF; >-- return; >-+ break; >-+ case ACTION_SET_NEXTHOP: >-+ nh = nexthop_get(nexthop); >-+ if (asp->flags & F_ATTR_LINKED) >-+ nexthop_unlink(asp); >-+ asp->nexthop = nh; >-+ if (asp->flags & F_ATTR_LINKED) >-+ nexthop_link(asp); >-+ break; >-+ default: >-+ break; >- } >-- if (af != nexthop->af) >-- return; >-- >-- nh = nexthop_get(nexthop); >-- if (asp->flags & F_ATTR_LINKED) >-- nexthop_unlink(asp); >-- asp->nexthop = nh; >-- if (asp->flags & F_ATTR_LINKED) >-- nexthop_link(asp); >- } >- >- void >-@@ -1233,17 +1254,17 @@ nexthop_compare(struct nexthop *na, stru >- a = &na->exit_nexthop; >- b = &nb->exit_nexthop; >- >-- if (a->af != b->af) >-- return (a->af - b->af); >-+ if (a->aid != b->aid) >-+ return (a->aid - b->aid); >- >-- switch (a->af) { >-- case AF_INET: >-+ switch (a->aid) { >-+ case AID_INET: >- if (ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr)) >- return (1); >- if (ntohl(a->v4.s_addr) < ntohl(b->v4.s_addr)) >- return (-1); >- return (0); >-- case AF_INET6: >-+ case AID_INET6: >- return (memcmp(&a->v6, &b->v6, sizeof(struct in6_addr))); >- default: >- fatalx("nexthop_cmp: unknown af"); >-@@ -1269,14 +1290,14 @@ nexthop_hash(struct bgpd_addr *nexthop) >- { >- u_int32_t h = 0; >- >-- switch (nexthop->af) { >-- case AF_INET: >-+ switch (nexthop->aid) { >-+ case AID_INET: >- h = (AF_INET ^ ntohl(nexthop->v4.s_addr) ^ >- ntohl(nexthop->v4.s_addr) >> 13) & >- nexthoptable.nexthop_hashmask; >- break; >-- case AF_INET6: >-- h = hash32_buf(nexthop->v6.s6_addr, sizeof(struct in6_addr), >-+ case AID_INET6: >-+ h = hash32_buf(&nexthop->v6, sizeof(struct in6_addr), >- HASHINIT) & nexthoptable.nexthop_hashmask; >- break; >- default: > >Property changes on: files/patch-bgpd_rde_rib.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_rde_update.c >=================================================================== >--- files/patch-bgpd_rde_update.c (revision 500577) >+++ files/patch-bgpd_rde_update.c (nonexistent) >@@ -1,644 +0,0 @@ >-Index: bgpd/rde_update.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_update.c,v >-retrieving revision 1.1.1.7 >-retrieving revision 1.8 >-diff -u -p -r1.1.1.7 -r1.8 >---- bgpd/rde_update.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 >-+++ bgpd/rde_update.c 13 Oct 2012 18:36:00 -0000 1.8 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: rde_update.c,v 1.68 2009/06/06 01:10:29 claudio Exp $ */ >-+/* $OpenBSD: rde_update.c,v 1.77 2010/01/13 06:02:37 claudio Exp $ */ >- >- /* >- * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> >-@@ -17,19 +17,27 @@ >- */ >- #include <sys/types.h> >- #include <sys/queue.h> >-+#if defined(__FreeBSD__) /* sys/hash.h */ >-+#include "hash.h" >-+#else >- #include <sys/hash.h> >-+#endif /* defined(__FreeBSD__) */ >- >-+#include <limits.h> >- #include <stdlib.h> >- #include <string.h> >-+#if defined(__FreeBSD__) /* limits.h */ >-+#include <limits.h> >-+#endif /* defined(__FreeBSD__) */ >- >- #include "bgpd.h" >- #include "rde.h" >- >- in_addr_t up_get_nexthop(struct rde_peer *, struct rde_aspath *); >- int up_generate_mp_reach(struct rde_peer *, struct update_attr *, >-- struct rde_aspath *, sa_family_t); >-+ struct rde_aspath *, u_int8_t); >- int up_generate_attr(struct rde_peer *, struct update_attr *, >-- struct rde_aspath *, sa_family_t); >-+ struct rde_aspath *, u_int8_t); >- >- /* update stuff. */ >- struct update_prefix { >-@@ -65,10 +73,12 @@ RB_GENERATE(uptree_attr, update_attr, en >- void >- up_init(struct rde_peer *peer) >- { >-- TAILQ_INIT(&peer->updates); >-- TAILQ_INIT(&peer->withdraws); >-- TAILQ_INIT(&peer->updates6); >-- TAILQ_INIT(&peer->withdraws6); >-+ u_int8_t i; >-+ >-+ for (i = 0; i < AID_MAX; i++) { >-+ TAILQ_INIT(&peer->updates[i]); >-+ TAILQ_INIT(&peer->withdraws[i]); >-+ } >- RB_INIT(&peer->up_prefix); >- RB_INIT(&peer->up_attrs); >- peer->up_pcnt = 0; >-@@ -103,8 +113,10 @@ up_clear(struct uplist_attr *updates, st >- void >- up_down(struct rde_peer *peer) >- { >-- up_clear(&peer->updates, &peer->withdraws); >-- up_clear(&peer->updates6, &peer->withdraws6); >-+ u_int8_t i; >-+ >-+ for (i = 0; i < AID_MAX; i++) >-+ up_clear(&peer->updates[i], &peer->withdraws[i]); >- >- RB_INIT(&peer->up_prefix); >- RB_INIT(&peer->up_attrs); >-@@ -120,19 +132,19 @@ up_prefix_cmp(struct update_prefix *a, s >- { >- int i; >- >-- if (a->prefix.af < b->prefix.af) >-+ if (a->prefix.aid < b->prefix.aid) >- return (-1); >-- if (a->prefix.af > b->prefix.af) >-+ if (a->prefix.aid > b->prefix.aid) >- return (1); >- >-- switch (a->prefix.af) { >-- case AF_INET: >-+ switch (a->prefix.aid) { >-+ case AID_INET: >- if (ntohl(a->prefix.v4.s_addr) < ntohl(b->prefix.v4.s_addr)) >- return (-1); >- if (ntohl(a->prefix.v4.s_addr) > ntohl(b->prefix.v4.s_addr)) >- return (1); >- break; >-- case AF_INET6: >-+ case AID_INET6: >- i = memcmp(&a->prefix.v6, &b->prefix.v6, >- sizeof(struct in6_addr)); >- if (i > 0) >-@@ -140,6 +152,25 @@ up_prefix_cmp(struct update_prefix *a, s >- if (i < 0) >- return (-1); >- break; >-+ case AID_VPN_IPv4: >-+ if (betoh64(a->prefix.vpn4.rd) < betoh64(b->prefix.vpn4.rd)) >-+ return (-1); >-+ if (betoh64(a->prefix.vpn4.rd) > betoh64(b->prefix.vpn4.rd)) >-+ return (1); >-+ if (ntohl(a->prefix.v4.s_addr) < ntohl(b->prefix.v4.s_addr)) >-+ return (-1); >-+ if (ntohl(a->prefix.v4.s_addr) > ntohl(b->prefix.v4.s_addr)) >-+ return (1); >-+ if (a->prefixlen < b->prefixlen) >-+ return (-1); >-+ if (a->prefixlen > b->prefixlen) >-+ return (1); >-+ if (a->prefix.vpn4.labellen < b->prefix.vpn4.labellen) >-+ return (-1); >-+ if (a->prefix.vpn4.labellen > b->prefix.vpn4.labellen) >-+ return (1); >-+ return (memcmp(a->prefix.vpn4.labelstack, >-+ b->prefix.vpn4.labelstack, a->prefix.vpn4.labellen)); >- default: >- fatalx("pt_prefix_cmp: unknown af"); >- } >-@@ -174,18 +205,8 @@ up_add(struct rde_peer *peer, struct upd >- struct uplist_attr *upl = NULL; >- struct uplist_prefix *wdl = NULL; >- >-- switch (p->prefix.af) { >-- case AF_INET: >-- upl = &peer->updates; >-- wdl = &peer->withdraws; >-- break; >-- case AF_INET6: >-- upl = &peer->updates6; >-- wdl = &peer->withdraws6; >-- break; >-- default: >-- fatalx("up_add: unknown AF"); >-- } >-+ upl = &peer->updates[p->prefix.aid]; >-+ wdl = &peer->withdraws[p->prefix.aid]; >- >- /* 1. search for attr */ >- if (a != NULL && (na = RB_FIND(uptree_attr, &peer->up_attrs, a)) == >-@@ -270,23 +291,16 @@ up_test_update(struct rde_peer *peer, st >- /* Do not send routes back to sender */ >- return (0); >- >-+ if (p->aspath->flags & F_ATTR_PARSE_ERR) >-+ fatalx("try to send out a botched path"); >- if (p->aspath->flags & F_ATTR_LOOP) >- fatalx("try to send out a looped path"); >- >- pt_getaddr(p->prefix, &addr); >-- switch (addr.af) { >-- case AF_INET: >-- if (peer->capa_announced.mp_v4 == SAFI_NONE && >-- peer->capa_received.mp_v6 != SAFI_NONE) >-- return (-1); >-- break; >-- case AF_INET6: >-- if (peer->capa_announced.mp_v6 == SAFI_NONE) >-- return (-1); >-- break; >-- } >-+ if (peer->capa.mp[addr.aid] == 0) >-+ return (-1); >- >-- if (p->aspath->peer->conf.ebgp == 0 && peer->conf.ebgp == 0) { >-+ if (!p->aspath->peer->conf.ebgp && !peer->conf.ebgp) { >- /* >- * route reflector redistribution rules: >- * 1. if announce is set -> announce >-@@ -325,13 +339,13 @@ up_test_update(struct rde_peer *peer, st >- } >- >- /* well known communities */ >-- if (rde_filter_community(p->aspath, >-+ if (community_match(p->aspath, >- COMMUNITY_WELLKNOWN, COMMUNITY_NO_ADVERTISE)) >- return (0); >-- if (peer->conf.ebgp && rde_filter_community(p->aspath, >-+ if (peer->conf.ebgp && community_match(p->aspath, >- COMMUNITY_WELLKNOWN, COMMUNITY_NO_EXPORT)) >- return (0); >-- if (peer->conf.ebgp && rde_filter_community(p->aspath, >-+ if (peer->conf.ebgp && community_match(p->aspath, >- COMMUNITY_WELLKNOWN, COMMUNITY_NO_EXPSUBCONFED)) >- return (0); >- >-@@ -362,7 +376,7 @@ up_generate(struct rde_peer *peer, struc >- if (ua == NULL) >- fatal("up_generate"); >- >-- if (up_generate_attr(peer, ua, asp, addr->af) == -1) { >-+ if (up_generate_attr(peer, ua, asp, addr->aid) == -1) { >- log_warnx("generation of bgp path attributes failed"); >- free(ua); >- return (-1); >-@@ -444,18 +458,12 @@ up_generate_updates(struct filter_head * >- /* send a default route to the specified peer */ >- void >- up_generate_default(struct filter_head *rules, struct rde_peer *peer, >-- sa_family_t af) >-+ u_int8_t aid) >- { >- struct rde_aspath *asp, *fasp; >- struct bgpd_addr addr; >- >-- if (peer->capa_received.mp_v4 == SAFI_NONE && >-- peer->capa_received.mp_v6 != SAFI_NONE && >-- af == AF_INET) >-- return; >-- >-- if (peer->capa_received.mp_v6 == SAFI_NONE && >-- af == AF_INET6) >-+ if (peer->capa.mp[aid] == 0) >- return; >- >- asp = path_get(); >-@@ -471,7 +479,7 @@ up_generate_default(struct filter_head * >- >- /* filter as usual */ >- bzero(&addr, sizeof(addr)); >-- addr.af = af; >-+ addr.aid = aid; >- >- if (rde_filter(peer->ribid, &fasp, rules, peer, asp, &addr, 0, NULL, >- DIR_OUT) == ACTION_DENY) { >-@@ -491,6 +499,43 @@ up_generate_default(struct filter_head * >- path_put(asp); >- } >- >-+/* generate a EoR marker in the update list. This is a horrible hack. */ >-+int >-+up_generate_marker(struct rde_peer *peer, u_int8_t aid) >-+{ >-+ struct update_attr *ua; >-+ struct update_attr *na = NULL; >-+ struct uplist_attr *upl = NULL; >-+ >-+ ua = calloc(1, sizeof(struct update_attr)); >-+ if (ua == NULL) >-+ fatal("up_generate_marker"); >-+ >-+ upl = &peer->updates[aid]; >-+ >-+ /* 1. search for attr */ >-+ if ((na = RB_FIND(uptree_attr, &peer->up_attrs, ua)) == NULL) { >-+ /* 1.1 if not found -> add */ >-+ TAILQ_INIT(&ua->prefix_h); >-+ if (RB_INSERT(uptree_attr, &peer->up_attrs, ua) != NULL) { >-+ log_warnx("uptree_attr insert failed"); >-+ /* cleanup */ >-+ free(ua); >-+ return (-1); >-+ } >-+ TAILQ_INSERT_TAIL(upl, ua, attr_l); >-+ peer->up_acnt++; >-+ } else { >-+ /* 1.2 if found -> use that, free ua */ >-+ free(ua); >-+ ua = na; >-+ /* move to end of update queue */ >-+ TAILQ_REMOVE(upl, ua, attr_l); >-+ TAILQ_INSERT_TAIL(upl, ua, attr_l); >-+ } >-+ return (0); >-+} >-+ >- u_char up_attr_buf[4096]; >- >- /* only for IPv4 */ >-@@ -551,28 +596,41 @@ up_get_nexthop(struct rde_peer *peer, st >- >- int >- up_generate_mp_reach(struct rde_peer *peer, struct update_attr *upa, >-- struct rde_aspath *a, sa_family_t af) >-+ struct rde_aspath *a, u_int8_t aid) >- { >- u_int16_t tmp; >- >-- switch (af) { >-- case AF_INET6: >-+ switch (aid) { >-+ case AID_INET6: >- upa->mpattr_len = 21; /* AFI + SAFI + NH LEN + NH + Reserved */ >- upa->mpattr = malloc(upa->mpattr_len); >- if (upa->mpattr == NULL) >- fatal("up_generate_mp_reach"); >-- tmp = htons(AFI_IPv6); >-+ if (aid2afi(aid, &tmp, &upa->mpattr[2])) >-+ fatalx("up_generate_mp_reachi: bad AID"); >-+ tmp = htons(tmp); >- memcpy(upa->mpattr, &tmp, sizeof(tmp)); >-- upa->mpattr[2] = SAFI_UNICAST; >- upa->mpattr[3] = sizeof(struct in6_addr); >- upa->mpattr[20] = 0; /* Reserved must be 0 */ >- >- /* nexthop dance see also up_get_nexthop() */ >-- if (peer->conf.ebgp == 0) { >-+ if (a->flags & F_NEXTHOP_NOMODIFY) { >-+ /* no modify flag set */ >-+ if (a->nexthop == NULL) >-+ memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, >-+ sizeof(struct in6_addr)); >-+ else >-+ memcpy(&upa->mpattr[4], >-+ &a->nexthop->exit_nexthop.v6, >-+ sizeof(struct in6_addr)); >-+ } else if (a->flags & F_NEXTHOP_SELF) >-+ memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, >-+ sizeof(struct in6_addr)); >-+ else if (!peer->conf.ebgp) { >- /* ibgp */ >- if (a->nexthop == NULL || >-- (a->nexthop->exit_nexthop.af == AF_INET6 && >-- memcmp(&a->nexthop->exit_nexthop.v6, >-+ (a->nexthop->exit_nexthop.aid == AID_INET6 && >-+ !memcmp(&a->nexthop->exit_nexthop.v6, >- &peer->remote_addr.v6, sizeof(struct in6_addr)))) >- memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, >- sizeof(struct in6_addr)); >-@@ -603,6 +661,68 @@ up_generate_mp_reach(struct rde_peer *pe >- memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, >- sizeof(struct in6_addr)); >- return (0); >-+ case AID_VPN_IPv4: >-+ upa->mpattr_len = 17; /* AFI + SAFI + NH LEN + NH + Reserved */ >-+ upa->mpattr = calloc(upa->mpattr_len, 1); >-+ if (upa->mpattr == NULL) >-+ fatal("up_generate_mp_reach"); >-+ if (aid2afi(aid, &tmp, &upa->mpattr[2])) >-+ fatalx("up_generate_mp_reachi: bad AID"); >-+ tmp = htons(tmp); >-+ memcpy(upa->mpattr, &tmp, sizeof(tmp)); >-+ upa->mpattr[3] = sizeof(u_int64_t) + sizeof(struct in_addr); >-+ >-+ /* nexthop dance see also up_get_nexthop() */ >-+ if (a->flags & F_NEXTHOP_NOMODIFY) { >-+ /* no modify flag set */ >-+ if (a->nexthop == NULL) >-+ memcpy(&upa->mpattr[12], >-+ &peer->local_v4_addr.v4, >-+ sizeof(struct in_addr)); >-+ else >-+ /* nexthops are stored as IPv4 addrs */ >-+ memcpy(&upa->mpattr[12], >-+ &a->nexthop->exit_nexthop.v4, >-+ sizeof(struct in_addr)); >-+ } else if (a->flags & F_NEXTHOP_SELF) >-+ memcpy(&upa->mpattr[12], &peer->local_v4_addr.v4, >-+ sizeof(struct in_addr)); >-+ else if (!peer->conf.ebgp) { >-+ /* ibgp */ >-+ if (a->nexthop == NULL || >-+ (a->nexthop->exit_nexthop.aid == AID_INET && >-+ !memcmp(&a->nexthop->exit_nexthop.v4, >-+ &peer->remote_addr.v4, sizeof(struct in_addr)))) >-+ memcpy(&upa->mpattr[12], >-+ &peer->local_v4_addr.v4, >-+ sizeof(struct in_addr)); >-+ else >-+ memcpy(&upa->mpattr[12], >-+ &a->nexthop->exit_nexthop.v4, >-+ sizeof(struct in_addr)); >-+ } else if (peer->conf.distance == 1) { >-+ /* ebgp directly connected */ >-+ if (a->nexthop != NULL && >-+ a->nexthop->flags & NEXTHOP_CONNECTED) >-+ if (prefix_compare(&peer->remote_addr, >-+ &a->nexthop->nexthop_net, >-+ a->nexthop->nexthop_netlen) == 0) { >-+ /* >-+ * nexthop and peer are in the same >-+ * subnet >-+ */ >-+ memcpy(&upa->mpattr[12], >-+ &a->nexthop->exit_nexthop.v4, >-+ sizeof(struct in_addr)); >-+ return (0); >-+ } >-+ memcpy(&upa->mpattr[12], &peer->local_v4_addr.v4, >-+ sizeof(struct in_addr)); >-+ } else >-+ /* ebgp multihop */ >-+ memcpy(&upa->mpattr[12], &peer->local_v4_addr.v4, >-+ sizeof(struct in_addr)); >-+ return (0); >- default: >- break; >- } >-@@ -611,7 +731,7 @@ up_generate_mp_reach(struct rde_peer *pe >- >- int >- up_generate_attr(struct rde_peer *peer, struct update_attr *upa, >-- struct rde_aspath *a, sa_family_t af) >-+ struct rde_aspath *a, u_int8_t aid) >- { >- struct attr *oa, *newaggr = NULL; >- u_char *pdata; >-@@ -643,8 +763,8 @@ up_generate_attr(struct rde_peer *peer, >- wlen += r; len -= r; >- free(pdata); >- >-- switch (af) { >-- case AF_INET: >-+ switch (aid) { >-+ case AID_INET: >- nexthop = up_get_nexthop(peer, a); >- if ((r = attr_write(up_attr_buf + wlen, len, ATTR_WELL_KNOWN, >- ATTR_NEXTHOP, &nexthop, 4)) == -1) >-@@ -659,9 +779,11 @@ up_generate_attr(struct rde_peer *peer, >- /* >- * The old MED from other peers MUST not be announced to others >- * unless the MED is originating from us or the peer is an IBGP one. >-+ * Only exception are routers with "transparent-as yes" set. >- */ >-- if (a->flags & F_ATTR_MED && (peer->conf.ebgp == 0 || >-- a->flags & F_ATTR_MED_ANNOUNCE)) { >-+ if (a->flags & F_ATTR_MED && (!peer->conf.ebgp || >-+ a->flags & F_ATTR_MED_ANNOUNCE || >-+ peer->conf.flags & PEERFLAG_TRANS_AS)) { >- tmp32 = htonl(a->med); >- if ((r = attr_write(up_attr_buf + wlen, len, ATTR_OPTIONAL, >- ATTR_MED, &tmp32, 4)) == -1) >-@@ -669,7 +791,7 @@ up_generate_attr(struct rde_peer *peer, >- wlen += r; len -= r; >- } >- >-- if (peer->conf.ebgp == 0) { >-+ if (!peer->conf.ebgp) { >- /* local preference, only valid for ibgp */ >- tmp32 = htonl(a->lpref); >- if ((r = attr_write(up_attr_buf + wlen, len, ATTR_WELL_KNOWN, >-@@ -704,7 +826,7 @@ up_generate_attr(struct rde_peer *peer, >- u_int16_t tas; >- >- if ((!(oa->flags & ATTR_TRANSITIVE)) && >-- peer->conf.ebgp != 0) { >-+ peer->conf.ebgp) { >- r = 0; >- break; >- } >-@@ -730,7 +852,7 @@ up_generate_attr(struct rde_peer *peer, >- case ATTR_ORIGINATOR_ID: >- case ATTR_CLUSTER_LIST: >- if ((!(oa->flags & ATTR_TRANSITIVE)) && >-- peer->conf.ebgp != 0) { >-+ peer->conf.ebgp) { >- r = 0; >- break; >- } >-@@ -791,7 +913,7 @@ up_generate_attr(struct rde_peer *peer, >- >- /* write mp attribute to different buffer */ >- if (ismp) >-- if (up_generate_mp_reach(peer, upa, a, AF_INET6) == -1) >-+ if (up_generate_mp_reach(peer, upa, a, aid) == -1) >- return (-1); >- >- /* the bgp path attributes are now stored in the global buf */ >-@@ -810,6 +932,7 @@ up_dump_prefix(u_char *buf, int len, str >- { >- struct update_prefix *upp; >- int r, wpos = 0; >-+ u_int8_t i; >- >- while ((upp = TAILQ_FIRST(prefix_head)) != NULL) { >- if ((r = prefix_write(buf + wpos, len - wpos, >-@@ -820,13 +943,14 @@ up_dump_prefix(u_char *buf, int len, str >- log_warnx("dequeuing update failed."); >- TAILQ_REMOVE(upp->prefix_h, upp, prefix_l); >- peer->up_pcnt--; >-- if (upp->prefix_h == &peer->withdraws || >-- upp->prefix_h == &peer->withdraws6) { >-- peer->up_wcnt--; >-- peer->prefix_sent_withdraw++; >-- } else { >-- peer->up_nlricnt--; >-- peer->prefix_sent_update++; >-+ for (i = 0; i < AID_MAX; i++) { >-+ if (upp->prefix_h == &peer->withdraws[i]) { >-+ peer->up_wcnt--; >-+ peer->prefix_sent_withdraw++; >-+ } else { >-+ peer->up_nlricnt--; >-+ peer->prefix_sent_update++; >-+ } >- } >- free(upp); >- } >-@@ -844,16 +968,21 @@ up_dump_attrnlri(u_char *buf, int len, s >- * It is possible that a queued path attribute has no nlri prefix. >- * Ignore and remove those path attributes. >- */ >-- while ((upa = TAILQ_FIRST(&peer->updates)) != NULL) >-+ while ((upa = TAILQ_FIRST(&peer->updates[AID_INET])) != NULL) >- if (TAILQ_EMPTY(&upa->prefix_h)) { >-+ attr_len = upa->attr_len; >- if (RB_REMOVE(uptree_attr, &peer->up_attrs, >- upa) == NULL) >- log_warnx("dequeuing update failed."); >-- TAILQ_REMOVE(&peer->updates, upa, attr_l); >-+ TAILQ_REMOVE(&peer->updates[AID_INET], upa, attr_l); >- free(upa->attr); >- free(upa->mpattr); >- free(upa); >- peer->up_acnt--; >-+ /* XXX horrible hack, >-+ * if attr_len is 0, it is a EoR marker */ >-+ if (attr_len == 0) >-+ return (-1); >- } else >- break; >- >-@@ -884,7 +1013,7 @@ up_dump_attrnlri(u_char *buf, int len, s >- if (TAILQ_EMPTY(&upa->prefix_h)) { >- if (RB_REMOVE(uptree_attr, &peer->up_attrs, upa) == NULL) >- log_warnx("dequeuing update failed."); >-- TAILQ_REMOVE(&peer->updates, upa, attr_l); >-+ TAILQ_REMOVE(&peer->updates[AID_INET], upa, attr_l); >- free(upa->attr); >- free(upa->mpattr); >- free(upa); >-@@ -895,12 +1024,13 @@ up_dump_attrnlri(u_char *buf, int len, s >- } >- >- u_char * >--up_dump_mp_unreach(u_char *buf, u_int16_t *len, struct rde_peer *peer) >-+up_dump_mp_unreach(u_char *buf, u_int16_t *len, struct rde_peer *peer, >-+ u_int8_t aid) >- { >- int wpos; >- u_int16_t datalen, tmp; >- u_int16_t attrlen = 2; /* attribute header (without len) */ >-- u_int8_t flags = ATTR_OPTIONAL; >-+ u_int8_t flags = ATTR_OPTIONAL, safi; >- >- /* >- * reserve space for withdraw len, attr len, the attribute header >-@@ -912,7 +1042,7 @@ up_dump_mp_unreach(u_char *buf, u_int16_ >- return (NULL); >- >- datalen = up_dump_prefix(buf + wpos, *len - wpos, >-- &peer->withdraws6, peer); >-+ &peer->withdraws[aid], peer); >- if (datalen == 0) >- return (NULL); >- >-@@ -920,9 +1050,11 @@ up_dump_mp_unreach(u_char *buf, u_int16_ >- >- /* prepend header, need to do it reverse */ >- /* safi & afi */ >-- buf[--wpos] = SAFI_UNICAST; >-+ if (aid2afi(aid, &tmp, &safi)) >-+ fatalx("up_dump_mp_unreach: bad AID"); >-+ buf[--wpos] = safi; >- wpos -= sizeof(u_int16_t); >-- tmp = htons(AFI_IPv6); >-+ tmp = htons(tmp); >- memcpy(buf + wpos, &tmp, sizeof(u_int16_t)); >- >- /* attribute length */ >-@@ -959,33 +1091,39 @@ up_dump_mp_unreach(u_char *buf, u_int16_ >- return (buf + wpos); >- } >- >--u_char * >--up_dump_mp_reach(u_char *buf, u_int16_t *len, struct rde_peer *peer) >-+int >-+up_dump_mp_reach(u_char *buf, u_int16_t *len, struct rde_peer *peer, >-+ u_int8_t aid) >- { >- struct update_attr *upa; >- int wpos; >-- u_int16_t datalen, tmp; >-+ u_int16_t attr_len, datalen, tmp; >- u_int8_t flags = ATTR_OPTIONAL; >- >- /* >- * It is possible that a queued path attribute has no nlri prefix. >- * Ignore and remove those path attributes. >- */ >-- while ((upa = TAILQ_FIRST(&peer->updates6)) != NULL) >-+ while ((upa = TAILQ_FIRST(&peer->updates[aid])) != NULL) >- if (TAILQ_EMPTY(&upa->prefix_h)) { >-+ attr_len = upa->attr_len; >- if (RB_REMOVE(uptree_attr, &peer->up_attrs, >- upa) == NULL) >- log_warnx("dequeuing update failed."); >-- TAILQ_REMOVE(&peer->updates6, upa, attr_l); >-+ TAILQ_REMOVE(&peer->updates[aid], upa, attr_l); >- free(upa->attr); >- free(upa->mpattr); >- free(upa); >- peer->up_acnt--; >-+ /* XXX horrible hack, >-+ * if attr_len is 0, it is a EoR marker */ >-+ if (attr_len == 0) >-+ return (-1); >- } else >- break; >- >- if (upa == NULL) >-- return (NULL); >-+ return (-2); >- >- /* >- * reserve space for attr len, the attributes, the >-@@ -993,12 +1131,12 @@ up_dump_mp_reach(u_char *buf, u_int16_t >- */ >- wpos = 2 + 2 + upa->attr_len + 4 + upa->mpattr_len; >- if (*len < wpos) >-- return (NULL); >-+ return (-2); >- >- datalen = up_dump_prefix(buf + wpos, *len - wpos, >- &upa->prefix_h, peer); >- if (datalen == 0) >-- return (NULL); >-+ return (-2); >- >- if (upa->mpattr_len == 0 || upa->mpattr == NULL) >- fatalx("mulitprotocol update without MP attrs"); >-@@ -1038,7 +1176,7 @@ up_dump_mp_reach(u_char *buf, u_int16_t >- if (TAILQ_EMPTY(&upa->prefix_h)) { >- if (RB_REMOVE(uptree_attr, &peer->up_attrs, upa) == NULL) >- log_warnx("dequeuing update failed."); >-- TAILQ_REMOVE(&peer->updates6, upa, attr_l); >-+ TAILQ_REMOVE(&peer->updates[aid], upa, attr_l); >- free(upa->attr); >- free(upa->mpattr); >- free(upa); >-@@ -1046,6 +1184,5 @@ up_dump_mp_reach(u_char *buf, u_int16_t >- } >- >- *len = datalen + 4; >-- return (buf + wpos); >-+ return (wpos); >- } >-- > >Property changes on: files/patch-bgpd_rde_update.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_session.c >=================================================================== >--- files/patch-bgpd_session.c (revision 500577) >+++ files/patch-bgpd_session.c (nonexistent) >@@ -1,2075 +0,0 @@ >-Index: bgpd/session.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/session.c,v >-retrieving revision 1.1.1.8 >-retrieving revision 1.13 >-diff -u -p -r1.1.1.8 -r1.13 >---- bgpd/session.c 14 Feb 2010 20:19:57 -0000 1.1.1.8 >-+++ bgpd/session.c 8 Dec 2012 20:17:59 -0000 1.13 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: session.c,v 1.293 2009/06/07 05:56:24 eric Exp $ */ >-+/* $OpenBSD: session.c,v 1.325 2012/09/18 09:45:50 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> >-@@ -21,18 +21,21 @@ >- >- #include <sys/mman.h> >- #include <sys/socket.h> >-+#include <sys/time.h> >-+#include <sys/resource.h> >- #include <sys/un.h> >-+#include <sys/queue.h> >- #include <net/if_types.h> >- #include <netinet/in.h> >- #include <netinet/in_systm.h> >- #include <netinet/ip.h> >- #include <netinet/tcp.h> >-+#include <netinet/tcp_var.h> >- #include <arpa/inet.h> >- >- #include <err.h> >- #include <errno.h> >- #include <fcntl.h> >--#include <limits.h> >- #include <poll.h> >- #include <pwd.h> >- #include <signal.h> >-@@ -50,7 +53,12 @@ >- #define PFD_PIPE_ROUTE_CTL 2 >- #define PFD_SOCK_CTL 3 >- #define PFD_SOCK_RCTL 4 >--#define PFD_LISTENERS_START 5 >-+#define PFD_SOCK_PFKEY 5 >-+#define PFD_LISTENERS_START 6 >-+ >-+#if defined(__FreeBSD__) /* FreeBSD has no LINK_STATE_IS_UP macro. */ >-+#define LINK_STATE_IS_UP(_s) ((_s) >= LINK_STATE_UP) >-+#endif /* defined(__FreeBSD__) */ >- >- void session_sighdlr(int); >- int setup_listeners(u_int *); >-@@ -65,9 +73,9 @@ void session_accept(int); >- int session_connect(struct peer *); >- void session_tcp_established(struct peer *); >- void session_capa_ann_none(struct peer *); >--int session_capa_add(struct peer *, struct buf *, u_int8_t, u_int8_t, >-- u_int8_t *); >--int session_capa_add_mp(struct buf *, u_int16_t, u_int8_t); >-+int session_capa_add(struct ibuf *, u_int8_t, u_int8_t); >-+int session_capa_add_mp(struct ibuf *, u_int8_t); >-+int session_capa_add_gr(struct peer *, struct ibuf *, u_int8_t); >- struct bgp_msg *session_newmsg(enum msg_type, u_int16_t); >- int session_sendmsg(struct bgp_msg *, struct peer *); >- void session_open(struct peer *); >-@@ -75,30 +83,34 @@ void session_keepalive(struct peer *); >- void session_update(u_int32_t, void *, size_t); >- void session_notification(struct peer *, u_int8_t, u_int8_t, void *, >- ssize_t); >--void session_rrefresh(struct peer *, u_int16_t, u_int8_t); >-+void session_rrefresh(struct peer *, u_int8_t); >-+int session_graceful_restart(struct peer *); >-+int session_graceful_is_restarting(struct peer *); >-+int session_graceful_stop(struct peer *); >- int session_dispatch_msg(struct pollfd *, struct peer *); >-+int session_process_msg(struct peer *); >- int parse_header(struct peer *, u_char *, u_int16_t *, u_int8_t *); >- int parse_open(struct peer *); >- int parse_update(struct peer *); >- int parse_refresh(struct peer *); >- int parse_notification(struct peer *); >- int parse_capabilities(struct peer *, u_char *, u_int16_t, u_int32_t *); >-+int capa_neg_calc(struct peer *); >- void session_dispatch_imsg(struct imsgbuf *, int, u_int *); >- void session_up(struct peer *); >- void session_down(struct peer *); >- void session_demote(struct peer *, int); >- >--int la_cmp(struct listen_addr *, struct listen_addr *); >--struct peer *getpeerbyip(struct sockaddr *); >--int session_match_mask(struct peer *, struct sockaddr *); >--struct peer *getpeerbyid(u_int32_t); >--static struct sockaddr *addr2sa(struct bgpd_addr *, u_int16_t); >-+int la_cmp(struct listen_addr *, struct listen_addr *); >-+struct peer *getpeerbyip(struct sockaddr *); >-+int session_match_mask(struct peer *, struct bgpd_addr *); >-+struct peer *getpeerbyid(u_int32_t); >- >--struct bgpd_config *conf, *nconf = NULL; >-+struct bgpd_config *conf, *nconf; >- struct bgpd_sysdep sysdep; >--struct peer *npeers; >--volatile sig_atomic_t session_quit = 0; >--int pending_reconf = 0; >-+struct peer *peers, *npeers; >-+volatile sig_atomic_t session_quit; >-+int pending_reconf; >- int csock = -1, rcsock = -1; >- u_int peer_cnt; >- struct imsgbuf *ibuf_rde; >-@@ -106,6 +118,7 @@ struct imsgbuf *ibuf_rde_ctl; >- struct imsgbuf *ibuf_main; >- >- struct mrt_head mrthead; >-+time_t pauseaccept; >- >- void >- session_sighdlr(int sig) >-@@ -125,6 +138,22 @@ setup_listeners(u_int *la_cnt) >- int opt; >- struct listen_addr *la; >- u_int cnt = 0; >-+#if defined(__FreeBSD__) >-+ int s; >-+ >-+ /* Check if TCP_MD5SIG is supported. */ >-+ s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); >-+ if (s < 0) >-+ fatal("socket open for TCP_MD5SIG check"); >-+ opt = TF_SIGNATURE; >-+ if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, &opt, sizeof(opt)) == -1) { >-+ if (errno == ENOPROTOOPT || errno == EINVAL) >-+ sysdep.no_md5sig = 1; >-+ else >-+ fatal("setsockopt TCP_MD5SIG"); >-+ } >-+ close(s); >-+#endif /* defined(__FreeBSD__) */ >- >- TAILQ_FOREACH(la, conf->listen_addrs, entry) { >- la->reconf = RECONF_NONE; >-@@ -140,6 +169,7 @@ setup_listeners(u_int *la_cnt) >- } >- >- opt = 1; >-+#if !defined(__FreeBSD__) >- if (setsockopt(la->fd, IPPROTO_TCP, TCP_MD5SIG, >- &opt, sizeof(opt)) == -1) { >- if (errno == ENOPROTOOPT) { /* system w/o md5sig */ >-@@ -148,6 +178,7 @@ setup_listeners(u_int *la_cnt) >- } else >- fatal("setsockopt TCP_MD5SIG"); >- } >-+#endif /* !defined(__FreeBSD__) */ >- >- /* set ttl to 255 so that ttl-security works */ >- if (la->sa.ss_family == AF_INET && setsockopt(la->fd, >-@@ -175,12 +206,10 @@ setup_listeners(u_int *la_cnt) >- } >- >- pid_t >--session_main(struct bgpd_config *config, struct peer *cpeers, >-- struct network_head *net_l, struct filter_head *rules, >-- struct mrt_head *m_l, struct rib_names *rib_l, int pipe_m2s[2], >-- int pipe_s2r[2], int pipe_m2r[2], int pipe_s2rctl[2]) >-+session_main(int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2], >-+ int pipe_s2rctl[2]) >- { >-- int nfds, timeout; >-+ int nfds, timeout, pfkeysock; >- unsigned int i, j, idx_peers, idx_listeners, idx_mrts; >- pid_t pid; >- u_int pfd_elms = 0, peer_l_elms = 0, mrt_l_elms = 0; >-@@ -189,19 +218,13 @@ session_main(struct bgpd_config *config, >- u_int32_t ctl_queued; >- struct passwd *pw; >- struct peer *p, **peer_l = NULL, *last, *next; >-- struct network *net; >-- struct mrt *m, **mrt_l = NULL; >-- struct filter_rule *r; >-+ struct mrt *m, *xm, **mrt_l = NULL; >- struct pollfd *pfd = NULL; >- struct ctl_conn *ctl_conn; >- struct listen_addr *la; >-- struct rde_rib *rr; >- void *newp; >- short events; >- >-- conf = config; >-- peers = cpeers; >-- >- switch (pid = fork()) { >- case -1: >- fatal("cannot fork"); >-@@ -211,13 +234,6 @@ session_main(struct bgpd_config *config, >- return (pid); >- } >- >-- /* control socket is outside chroot */ >-- if ((csock = control_init(0, conf->csock)) == -1) >-- fatalx("control socket setup failed"); >-- if (conf->rcsock != NULL && >-- (rcsock = control_init(1, conf->rcsock)) == -1) >-- fatalx("control socket setup failed"); >-- >- if ((pw = getpwnam(BGPD_USER)) == NULL) >- fatal(NULL); >- >-@@ -228,29 +244,25 @@ session_main(struct bgpd_config *config, >- >- setproctitle("session engine"); >- bgpd_process = PROC_SE; >-- >-- if (pfkey_init(&sysdep) == -1) >-- fatalx("pfkey setup failed"); >-+ pfkeysock = pfkey_init(&sysdep); >- >- if (setgroups(1, &pw->pw_gid) || >- setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || >- setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) >- fatal("can't drop privileges"); >- >-- listener_cnt = 0; >-- setup_listeners(&listener_cnt); >-- >- signal(SIGTERM, session_sighdlr); >- signal(SIGINT, session_sighdlr); >- signal(SIGPIPE, SIG_IGN); >- signal(SIGHUP, SIG_IGN); >-- log_info("session engine ready"); >-+ signal(SIGALRM, SIG_IGN); >-+ signal(SIGUSR1, SIG_IGN); >-+ >- close(pipe_m2s[0]); >- close(pipe_s2r[1]); >- close(pipe_s2rctl[1]); >- close(pipe_m2r[0]); >- close(pipe_m2r[1]); >-- init_conf(conf); >- if ((ibuf_rde = malloc(sizeof(struct imsgbuf))) == NULL || >- (ibuf_rde_ctl = malloc(sizeof(struct imsgbuf))) == NULL || >- (ibuf_main = malloc(sizeof(struct imsgbuf))) == NULL) >-@@ -258,37 +270,21 @@ session_main(struct bgpd_config *config, >- imsg_init(ibuf_rde, pipe_s2r[0]); >- imsg_init(ibuf_rde_ctl, pipe_s2rctl[0]); >- imsg_init(ibuf_main, pipe_m2s[1]); >-+ >- TAILQ_INIT(&ctl_conns); >-- control_listen(csock); >-- control_listen(rcsock); >- LIST_INIT(&mrthead); >-+ listener_cnt = 0; >- peer_cnt = 0; >- ctl_cnt = 0; >- >-- /* filter rules are not used in the SE */ >-- while ((r = TAILQ_FIRST(rules)) != NULL) { >-- TAILQ_REMOVE(rules, r, entry); >-- free(r); >-- } >-- free(rules); >-- >-- /* network list is not used in the SE */ >-- while ((net = TAILQ_FIRST(net_l)) != NULL) { >-- TAILQ_REMOVE(net_l, net, entry); >-- filterset_free(&net->net.attrset); >-- free(net); >-- } >-+ if ((conf = calloc(1, sizeof(struct bgpd_config))) == NULL) >-+ fatal(NULL); >-+ if ((conf->listen_addrs = calloc(1, sizeof(struct listen_addrs))) == >-+ NULL) >-+ fatal(NULL); >-+ TAILQ_INIT(conf->listen_addrs); >- >-- /* main mrt list is not used in the SE */ >-- while ((m = LIST_FIRST(m_l)) != NULL) { >-- LIST_REMOVE(m, entry); >-- free(m); >-- } >-- /* rib names not used in the SE */ >-- while ((rr = SIMPLEQ_FIRST(&ribnames))) { >-- SIMPLEQ_REMOVE_HEAD(&ribnames, entry); >-- free(rr); >-- } >-+ log_info("session engine ready"); >- >- while (session_quit == 0) { >- /* check for peers to be initialized or deleted */ >-@@ -308,8 +304,9 @@ session_main(struct bgpd_config *config, >- >- /* reinit due? */ >- if (p->conf.reconf_action == RECONF_REINIT) { >-- bgp_fsm(p, EVNT_STOP); >-- timer_set(p, Timer_IdleHold, 0); >-+ session_stop(p, ERR_CEASE_ADMIN_RESET); >-+ if (!p->conf.down) >-+ timer_set(p, Timer_IdleHold, 0); >- } >- >- /* deletion due? */ >-@@ -317,7 +314,7 @@ session_main(struct bgpd_config *config, >- if (p->demoted) >- session_demote(p, -1); >- p->conf.demote_group[0] = 0; >-- bgp_fsm(p, EVNT_STOP); >-+ session_stop(p, ERR_CEASE_PEER_UNCONF); >- log_peer_warnx(&p->conf, "removed"); >- if (last != NULL) >- last->next = next; >-@@ -346,9 +343,17 @@ session_main(struct bgpd_config *config, >- } >- >- mrt_cnt = 0; >-- LIST_FOREACH(m, &mrthead, entry) >-+ for (m = LIST_FIRST(&mrthead); m != NULL; m = xm) { >-+ xm = LIST_NEXT(m, entry); >-+ if (m->state == MRT_STATE_REMOVE) { >-+ mrt_clean(m); >-+ LIST_REMOVE(m, entry); >-+ free(m); >-+ continue; >-+ } >- if (m->wbuf.queued) >- mrt_cnt++; >-+ } >- >- if (mrt_cnt > mrt_l_elms) { >- if ((newp = realloc(mrt_l, sizeof(struct mrt *) * >-@@ -394,18 +399,31 @@ session_main(struct bgpd_config *config, >- if (ctl_queued < SESSION_CTL_QUEUE_MAX) >- /* >- * Do not act as unlimited buffer. Don't read in more >-- * messages if the ctl sockets are getting full. >-+ * messages if the ctl sockets are getting full. >- */ >- pfd[PFD_PIPE_ROUTE_CTL].events = POLLIN; >-- pfd[PFD_SOCK_CTL].fd = csock; >-- pfd[PFD_SOCK_CTL].events = POLLIN; >-- pfd[PFD_SOCK_RCTL].fd = rcsock; >-- pfd[PFD_SOCK_RCTL].events = POLLIN; >-- >-+ if (pauseaccept == 0) { >-+ pfd[PFD_SOCK_CTL].fd = csock; >-+ pfd[PFD_SOCK_CTL].events = POLLIN; >-+ pfd[PFD_SOCK_RCTL].fd = rcsock; >-+ pfd[PFD_SOCK_RCTL].events = POLLIN; >-+ } else { >-+ pfd[PFD_SOCK_CTL].fd = -1; >-+ pfd[PFD_SOCK_RCTL].fd = -1; >-+ } >-+ pfd[PFD_SOCK_PFKEY].fd = pfkeysock; >-+#if !defined(__FreeBSD__) >-+ pfd[PFD_SOCK_PFKEY].events = POLLIN; >-+#else >-+ pfd[PFD_SOCK_PFKEY].events = 0; >-+#endif >- i = PFD_LISTENERS_START; >- TAILQ_FOREACH(la, conf->listen_addrs, entry) { >-- pfd[i].fd = la->fd; >-- pfd[i].events = POLLIN; >-+ if (pauseaccept == 0) { >-+ pfd[i].fd = la->fd; >-+ pfd[i].events = POLLIN; >-+ } else >-+ pfd[i].fd = -1; >- i++; >- } >- idx_listeners = i; >-@@ -450,6 +468,10 @@ session_main(struct bgpd_config *config, >- p->state == STATE_ESTABLISHED) >- session_demote(p, -1); >- break; >-+ case Timer_RestartTimeout: >-+ timer_stop(p, Timer_RestartTimeout); >-+ session_graceful_stop(p); >-+ break; >- default: >- fatalx("King Bula lost in time"); >- } >-@@ -462,6 +484,9 @@ session_main(struct bgpd_config *config, >- events = POLLIN; >- if (p->wbuf.queued > 0 || p->state == STATE_CONNECT) >- events |= POLLOUT; >-+ /* is there still work to do? */ >-+ if (p->rbuf && p->rbuf->wpos) >-+ timeout = 0; >- >- /* poll events */ >- if (p->fd != -1 && events != 0) { >-@@ -492,12 +517,21 @@ session_main(struct bgpd_config *config, >- i++; >- } >- >-+ if (pauseaccept && timeout > 1) >-+ timeout = 1; >- if (timeout < 0) >- timeout = 0; >- if ((nfds = poll(pfd, i, timeout * 1000)) == -1) >- if (errno != EINTR) >- fatal("poll error"); >- >-+ /* >-+ * If we previously saw fd exhaustion, we stop accept() >-+ * for 1 second to throttle the accept() loop. >-+ */ >-+ if (pauseaccept && getmonotime() > pauseaccept + 1) >-+ pauseaccept = 0; >-+ >- if (nfds > 0 && pfd[PFD_PIPE_MAIN].revents & POLLOUT) >- if (msgbuf_write(&ibuf_main->w) < 0) >- fatal("pipe write error"); >-@@ -534,6 +568,14 @@ session_main(struct bgpd_config *config, >- ctl_cnt += control_accept(rcsock, 1); >- } >- >-+ if (nfds > 0 && pfd[PFD_SOCK_PFKEY].revents & POLLIN) { >-+ nfds--; >-+ if (pfkey_read(pfkeysock, NULL) == -1) { >-+ log_warnx("pfkey_read failed, exiting..."); >-+ session_quit = 1; >-+ } >-+ } >-+ >- for (j = PFD_LISTENERS_START; nfds > 0 && j < idx_listeners; >- j++) >- if (pfd[j].revents & POLLIN) { >-@@ -545,6 +587,10 @@ session_main(struct bgpd_config *config, >- nfds -= session_dispatch_msg(&pfd[j], >- peer_l[j - idx_listeners]); >- >-+ for (p = peers; p != NULL; p = p->next) >-+ if (p->rbuf && p->rbuf->wpos) >-+ session_process_msg(p); >-+ >- for (; nfds > 0 && j < idx_mrts; j++) >- if (pfd[j].revents & POLLOUT) { >- nfds--; >-@@ -557,7 +603,7 @@ session_main(struct bgpd_config *config, >- >- while ((p = peers) != NULL) { >- peers = p->next; >-- bgp_fsm(p, EVNT_STOP); >-+ session_stop(p, ERR_CEASE_ADMIN_DOWN); >- pfkey_remove(p); >- free(p); >- } >-@@ -643,10 +689,9 @@ bgp_fsm(struct peer *peer, enum session_ >- timer_stop(peer, Timer_IdleHold); >- >- /* allocate read buffer */ >-- peer->rbuf = calloc(1, sizeof(struct buf_read)); >-+ peer->rbuf = calloc(1, sizeof(struct ibuf_read)); >- if (peer->rbuf == NULL) >- fatal(NULL); >-- peer->rbuf->wpos = 0; >- >- /* init write buffer */ >- msgbuf_init(&peer->wbuf); >-@@ -746,7 +791,6 @@ bgp_fsm(struct peer *peer, enum session_ >- /* ignore */ >- break; >- case EVNT_STOP: >-- session_notification(peer, ERR_CEASE, 0, NULL, 0); >- change_state(peer, STATE_IDLE, event); >- break; >- case EVNT_CON_CLOSED: >-@@ -780,7 +824,8 @@ bgp_fsm(struct peer *peer, enum session_ >- change_state(peer, STATE_IDLE, event); >- break; >- default: >-- session_notification(peer, ERR_FSM, 0, NULL, 0); >-+ session_notification(peer, >-+ ERR_FSM, ERR_FSM_UNEX_OPENSENT, NULL, 0); >- change_state(peer, STATE_IDLE, event); >- break; >- } >-@@ -791,7 +836,6 @@ bgp_fsm(struct peer *peer, enum session_ >- /* ignore */ >- break; >- case EVNT_STOP: >-- session_notification(peer, ERR_CEASE, 0, NULL, 0); >- change_state(peer, STATE_IDLE, event); >- break; >- case EVNT_CON_CLOSED: >-@@ -815,7 +859,8 @@ bgp_fsm(struct peer *peer, enum session_ >- change_state(peer, STATE_IDLE, event); >- break; >- default: >-- session_notification(peer, ERR_FSM, 0, NULL, 0); >-+ session_notification(peer, >-+ ERR_FSM, ERR_FSM_UNEX_OPENCONFIRM, NULL, 0); >- change_state(peer, STATE_IDLE, event); >- break; >- } >-@@ -826,7 +871,6 @@ bgp_fsm(struct peer *peer, enum session_ >- /* ignore */ >- break; >- case EVNT_STOP: >-- session_notification(peer, ERR_CEASE, 0, NULL, 0); >- change_state(peer, STATE_IDLE, event); >- break; >- case EVNT_CON_CLOSED: >-@@ -856,7 +900,8 @@ bgp_fsm(struct peer *peer, enum session_ >- change_state(peer, STATE_IDLE, event); >- break; >- default: >-- session_notification(peer, ERR_FSM, 0, NULL, 0); >-+ session_notification(peer, >-+ ERR_FSM, ERR_FSM_UNEX_ESTABLISHED, NULL, 0); >- change_state(peer, STATE_IDLE, event); >- break; >- } >-@@ -885,9 +930,10 @@ start_timer_keepalive(struct peer *peer) >- void >- session_close_connection(struct peer *peer) >- { >-- if (peer->fd != -1) >-+ if (peer->fd != -1) { >- close(peer->fd); >-- >-+ pauseaccept = 0; >-+ } >- peer->fd = peer->wbuf.fd = -1; >- } >- >-@@ -923,20 +969,31 @@ change_state(struct peer *peer, enum ses >- timer_stop(peer, Timer_ConnectRetry); >- timer_stop(peer, Timer_Keepalive); >- timer_stop(peer, Timer_Hold); >-+ timer_stop(peer, Timer_IdleHold); >- timer_stop(peer, Timer_IdleHoldReset); >- session_close_connection(peer); >- msgbuf_clear(&peer->wbuf); >- free(peer->rbuf); >- peer->rbuf = NULL; >- bzero(&peer->capa.peer, sizeof(peer->capa.peer)); >-- if (peer->state == STATE_ESTABLISHED) >-- session_down(peer); >-+ >- if (event != EVNT_STOP) { >- timer_set(peer, Timer_IdleHold, peer->IdleHoldTime); >- if (event != EVNT_NONE && >- peer->IdleHoldTime < MAX_IDLE_HOLD/2) >- peer->IdleHoldTime *= 2; >- } >-+ if (peer->state == STATE_ESTABLISHED) { >-+ if (peer->capa.neg.grestart.restart == 2 && >-+ (event == EVNT_CON_CLOSED || >-+ event == EVNT_CON_FATAL)) { >-+ /* don't punish graceful restart */ >-+ timer_set(peer, Timer_IdleHold, 0); >-+ peer->IdleHoldTime /= 2; >-+ session_graceful_restart(peer); >-+ } else >-+ session_down(peer); >-+ } >- if (peer->state == STATE_NONE || >- peer->state == STATE_ESTABLISHED) { >- /* initialize capability negotiation structures */ >-@@ -947,6 +1004,20 @@ change_state(struct peer *peer, enum ses >- } >- break; >- case STATE_CONNECT: >-+ if (peer->state == STATE_ESTABLISHED && >-+ peer->capa.neg.grestart.restart == 2) { >-+ /* do the graceful restart dance */ >-+ session_graceful_restart(peer); >-+ peer->holdtime = INTERVAL_HOLD_INITIAL; >-+ timer_stop(peer, Timer_ConnectRetry); >-+ timer_stop(peer, Timer_Keepalive); >-+ timer_stop(peer, Timer_Hold); >-+ timer_stop(peer, Timer_IdleHold); >-+ timer_stop(peer, Timer_IdleHoldReset); >-+ session_close_connection(peer); >-+ msgbuf_clear(&peer->wbuf); >-+ bzero(&peer->capa.peer, sizeof(peer->capa.peer)); >-+ } >- break; >- case STATE_ACTIVE: >- break; >-@@ -990,7 +1061,10 @@ session_accept(int listenfd) >- len = sizeof(cliaddr); >- if ((connfd = accept(listenfd, >- (struct sockaddr *)&cliaddr, &len)) == -1) { >-- if (errno == EWOULDBLOCK || errno == EINTR) >-+ if (errno == ENFILE || errno == EMFILE) { >-+ pauseaccept = getmonotime(); >-+ return; >-+ } else if (errno == EWOULDBLOCK || errno == EINTR) >- return; >- else >- log_warn("accept"); >-@@ -1017,6 +1091,7 @@ session_accept(int listenfd) >- } >- } >- >-+open: >- if (p->conf.auth.method != AUTH_NONE && sysdep.no_pfkey) { >- log_peer_warnx(&p->conf, >- "ipsec or md5sig configured but not available"); >-@@ -1049,6 +1124,13 @@ session_accept(int listenfd) >- } >- session_socket_blockmode(connfd, BM_NONBLOCK); >- bgp_fsm(p, EVNT_CON_OPEN); >-+ return; >-+ } else if (p != NULL && p->state == STATE_ESTABLISHED && >-+ p->capa.neg.grestart.restart == 2) { >-+ /* first do the graceful restart dance */ >-+ change_state(p, STATE_CONNECT, EVNT_CON_CLOSED); >-+ /* then do part of the open dance */ >-+ goto open; >- } else { >- log_conn_attempt(p, (struct sockaddr *)&cliaddr); >- close(connfd); >-@@ -1069,7 +1151,7 @@ session_connect(struct peer *peer) >- if (peer->fd != -1) >- return (-1); >- >-- if ((peer->fd = socket(peer->conf.remote_addr.af, SOCK_STREAM, >-+ if ((peer->fd = socket(aid2af(peer->conf.remote_addr.aid), SOCK_STREAM, >- IPPROTO_TCP)) == -1) { >- log_peer_warn(&peer->conf, "session_connect socket"); >- bgp_fsm(peer, EVNT_CON_OPENFAIL); >-@@ -1100,8 +1182,7 @@ session_connect(struct peer *peer) >- peer->wbuf.fd = peer->fd; >- >- /* if update source is set we need to bind() */ >-- if (peer->conf.local_addr.af) { >-- sa = addr2sa(&peer->conf.local_addr, 0); >-+ if ((sa = addr2sa(&peer->conf.local_addr, 0)) != NULL) { >- if (bind(peer->fd, sa, sa->sa_len) == -1) { >- log_peer_warn(&peer->conf, "session_connect bind"); >- bgp_fsm(peer, EVNT_CON_OPENFAIL); >-@@ -1139,42 +1220,50 @@ session_setup_socket(struct peer *p) >- int nodelay = 1; >- int bsize; >- >-- if (p->conf.ebgp && p->conf.remote_addr.af == AF_INET) { >-- /* set TTL to foreign router's distance - 1=direct n=multihop >-- with ttlsec, we always use 255 */ >-- if (p->conf.ttlsec) { >-- ttl = 256 - p->conf.distance; >-- if (setsockopt(p->fd, IPPROTO_IP, IP_MINTTL, &ttl, >-+ switch (p->conf.remote_addr.aid) { >-+ case AID_INET: >-+ /* set precedence, see RFC 1771 appendix 5 */ >-+ if (setsockopt(p->fd, IPPROTO_IP, IP_TOS, &pre, sizeof(pre)) == >-+ -1) { >-+ log_peer_warn(&p->conf, >-+ "session_setup_socket setsockopt TOS"); >-+ return (-1); >-+ } >-+ >-+ if (p->conf.ebgp) { >-+ /* set TTL to foreign router's distance >-+ 1=direct n=multihop with ttlsec, we always use 255 */ >-+ if (p->conf.ttlsec) { >-+ ttl = 256 - p->conf.distance; >-+ if (setsockopt(p->fd, IPPROTO_IP, IP_MINTTL, >-+ &ttl, sizeof(ttl)) == -1) { >-+ log_peer_warn(&p->conf, >-+ "session_setup_socket: " >-+ "setsockopt MINTTL"); >-+ return (-1); >-+ } >-+ ttl = 255; >-+ } >-+ >-+ if (setsockopt(p->fd, IPPROTO_IP, IP_TTL, &ttl, >- sizeof(ttl)) == -1) { >- log_peer_warn(&p->conf, >-- "session_setup_socket setsockopt MINTTL"); >-+ "session_setup_socket setsockopt TTL"); >- return (-1); >- } >-- ttl = 255; >-- } >-- >-- if (setsockopt(p->fd, IPPROTO_IP, IP_TTL, &ttl, >-- sizeof(ttl)) == -1) { >-- log_peer_warn(&p->conf, >-- "session_setup_socket setsockopt TTL"); >-- return (-1); >- } >-- } >-- >-- if (p->conf.ebgp && p->conf.remote_addr.af == AF_INET6) >-- /* set hoplimit to foreign router's distance */ >-- if (setsockopt(p->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, >-- sizeof(ttl)) == -1) { >-- log_peer_warn(&p->conf, >-- "session_setup_socket setsockopt hoplimit"); >-- return (-1); >-+ break; >-+ case AID_INET6: >-+ if (p->conf.ebgp) { >-+ /* set hoplimit to foreign router's distance */ >-+ if (setsockopt(p->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, >-+ &ttl, sizeof(ttl)) == -1) { >-+ log_peer_warn(&p->conf, >-+ "session_setup_socket setsockopt hoplimit"); >-+ return (-1); >-+ } >- } >-- >-- /* if ttlsec is in use, set minttl */ >-- if (p->conf.ttlsec) { >-- ttl = 256 - p->conf.distance; >-- setsockopt(p->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)); >-- >-+ break; >- } >- >- /* set TCP_NODELAY */ >-@@ -1185,24 +1274,18 @@ session_setup_socket(struct peer *p) >- return (-1); >- } >- >-- /* set precedence, see RFC 1771 appendix 5 */ >-- if (p->conf.remote_addr.af == AF_INET && >-- setsockopt(p->fd, IPPROTO_IP, IP_TOS, &pre, sizeof(pre)) == -1) { >-- log_peer_warn(&p->conf, >-- "session_setup_socket setsockopt TOS"); >-- return (-1); >-- } >-- >- /* only increase bufsize (and thus window) if md5 or ipsec is in use */ >- if (p->conf.auth.method != AUTH_NONE) { >- /* try to increase bufsize. no biggie if it fails */ >- bsize = 65535; >-- while (setsockopt(p->fd, SOL_SOCKET, SO_RCVBUF, &bsize, >-- sizeof(bsize)) == -1) >-+ while (bsize > 8192 && >-+ setsockopt(p->fd, SOL_SOCKET, SO_RCVBUF, &bsize, >-+ sizeof(bsize)) == -1 && errno != EINVAL) >- bsize /= 2; >- bsize = 65535; >-- while (setsockopt(p->fd, SOL_SOCKET, SO_SNDBUF, &bsize, >-- sizeof(bsize)) == -1) >-+ while (bsize > 8192 && >-+ setsockopt(p->fd, SOL_SOCKET, SO_SNDBUF, &bsize, >-+ sizeof(bsize)) == -1 && errno != EINVAL) >- bsize /= 2; >- } >- >-@@ -1244,40 +1327,56 @@ session_tcp_established(struct peer *pee >- void >- session_capa_ann_none(struct peer *peer) >- { >-- peer->capa.ann.mp_v4 = SAFI_NONE; >-- peer->capa.ann.mp_v4 = SAFI_NONE; >-- peer->capa.ann.refresh = 0; >-- peer->capa.ann.restart = 0; >-- peer->capa.ann.as4byte = 0; >-+ bzero(&peer->capa.ann, sizeof(peer->capa.ann)); >- } >- >- int >--session_capa_add(struct peer *p, struct buf *opb, u_int8_t capa_code, >-- u_int8_t capa_len, u_int8_t *optparamlen) >--{ >-- u_int8_t op_type, op_len, tot_len, errs = 0; >-- >-- op_type = OPT_PARAM_CAPABILITIES; >-- op_len = sizeof(capa_code) + sizeof(capa_len) + capa_len; >-- tot_len = sizeof(op_type) + sizeof(op_len) + op_len; >-- errs += buf_add(opb, &op_type, sizeof(op_type)); >-- errs += buf_add(opb, &op_len, sizeof(op_len)); >-- errs += buf_add(opb, &capa_code, sizeof(capa_code)); >-- errs += buf_add(opb, &capa_len, sizeof(capa_len)); >-- *optparamlen += tot_len; >-+session_capa_add(struct ibuf *opb, u_int8_t capa_code, u_int8_t capa_len) >-+{ >-+ int errs = 0; >-+ >-+ errs += ibuf_add(opb, &capa_code, sizeof(capa_code)); >-+ errs += ibuf_add(opb, &capa_len, sizeof(capa_len)); >- return (errs); >- } >- >- int >--session_capa_add_mp(struct buf *buf, u_int16_t afi, u_int8_t safi) >-+session_capa_add_mp(struct ibuf *buf, u_int8_t aid) >- { >-- u_int8_t pad = 0; >-+ u_int8_t safi, pad = 0; >-+ u_int16_t afi; >- int errs = 0; >- >-+ if (aid2afi(aid, &afi, &safi) == -1) >-+ fatalx("session_capa_add_mp: bad afi/safi pair"); >-+ afi = htons(afi); >-+ errs += ibuf_add(buf, &afi, sizeof(afi)); >-+ errs += ibuf_add(buf, &pad, sizeof(pad)); >-+ errs += ibuf_add(buf, &safi, sizeof(safi)); >-+ >-+ return (errs); >-+} >-+ >-+int >-+session_capa_add_gr(struct peer *p, struct ibuf *b, u_int8_t aid) >-+{ >-+ u_int errs = 0; >-+ u_int16_t afi; >-+ u_int8_t flags, safi; >-+ >-+ if (aid2afi(aid, &afi, &safi)) { >-+ log_warn("session_capa_add_gr: bad AID"); >-+ return (1); >-+ } >-+ if (p->capa.neg.grestart.flags[aid] & CAPA_GR_RESTARTING) >-+ flags = CAPA_GR_F_FLAG; >-+ else >-+ flags = 0; >-+ >- afi = htons(afi); >-- errs += buf_add(buf, &afi, sizeof(afi)); >-- errs += buf_add(buf, &pad, sizeof(pad)); >-- errs += buf_add(buf, &safi, sizeof(safi)); >-+ errs += ibuf_add(b, &afi, sizeof(afi)); >-+ errs += ibuf_add(b, &safi, sizeof(safi)); >-+ errs += ibuf_add(b, &flags, sizeof(flags)); >- >- return (errs); >- } >-@@ -1287,23 +1386,22 @@ session_newmsg(enum msg_type msgtype, u_ >- { >- struct bgp_msg *msg; >- struct msg_header hdr; >-- struct buf *buf; >-+ struct ibuf *buf; >- int errs = 0; >- >- memset(&hdr.marker, 0xff, sizeof(hdr.marker)); >- hdr.len = htons(len); >- hdr.type = msgtype; >- >-- if ((buf = buf_open(len)) == NULL) >-+ if ((buf = ibuf_open(len)) == NULL) >- return (NULL); >- >-- errs += buf_add(buf, &hdr.marker, sizeof(hdr.marker)); >-- errs += buf_add(buf, &hdr.len, sizeof(hdr.len)); >-- errs += buf_add(buf, &hdr.type, sizeof(hdr.type)); >-- >-- if (errs > 0 || >-- (msg = calloc(1, sizeof(*msg))) == NULL) { >-- buf_free(buf); >-+ errs += ibuf_add(buf, &hdr.marker, sizeof(hdr.marker)); >-+ errs += ibuf_add(buf, &hdr.len, sizeof(hdr.len)); >-+ errs += ibuf_add(buf, &hdr.type, sizeof(hdr.type)); >-+ >-+ if (errs || (msg = calloc(1, sizeof(*msg))) == NULL) { >-+ ibuf_free(buf); >- return (NULL); >- } >- >-@@ -1329,7 +1427,7 @@ session_sendmsg(struct bgp_msg *msg, str >- mrt_dump_bgp_msg(mrt, msg->buf->buf, msg->len, p); >- } >- >-- buf_close(&p->wbuf, msg->buf); >-+ ibuf_close(&p->wbuf, msg->buf); >- free(msg); >- return (0); >- } >-@@ -1338,40 +1436,70 @@ void >- session_open(struct peer *p) >- { >- struct bgp_msg *buf; >-- struct buf *opb; >-+ struct ibuf *opb; >- struct msg_open msg; >- u_int16_t len; >-- u_int8_t optparamlen = 0; >-- u_int errs = 0; >-+ u_int8_t i, op_type, optparamlen = 0; >-+ int errs = 0; >-+ int mpcapa = 0; >- >- >-- if ((opb = buf_dynamic(0, MAX_PKTSIZE - MSGSIZE_OPEN_MIN)) == NULL) { >-+ if ((opb = ibuf_dynamic(0, UCHAR_MAX - sizeof(op_type) - >-+ sizeof(optparamlen))) == NULL) { >- bgp_fsm(p, EVNT_CON_FATAL); >- return; >- } >- >- /* multiprotocol extensions, RFC 4760 */ >-- if (p->capa.ann.mp_v4) { /* 4 bytes data */ >-- errs += session_capa_add(p, opb, CAPA_MP, 4, &optparamlen); >-- errs += session_capa_add_mp(opb, AFI_IPv4, p->capa.ann.mp_v4); >-- } >-- if (p->capa.ann.mp_v6) { /* 4 bytes data */ >-- errs += session_capa_add(p, opb, CAPA_MP, 4, &optparamlen); >-- errs += session_capa_add_mp(opb, AFI_IPv6, p->capa.ann.mp_v6); >-- } >-+ for (i = 0; i < AID_MAX; i++) >-+ if (p->capa.ann.mp[i]) { /* 4 bytes data */ >-+ errs += session_capa_add(opb, CAPA_MP, 4); >-+ errs += session_capa_add_mp(opb, i); >-+ mpcapa++; >-+ } >- >- /* route refresh, RFC 2918 */ >- if (p->capa.ann.refresh) /* no data */ >-- errs += session_capa_add(p, opb, CAPA_REFRESH, 0, &optparamlen); >-+ errs += session_capa_add(opb, CAPA_REFRESH, 0); >- >-- /* End-of-RIB marker, RFC 4724 */ >-- if (p->capa.ann.restart) { /* 2 bytes data */ >-- u_char c[2]; >-- >-- bzero(&c, 2); >-- c[0] = 0x80; /* we're always restarting */ >-- errs += session_capa_add(p, opb, CAPA_RESTART, 2, &optparamlen); >-- errs += buf_add(opb, &c, 2); >-+ /* graceful restart and End-of-RIB marker, RFC 4724 */ >-+ if (p->capa.ann.grestart.restart) { >-+ int rst = 0; >-+ u_int16_t hdr; >-+ u_int8_t grlen; >-+ >-+ if (mpcapa) { >-+ grlen = 2 + 4 * mpcapa; >-+ for (i = 0; i < AID_MAX; i++) { >-+ if (p->capa.neg.grestart.flags[i] & >-+ CAPA_GR_RESTARTING) >-+ rst++; >-+ } >-+ } else { /* AID_INET */ >-+ grlen = 2 + 4; >-+ if (p->capa.neg.grestart.flags[AID_INET] & >-+ CAPA_GR_RESTARTING) >-+ rst++; >-+ } >-+ >-+ hdr = conf->holdtime; /* default timeout */ >-+ /* if client does graceful restart don't set R flag */ >-+ if (!rst) >-+ hdr |= CAPA_GR_R_FLAG; >-+ hdr = htons(hdr); >-+ >-+ errs += session_capa_add(opb, CAPA_RESTART, grlen); >-+ errs += ibuf_add(opb, &hdr, sizeof(hdr)); >-+ >-+ if (mpcapa) { >-+ for (i = 0; i < AID_MAX; i++) { >-+ if (p->capa.ann.mp[i]) { >-+ errs += session_capa_add_gr(p, opb, i); >-+ } >-+ } >-+ } else { /* AID_INET */ >-+ errs += session_capa_add_gr(p, opb, AID_INET); >-+ } >- } >- >- /* 4-bytes AS numbers, draft-ietf-idr-as4bytes-13 */ >-@@ -1379,13 +1507,17 @@ session_open(struct peer *p) >- u_int32_t nas; >- >- nas = htonl(conf->as); >-- errs += session_capa_add(p, opb, CAPA_AS4BYTE, 4, &optparamlen); >-- errs += buf_add(opb, &nas, 4); >-+ errs += session_capa_add(opb, CAPA_AS4BYTE, sizeof(nas)); >-+ errs += ibuf_add(opb, &nas, sizeof(nas)); >- } >- >-+ if (ibuf_size(opb)) >-+ optparamlen = ibuf_size(opb) + sizeof(op_type) + >-+ sizeof(optparamlen); >-+ >- len = MSGSIZE_OPEN_MIN + optparamlen; >- if (errs || (buf = session_newmsg(OPEN, len)) == NULL) { >-- buf_free(opb); >-+ ibuf_free(opb); >- bgp_fsm(p, EVNT_CON_FATAL); >- return; >- } >-@@ -1399,19 +1531,24 @@ session_open(struct peer *p) >- msg.bgpid = conf->bgpid; /* is already in network byte order */ >- msg.optparamlen = optparamlen; >- >-- errs += buf_add(buf->buf, &msg.version, sizeof(msg.version)); >-- errs += buf_add(buf->buf, &msg.myas, sizeof(msg.myas)); >-- errs += buf_add(buf->buf, &msg.holdtime, sizeof(msg.holdtime)); >-- errs += buf_add(buf->buf, &msg.bgpid, sizeof(msg.bgpid)); >-- errs += buf_add(buf->buf, &msg.optparamlen, sizeof(msg.optparamlen)); >-- >-- if (optparamlen) >-- errs += buf_add(buf->buf, opb->buf, optparamlen); >-+ errs += ibuf_add(buf->buf, &msg.version, sizeof(msg.version)); >-+ errs += ibuf_add(buf->buf, &msg.myas, sizeof(msg.myas)); >-+ errs += ibuf_add(buf->buf, &msg.holdtime, sizeof(msg.holdtime)); >-+ errs += ibuf_add(buf->buf, &msg.bgpid, sizeof(msg.bgpid)); >-+ errs += ibuf_add(buf->buf, &msg.optparamlen, sizeof(msg.optparamlen)); >-+ >-+ if (optparamlen) { >-+ op_type = OPT_PARAM_CAPABILITIES; >-+ optparamlen = ibuf_size(opb); >-+ errs += ibuf_add(buf->buf, &op_type, sizeof(op_type)); >-+ errs += ibuf_add(buf->buf, &optparamlen, sizeof(optparamlen)); >-+ errs += ibuf_add(buf->buf, opb->buf, ibuf_size(opb)); >-+ } >- >-- buf_free(opb); >-+ ibuf_free(opb); >- >-- if (errs > 0) { >-- buf_free(buf->buf); >-+ if (errs) { >-+ ibuf_free(buf->buf); >- free(buf); >- bgp_fsm(p, EVNT_CON_FATAL); >- return; >-@@ -1459,8 +1596,8 @@ session_update(u_int32_t peerid, void *d >- return; >- } >- >-- if (buf_add(buf->buf, data, datalen)) { >-- buf_free(buf->buf); >-+ if (ibuf_add(buf->buf, data, datalen)) { >-+ ibuf_free(buf->buf); >- free(buf); >- bgp_fsm(p, EVNT_CON_FATAL); >- return; >-@@ -1480,29 +1617,27 @@ session_notification(struct peer *p, u_i >- void *data, ssize_t datalen) >- { >- struct bgp_msg *buf; >-- u_int errs = 0; >-- u_int8_t null8 = 0; >-+ int errs = 0; >- >- if (p->stats.last_sent_errcode) /* some notification already sent */ >- return; >- >-+ log_notification(p, errcode, subcode, data, datalen, "sending"); >-+ >- if ((buf = session_newmsg(NOTIFICATION, >- MSGSIZE_NOTIFICATION_MIN + datalen)) == NULL) { >- bgp_fsm(p, EVNT_CON_FATAL); >- return; >- } >- >-- errs += buf_add(buf->buf, &errcode, sizeof(errcode)); >-- if (errcode == ERR_CEASE) >-- errs += buf_add(buf->buf, &null8, sizeof(null8)); >-- else >-- errs += buf_add(buf->buf, &subcode, sizeof(subcode)); >-+ errs += ibuf_add(buf->buf, &errcode, sizeof(errcode)); >-+ errs += ibuf_add(buf->buf, &subcode, sizeof(subcode)); >- >- if (datalen > 0) >-- errs += buf_add(buf->buf, data, datalen); >-+ errs += ibuf_add(buf->buf, data, datalen); >- >-- if (errs > 0) { >-- buf_free(buf->buf); >-+ if (errs) { >-+ ibuf_free(buf->buf); >- free(buf); >- bgp_fsm(p, EVNT_CON_FATAL); >- return; >-@@ -1521,23 +1656,29 @@ session_notification(struct peer *p, u_i >- int >- session_neighbor_rrefresh(struct peer *p) >- { >-+ u_int8_t i; >-+ >- if (!p->capa.peer.refresh) >- return (-1); >- >-- if (p->capa.peer.mp_v4 != SAFI_NONE) >-- session_rrefresh(p, AFI_IPv4, p->capa.peer.mp_v4); >-- if (p->capa.peer.mp_v6 != SAFI_NONE) >-- session_rrefresh(p, AFI_IPv6, p->capa.peer.mp_v6); >-+ for (i = 0; i < AID_MAX; i++) { >-+ if (p->capa.peer.mp[i] != 0) >-+ session_rrefresh(p, i); >-+ } >- >- return (0); >- } >- >- void >--session_rrefresh(struct peer *p, u_int16_t afi, u_int8_t safi) >-+session_rrefresh(struct peer *p, u_int8_t aid) >- { >- struct bgp_msg *buf; >- int errs = 0; >-- u_int8_t null8 = 0; >-+ u_int16_t afi; >-+ u_int8_t safi, null8 = 0; >-+ >-+ if (aid2afi(aid, &afi, &safi) == -1) >-+ fatalx("session_rrefresh: bad afi/safi pair"); >- >- if ((buf = session_newmsg(RREFRESH, MSGSIZE_RREFRESH)) == NULL) { >- bgp_fsm(p, EVNT_CON_FATAL); >-@@ -1545,12 +1686,12 @@ session_rrefresh(struct peer *p, u_int16 >- } >- >- afi = htons(afi); >-- errs += buf_add(buf->buf, &afi, sizeof(afi)); >-- errs += buf_add(buf->buf, &null8, sizeof(null8)); >-- errs += buf_add(buf->buf, &safi, sizeof(safi)); >-+ errs += ibuf_add(buf->buf, &afi, sizeof(afi)); >-+ errs += ibuf_add(buf->buf, &null8, sizeof(null8)); >-+ errs += ibuf_add(buf->buf, &safi, sizeof(safi)); >- >-- if (errs > 0) { >-- buf_free(buf->buf); >-+ if (errs) { >-+ ibuf_free(buf->buf); >- free(buf); >- bgp_fsm(p, EVNT_CON_FATAL); >- return; >-@@ -1565,13 +1706,74 @@ session_rrefresh(struct peer *p, u_int16 >- } >- >- int >-+session_graceful_restart(struct peer *p) >-+{ >-+ u_int8_t i; >-+ >-+ timer_set(p, Timer_RestartTimeout, p->capa.neg.grestart.timeout); >-+ >-+ for (i = 0; i < AID_MAX; i++) { >-+ if (p->capa.neg.grestart.flags[i] & CAPA_GR_PRESENT) { >-+ if (imsg_compose(ibuf_rde, IMSG_SESSION_STALE, >-+ p->conf.id, 0, -1, &i, sizeof(i)) == -1) >-+ return (-1); >-+ log_peer_warnx(&p->conf, >-+ "graceful restart of %s, keeping routes", >-+ aid2str(i)); >-+ p->capa.neg.grestart.flags[i] |= CAPA_GR_RESTARTING; >-+ } else if (p->capa.neg.mp[i]) { >-+ if (imsg_compose(ibuf_rde, IMSG_SESSION_FLUSH, >-+ p->conf.id, 0, -1, &i, sizeof(i)) == -1) >-+ return (-1); >-+ log_peer_warnx(&p->conf, >-+ "graceful restart of %s, flushing routes", >-+ aid2str(i)); >-+ } >-+ } >-+ return (0); >-+} >-+ >-+int >-+session_graceful_is_restarting(struct peer *p) >-+{ >-+ u_int8_t i; >-+ >-+ for (i = 0; i < AID_MAX; i++) >-+ if (p->capa.neg.grestart.flags[i] & CAPA_GR_RESTARTING) >-+ return (1); >-+ return (0); >-+} >-+ >-+int >-+session_graceful_stop(struct peer *p) >-+{ >-+ u_int8_t i; >-+ >-+ for (i = 0; i < AID_MAX; i++) { >-+ /* >-+ * Only flush if the peer is restarting and the peer indicated >-+ * it hold the forwarding state. In all other cases the >-+ * session was already flushed when the session came up. >-+ */ >-+ if (p->capa.neg.grestart.flags[i] & CAPA_GR_RESTARTING && >-+ p->capa.neg.grestart.flags[i] & CAPA_GR_FORWARD) { >-+ log_peer_warnx(&p->conf, "graceful restart of %s, " >-+ "time-out, flushing", aid2str(i)); >-+ if (imsg_compose(ibuf_rde, IMSG_SESSION_FLUSH, >-+ p->conf.id, 0, -1, &i, sizeof(i)) == -1) >-+ return (-1); >-+ } >-+ p->capa.neg.grestart.flags[i] &= ~CAPA_GR_RESTARTING; >-+ } >-+ return (0); >-+} >-+ >-+int >- session_dispatch_msg(struct pollfd *pfd, struct peer *p) >- { >-- ssize_t n, rpos, av, left; >-+ ssize_t n; >- socklen_t len; >-- int error, processed = 0; >-- u_int16_t msglen; >-- u_int8_t msgtype; >-+ int error; >- >- if (p->state == STATE_CONNECT) { >- if (pfd->revents & POLLOUT) { >-@@ -1641,71 +1843,83 @@ session_dispatch_msg(struct pollfd *pfd, >- return (1); >- } >- >-- rpos = 0; >-- av = p->rbuf->wpos + n; >-+ p->rbuf->wpos += n; >- p->stats.last_read = time(NULL); >-+ return (1); >-+ } >-+ return (0); >-+} >- >-- /* >-- * session might drop to IDLE -> buffers deallocated >-- * we MUST check rbuf != NULL before use >-- */ >-- for (;;) { >-- if (rpos + MSGSIZE_HEADER > av) >-- break; >-- if (p->rbuf == NULL) >-- break; >-- if (parse_header(p, p->rbuf->buf + rpos, &msglen, >-- &msgtype) == -1) >-- return (0); >-- if (rpos + msglen > av) >-- break; >-- p->rbuf->rptr = p->rbuf->buf + rpos; >-- >-- switch (msgtype) { >-- case OPEN: >-- bgp_fsm(p, EVNT_RCVD_OPEN); >-- p->stats.msg_rcvd_open++; >-- break; >-- case UPDATE: >-- bgp_fsm(p, EVNT_RCVD_UPDATE); >-- p->stats.msg_rcvd_update++; >-- break; >-- case NOTIFICATION: >-- bgp_fsm(p, EVNT_RCVD_NOTIFICATION); >-- p->stats.msg_rcvd_notification++; >-- break; >-- case KEEPALIVE: >-- bgp_fsm(p, EVNT_RCVD_KEEPALIVE); >-- p->stats.msg_rcvd_keepalive++; >-- break; >-- case RREFRESH: >-- parse_refresh(p); >-- p->stats.msg_rcvd_rrefresh++; >-- break; >-- default: /* cannot happen */ >-- session_notification(p, ERR_HEADER, >-- ERR_HDR_TYPE, &msgtype, 1); >-- log_warnx("received message with " >-- "unknown type %u", msgtype); >-- bgp_fsm(p, EVNT_CON_FATAL); >-- } >-- rpos += msglen; >-- if (++processed > MSG_PROCESS_LIMIT) >-- break; >-- } >-- if (p->rbuf == NULL) >-- return (1); >-+int >-+session_process_msg(struct peer *p) >-+{ >-+ ssize_t rpos, av, left; >-+ int processed = 0; >-+ u_int16_t msglen; >-+ u_int8_t msgtype; >- >-- if (rpos < av) { >-- left = av - rpos; >-- memcpy(&p->rbuf->buf, p->rbuf->buf + rpos, left); >-- p->rbuf->wpos = left; >-- } else >-- p->rbuf->wpos = 0; >-+ rpos = 0; >-+ av = p->rbuf->wpos; >- >-- return (1); >-+ /* >-+ * session might drop to IDLE -> buffers deallocated >-+ * we MUST check rbuf != NULL before use >-+ */ >-+ for (;;) { >-+ if (rpos + MSGSIZE_HEADER > av) >-+ break; >-+ if (p->rbuf == NULL) >-+ break; >-+ if (parse_header(p, p->rbuf->buf + rpos, &msglen, >-+ &msgtype) == -1) >-+ return (0); >-+ if (rpos + msglen > av) >-+ break; >-+ p->rbuf->rptr = p->rbuf->buf + rpos; >-+ >-+ switch (msgtype) { >-+ case OPEN: >-+ bgp_fsm(p, EVNT_RCVD_OPEN); >-+ p->stats.msg_rcvd_open++; >-+ break; >-+ case UPDATE: >-+ bgp_fsm(p, EVNT_RCVD_UPDATE); >-+ p->stats.msg_rcvd_update++; >-+ break; >-+ case NOTIFICATION: >-+ bgp_fsm(p, EVNT_RCVD_NOTIFICATION); >-+ p->stats.msg_rcvd_notification++; >-+ break; >-+ case KEEPALIVE: >-+ bgp_fsm(p, EVNT_RCVD_KEEPALIVE); >-+ p->stats.msg_rcvd_keepalive++; >-+ break; >-+ case RREFRESH: >-+ parse_refresh(p); >-+ p->stats.msg_rcvd_rrefresh++; >-+ break; >-+ default: /* cannot happen */ >-+ session_notification(p, ERR_HEADER, ERR_HDR_TYPE, >-+ &msgtype, 1); >-+ log_warnx("received message with unknown type %u", >-+ msgtype); >-+ bgp_fsm(p, EVNT_CON_FATAL); >-+ } >-+ rpos += msglen; >-+ if (++processed > MSG_PROCESS_LIMIT) >-+ break; >- } >-- return (0); >-+ if (p->rbuf == NULL) >-+ return (1); >-+ >-+ if (rpos < av) { >-+ left = av - rpos; >-+ memcpy(&p->rbuf->buf, p->rbuf->buf + rpos, left); >-+ p->rbuf->wpos = left; >-+ } else >-+ p->rbuf->wpos = 0; >-+ >-+ return (1); >- } >- >- int >-@@ -1853,12 +2067,6 @@ parse_open(struct peer *peer) >- p += sizeof(short_as); >- as = peer->short_as = ntohs(short_as); >- >-- /* if remote-as is zero and it's a cloned neighbor, accept any */ >-- if (peer->conf.cloned && !peer->conf.remote_as && as != AS_TRANS) { >-- peer->conf.remote_as = as; >-- peer->conf.ebgp = (peer->conf.remote_as != conf->as); >-- } >-- >- memcpy(&oholdtime, p, sizeof(oholdtime)); >- p += sizeof(oholdtime); >- >-@@ -1966,6 +2174,15 @@ parse_open(struct peer *peer) >- } >- } >- >-+ /* if remote-as is zero and it's a cloned neighbor, accept any */ >-+ if (peer->conf.cloned && !peer->conf.remote_as && as != AS_TRANS) { >-+ peer->conf.remote_as = as; >-+ peer->conf.ebgp = (peer->conf.remote_as != conf->as); >-+ if (!peer->conf.ebgp) >-+ /* force enforce_as off for iBGP sessions */ >-+ peer->conf.enforce_as = ENFORCE_AS_OFF; >-+ } >-+ >- if (peer->conf.remote_as != as) { >- log_peer_warnx(&peer->conf, "peer sent wrong AS %s", >- log_as(as)); >-@@ -1974,6 +2191,14 @@ parse_open(struct peer *peer) >- return (-1); >- } >- >-+ if (capa_neg_calc(peer) == -1) { >-+ log_peer_warnx(&peer->conf, >-+ "capability negotiation calculation failed"); >-+ session_notification(peer, ERR_OPEN, 0, NULL, 0); >-+ change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); >-+ return (-1); >-+ } >-+ >- return (0); >- } >- >-@@ -2008,24 +2233,35 @@ int >- parse_refresh(struct peer *peer) >- { >- u_char *p; >-- struct rrefresh r; >-+ u_int16_t afi; >-+ u_int8_t aid, safi; >- >- p = peer->rbuf->rptr; >- p += MSGSIZE_HEADER; /* header is already checked */ >- >-+ /* >-+ * We could check if we actually announced the capability but >-+ * as long as the message is correctly encoded we don't care. >-+ */ >-+ >- /* afi, 2 byte */ >-- memcpy(&r.afi, p, sizeof(r.afi)); >-- r.afi = ntohs(r.afi); >-+ memcpy(&afi, p, sizeof(afi)); >-+ afi = ntohs(afi); >- p += 2; >- /* reserved, 1 byte */ >- p += 1; >- /* safi, 1 byte */ >-- memcpy(&r.safi, p, sizeof(r.safi)); >-+ memcpy(&safi, p, sizeof(safi)); >- >- /* afi/safi unchecked - unrecognized values will be ignored anyway */ >-+ if (afi2aid(afi, safi, &aid) == -1) { >-+ log_peer_warnx(&peer->conf, "peer sent bad refresh, " >-+ "invalid afi/safi pair"); >-+ return (0); >-+ } >- >-- if (imsg_compose(ibuf_rde, IMSG_REFRESH, peer->conf.id, 0, -1, &r, >-- sizeof(r)) == -1) >-+ if (imsg_compose(ibuf_rde, IMSG_REFRESH, peer->conf.id, 0, -1, &aid, >-+ sizeof(aid)) == -1) >- return (-1); >- >- return (0); >-@@ -2035,11 +2271,12 @@ int >- parse_notification(struct peer *peer) >- { >- u_char *p; >-+ u_int16_t datalen; >- u_int8_t errcode; >- u_int8_t subcode; >-- u_int16_t datalen; >- u_int8_t capa_code; >- u_int8_t capa_len; >-+ u_int8_t i; >- >- /* just log */ >- p = peer->rbuf->rptr; >-@@ -2059,7 +2296,7 @@ parse_notification(struct peer *peer) >- p += sizeof(subcode); >- datalen -= sizeof(subcode); >- >-- log_notification(peer, errcode, subcode, p, datalen); >-+ log_notification(peer, errcode, subcode, p, datalen, "received"); >- peer->errcnt++; >- >- if (errcode == ERR_OPEN && subcode == ERR_OPEN_CAPA) { >-@@ -2094,8 +2331,8 @@ parse_notification(struct peer *peer) >- datalen -= capa_len; >- switch (capa_code) { >- case CAPA_MP: >-- peer->capa.ann.mp_v4 = SAFI_NONE; >-- peer->capa.ann.mp_v6 = SAFI_NONE; >-+ for (i = 0; i < AID_MAX; i++) >-+ peer->capa.ann.mp[i] = 0; >- log_peer_warnx(&peer->conf, >- "disabling multiprotocol capability"); >- break; >-@@ -2105,7 +2342,7 @@ parse_notification(struct peer *peer) >- "disabling route refresh capability"); >- break; >- case CAPA_RESTART: >-- peer->capa.ann.restart = 0; >-+ peer->capa.ann.grestart.restart = 0; >- log_peer_warnx(&peer->conf, >- "disabling restart capability"); >- break; >-@@ -2139,19 +2376,23 @@ parse_notification(struct peer *peer) >- int >- parse_capabilities(struct peer *peer, u_char *d, u_int16_t dlen, u_int32_t *as) >- { >-+ u_char *capa_val; >-+ u_int32_t remote_as; >- u_int16_t len; >-+ u_int16_t afi; >-+ u_int16_t gr_header; >-+ u_int8_t safi; >-+ u_int8_t aid; >-+ u_int8_t gr_flags; >- u_int8_t capa_code; >- u_int8_t capa_len; >-- u_char *capa_val; >-- u_int16_t mp_afi; >-- u_int8_t mp_safi; >-- u_int32_t remote_as; >-+ u_int8_t i; >- >- len = dlen; >- while (len > 0) { >- if (len < 2) { >-- log_peer_warnx(&peer->conf, "parse_capabilities: " >-- "expect len >= 2, len is %u", len); >-+ log_peer_warnx(&peer->conf, "Bad capabilities attr " >-+ "length: %u, too short", len); >- return (-1); >- } >- memcpy(&capa_code, d, sizeof(capa_code)); >-@@ -2163,7 +2404,7 @@ parse_capabilities(struct peer *peer, u_ >- if (capa_len > 0) { >- if (len < capa_len) { >- log_peer_warnx(&peer->conf, >-- "parse_capabilities: " >-+ "Bad capabilities attr length: " >- "len %u smaller than capa_len %u", >- len, capa_len); >- return (-1); >-@@ -2178,47 +2419,82 @@ parse_capabilities(struct peer *peer, u_ >- case CAPA_MP: /* RFC 4760 */ >- if (capa_len != 4) { >- log_peer_warnx(&peer->conf, >-- "parse_capabilities: " >-- "expect len 4, len is %u", capa_len); >-- return (-1); >-- } >-- memcpy(&mp_afi, capa_val, sizeof(mp_afi)); >-- mp_afi = ntohs(mp_afi); >-- memcpy(&mp_safi, capa_val + 3, sizeof(mp_safi)); >-- switch (mp_afi) { >-- case AFI_IPv4: >-- if (mp_safi < 1 || mp_safi > 3) >-- log_peer_warnx(&peer->conf, >-- "parse_capabilities: AFI IPv4, " >-- "mp_safi %u unknown", mp_safi); >-- else >-- peer->capa.peer.mp_v4 = mp_safi; >-+ "Bad multi protocol capability length: " >-+ "%u", capa_len); >- break; >-- case AFI_IPv6: >-- if (mp_safi < 1 || mp_safi > 3) >-- log_peer_warnx(&peer->conf, >-- "parse_capabilities: AFI IPv6, " >-- "mp_safi %u unknown", mp_safi); >-- else >-- peer->capa.peer.mp_v6 = mp_safi; >-- break; >-- default: /* ignore */ >-+ } >-+ memcpy(&afi, capa_val, sizeof(afi)); >-+ afi = ntohs(afi); >-+ memcpy(&safi, capa_val + 3, sizeof(safi)); >-+ if (afi2aid(afi, safi, &aid) == -1) { >-+ log_peer_warnx(&peer->conf, >-+ "Received multi protocol capability: " >-+ " unknown AFI %u, safi %u pair", >-+ afi, safi); >- break; >- } >-+ peer->capa.peer.mp[aid] = 1; >- break; >- case CAPA_REFRESH: >- peer->capa.peer.refresh = 1; >- break; >- case CAPA_RESTART: >-- peer->capa.peer.restart = 1; >-- /* we don't care about the further restart capas yet */ >-+ if (capa_len == 2) { >-+ /* peer only supports EoR marker */ >-+ peer->capa.peer.grestart.restart = 1; >-+ peer->capa.peer.grestart.timeout = 0; >-+ break; >-+ } else if (capa_len % 4 != 2) { >-+ log_peer_warnx(&peer->conf, >-+ "Bad graceful restart capability length: " >-+ "%u", capa_len); >-+ peer->capa.peer.grestart.restart = 0; >-+ peer->capa.peer.grestart.timeout = 0; >-+ break; >-+ } >-+ >-+ memcpy(&gr_header, capa_val, sizeof(gr_header)); >-+ gr_header = ntohs(gr_header); >-+ peer->capa.peer.grestart.timeout = >-+ gr_header & CAPA_GR_TIMEMASK; >-+ if (peer->capa.peer.grestart.timeout == 0) { >-+ log_peer_warnx(&peer->conf, "Received " >-+ "graceful restart timeout is zero"); >-+ peer->capa.peer.grestart.restart = 0; >-+ break; >-+ } >-+ >-+ for (i = 2; i <= capa_len - 4; i += 4) { >-+ memcpy(&afi, capa_val + i, sizeof(afi)); >-+ afi = ntohs(afi); >-+ memcpy(&safi, capa_val + i + 2, sizeof(safi)); >-+ if (afi2aid(afi, safi, &aid) == -1) { >-+ log_peer_warnx(&peer->conf, >-+ "Received graceful restart capa: " >-+ " unknown AFI %u, safi %u pair", >-+ afi, safi); >-+ continue; >-+ } >-+ memcpy(&gr_flags, capa_val + i + 3, >-+ sizeof(gr_flags)); >-+ peer->capa.peer.grestart.flags[aid] |= >-+ CAPA_GR_PRESENT; >-+ if (gr_flags & CAPA_GR_F_FLAG) >-+ peer->capa.peer.grestart.flags[aid] |= >-+ CAPA_GR_FORWARD; >-+ if (gr_header & CAPA_GR_R_FLAG) >-+ peer->capa.peer.grestart.flags[aid] |= >-+ CAPA_GR_RESTART; >-+ peer->capa.peer.grestart.restart = 2; >-+ } >- break; >- case CAPA_AS4BYTE: >- if (capa_len != 4) { >- log_peer_warnx(&peer->conf, >-- "parse_capabilities: " >-- "expect len 4, len is %u", capa_len); >-- return (-1); >-+ "Bad AS4BYTE capability length: " >-+ "%u", capa_len); >-+ peer->capa.peer.as4byte = 0; >-+ break; >- } >- memcpy(&remote_as, capa_val, sizeof(remote_as)); >- *as = ntohl(remote_as); >-@@ -2232,6 +2508,66 @@ parse_capabilities(struct peer *peer, u_ >- return (0); >- } >- >-+int >-+capa_neg_calc(struct peer *p) >-+{ >-+ u_int8_t i, hasmp = 0; >-+ >-+ /* refresh: does not realy matter here, use peer setting */ >-+ p->capa.neg.refresh = p->capa.peer.refresh; >-+ >-+ /* as4byte: both side must announce capability */ >-+ if (p->capa.ann.as4byte && p->capa.peer.as4byte) >-+ p->capa.neg.as4byte = 1; >-+ else >-+ p->capa.neg.as4byte = 0; >-+ >-+ /* MP: both side must announce capability */ >-+ for (i = 0; i < AID_MAX; i++) { >-+ if (p->capa.ann.mp[i] && p->capa.peer.mp[i]) { >-+ p->capa.neg.mp[i] = 1; >-+ hasmp = 1; >-+ } else >-+ p->capa.neg.mp[i] = 0; >-+ } >-+ /* if no MP capability present default to IPv4 unicast mode */ >-+ if (!hasmp) >-+ p->capa.neg.mp[AID_INET] = 1; >-+ >-+ /* >-+ * graceful restart: only the peer capabilities are of interest here. >-+ * It is necessary to compare the new values with the previous ones >-+ * and act acordingly. AFI/SAFI that are not part in the MP capability >-+ * are treated as not being present. >-+ */ >-+ >-+ for (i = 0; i < AID_MAX; i++) { >-+ /* disable GR if the AFI/SAFI is not present */ >-+ if (p->capa.peer.grestart.flags[i] & CAPA_GR_PRESENT && >-+ p->capa.neg.mp[i] == 0) >-+ p->capa.peer.grestart.flags[i] = 0; /* disable */ >-+ /* look at current GR state and decide what to do */ >-+ if (p->capa.neg.grestart.flags[i] & CAPA_GR_RESTARTING) { >-+ if (!(p->capa.peer.grestart.flags[i] & >-+ CAPA_GR_FORWARD)) { >-+ if (imsg_compose(ibuf_rde, IMSG_SESSION_FLUSH, >-+ p->conf.id, 0, -1, &i, sizeof(i)) == -1) >-+ return (-1); >-+ log_peer_warnx(&p->conf, "graceful restart of " >-+ "%s, not restarted, flushing", aid2str(i)); >-+ } >-+ p->capa.neg.grestart.flags[i] = >-+ p->capa.peer.grestart.flags[i] | CAPA_GR_RESTARTING; >-+ } else >-+ p->capa.neg.grestart.flags[i] = >-+ p->capa.peer.grestart.flags[i]; >-+ } >-+ p->capa.neg.grestart.timeout = p->capa.peer.grestart.timeout; >-+ p->capa.neg.grestart.restart = p->capa.peer.grestart.restart; >-+ >-+ return (0); >-+} >-+ >- void >- session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt) >- { >-@@ -2244,8 +2580,8 @@ session_dispatch_imsg(struct imsgbuf *ib >- struct kif *kif; >- u_char *data; >- enum reconf_action reconf; >-- int n, depend_ok; >-- u_int8_t errcode, subcode; >-+ int n, depend_ok, restricted; >-+ u_int8_t aid, errcode, subcode; >- >- if ((n = imsg_read(ibuf)) == -1) >- fatal("session_dispatch_imsg: imsg_read error"); >-@@ -2332,15 +2668,42 @@ session_dispatch_imsg(struct imsgbuf *ib >- } >- >- break; >-+ case IMSG_RECONF_CTRL: >-+ if (idx != PFD_PIPE_MAIN) >-+ fatalx("reconf request not from parent"); >-+ if (imsg.hdr.len != IMSG_HEADER_SIZE + >-+ sizeof(restricted)) >-+ fatalx("IFINFO imsg with wrong len"); >-+ memcpy(&restricted, imsg.data, sizeof(restricted)); >-+ if (imsg.fd == -1) { >-+ log_warnx("expected to receive fd for control " >-+ "socket but didn't receive any"); >-+ break; >-+ } >-+ if (restricted) { >-+ control_shutdown(rcsock); >-+ rcsock = imsg.fd; >-+ control_listen(rcsock); >-+ } else { >-+ control_shutdown(csock); >-+ csock = imsg.fd; >-+ control_listen(csock); >-+ } >-+ break; >- case IMSG_RECONF_DONE: >- if (idx != PFD_PIPE_MAIN) >- fatalx("reconf request not from parent"); >- if (nconf == NULL) >- fatalx("got IMSG_RECONF_DONE but no config"); >-+ conf->flags = nconf->flags; >-+ conf->log = nconf->log; >-+ conf->bgpid = nconf->bgpid; >-+ conf->clusterid = nconf->clusterid; >- conf->as = nconf->as; >-+ conf->short_as = nconf->short_as; >- conf->holdtime = nconf->holdtime; >-- conf->bgpid = nconf->bgpid; >- conf->min_holdtime = nconf->min_holdtime; >-+ conf->connectretry = nconf->connectretry; >- >- /* add new peers */ >- for (p = npeers; p != NULL; p = next) { >-@@ -2388,6 +2751,8 @@ session_dispatch_imsg(struct imsgbuf *ib >- nconf = NULL; >- pending_reconf = 0; >- log_info("SE reconfigured"); >-+ imsg_compose(ibuf_main, IMSG_RECONF_DONE, 0, 0, >-+ -1, NULL, 0); >- break; >- case IMSG_IFINFO: >- if (idx != PFD_PIPE_MAIN) >-@@ -2397,9 +2762,7 @@ session_dispatch_imsg(struct imsgbuf *ib >- fatalx("IFINFO imsg with wrong len"); >- kif = imsg.data; >- depend_ok = (kif->flags & IFF_UP) && >-- (LINK_STATE_IS_UP(kif->link_state) || >-- (kif->link_state == LINK_STATE_UNKNOWN && >-- kif->media_type != IFT_CARP)); >-+ LINK_STATE_IS_UP(kif->link_state); >- >- for (p = peers; p != NULL; p = p->next) >- if (!strcmp(p->conf.if_depend, kif->ifname)) { >-@@ -2408,7 +2771,8 @@ session_dispatch_imsg(struct imsgbuf *ib >- bgp_fsm(p, EVNT_START); >- } else if (!depend_ok && p->depend_ok) { >- p->depend_ok = depend_ok; >-- bgp_fsm(p, EVNT_STOP); >-+ session_stop(p, >-+ ERR_CEASE_OTHER_CHANGE); >- } >- } >- break; >-@@ -2456,10 +2820,10 @@ session_dispatch_imsg(struct imsgbuf *ib >- } >- break; >- case IMSG_CTL_KROUTE: >-- case IMSG_CTL_KROUTE6: >- case IMSG_CTL_KROUTE_ADDR: >- case IMSG_CTL_SHOW_NEXTHOP: >- case IMSG_CTL_SHOW_INTERFACE: >-+ case IMSG_CTL_SHOW_FIB_TABLES: >- if (idx != PFD_PIPE_MAIN) >- fatalx("ctl kroute request not from parent"); >- control_imsg_relay(&imsg); >-@@ -2469,7 +2833,6 @@ session_dispatch_imsg(struct imsgbuf *ib >- case IMSG_CTL_SHOW_RIB_ATTR: >- case IMSG_CTL_SHOW_RIB_MEM: >- case IMSG_CTL_SHOW_NETWORK: >-- case IMSG_CTL_SHOW_NETWORK6: >- case IMSG_CTL_SHOW_NEIGHBOR: >- if (idx != PFD_PIPE_ROUTE_CTL) >- fatalx("ctl rib request not from RDE"); >-@@ -2531,6 +2894,40 @@ session_dispatch_imsg(struct imsgbuf *ib >- break; >- } >- break; >-+ case IMSG_SESSION_RESTARTED: >-+ if (idx != PFD_PIPE_ROUTE) >-+ fatalx("update request not from RDE"); >-+ if (imsg.hdr.len < IMSG_HEADER_SIZE + sizeof(aid)) { >-+ log_warnx("RDE sent invalid restart msg"); >-+ break; >-+ } >-+ if ((p = getpeerbyid(imsg.hdr.peerid)) == NULL) { >-+ log_warnx("no such peer: id=%u", >-+ imsg.hdr.peerid); >-+ break; >-+ } >-+ memcpy(&aid, imsg.data, sizeof(aid)); >-+ if (aid >= AID_MAX) >-+ fatalx("IMSG_SESSION_RESTARTED: bad AID"); >-+ if (p->capa.neg.grestart.flags[aid] & >-+ CAPA_GR_RESTARTING && >-+ p->capa.neg.grestart.flags[aid] & >-+ CAPA_GR_FORWARD) { >-+ log_peer_warnx(&p->conf, >-+ "graceful restart of %s finished", >-+ aid2str(aid)); >-+ p->capa.neg.grestart.flags[aid] &= >-+ ~CAPA_GR_RESTARTING; >-+ timer_stop(p, Timer_RestartTimeout); >-+ >-+ /* signal back to RDE to cleanup stale routes */ >-+ if (imsg_compose(ibuf_rde, >-+ IMSG_SESSION_RESTARTED, imsg.hdr.peerid, 0, >-+ -1, &aid, sizeof(aid)) == -1) >-+ fatal("imsg_compose: " >-+ "IMSG_SESSION_RESTARTED"); >-+ } >-+ break; >- default: >- break; >- } >-@@ -2612,29 +3009,23 @@ getpeerbydesc(const char *descr) >- struct peer * >- getpeerbyip(struct sockaddr *ip) >- { >-+ struct bgpd_addr addr; >- struct peer *p, *newpeer, *loose = NULL; >- u_int32_t id; >- >-+ sa2addr(ip, &addr); >-+ >- /* we might want a more effective way to find peers by IP */ >- for (p = peers; p != NULL; p = p->next) >- if (!p->conf.template && >-- p->conf.remote_addr.af == ip->sa_family) { >-- if (p->conf.remote_addr.af == AF_INET && >-- p->conf.remote_addr.v4.s_addr == >-- ((struct sockaddr_in *)ip)->sin_addr.s_addr) >-- return (p); >-- if (p->conf.remote_addr.af == AF_INET6 && >-- !bcmp(&p->conf.remote_addr.v6, >-- &((struct sockaddr_in6 *)ip)->sin6_addr, >-- sizeof(p->conf.remote_addr.v6))) >-- return (p); >-- } >-+ !memcmp(&addr, &p->conf.remote_addr, sizeof(addr))) >-+ return (p); >- >- /* try template matching */ >- for (p = peers; p != NULL; p = p->next) >- if (p->conf.template && >-- p->conf.remote_addr.af == ip->sa_family && >-- session_match_mask(p, ip)) >-+ p->conf.remote_addr.aid == addr.aid && >-+ session_match_mask(p, &addr)) >- if (loose == NULL || loose->conf.remote_masklen < >- p->conf.remote_masklen) >- loose = p; >-@@ -2653,21 +3044,19 @@ getpeerbyip(struct sockaddr *ip) >- break; >- } >- } >-- if (newpeer->conf.remote_addr.af == AF_INET) { >-- newpeer->conf.remote_addr.v4.s_addr = >-- ((struct sockaddr_in *)ip)->sin_addr.s_addr; >-+ sa2addr(ip, &newpeer->conf.remote_addr); >-+ switch (ip->sa_family) { >-+ case AF_INET: >- newpeer->conf.remote_masklen = 32; >-- } >-- if (newpeer->conf.remote_addr.af == AF_INET6) { >-- memcpy(&p->conf.remote_addr.v6, >-- &((struct sockaddr_in6 *)ip)->sin6_addr, >-- sizeof(newpeer->conf.remote_addr.v6)); >-+ break; >-+ case AF_INET6: >- newpeer->conf.remote_masklen = 128; >-+ break; >- } >- newpeer->conf.template = 0; >- newpeer->conf.cloned = 1; >- newpeer->state = newpeer->prev_state = STATE_NONE; >-- newpeer->conf.reconf_action = RECONF_REINIT; >-+ newpeer->conf.reconf_action = RECONF_KEEP; >- newpeer->rbuf = NULL; >- init_peer(newpeer); >- bgp_fsm(newpeer, EVNT_START); >-@@ -2680,40 +3069,24 @@ getpeerbyip(struct sockaddr *ip) >- } >- >- int >--session_match_mask(struct peer *p, struct sockaddr *ip) >-+session_match_mask(struct peer *p, struct bgpd_addr *a) >- { >-- int i; >- in_addr_t v4mask; >-- struct in6_addr *in; >-- struct in6_addr mask; >-+ struct in6_addr masked; >- >-- if (p->conf.remote_addr.af == AF_INET) { >-+ switch (p->conf.remote_addr.aid) { >-+ case AID_INET: >- v4mask = htonl(prefixlen2mask(p->conf.remote_masklen)); >-- if (p->conf.remote_addr.v4.s_addr == >-- ((((struct sockaddr_in *)ip)->sin_addr.s_addr) & v4mask)) >-+ if (p->conf.remote_addr.v4.s_addr == (a->v4.s_addr & v4mask)) >- return (1); >-- else >-- return (0); >-- } >-- >-- if (p->conf.remote_addr.af == AF_INET6) { >-- bzero(&mask, sizeof(mask)); >-- for (i = 0; i < p->conf.remote_masklen / 8; i++) >-- mask.s6_addr[i] = 0xff; >-- i = p->conf.remote_masklen % 8; >-- if (i) >-- mask.s6_addr[p->conf.remote_masklen / 8] = 0xff00 >> i; >-- >-- in = &((struct sockaddr_in6 *)ip)->sin6_addr; >-- >-- for (i = 0; i < 16; i++) >-- if ((in->s6_addr[i] & mask.s6_addr[i]) != >-- p->conf.remote_addr.addr8[i]) >-- return (0); >-+ return (0); >-+ case AID_INET6: >-+ inet6applymask(&masked, &a->v6, p->conf.remote_masklen); >- >-- return (1); >-+ if (!memcmp(&masked, &p->conf.remote_addr.v6, sizeof(masked))) >-+ return (1); >-+ return (0); >- } >-- >- return (0); >- } >- >-@@ -2733,6 +3106,7 @@ getpeerbyid(u_int32_t peerid) >- void >- session_down(struct peer *peer) >- { >-+ bzero(&peer->capa.neg, sizeof(peer->capa.neg)); >- peer->stats.last_updown = time(NULL); >- if (imsg_compose(ibuf_rde, IMSG_SESSION_DOWN, peer->conf.id, 0, -1, >- NULL, 0) == -1) >-@@ -2744,39 +3118,17 @@ session_up(struct peer *p) >- { >- struct session_up sup; >- >-- if (imsg_compose(ibuf_rde, IMSG_SESSION_ADD, p->conf.id, 0, -1, >-- &p->conf, sizeof(p->conf)) == -1) >-- fatalx("imsg_compose error"); >-+ if (!session_graceful_is_restarting(p)) >-+ if (imsg_compose(ibuf_rde, IMSG_SESSION_ADD, p->conf.id, 0, -1, >-+ &p->conf, sizeof(p->conf)) == -1) >-+ fatalx("imsg_compose error"); >- >-- switch (p->sa_local.ss_family) { >-- case AF_INET: >-- sup.local_addr.af = AF_INET; >-- memcpy(&sup.local_addr.v4, >-- &((struct sockaddr_in *)&p->sa_local)->sin_addr, >-- sizeof(sup.local_addr.v4)); >-- sup.remote_addr.af = AF_INET; >-- memcpy(&sup.remote_addr.v4, >-- &((struct sockaddr_in *)&p->sa_remote)->sin_addr, >-- sizeof(sup.remote_addr.v4)); >-- break; >-- case AF_INET6: >-- sup.local_addr.af = AF_INET6; >-- memcpy(&sup.local_addr.v6, >-- &((struct sockaddr_in6 *)&p->sa_local)->sin6_addr, >-- sizeof(sup.local_addr.v6)); >-- sup.remote_addr.af = AF_INET6; >-- memcpy(&sup.remote_addr.v6, >-- &((struct sockaddr_in6 *)&p->sa_remote)->sin6_addr, >-- sizeof(sup.remote_addr.v6)); >-- break; >-- default: >-- fatalx("session_up: unsupported address family"); >-- } >-+ sa2addr((struct sockaddr *)&p->sa_local, &sup.local_addr); >-+ sa2addr((struct sockaddr *)&p->sa_remote, &sup.remote_addr); >- >- sup.remote_bgpid = p->remote_bgpid; >- sup.short_as = p->short_as; >-- memcpy(&sup.capa_announced, &p->capa.ann, sizeof(sup.capa_announced)); >-- memcpy(&sup.capa_received, &p->capa.peer, sizeof(sup.capa_received)); >-+ memcpy(&sup.capa, &p->capa.neg, sizeof(sup.capa)); >- p->stats.last_updown = time(NULL); >- if (imsg_compose(ibuf_rde, IMSG_SESSION_UP, p->conf.id, 0, -1, >- &sup, sizeof(sup)) == -1) >-@@ -2784,9 +3136,10 @@ session_up(struct peer *p) >- } >- >- int >--imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen) >-+imsg_compose_parent(int type, u_int32_t peerid, pid_t pid, void *data, >-+ u_int16_t datalen) >- { >-- return (imsg_compose(ibuf_main, type, 0, pid, -1, data, datalen)); >-+ return (imsg_compose(ibuf_main, type, peerid, pid, -1, data, datalen)); >- } >- >- int >-@@ -2795,34 +3148,6 @@ imsg_compose_rde(int type, pid_t pid, vo >- return (imsg_compose(ibuf_rde, type, 0, pid, -1, data, datalen)); >- } >- >--static struct sockaddr * >--addr2sa(struct bgpd_addr *addr, u_int16_t port) >--{ >-- static struct sockaddr_storage ss; >-- struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss; >-- struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss; >-- >-- bzero(&ss, sizeof(ss)); >-- switch (addr->af) { >-- case AF_INET: >-- sa_in->sin_family = AF_INET; >-- sa_in->sin_len = sizeof(struct sockaddr_in); >-- sa_in->sin_addr.s_addr = addr->v4.s_addr; >-- sa_in->sin_port = htons(port); >-- break; >-- case AF_INET6: >-- sa_in6->sin6_family = AF_INET6; >-- sa_in6->sin6_len = sizeof(struct sockaddr_in6); >-- memcpy(&sa_in6->sin6_addr, &addr->v6, >-- sizeof(sa_in6->sin6_addr)); >-- sa_in6->sin6_port = htons(port); >-- sa_in6->sin6_scope_id = addr->scope_id; >-- break; >-- } >-- >-- return ((struct sockaddr *)&ss); >--} >-- >- void >- session_demote(struct peer *p, int level) >- { >-@@ -2837,3 +3162,19 @@ session_demote(struct peer *p, int level >- >- p->demoted += level; >- } >-+ >-+void >-+session_stop(struct peer *peer, u_int8_t subcode) >-+{ >-+ switch (peer->state) { >-+ case STATE_OPENSENT: >-+ case STATE_OPENCONFIRM: >-+ case STATE_ESTABLISHED: >-+ session_notification(peer, ERR_CEASE, subcode, NULL, 0); >-+ break; >-+ default: >-+ /* session not open, no need to send notification */ >-+ break; >-+ } >-+ bgp_fsm(peer, EVNT_STOP); >-+} > >Property changes on: files/patch-bgpd_session.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_session.h >=================================================================== >--- files/patch-bgpd_session.h (revision 500577) >+++ files/patch-bgpd_session.h (nonexistent) >@@ -1,188 +0,0 @@ >-Index: bgpd/session.h >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/session.h,v >-retrieving revision 1.1.1.7 >-retrieving revision 1.1.1.10 >-diff -u -p -r1.1.1.7 -r1.1.1.10 >---- bgpd/session.h 14 Feb 2010 20:19:57 -0000 1.1.1.7 >-+++ bgpd/session.h 13 Oct 2012 18:22:50 -0000 1.1.1.10 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: session.h,v 1.101 2009/06/05 20:26:38 claudio Exp $ */ >-+/* $OpenBSD: session.h,v 1.113 2012/04/12 17:26:09 claudio Exp $ */ >- >- /* >- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-@@ -94,6 +94,13 @@ enum suberr_open { >- ERR_OPEN_CAPA >- }; >- >-+enum suberr_fsm { >-+ ERR_FSM_UNSPECIFIC = 0, >-+ ERR_FSM_UNEX_OPENSENT, >-+ ERR_FSM_UNEX_OPENCONFIRM, >-+ ERR_FSM_UNEX_ESTABLISHED >-+}; >-+ >- enum opt_params { >- OPT_PARAM_NONE, >- OPT_PARAM_AUTH, >-@@ -109,7 +116,7 @@ enum capa_codes { >- }; >- >- struct bgp_msg { >-- struct buf *buf; >-+ struct ibuf *buf; >- enum msg_type type; >- u_int16_t len; >- }; >-@@ -155,8 +162,10 @@ struct peer_stats { >- u_int64_t msg_sent_rrefresh; >- u_int64_t prefix_rcvd_update; >- u_int64_t prefix_rcvd_withdraw; >-+ u_int64_t prefix_rcvd_eor; >- u_int64_t prefix_sent_update; >- u_int64_t prefix_sent_withdraw; >-+ u_int64_t prefix_sent_eor; >- time_t last_updown; >- time_t last_read; >- u_int32_t prefix_cnt; >-@@ -172,6 +181,7 @@ enum Timer { >- Timer_IdleHold, >- Timer_IdleHoldReset, >- Timer_CarpUndemote, >-+ Timer_RestartTimeout, >- Timer_Max >- }; >- >-@@ -189,6 +199,7 @@ struct peer { >- struct { >- struct capabilities ann; >- struct capabilities peer; >-+ struct capabilities neg; >- } capa; >- struct { >- struct bgpd_addr local_addr; >-@@ -201,7 +212,7 @@ struct peer { >- struct sockaddr_storage sa_remote; >- struct peer_timer_head timers; >- struct msgbuf wbuf; >-- struct buf_read *rbuf; >-+ struct ibuf_read *rbuf; >- struct peer *next; >- int fd; >- int lasterr; >-@@ -217,47 +228,25 @@ struct peer { >- u_int8_t passive; >- }; >- >--struct peer *peers; >-+extern struct peer *peers; >-+extern time_t pauseaccept; >- >- struct ctl_timer { >- enum Timer type; >- time_t val; >- }; >- >--/* session.c */ >--void session_socket_blockmode(int, enum blockmodes); >--pid_t session_main(struct bgpd_config *, struct peer *, >-- struct network_head *, struct filter_head *, >-- struct mrt_head *, struct rib_names *, >-- int[2], int[2], int[2], int[2]); >--void bgp_fsm(struct peer *, enum session_events); >--int session_neighbor_rrefresh(struct peer *p); >--struct peer *getpeerbyaddr(struct bgpd_addr *); >--struct peer *getpeerbydesc(const char *); >--int imsg_compose_parent(int, pid_t, void *, u_int16_t); >--int imsg_compose_rde(int, pid_t, void *, u_int16_t); >-- >--/* log.c */ >--char *log_fmt_peer(const struct peer_config *); >--void log_statechange(struct peer *, enum session_state, >-- enum session_events); >--void log_notification(const struct peer *, u_int8_t, u_int8_t, >-- u_char *, u_int16_t); >--void log_conn_attempt(const struct peer *, struct sockaddr *); >-- >--/* parse.y */ >--int parse_config(char *, struct bgpd_config *, struct mrt_head *, >-- struct peer **, struct network_head *, struct filter_head *); >-+/* carp.c */ >-+int carp_demote_init(char *, int); >-+void carp_demote_shutdown(void); >-+int carp_demote_get(char *); >-+int carp_demote_set(char *, int); >- >- /* config.c */ >- int merge_config(struct bgpd_config *, struct bgpd_config *, >- struct peer *, struct listen_addrs *); >- void prepare_listeners(struct bgpd_config *); >-- >--/* rde.c */ >--pid_t rde_main(struct bgpd_config *, struct peer *, struct network_head *, >-- struct filter_head *, struct mrt_head *, struct rib_names *, >-- int[2], int[2], int[2], int[2], int); >-+int get_mpe_label(struct rdomain *); >- >- /* control.c */ >- int control_init(int, char *); >-@@ -266,7 +255,27 @@ void control_shutdown(int); >- int control_dispatch_msg(struct pollfd *, u_int *); >- unsigned int control_accept(int, int); >- >-+/* log.c */ >-+char *log_fmt_peer(const struct peer_config *); >-+void log_statechange(struct peer *, enum session_state, >-+ enum session_events); >-+void log_notification(const struct peer *, u_int8_t, u_int8_t, >-+ u_char *, u_int16_t, const char *); >-+void log_conn_attempt(const struct peer *, struct sockaddr *); >-+ >-+/* mrt.c */ >-+void mrt_dump_bgp_msg(struct mrt *, void *, u_int16_t, >-+ struct peer *); >-+void mrt_dump_state(struct mrt *, u_int16_t, u_int16_t, >-+ struct peer *); >-+ >-+/* parse.y */ >-+int parse_config(char *, struct bgpd_config *, struct mrt_head *, >-+ struct peer **, struct network_head *, struct filter_head *, >-+ struct rdomain_head *); >-+ >- /* pfkey.c */ >-+int pfkey_read(int, struct sadb_msg *); >- int pfkey_establish(struct peer *); >- int pfkey_remove(struct peer *); >- int pfkey_init(struct bgpd_sysdep *); >-@@ -274,15 +283,24 @@ int pfkey_init(struct bgpd_sysdep *); >- /* printconf.c */ >- void print_config(struct bgpd_config *, struct rib_names *, >- struct network_head *, struct peer *, struct filter_head *, >-- struct mrt_head *); >-+ struct mrt_head *, struct rdomain_head *); >- >--/* carp.c */ >--int carp_demote_init(char *, int); >--void carp_demote_shutdown(void); >--int carp_demote_get(char *); >--int carp_demote_set(char *, int); >-+/* rde.c */ >-+pid_t rde_main(int[2], int[2], int[2], int[2], int); >-+ >-+/* session.c */ >-+void session_socket_blockmode(int, enum blockmodes); >-+pid_t session_main(int[2], int[2], int[2], int[2]); >-+void bgp_fsm(struct peer *, enum session_events); >-+int session_neighbor_rrefresh(struct peer *p); >-+struct peer *getpeerbyaddr(struct bgpd_addr *); >-+struct peer *getpeerbydesc(const char *); >-+int imsg_compose_parent(int, u_int32_t, pid_t, void *, u_int16_t); >-+int imsg_compose_rde(int, pid_t, void *, u_int16_t); >-+void session_stop(struct peer *, u_int8_t); >- >- /* timer.c */ >-+time_t getmonotime(void); >- struct peer_timer *timer_get(struct peer *, enum Timer); >- struct peer_timer *timer_nextisdue(struct peer *); >- time_t timer_nextduein(struct peer *); > >Property changes on: files/patch-bgpd_session.h >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_timer.c >=================================================================== >--- files/patch-bgpd_timer.c (revision 500577) >+++ files/patch-bgpd_timer.c (nonexistent) >@@ -1,32 +0,0 @@ >-Index: bgpd/timer.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/timer.c,v >-retrieving revision 1.1.1.2 >-retrieving revision 1.1.1.4 >-diff -u -p -r1.1.1.2 -r1.1.1.4 >---- bgpd/timer.c 9 Jul 2009 16:49:54 -0000 1.1.1.2 >-+++ bgpd/timer.c 13 Oct 2012 18:22:50 -0000 1.1.1.4 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: timer.c,v 1.13 2009/01/21 20:32:53 henning Exp $ */ >-+/* $OpenBSD: timer.c,v 1.14 2010/10/24 17:20:08 deraadt Exp $ */ >- >- /* >- * Copyright (c) 2003-2007 Henning Brauer <henning@openbsd.org> >-@@ -23,8 +23,6 @@ >- #include "bgpd.h" >- #include "session.h" >- >--time_t getmonotime(void); >-- >- time_t >- getmonotime(void) >- { >-@@ -43,7 +41,7 @@ timer_get(struct peer *p, enum Timer tim >- >- TAILQ_FOREACH(pt, &p->timers, entry) >- if (pt->type == timer) >-- break; >-+ break; >- >- return (pt); >- } > >Property changes on: files/patch-bgpd_timer.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-bgpd_util.c >=================================================================== >--- files/patch-bgpd_util.c (revision 500577) >+++ files/patch-bgpd_util.c (nonexistent) >@@ -1,440 +0,0 @@ >-Index: bgpd/util.c >-=================================================================== >-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/util.c,v >-retrieving revision 1.1.1.6 >-retrieving revision 1.7 >-diff -u -p -r1.1.1.6 -r1.7 >---- bgpd/util.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 >-+++ bgpd/util.c 13 Oct 2012 18:36:00 -0000 1.7 >-@@ -1,4 +1,4 @@ >--/* $OpenBSD: util.c,v 1.6 2009/06/12 16:42:53 claudio Exp $ */ >-+/* $OpenBSD: util.c,v 1.11 2010/03/29 09:04:43 claudio Exp $ */ >- >- /* >- * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org> >-@@ -18,6 +18,9 @@ >- */ >- #include <sys/types.h> >- #include <sys/socket.h> >-+#if defined(__FreeBSD__) /* sys/limits.h */ >-+#include <sys/limits.h> >-+#endif /* defined(__FreeBSD__) */ >- #include <netinet/in.h> >- #include <arpa/inet.h> >- #include <netdb.h> >-@@ -28,15 +31,30 @@ >- #include "bgpd.h" >- #include "rde.h" >- >-+const char *aspath_delim(u_int8_t, int); >-+ >- const char * >- log_addr(const struct bgpd_addr *addr) >- { >- static char buf[48]; >-+ char tbuf[16]; >- >-- if (inet_ntop(addr->af, &addr->ba, buf, sizeof(buf)) == NULL) >-- return ("?"); >-- else >-+ switch (addr->aid) { >-+ case AID_INET: >-+ case AID_INET6: >-+ if (inet_ntop(aid2af(addr->aid), &addr->ba, buf, >-+ sizeof(buf)) == NULL) >-+ return ("?"); >- return (buf); >-+ case AID_VPN_IPv4: >-+ if (inet_ntop(AF_INET, &addr->vpn4.addr, tbuf, >-+ sizeof(tbuf)) == NULL) >-+ return ("?"); >-+ snprintf(buf, sizeof(buf), "%s %s", log_rd(addr->vpn4.rd), >-+ tbuf); >-+ return (buf); >-+ } >-+ return ("???"); >- } >- >- const char * >-@@ -90,6 +108,96 @@ log_as(u_int32_t as) >- return (buf); >- } >- >-+const char * >-+log_rd(u_int64_t rd) >-+{ >-+ static char buf[32]; >-+ struct in_addr addr; >-+ u_int32_t u32; >-+ u_int16_t u16; >-+ >-+ rd = betoh64(rd); >-+ switch (rd >> 48) { >-+ case EXT_COMMUNITY_TWO_AS: >-+ u32 = rd & 0xffffffff; >-+ u16 = (rd >> 32) & 0xffff; >-+ snprintf(buf, sizeof(buf), "rd %i:%i", u16, u32); >-+ break; >-+ case EXT_COMMUNITY_FOUR_AS: >-+ u32 = (rd >> 16) & 0xffffffff; >-+ u16 = rd & 0xffff; >-+ snprintf(buf, sizeof(buf), "rd %s:%i", log_as(u32), u16); >-+ break; >-+ case EXT_COMMUNITY_IPV4: >-+ u32 = (rd >> 16) & 0xffffffff; >-+ u16 = rd & 0xffff; >-+ addr.s_addr = htonl(u32); >-+ snprintf(buf, sizeof(buf), "rd %s:%i", inet_ntoa(addr), u16); >-+ break; >-+ default: >-+ return ("rd ?"); >-+ } >-+ return (buf); >-+} >-+ >-+/* NOTE: this function does not check if the type/subtype combo is >-+ * actually valid. */ >-+const char * >-+log_ext_subtype(u_int8_t subtype) >-+{ >-+ static char etype[6]; >-+ >-+ switch (subtype) { >-+ case EXT_COMMUNITY_ROUTE_TGT: >-+ return ("rt"); /* route target */ >-+ case EXT_CUMMUNITY_ROUTE_ORIG: >-+ return ("soo"); /* source of origin */ >-+ case EXT_COMMUNITY_OSPF_DOM_ID: >-+ return ("odi"); /* ospf domain id */ >-+ case EXT_COMMUNITY_OSPF_RTR_TYPE: >-+ return ("ort"); /* ospf route type */ >-+ case EXT_COMMUNITY_OSPF_RTR_ID: >-+ return ("ori"); /* ospf router id */ >-+ case EXT_COMMUNITY_BGP_COLLECT: >-+ return ("bdc"); /* bgp data collection */ >-+ default: >-+ snprintf(etype, sizeof(etype), "[%u]", subtype); >-+ return (etype); >-+ } >-+} >-+ >-+const char * >-+aspath_delim(u_int8_t seg_type, int closing) >-+{ >-+ static char db[8]; >-+ >-+ switch (seg_type) { >-+ case AS_SET: >-+ if (!closing) >-+ return ("{ "); >-+ else >-+ return (" }"); >-+ case AS_SEQUENCE: >-+ return (""); >-+ case AS_CONFED_SEQUENCE: >-+ if (!closing) >-+ return ("( "); >-+ else >-+ return (" )"); >-+ case AS_CONFED_SET: >-+ if (!closing) >-+ return ("[ "); >-+ else >-+ return (" ]"); >-+ default: >-+ if (!closing) >-+ snprintf(db, sizeof(db), "!%u ", seg_type); >-+ else >-+ snprintf(db, sizeof(db), " !%u", seg_type); >-+ return (db); >-+ } >-+} >-+ >- int >- aspath_snprint(char *buf, size_t size, void *data, u_int16_t len) >- { >-@@ -118,16 +226,10 @@ aspath_snprint(char *buf, size_t size, v >- seg_len = seg[1]; >- seg_size = 2 + sizeof(u_int32_t) * seg_len; >- >-- if (seg_type == AS_SET) { >-- if (total_size != 0) >-- r = snprintf(buf, size, " { "); >-- else >-- r = snprintf(buf, size, "{ "); >-- UPDATE(); >-- } else if (total_size != 0) { >-- r = snprintf(buf, size, " "); >-- UPDATE(); >-- } >-+ r = snprintf(buf, size, "%s%s", >-+ total_size != 0 ? " " : "", >-+ aspath_delim(seg_type, 0)); >-+ UPDATE(); >- >- for (i = 0; i < seg_len; i++) { >- r = snprintf(buf, size, "%s", >-@@ -138,10 +240,8 @@ aspath_snprint(char *buf, size_t size, v >- UPDATE(); >- } >- } >-- if (seg_type == AS_SET) { >-- r = snprintf(buf, size, " }"); >-- UPDATE(); >-- } >-+ r = snprintf(buf, size, "%s", aspath_delim(seg_type, 1)); >-+ UPDATE(); >- } >- /* ensure that we have a valid C-string especially for empty as path */ >- if (size > 0) >-@@ -235,6 +335,67 @@ aspath_strlen(void *data, u_int16_t len) >- return (total_size); >- } >- >-+/* we need to be able to search more than one as */ >-+int >-+aspath_match(void *data, u_int16_t len, enum as_spec type, u_int32_t as) >-+{ >-+ u_int8_t *seg; >-+ int final; >-+ u_int16_t seg_size; >-+ u_int8_t i, seg_type, seg_len; >-+ >-+ if (type == AS_EMPTY) { >-+ if (len == 0) >-+ return (1); >-+ else >-+ return (0); >-+ } >-+ >-+ final = 0; >-+ seg = data; >-+ for (; len > 0; len -= seg_size, seg += seg_size) { >-+ seg_type = seg[0]; >-+ seg_len = seg[1]; >-+ seg_size = 2 + sizeof(u_int32_t) * seg_len; >-+ >-+ final = (len == seg_size); >-+ >-+ /* just check the first (leftmost) AS */ >-+ if (type == AS_PEER) { >-+ if (as == aspath_extract(seg, 0)) >-+ return (1); >-+ else >-+ return (0); >-+ } >-+ /* just check the final (rightmost) AS */ >-+ if (type == AS_SOURCE) { >-+ /* not yet in the final segment */ >-+ if (!final) >-+ continue; >-+ >-+ if (as == aspath_extract(seg, seg_len - 1)) >-+ return (1); >-+ else >-+ return (0); >-+ } >-+ >-+ /* AS_TRANSIT or AS_ALL */ >-+ for (i = 0; i < seg_len; i++) { >-+ if (as == aspath_extract(seg, i)) { >-+ /* >-+ * the source (rightmost) AS is excluded from >-+ * AS_TRANSIT matches. >-+ */ >-+ if (final && i == seg_len - 1 && >-+ type == AS_TRANSIT) >-+ return (0); >-+ return (1); >-+ } >-+ } >-+ } >-+ return (0); >-+} >-+ >- /* >- * Extract the asnum out of the as segment at the specified position. >- * Direct access is not possible because of non-aligned reads. >-@@ -251,6 +412,66 @@ aspath_extract(const void *seg, int pos) >- return (ntohl(as)); >- } >- >-+int >-+prefix_compare(const struct bgpd_addr *a, const struct bgpd_addr *b, >-+ int prefixlen) >-+{ >-+ in_addr_t mask, aa, ba; >-+ int i; >-+ u_int8_t m; >-+ >-+ if (a->aid != b->aid) >-+ return (a->aid - b->aid); >-+ >-+ switch (a->aid) { >-+ case AID_INET: >-+ if (prefixlen > 32) >-+ fatalx("prefix_cmp: bad IPv4 prefixlen"); >-+ mask = htonl(prefixlen2mask(prefixlen)); >-+ aa = ntohl(a->v4.s_addr & mask); >-+ ba = ntohl(b->v4.s_addr & mask); >-+ if (aa != ba) >-+ return (aa - ba); >-+ return (0); >-+ case AID_INET6: >-+ if (prefixlen > 128) >-+ fatalx("prefix_cmp: bad IPv6 prefixlen"); >-+ for (i = 0; i < prefixlen / 8; i++) >-+ if (a->v6.s6_addr[i] != b->v6.s6_addr[i]) >-+ return (a->v6.s6_addr[i] - b->v6.s6_addr[i]); >-+ i = prefixlen % 8; >-+ if (i) { >-+ m = 0xff00 >> i; >-+ if ((a->v6.s6_addr[prefixlen / 8] & m) != >-+ (b->v6.s6_addr[prefixlen / 8] & m)) >-+ return ((a->v6.s6_addr[prefixlen / 8] & m) - >-+ (b->v6.s6_addr[prefixlen / 8] & m)); >-+ } >-+ return (0); >-+ case AID_VPN_IPv4: >-+ if (prefixlen > 32) >-+ fatalx("prefix_cmp: bad IPv4 VPN prefixlen"); >-+ if (betoh64(a->vpn4.rd) > betoh64(b->vpn4.rd)) >-+ return (1); >-+ if (betoh64(a->vpn4.rd) < betoh64(b->vpn4.rd)) >-+ return (-1); >-+ mask = htonl(prefixlen2mask(prefixlen)); >-+ aa = ntohl(a->vpn4.addr.s_addr & mask); >-+ ba = ntohl(b->vpn4.addr.s_addr & mask); >-+ if (aa != ba) >-+ return (aa - ba); >-+ if (a->vpn4.labellen > b->vpn4.labellen) >-+ return (1); >-+ if (a->vpn4.labellen < b->vpn4.labellen) >-+ return (-1); >-+ return (memcmp(a->vpn4.labelstack, b->vpn4.labelstack, >-+ a->vpn4.labellen)); >-+ default: >-+ fatalx("prefix_cmp: unknown af"); >-+ } >-+ return (-1); >-+} >-+ >- in_addr_t >- prefixlen2mask(u_int8_t prefixlen) >- { >-@@ -276,3 +497,115 @@ inet6applymask(struct in6_addr *dest, co >- for (i = 0; i < 16; i++) >- dest->s6_addr[i] = src->s6_addr[i] & mask.s6_addr[i]; >- } >-+ >-+/* address family translation functions */ >-+const struct aid aid_vals[AID_MAX] = AID_VALS; >-+ >-+const char * >-+aid2str(u_int8_t aid) >-+{ >-+ if (aid < AID_MAX) >-+ return (aid_vals[aid].name); >-+ return ("unknown AID"); >-+} >-+ >-+int >-+aid2afi(u_int8_t aid, u_int16_t *afi, u_int8_t *safi) >-+{ >-+ if (aid < AID_MAX) { >-+ *afi = aid_vals[aid].afi; >-+ *safi = aid_vals[aid].safi; >-+ return (0); >-+ } >-+ return (-1); >-+} >-+ >-+int >-+afi2aid(u_int16_t afi, u_int8_t safi, u_int8_t *aid) >-+{ >-+ u_int8_t i; >-+ >-+ for (i = 0; i < AID_MAX; i++) >-+ if (aid_vals[i].afi == afi && aid_vals[i].safi == safi) { >-+ *aid = i; >-+ return (0); >-+ } >-+ >-+ return (-1); >-+} >-+ >-+sa_family_t >-+aid2af(u_int8_t aid) >-+{ >-+ if (aid < AID_MAX) >-+ return (aid_vals[aid].af); >-+ return (AF_UNSPEC); >-+} >-+ >-+int >-+af2aid(sa_family_t af, u_int8_t safi, u_int8_t *aid) >-+{ >-+ u_int8_t i; >-+ >-+ if (safi == 0) /* default to unicast subclass */ >-+ safi = SAFI_UNICAST; >-+ >-+ for (i = 0; i < AID_MAX; i++) >-+ if (aid_vals[i].af == af && aid_vals[i].safi == safi) { >-+ *aid = i; >-+ return (0); >-+ } >-+ >-+ return (-1); >-+} >-+ >-+struct sockaddr * >-+addr2sa(struct bgpd_addr *addr, u_int16_t port) >-+{ >-+ static struct sockaddr_storage ss; >-+ struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss; >-+ struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss; >-+ >-+ if (addr->aid == AID_UNSPEC) >-+ return (NULL); >-+ >-+ bzero(&ss, sizeof(ss)); >-+ switch (addr->aid) { >-+ case AID_INET: >-+ sa_in->sin_family = AF_INET; >-+ sa_in->sin_len = sizeof(struct sockaddr_in); >-+ sa_in->sin_addr.s_addr = addr->v4.s_addr; >-+ sa_in->sin_port = htons(port); >-+ break; >-+ case AID_INET6: >-+ sa_in6->sin6_family = AF_INET6; >-+ sa_in6->sin6_len = sizeof(struct sockaddr_in6); >-+ memcpy(&sa_in6->sin6_addr, &addr->v6, >-+ sizeof(sa_in6->sin6_addr)); >-+ sa_in6->sin6_port = htons(port); >-+ sa_in6->sin6_scope_id = addr->scope_id; >-+ break; >-+ } >-+ >-+ return ((struct sockaddr *)&ss); >-+} >-+ >-+void >-+sa2addr(struct sockaddr *sa, struct bgpd_addr *addr) >-+{ >-+ struct sockaddr_in *sa_in = (struct sockaddr_in *)sa; >-+ struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa; >-+ >-+ bzero(addr, sizeof(*addr)); >-+ switch (sa->sa_family) { >-+ case AF_INET: >-+ addr->aid = AID_INET; >-+ memcpy(&addr->v4, &sa_in->sin_addr, sizeof(addr->v4)); >-+ break; >-+ case AF_INET6: >-+ addr->aid = AID_INET6; >-+ memcpy(&addr->v6, &sa_in6->sin6_addr, sizeof(addr->v6)); >-+ addr->scope_id = sa_in6->sin6_scope_id; /* I hate v6 */ >-+ break; >-+ } >-+} > >Property changes on: files/patch-bgpd_util.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-openbsd-compat_fmt_scaled.c >=================================================================== >--- files/patch-openbsd-compat_fmt_scaled.c (revision 500577) >+++ files/patch-openbsd-compat_fmt_scaled.c (nonexistent) >@@ -1,275 +0,0 @@ >-Index: openbsd-compat/fmt_scaled.c >-=================================================================== >-RCS file: openbsd-compat/fmt_scaled.c >-diff -N openbsd-compat/fmt_scaled.c >---- /dev/null 1 Jan 1970 00:00:00 -0000 >-+++ openbsd-compat/fmt_scaled.c 30 Jun 2009 06:40:07 -0000 1.1 >-@@ -0,0 +1,268 @@ >-+/* $OpenBSD: fmt_scaled.c,v 1.9 2007/03/20 03:42:52 tedu Exp $ */ >-+ >-+/* >-+ * Copyright (c) 2001, 2002, 2003 Ian F. Darwin. All rights reserved. >-+ * >-+ * Redistribution and use in source and binary forms, with or without >-+ * modification, are permitted provided that the following conditions >-+ * are met: >-+ * 1. Redistributions of source code must retain the above copyright >-+ * notice, this list of conditions and the following disclaimer. >-+ * 2. Redistributions in binary form must reproduce the above copyright >-+ * notice, this list of conditions and the following disclaimer in the >-+ * documentation and/or other materials provided with the distribution. >-+ * 3. The name of the author may not be used to endorse or promote products >-+ * derived from this software without specific prior written permission. >-+ * >-+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR >-+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES >-+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. >-+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, >-+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT >-+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, >-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY >-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF >-+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >-+ */ >-+ >-+/* >-+ * fmt_scaled: Format numbers scaled for human comprehension >-+ * scan_scaled: Scan numbers in this format. >-+ * >-+ * "Human-readable" output uses 4 digits max, and puts a unit suffix at >-+ * the end. Makes output compact and easy-to-read esp. on huge disks. >-+ * Formatting code was originally in OpenBSD "df", converted to library routine. >-+ * Scanning code written for OpenBSD libutil. >-+ */ >-+ >-+#include <stdio.h> >-+#include <stdlib.h> >-+#include <errno.h> >-+#include <string.h> >-+#include <ctype.h> >-+#include <limits.h> >-+ >-+#include "util.h" >-+ >-+typedef enum { >-+ NONE = 0, KILO = 1, MEGA = 2, GIGA = 3, TERA = 4, PETA = 5, EXA = 6 >-+} unit_type; >-+ >-+/* These three arrays MUST be in sync! XXX make a struct */ >-+static unit_type units[] = { NONE, KILO, MEGA, GIGA, TERA, PETA, EXA }; >-+static char scale_chars[] = "BKMGTPE"; >-+static long long scale_factors[] = { >-+ 1LL, >-+ 1024LL, >-+ 1024LL*1024, >-+ 1024LL*1024*1024, >-+ 1024LL*1024*1024*1024, >-+ 1024LL*1024*1024*1024*1024, >-+ 1024LL*1024*1024*1024*1024*1024, >-+}; >-+#define SCALE_LENGTH (sizeof(units)/sizeof(units[0])) >-+ >-+#define MAX_DIGITS (SCALE_LENGTH * 3) /* XXX strlen(sprintf("%lld", -1)? */ >-+ >-+/** Convert the given input string "scaled" into numeric in "result". >-+ * Return 0 on success, -1 and errno set on error. >-+ */ >-+int >-+scan_scaled(char *scaled, long long *result) >-+{ >-+ char *p = scaled; >-+ int sign = 0; >-+ unsigned int i, ndigits = 0, fract_digits = 0; >-+ long long scale_fact = 1, whole = 0, fpart = 0; >-+ >-+ /* Skip leading whitespace */ >-+ while (isascii(*p) && isspace(*p)) >-+ ++p; >-+ >-+ /* Then at most one leading + or - */ >-+ while (*p == '-' || *p == '+') { >-+ if (*p == '-') { >-+ if (sign) { >-+ errno = EINVAL; >-+ return -1; >-+ } >-+ sign = -1; >-+ ++p; >-+ } else if (*p == '+') { >-+ if (sign) { >-+ errno = EINVAL; >-+ return -1; >-+ } >-+ sign = +1; >-+ ++p; >-+ } >-+ } >-+ >-+ /* Main loop: Scan digits, find decimal point, if present. >-+ * We don't allow exponentials, so no scientific notation >-+ * (but note that E for Exa might look like e to some!). >-+ * Advance 'p' to end, to get scale factor. >-+ */ >-+ for (; isascii(*p) && (isdigit(*p) || *p=='.'); ++p) { >-+ if (*p == '.') { >-+ if (fract_digits > 0) { /* oops, more than one '.' */ >-+ errno = EINVAL; >-+ return -1; >-+ } >-+ fract_digits = 1; >-+ continue; >-+ } >-+ >-+ i = (*p) - '0'; /* whew! finally a digit we can use */ >-+ if (fract_digits > 0) { >-+ if (fract_digits >= MAX_DIGITS-1) >-+ /* ignore extra fractional digits */ >-+ continue; >-+ fract_digits++; /* for later scaling */ >-+ fpart *= 10; >-+ fpart += i; >-+ } else { /* normal digit */ >-+ if (++ndigits >= MAX_DIGITS) { >-+ errno = ERANGE; >-+ return -1; >-+ } >-+ whole *= 10; >-+ whole += i; >-+ } >-+ } >-+ >-+ if (sign) { >-+ whole *= sign; >-+ fpart *= sign; >-+ } >-+ >-+ /* If no scale factor given, we're done. fraction is discarded. */ >-+ if (!*p) { >-+ *result = whole; >-+ return 0; >-+ } >-+ >-+ /* Validate scale factor, and scale whole and fraction by it. */ >-+ for (i = 0; i < SCALE_LENGTH; i++) { >-+ >-+ /** Are we there yet? */ >-+ if (*p == scale_chars[i] || >-+ *p == tolower(scale_chars[i])) { >-+ >-+ /* If it ends with alphanumerics after the scale char, bad. */ >-+ if (isalnum(*(p+1))) { >-+ errno = EINVAL; >-+ return -1; >-+ } >-+ scale_fact = scale_factors[i]; >-+ >-+ /* scale whole part */ >-+ whole *= scale_fact; >-+ >-+ /* truncate fpart so it does't overflow. >-+ * then scale fractional part. >-+ */ >-+ while (fpart >= LLONG_MAX / scale_fact) { >-+ fpart /= 10; >-+ fract_digits--; >-+ } >-+ fpart *= scale_fact; >-+ if (fract_digits > 0) { >-+ for (i = 0; i < fract_digits -1; i++) >-+ fpart /= 10; >-+ } >-+ whole += fpart; >-+ *result = whole; >-+ return 0; >-+ } >-+ } >-+ errno = ERANGE; >-+ return -1; >-+} >-+ >-+/* Format the given "number" into human-readable form in "result". >-+ * Result must point to an allocated buffer of length FMT_SCALED_STRSIZE. >-+ * Return 0 on success, -1 and errno set if error. >-+ */ >-+int >-+fmt_scaled(long long number, char *result) >-+{ >-+ long long abval, fract = 0; >-+ unsigned int i; >-+ unit_type unit = NONE; >-+ >-+ abval = (number < 0LL) ? -number : number; /* no long long_abs yet */ >-+ >-+ /* Not every negative long long has a positive representation. >-+ * Also check for numbers that are just too darned big to format >-+ */ >-+ if (abval < 0 || abval / 1024 >= scale_factors[SCALE_LENGTH-1]) { >-+ errno = ERANGE; >-+ return -1; >-+ } >-+ >-+ /* scale whole part; get unscaled fraction */ >-+ for (i = 0; i < SCALE_LENGTH; i++) { >-+ if (abval/1024 < scale_factors[i]) { >-+ unit = units[i]; >-+ fract = (i == 0) ? 0 : abval % scale_factors[i]; >-+ number /= scale_factors[i]; >-+ if (i > 0) >-+ fract /= scale_factors[i - 1]; >-+ break; >-+ } >-+ } >-+ >-+ fract = (10 * fract + 512) / 1024; >-+ /* if the result would be >= 10, round main number */ >-+ if (fract == 10) { >-+ if (number >= 0) >-+ number++; >-+ else >-+ number--; >-+ fract = 0; >-+ } >-+ >-+ if (number == 0) >-+ strlcpy(result, "0B", FMT_SCALED_STRSIZE); >-+ else if (unit == NONE || number >= 100 || number <= -100) { >-+ if (fract >= 5) { >-+ if (number >= 0) >-+ number++; >-+ else >-+ number--; >-+ } >-+ (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld%c", >-+ number, scale_chars[unit]); >-+ } else >-+ (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld.%1lld%c", >-+ number, fract, scale_chars[unit]); >-+ >-+ return 0; >-+} >-+ >-+#ifdef MAIN >-+/* >-+ * This is the original version of the program in the man page. >-+ * Copy-and-paste whatever you need from it. >-+ */ >-+int >-+main(int argc, char **argv) >-+{ >-+ char *cinput = "1.5K", buf[FMT_SCALED_STRSIZE]; >-+ long long ninput = 10483892, result; >-+ >-+ if (scan_scaled(cinput, &result) == 0) >-+ printf("\"%s\" -> %lld\n", cinput, result); >-+ else >-+ perror(cinput); >-+ >-+ if (fmt_scaled(ninput, buf) == 0) >-+ printf("%lld -> \"%s\"\n", ninput, buf); >-+ else >-+ fprintf(stderr, "%lld invalid (%s)\n", ninput, strerror(errno)); >-+ >-+ return 0; >-+} >-+#endif > >Property changes on: files/patch-openbsd-compat_fmt_scaled.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-openbsd-compat_hash.h >=================================================================== >--- files/patch-openbsd-compat_hash.h (revision 500577) >+++ files/patch-openbsd-compat_hash.h (nonexistent) >@@ -1,134 +0,0 @@ >-Index: openbsd-compat/hash.h >-=================================================================== >-RCS file: openbsd-compat/hash.h >-diff -N openbsd-compat/hash.h >---- /dev/null 1 Jan 1970 00:00:00 -0000 >-+++ openbsd-compat/hash.h 30 Jun 2009 05:48:11 -0000 1.1 >-@@ -0,0 +1,127 @@ >-+/* $OpenBSD: hash.h,v 1.4 2004/05/25 18:37:23 jmc Exp $ */ >-+ >-+/* >-+ * Copyright (c) 2001 Tobias Weingartner >-+ * All rights reserved. >-+ * >-+ * Redistribution and use in source and binary forms, with or without >-+ * modification, are permitted provided that the following conditions >-+ * are met: >-+ * 1. Redistributions of source code must retain the above copyright >-+ * notice, this list of conditions and the following disclaimer. >-+ * 2. Redistributions in binary form must reproduce the above copyright >-+ * notice, this list of conditions and the following disclaimer in the >-+ * documentation and/or other materials provided with the distribution. >-+ * >-+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR >-+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES >-+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. >-+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, >-+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT >-+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, >-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY >-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF >-+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >-+ */ >-+ >-+#ifndef _SYS_HASH_H_ >-+#define _SYS_HASH_H_ >-+#include <sys/types.h> >-+ >-+/* >-+ * Note: SMALL_KERNEL might be used to shrink these, right now I >-+ * do not see the point, as my kernel did not grow appreciably when >-+ * I switched to these from other inline code. This may have to be >-+ * revisited when/if these functions become more prevalent in the >-+ * kernel. >-+ */ >-+ >-+/* Convenience */ >-+#ifndef HASHINIT >-+#define HASHINIT 5381 >-+#define HASHSTEP(x,c) (((x << 5) + x) + (c)) >-+#endif >-+ >-+/* >-+ * Return a 32-bit hash of the given buffer. The init >-+ * value should be 0, or the previous hash value to extend >-+ * the previous hash. >-+ */ >-+static __inline uint32_t >-+hash32_buf(const void *buf, size_t len, uint32_t hash) >-+{ >-+ const unsigned char *p = buf; >-+ >-+ while (len--) >-+ hash = HASHSTEP(hash, *p++); >-+ >-+ return hash; >-+} >-+ >-+/* >-+ * Return a 32-bit hash of the given string. >-+ */ >-+static __inline uint32_t >-+hash32_str(const void *buf, uint32_t hash) >-+{ >-+ const unsigned char *p = buf; >-+ >-+ while (*p) >-+ hash = HASHSTEP(hash, *p++); >-+ >-+ return hash; >-+} >-+ >-+/* >-+ * Return a 32-bit hash of the given string, limited by N. >-+ */ >-+static __inline uint32_t >-+hash32_strn(const void *buf, size_t len, uint32_t hash) >-+{ >-+ const unsigned char *p = buf; >-+ >-+ while (*p && len--) >-+ hash = HASHSTEP(hash, *p++); >-+ >-+ return hash; >-+} >-+ >-+/* >-+ * Return a 32-bit hash of the given string terminated by C, >-+ * (as well as 0). This is mainly here as a helper for the >-+ * namei() hashing of path name parts. >-+ */ >-+static __inline uint32_t >-+hash32_stre(const void *buf, int end, char **ep, uint32_t hash) >-+{ >-+ const unsigned char *p = buf; >-+ >-+ while (*p && (*p != end)) >-+ hash = HASHSTEP(hash, *p++); >-+ >-+ if (ep) >-+ *ep = (char *)p; >-+ >-+ return hash; >-+} >-+ >-+/* >-+ * Return a 32-bit hash of the given string, limited by N, >-+ * and terminated by C (as well as 0). This is mainly here >-+ * as a helper for the namei() hashing of path name parts. >-+ */ >-+static __inline uint32_t >-+hash32_strne(const void *buf, size_t len, int end, char **ep, uint32_t hash) >-+{ >-+ const unsigned char *p = buf; >-+ >-+ while (*p && (*p != end) && len--) >-+ hash = HASHSTEP(hash, *p++); >-+ >-+ if (ep) >-+ *ep = (char *)p; >-+ >-+ return hash; >-+} >-+#endif /* !_SYS_HASH_H_ */ > >Property changes on: files/patch-openbsd-compat_hash.h >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-openbsd-compat_if_media.h >=================================================================== >--- files/patch-openbsd-compat_if_media.h (revision 500577) >+++ files/patch-openbsd-compat_if_media.h (nonexistent) >@@ -1,619 +0,0 @@ >-Index: openbsd-compat/if_media.h >-=================================================================== >-RCS file: openbsd-compat/if_media.h >-diff -N openbsd-compat/if_media.h >---- /dev/null 1 Jan 1970 00:00:00 -0000 >-+++ openbsd-compat/if_media.h 30 Jun 2009 05:48:11 -0000 1.1 >-@@ -0,0 +1,612 @@ >-+/* $OpenBSD: if_media.h,v 1.17 2004/11/02 02:12:16 reyk Exp $ */ >-+/* $NetBSD: if_media.h,v 1.22 2000/02/17 21:53:16 sommerfeld Exp $ */ >-+ >-+/*- >-+ * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. >-+ * All rights reserved. >-+ * >-+ * This code is derived from software contributed to The NetBSD Foundation >-+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, >-+ * NASA Ames Research Center. >-+ * >-+ * Redistribution and use in source and binary forms, with or without >-+ * modification, are permitted provided that the following conditions >-+ * are met: >-+ * 1. Redistributions of source code must retain the above copyright >-+ * notice, this list of conditions and the following disclaimer. >-+ * 2. Redistributions in binary form must reproduce the above copyright >-+ * notice, this list of conditions and the following disclaimer in the >-+ * documentation and/or other materials provided with the distribution. >-+ * 3. All advertising materials mentioning features or use of this software >-+ * must display the following acknowledgement: >-+ * This product includes software developed by the NetBSD >-+ * Foundation, Inc. and its contributors. >-+ * 4. Neither the name of The NetBSD Foundation nor the names of its >-+ * contributors may be used to endorse or promote products derived >-+ * from this software without specific prior written permission. >-+ * >-+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS >-+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED >-+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >-+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS >-+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >-+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >-+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >-+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >-+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >-+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE >-+ * POSSIBILITY OF SUCH DAMAGE. >-+ */ >-+ >-+/* >-+ * Copyright (c) 1997 >-+ * Jonathan Stone and Jason R. Thorpe. All rights reserved. >-+ * >-+ * This software is derived from information provided by Matt Thomas. >-+ * >-+ * Redistribution and use in source and binary forms, with or without >-+ * modification, are permitted provided that the following conditions >-+ * are met: >-+ * 1. Redistributions of source code must retain the above copyright >-+ * notice, this list of conditions and the following disclaimer. >-+ * 2. Redistributions in binary form must reproduce the above copyright >-+ * notice, this list of conditions and the following disclaimer in the >-+ * documentation and/or other materials provided with the distribution. >-+ * 3. All advertising materials mentioning features or use of this software >-+ * must display the following acknowledgement: >-+ * This product includes software developed by Jonathan Stone >-+ * and Jason R. Thorpe for the NetBSD Project. >-+ * 4. The names of the authors may not be used to endorse or promote products >-+ * derived from this software without specific prior written permission. >-+ * >-+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR >-+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES >-+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. >-+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, >-+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, >-+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; >-+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED >-+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, >-+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >-+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >-+ * SUCH DAMAGE. >-+ */ >-+ >-+#ifndef _NET_IF_MEDIA_H_ >-+#define _NET_IF_MEDIA_H_ >-+ >-+/* >-+ * Prototypes and definitions for BSD/OS-compatible network interface >-+ * media selection. >-+ * >-+ * Where it is safe to do so, this code strays slightly from the BSD/OS >-+ * design. Software which uses the API (device drivers, basically) >-+ * shouldn't notice any difference. >-+ * >-+ * Many thanks to Matt Thomas for providing the information necessary >-+ * to implement this interface. >-+ */ >-+ >-+#ifdef _KERNEL >-+ >-+#include <sys/queue.h> >-+ >-+/* >-+ * Driver callbacks for media status and change requests. >-+ */ >-+typedef int (*ifm_change_cb_t)(struct ifnet *ifp); >-+typedef void (*ifm_stat_cb_t)(struct ifnet *ifp, struct ifmediareq *req); >-+ >-+/* >-+ * In-kernel representation of a single supported media type. >-+ */ >-+struct ifmedia_entry { >-+ TAILQ_ENTRY(ifmedia_entry) ifm_list; >-+ int ifm_media; /* description of this media attachment */ >-+ int ifm_data; /* for driver-specific use */ >-+ void *ifm_aux; /* for driver-specific use */ >-+}; >-+ >-+/* >-+ * One of these goes into a network interface's softc structure. >-+ * It is used to keep general media state. >-+ */ >-+struct ifmedia { >-+ int ifm_mask; /* mask of changes we don't care about */ >-+ int ifm_media; /* current user-set media word */ >-+ struct ifmedia_entry *ifm_cur; /* currently selected media */ >-+ TAILQ_HEAD(, ifmedia_entry) ifm_list; /* list of all supported media */ >-+ ifm_change_cb_t ifm_change; /* media change driver callback */ >-+ ifm_stat_cb_t ifm_status; /* media status driver callback */ >-+}; >-+ >-+/* Initialize an interface's struct if_media field. */ >-+void ifmedia_init(struct ifmedia *ifm, int dontcare_mask, >-+ ifm_change_cb_t change_callback, ifm_stat_cb_t status_callback); >-+ >-+/* Add one supported medium to a struct ifmedia. */ >-+void ifmedia_add(struct ifmedia *ifm, int mword, int data, void *aux); >-+ >-+/* Add an array (of ifmedia_entry) media to a struct ifmedia. */ >-+void ifmedia_list_add(struct ifmedia *mp, struct ifmedia_entry *lp, >-+ int count); >-+ >-+/* Set default media type on initialization. */ >-+void ifmedia_set(struct ifmedia *ifm, int mword); >-+ >-+/* Common ioctl function for getting/setting media, called by driver. */ >-+int ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr, >-+ struct ifmedia *ifm, u_long cmd); >-+ >-+/* Locate a media entry */ >-+struct ifmedia_entry *ifmedia_match(struct ifmedia *ifm, >-+ int flags, int mask); >-+ >-+/* Delete all media for a given media instance */ >-+void ifmedia_delete_instance(struct ifmedia *, int); >-+ >-+/* Compute baudrate for a given media. */ >-+int ifmedia_baudrate(int); >-+#endif /*_KERNEL */ >-+ >-+/* >-+ * if_media Options word: >-+ * Bits Use >-+ * ---- ------- >-+ * 0-4 Media subtype MAX SUBTYPE == 31! >-+ * 5-7 Media type >-+ * 8-15 Type specific options >-+ * 16-19 RFU >-+ * 20-27 Shared (global) options >-+ * 28-31 Instance >-+ */ >-+ >-+/* >-+ * Ethernet >-+ */ >-+#define IFM_ETHER 0x00000020 >-+#define IFM_10_T 3 /* 10BaseT - RJ45 */ >-+#define IFM_10_2 4 /* 10Base2 - Thinnet */ >-+#define IFM_10_5 5 /* 10Base5 - AUI */ >-+#define IFM_100_TX 6 /* 100BaseTX - RJ45 */ >-+#define IFM_100_FX 7 /* 100BaseFX - Fiber */ >-+#define IFM_100_T4 8 /* 100BaseT4 - 4 pair cat 3 */ >-+#define IFM_100_VG 9 /* 100VG-AnyLAN */ >-+#define IFM_100_T2 10 /* 100BaseT2 */ >-+#define IFM_1000_SX 11 /* 1000BaseSX - multi-mode fiber */ >-+#define IFM_10_STP 12 /* 10BaseT over shielded TP */ >-+#define IFM_10_FL 13 /* 10BaseFL - Fiber */ >-+#define IFM_1000_LX 14 /* 1000baseLX - single-mode fiber */ >-+#define IFM_1000_CX 15 /* 1000baseCX - 150ohm STP */ >-+#define IFM_1000_T 16 /* 1000baseT - 4 pair cat 5 */ >-+#define IFM_1000_TX IFM_1000_T /* for backwards compatibility */ >-+#define IFM_HPNA_1 17 /* HomePNA 1.0 (1Mb/s) */ >-+ >-+#define IFM_ETH_MASTER 0x00000100 /* master mode (1000baseT) */ >-+ >-+/* >-+ * Token ring >-+ */ >-+#define IFM_TOKEN 0x00000040 >-+#define IFM_TOK_STP4 3 /* Shielded twisted pair 4m - DB9 */ >-+#define IFM_TOK_STP16 4 /* Shielded twisted pair 16m - DB9 */ >-+#define IFM_TOK_UTP4 5 /* Unshielded twisted pair 4m - RJ45 */ >-+#define IFM_TOK_UTP16 6 /* Unshielded twisted pair 16m - RJ45 */ >-+#define IFM_TOK_ETR 0x00000200 /* Early token release */ >-+#define IFM_TOK_SRCRT 0x00000400 /* Enable source routing features */ >-+#define IFM_TOK_ALLR 0x00000800 /* All routes / Single route bcast */ >-+ >-+/* >-+ * FDDI >-+ */ >-+#define IFM_FDDI 0x00000060 >-+#define IFM_FDDI_SMF 3 /* Single-mode fiber */ >-+#define IFM_FDDI_MMF 4 /* Multi-mode fiber */ >-+#define IFM_FDDI_UTP 5 /* CDDI / UTP */ >-+#define IFM_FDDI_DA 0x00000100 /* Dual attach / single attach */ >-+ >-+/* >-+ * IEEE 802.11 Wireless >-+ */ >-+#define IFM_IEEE80211 0x00000080 >-+#define IFM_IEEE80211_FH1 3 /* Frequency Hopping 1Mbps */ >-+#define IFM_IEEE80211_FH2 4 /* Frequency Hopping 2Mbps */ >-+#define IFM_IEEE80211_DS2 5 /* Direct Sequence 2Mbps */ >-+#define IFM_IEEE80211_DS5 6 /* Direct Sequence 5Mbps*/ >-+#define IFM_IEEE80211_DS11 7 /* Direct Sequence 11Mbps*/ >-+#define IFM_IEEE80211_DS1 8 /* Direct Sequence 1Mbps*/ >-+#define IFM_IEEE80211_DS22 9 /* Direct Sequence 22Mbps */ >-+#define IFM_IEEE80211_OFDM6 10 /* OFDM 6Mbps */ >-+#define IFM_IEEE80211_OFDM9 11 /* OFDM 9Mbps */ >-+#define IFM_IEEE80211_OFDM12 12 /* OFDM 12Mbps */ >-+#define IFM_IEEE80211_OFDM18 13 /* OFDM 18Mbps */ >-+#define IFM_IEEE80211_OFDM24 14 /* OFDM 24Mbps */ >-+#define IFM_IEEE80211_OFDM36 15 /* OFDM 36Mbps */ >-+#define IFM_IEEE80211_OFDM48 16 /* OFDM 48Mbps */ >-+#define IFM_IEEE80211_OFDM54 17 /* OFDM 54Mbps */ >-+#define IFM_IEEE80211_OFDM72 18 /* OFDM 72Mbps */ >-+ >-+#define IFM_IEEE80211_ADHOC 0x100 /* Operate in Adhoc mode */ >-+#define IFM_IEEE80211_HOSTAP 0x200 /* Operate in Host AP mode */ >-+#define IFM_IEEE80211_IBSS 0x400 /* Operate in IBSS mode */ >-+#define IFM_IEEE80211_IBSSMASTER 0x800 /* Operate as an IBSS master */ >-+#define IFM_IEEE80211_MONITOR 0x1000 /* Operate in Monitor mode */ >-+#define IFM_IEEE80211_TURBO 0x2000 /* Operate in Turbo mode */ >-+ >-+/* operating mode for multi-mode devices */ >-+#define IFM_IEEE80211_11A 0x00010000 /* 5Ghz, OFDM mode */ >-+#define IFM_IEEE80211_11B 0x00020000 /* Direct Sequence mode */ >-+#define IFM_IEEE80211_11G 0x00030000 /* 2Ghz, CCK mode */ >-+#define IFM_IEEE80211_FH 0x00040000 /* 2Ghz, GFSK mode */ >-+ >-+/* >-+ * Digitally multiplexed "Carrier" Serial Interfaces >-+ */ >-+#define IFM_TDM 0x000000a0 >-+#define IFM_TDM_T1 3 /* T1 B8ZS+ESF 24 ts */ >-+#define IFM_TDM_T1_AMI 4 /* T1 AMI+SF 24 ts */ >-+#define IFM_TDM_E1 5 /* E1 HDB3+G.703 clearchannel 32 ts */ >-+#define IFM_TDM_E1_G704 6 /* E1 HDB3+G.703+G.704 channelized 31 ts */ >-+#define IFM_TDM_E1_AMI 7 /* E1 AMI+G.703 32 ts */ >-+#define IFM_TDM_E1_AMI_G704 8 /* E1 AMI+G.703+G.704 31 ts */ >-+#define IFM_TDM_T3 9 /* T3 B3ZS+C-bit 672 ts */ >-+#define IFM_TDM_T3_M13 10 /* T3 B3ZS+M13 672 ts */ >-+#define IFM_TDM_E3 11 /* E3 HDB3+G.751 512? ts */ >-+#define IFM_TDM_E3_G751 12 /* E3 G.751 512 ts */ >-+#define IFM_TDM_E3_G832 13 /* E3 G.832 512 ts */ >-+/* >-+ * 6 major ways that networks talk: Drivers enforce independent selection, >-+ * meaning, a driver will ensure that only one of these is set at a time. >-+ */ >-+#define IFM_TDM_HDLC_CRC16 0x0100 /* Use 16-bit CRC for HDLC instead */ >-+#define IFM_TDM_PPP 0x0200 /* SPPP (dumb) */ >-+#define IFM_TDM_FR_ANSI 0x0400 /* Frame Relay + LMI ANSI "Annex D" */ >-+#define IFM_TDM_FR_CISCO 0x0800 /* Frame Relay + LMI Cisco */ >-+#define IFM_TDM_FR_ITU 0x1000 /* Frame Relay + LMI ITU "Q933A" */ >-+ >-+/* >-+ * Common Access Redundancy Protocol >-+ */ >-+#define IFM_CARP 0x000000c0 >-+ >-+/* >-+ * Shared media sub-types >-+ */ >-+#define IFM_AUTO 0 /* Autoselect best media */ >-+#define IFM_MANUAL 1 /* Jumper/dipswitch selects media */ >-+#define IFM_NONE 2 /* Deselect all media */ >-+ >-+/* >-+ * Shared options >-+ */ >-+#define IFM_FDX 0x00100000 /* Force full duplex */ >-+#define IFM_HDX 0x00200000 /* Force half duplex */ >-+#define IFM_FLOW 0x00400000 /* enable hardware flow control */ >-+#define IFM_FLAG0 0x01000000 /* Driver defined flag */ >-+#define IFM_FLAG1 0x02000000 /* Driver defined flag */ >-+#define IFM_FLAG2 0x04000000 /* Driver defined flag */ >-+#define IFM_LOOP 0x08000000 /* Put hardware in loopback */ >-+ >-+/* >-+ * Masks >-+ */ >-+#define IFM_NMASK 0x000000e0 /* Network type */ >-+#define IFM_TMASK 0x0000001f /* Media sub-type */ >-+#define IFM_IMASK 0xf0000000 /* Instance */ >-+#define IFM_ISHIFT 28 /* Instance shift */ >-+#define IFM_OMASK 0x0000ff00 /* Type specific options */ >-+#define IFM_MMASK 0x00070000 /* Mode */ >-+#define IFM_MSHIFT 16 /* Mode shift */ >-+#define IFM_GMASK 0x0ff00000 /* Global options */ >-+ >-+#define IFM_NMIN IFM_ETHER /* lowest Network type */ >-+#define IFM_NMAX IFM_NMASK /* highest Network type */ >-+ >-+/* >-+ * Status bits >-+ */ >-+#define IFM_AVALID 0x00000001 /* Active bit valid */ >-+#define IFM_ACTIVE 0x00000002 /* Interface attached to working net */ >-+ >-+/* Mask of "status valid" bits, for ifconfig(8). */ >-+#define IFM_STATUS_VALID IFM_AVALID >-+ >-+/* List of "status valid" bits, for ifconfig(8). */ >-+#define IFM_STATUS_VALID_LIST { \ >-+ IFM_AVALID, \ >-+ 0 \ >-+} >-+ >-+/* >-+ * Macros to extract various bits of information from the media word. >-+ */ >-+#define IFM_TYPE(x) ((x) & IFM_NMASK) >-+#define IFM_SUBTYPE(x) ((x) & IFM_TMASK) >-+#define IFM_INST(x) (((x) & IFM_IMASK) >> IFM_ISHIFT) >-+#define IFM_OPTIONS(x) ((x) & (IFM_OMASK|IFM_GMASK)) >-+#define IFM_MODE(x) ((x) & IFM_MMASK) >-+ >-+#define IFM_INST_MAX IFM_INST(IFM_IMASK) >-+#define IFM_INST_ANY (-1) >-+ >-+/* >-+ * Macro to create a media word. >-+ */ >-+#define IFM_MAKEWORD(type, subtype, options, instance) \ >-+ ((type) | (subtype) | (options) | ((instance) << IFM_ISHIFT)) >-+#define IFM_MAKEMODE(mode) \ >-+ (((mode) << IFM_MSHIFT) & IFM_MMASK) >-+/* >-+ * NetBSD extension not defined in the BSDI API. This is used in various >-+ * places to get the canonical description for a given type/subtype. >-+ * >-+ * In the subtype and mediaopt descriptions, the valid TYPE bits are OR'd >-+ * in to indicate which TYPE the subtype/option corresponds to. If no >-+ * TYPE is present, it is a shared media/mediaopt. >-+ * >-+ * Note that these are parsed case-insensitive. >-+ * >-+ * Order is important. The first matching entry is the canonical name >-+ * for a media type; subsequent matches are aliases. >-+ */ >-+struct ifmedia_description { >-+ int ifmt_word; /* word value; may be masked */ >-+ const char *ifmt_string; /* description */ >-+}; >-+ >-+#define IFM_TYPE_DESCRIPTIONS { \ >-+ { IFM_ETHER, "Ethernet" }, \ >-+ { IFM_ETHER, "ether" }, \ >-+ { IFM_TOKEN, "TokenRing" }, \ >-+ { IFM_TOKEN, "token" }, \ >-+ { IFM_FDDI, "FDDI" }, \ >-+ { IFM_IEEE80211, "IEEE802.11" }, \ >-+ { IFM_TDM, "TDM" }, \ >-+ { IFM_CARP, "CARP" }, \ >-+ { 0, NULL }, \ >-+} >-+ >-+#define IFM_TYPE_MATCH(dt, t) \ >-+ (IFM_TYPE((dt)) == 0 || IFM_TYPE((dt)) == IFM_TYPE((t))) >-+ >-+#define IFM_SUBTYPE_DESCRIPTIONS { \ >-+ { IFM_AUTO, "autoselect" }, \ >-+ { IFM_AUTO, "auto" }, \ >-+ { IFM_MANUAL, "manual" }, \ >-+ { IFM_NONE, "none" }, \ >-+ \ >-+ { IFM_ETHER|IFM_10_T, "10baseT" }, \ >-+ { IFM_ETHER|IFM_10_T, "10baseT/UTP" }, \ >-+ { IFM_ETHER|IFM_10_T, "UTP" }, \ >-+ { IFM_ETHER|IFM_10_T, "10UTP" }, \ >-+ { IFM_ETHER|IFM_10_2, "10base2" }, \ >-+ { IFM_ETHER|IFM_10_2, "10base2/BNC" }, \ >-+ { IFM_ETHER|IFM_10_2, "BNC" }, \ >-+ { IFM_ETHER|IFM_10_2, "10BNC" }, \ >-+ { IFM_ETHER|IFM_10_5, "10base5" }, \ >-+ { IFM_ETHER|IFM_10_5, "10base5/AUI" }, \ >-+ { IFM_ETHER|IFM_10_5, "AUI" }, \ >-+ { IFM_ETHER|IFM_10_5, "10AUI" }, \ >-+ { IFM_ETHER|IFM_100_TX, "100baseTX" }, \ >-+ { IFM_ETHER|IFM_100_TX, "100TX" }, \ >-+ { IFM_ETHER|IFM_100_FX, "100baseFX" }, \ >-+ { IFM_ETHER|IFM_100_FX, "100FX" }, \ >-+ { IFM_ETHER|IFM_100_T4, "100baseT4" }, \ >-+ { IFM_ETHER|IFM_100_T4, "100T4" }, \ >-+ { IFM_ETHER|IFM_100_VG, "100baseVG" }, \ >-+ { IFM_ETHER|IFM_100_VG, "100VG" }, \ >-+ { IFM_ETHER|IFM_100_T2, "100baseT2" }, \ >-+ { IFM_ETHER|IFM_100_T2, "100T2" }, \ >-+ { IFM_ETHER|IFM_1000_SX, "1000baseSX" }, \ >-+ { IFM_ETHER|IFM_1000_SX, "1000SX" }, \ >-+ { IFM_ETHER|IFM_10_STP, "10baseSTP" }, \ >-+ { IFM_ETHER|IFM_10_STP, "STP" }, \ >-+ { IFM_ETHER|IFM_10_STP, "10STP" }, \ >-+ { IFM_ETHER|IFM_10_FL, "10baseFL" }, \ >-+ { IFM_ETHER|IFM_10_FL, "FL" }, \ >-+ { IFM_ETHER|IFM_10_FL, "10FL" }, \ >-+ { IFM_ETHER|IFM_1000_LX, "1000baseLX" }, \ >-+ { IFM_ETHER|IFM_1000_LX, "1000LX" }, \ >-+ { IFM_ETHER|IFM_1000_CX, "1000baseCX" }, \ >-+ { IFM_ETHER|IFM_1000_CX, "1000CX" }, \ >-+ { IFM_ETHER|IFM_1000_T, "1000baseT" }, \ >-+ { IFM_ETHER|IFM_1000_T, "1000T" }, \ >-+ { IFM_ETHER|IFM_1000_T, "1000baseTX" }, \ >-+ { IFM_ETHER|IFM_1000_T, "1000TX" }, \ >-+ { IFM_ETHER|IFM_HPNA_1, "HomePNA1" }, \ >-+ { IFM_ETHER|IFM_HPNA_1, "HPNA1" }, \ >-+ \ >-+ { IFM_TOKEN|IFM_TOK_STP4, "DB9/4Mbit" }, \ >-+ { IFM_TOKEN|IFM_TOK_STP4, "4STP" }, \ >-+ { IFM_TOKEN|IFM_TOK_STP16, "DB9/16Mbit" }, \ >-+ { IFM_TOKEN|IFM_TOK_STP16, "16STP" }, \ >-+ { IFM_TOKEN|IFM_TOK_UTP4, "UTP/4Mbit" }, \ >-+ { IFM_TOKEN|IFM_TOK_UTP4, "4UTP" }, \ >-+ { IFM_TOKEN|IFM_TOK_UTP16, "UTP/16Mbit" }, \ >-+ { IFM_TOKEN|IFM_TOK_UTP16, "16UTP" }, \ >-+ \ >-+ { IFM_FDDI|IFM_FDDI_SMF, "Single-mode" }, \ >-+ { IFM_FDDI|IFM_FDDI_SMF, "SMF" }, \ >-+ { IFM_FDDI|IFM_FDDI_MMF, "Multi-mode" }, \ >-+ { IFM_FDDI|IFM_FDDI_MMF, "MMF" }, \ >-+ { IFM_FDDI|IFM_FDDI_UTP, "UTP" }, \ >-+ { IFM_FDDI|IFM_FDDI_UTP, "CDDI" }, \ >-+ \ >-+ { IFM_IEEE80211|IFM_IEEE80211_FH1, "FH1" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_FH2, "FH2" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_DS2, "DS2" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_DS5, "DS5" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_DS11, "DS11" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_DS1, "DS1" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_DS22, "DS22" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM6, "OFDM6" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM9, "OFDM9" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM12, "OFDM12" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM18, "OFDM18" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM24, "OFDM24" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM36, "OFDM36" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM48, "OFDM48" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM54, "OFDM54" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM72, "OFDM72" }, \ >-+ \ >-+ { IFM_TDM|IFM_TDM_T1, "t1" }, \ >-+ { IFM_TDM|IFM_TDM_T1_AMI, "t1-ami" }, \ >-+ { IFM_TDM|IFM_TDM_E1, "e1" }, \ >-+ { IFM_TDM|IFM_TDM_E1_G704, "e1-g.704" }, \ >-+ { IFM_TDM|IFM_TDM_E1_AMI, "e1-ami" }, \ >-+ { IFM_TDM|IFM_TDM_E1_AMI_G704, "e1-ami-g.704" }, \ >-+ { IFM_TDM|IFM_TDM_T3, "t3" }, \ >-+ { IFM_TDM|IFM_TDM_T3_M13, "t3-m13" }, \ >-+ { IFM_TDM|IFM_TDM_E3, "e3" }, \ >-+ { IFM_TDM|IFM_TDM_E3_G751, "e3-g.751" }, \ >-+ { IFM_TDM|IFM_TDM_E3_G832, "e3-g.832" }, \ >-+ \ >-+ { 0, NULL }, \ >-+} >-+ >-+#define IFM_MODE_DESCRIPTIONS { \ >-+ { IFM_AUTO, "autoselect" }, \ >-+ { IFM_AUTO, "auto" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_11A, "11a" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_11B, "11b" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_11G, "11g" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_FH, "fh" }, \ >-+ { 0, NULL }, \ >-+} >-+ >-+#define IFM_OPTION_DESCRIPTIONS { \ >-+ { IFM_FDX, "full-duplex" }, \ >-+ { IFM_FDX, "fdx" }, \ >-+ { IFM_HDX, "half-duplex" }, \ >-+ { IFM_HDX, "hdx" }, \ >-+ { IFM_FLAG0, "flag0" }, \ >-+ { IFM_FLAG1, "flag1" }, \ >-+ { IFM_FLAG2, "flag2" }, \ >-+ { IFM_LOOP, "loopback" }, \ >-+ { IFM_LOOP, "hw-loopback"}, \ >-+ { IFM_LOOP, "loop" }, \ >-+ \ >-+ { IFM_ETHER|IFM_ETH_MASTER, "master" }, \ >-+ \ >-+ { IFM_TOKEN|IFM_TOK_ETR, "EarlyTokenRelease" }, \ >-+ { IFM_TOKEN|IFM_TOK_ETR, "ETR" }, \ >-+ { IFM_TOKEN|IFM_TOK_SRCRT, "SourceRouting" }, \ >-+ { IFM_TOKEN|IFM_TOK_SRCRT, "SRCRT" }, \ >-+ { IFM_TOKEN|IFM_TOK_ALLR, "AllRoutes" }, \ >-+ { IFM_TOKEN|IFM_TOK_ALLR, "ALLR" }, \ >-+ \ >-+ { IFM_FDDI|IFM_FDDI_DA, "dual-attach" }, \ >-+ { IFM_FDDI|IFM_FDDI_DA, "das" }, \ >-+ \ >-+ { IFM_IEEE80211|IFM_IEEE80211_ADHOC, "adhoc" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_HOSTAP, "hostap" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_IBSS, "ibss" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_IBSSMASTER, "ibss-master" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_MONITOR, "monitor" }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_TURBO, "turbo" }, \ >-+ \ >-+ { IFM_TDM|IFM_TDM_HDLC_CRC16, "hdlc-crc16" }, \ >-+ { IFM_TDM|IFM_TDM_PPP, "ppp" }, \ >-+ { IFM_TDM|IFM_TDM_FR_ANSI, "framerelay-ansi" }, \ >-+ { IFM_TDM|IFM_TDM_FR_CISCO, "framerelay-cisco" }, \ >-+ { IFM_TDM|IFM_TDM_FR_ANSI, "framerelay-itu" }, \ >-+ \ >-+ { 0, NULL }, \ >-+} >-+ >-+/* >-+ * Baudrate descriptions for the various media types. >-+ */ >-+struct ifmedia_baudrate { >-+ int ifmb_word; /* media word */ >-+ int ifmb_baudrate; /* corresponding baudrate */ >-+}; >-+ >-+#define IFM_BAUDRATE_DESCRIPTIONS { \ >-+ { IFM_ETHER|IFM_10_T, IF_Mbps(10) }, \ >-+ { IFM_ETHER|IFM_10_2, IF_Mbps(10) }, \ >-+ { IFM_ETHER|IFM_10_5, IF_Mbps(10) }, \ >-+ { IFM_ETHER|IFM_100_TX, IF_Mbps(100) }, \ >-+ { IFM_ETHER|IFM_100_FX, IF_Mbps(100) }, \ >-+ { IFM_ETHER|IFM_100_T4, IF_Mbps(100) }, \ >-+ { IFM_ETHER|IFM_100_VG, IF_Mbps(100) }, \ >-+ { IFM_ETHER|IFM_100_T2, IF_Mbps(100) }, \ >-+ { IFM_ETHER|IFM_1000_SX, IF_Mbps(1000) }, \ >-+ { IFM_ETHER|IFM_10_STP, IF_Mbps(10) }, \ >-+ { IFM_ETHER|IFM_10_FL, IF_Mbps(10) }, \ >-+ { IFM_ETHER|IFM_1000_LX, IF_Mbps(1000) }, \ >-+ { IFM_ETHER|IFM_1000_CX, IF_Mbps(1000) }, \ >-+ { IFM_ETHER|IFM_1000_T, IF_Mbps(1000) }, \ >-+ { IFM_ETHER|IFM_HPNA_1, IF_Mbps(1) }, \ >-+ \ >-+ { IFM_TOKEN|IFM_TOK_STP4, IF_Mbps(4) }, \ >-+ { IFM_TOKEN|IFM_TOK_STP16, IF_Mbps(16) }, \ >-+ { IFM_TOKEN|IFM_TOK_UTP4, IF_Mbps(4) }, \ >-+ { IFM_TOKEN|IFM_TOK_UTP16, IF_Mbps(16) }, \ >-+ \ >-+ { IFM_FDDI|IFM_FDDI_SMF, IF_Mbps(100) }, \ >-+ { IFM_FDDI|IFM_FDDI_MMF, IF_Mbps(100) }, \ >-+ { IFM_FDDI|IFM_FDDI_UTP, IF_Mbps(100) }, \ >-+ \ >-+ { IFM_IEEE80211|IFM_IEEE80211_FH1, IF_Mbps(1) }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_FH2, IF_Mbps(2) }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_DS1, IF_Mbps(1) }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_DS2, IF_Mbps(2) }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_DS5, IF_Mbps(5) }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_DS11, IF_Mbps(11) }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_DS22, IF_Mbps(22) }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM6, IF_Mbps(6) }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM9, IF_Mbps(9) }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM12, IF_Mbps(12) }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM18, IF_Mbps(18) }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM24, IF_Mbps(24) }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM36, IF_Mbps(36) }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM48, IF_Mbps(48) }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM54, IF_Mbps(54) }, \ >-+ { IFM_IEEE80211|IFM_IEEE80211_OFDM72, IF_Mbps(72) }, \ >-+ \ >-+ { IFM_TDM|IFM_TDM_T1, IF_Kbps(1536) }, \ >-+ { IFM_TDM|IFM_TDM_T1_AMI, IF_Kbps(1536) }, \ >-+ { IFM_TDM|IFM_TDM_E1, IF_Kbps(2048) }, \ >-+ { IFM_TDM|IFM_TDM_E1_G704, IF_Kbps(2048) }, \ >-+ { IFM_TDM|IFM_TDM_E1_AMI, IF_Kbps(2048) }, \ >-+ { IFM_TDM|IFM_TDM_E1_AMI_G704, IF_Kbps(2048) }, \ >-+ { IFM_TDM|IFM_TDM_T3, IF_Kbps(44736) }, \ >-+ { IFM_TDM|IFM_TDM_T3_M13, IF_Kbps(44736) }, \ >-+ { IFM_TDM|IFM_TDM_E3, IF_Kbps(34368) }, \ >-+ { IFM_TDM|IFM_TDM_E3_G751, IF_Kbps(34368) }, \ >-+ { IFM_TDM|IFM_TDM_E3_G832, IF_Kbps(34368) }, \ >-+ \ >-+ { 0, 0 }, \ >-+} >-+ >-+/* >-+ * Status bit descriptions for the various media types. >-+ */ >-+struct ifmedia_status_description { >-+ int ifms_type; >-+ int ifms_valid; >-+ int ifms_bit; >-+ const char *ifms_string[2]; >-+}; >-+ >-+#define IFM_STATUS_DESC(ifms, bit) \ >-+ (ifms)->ifms_string[((ifms)->ifms_bit & (bit)) ? 1 : 0] >-+ >-+#define IFM_STATUS_DESCRIPTIONS { \ >-+ { IFM_ETHER, IFM_AVALID, IFM_ACTIVE, \ >-+ { "no carrier", "active" } }, \ >-+ { IFM_FDDI, IFM_AVALID, IFM_ACTIVE, \ >-+ { "no ring", "inserted" } }, \ >-+ { IFM_TOKEN, IFM_AVALID, IFM_ACTIVE, \ >-+ { "no ring", "inserted" } }, \ >-+ { IFM_IEEE80211, IFM_AVALID, IFM_ACTIVE, \ >-+ { "no network", "active" } }, \ >-+ { IFM_TDM, IFM_AVALID, IFM_ACTIVE, \ >-+ { "no carrier", "active" } }, \ >-+ { IFM_CARP, IFM_AVALID, IFM_ACTIVE, \ >-+ { "backup", "master" } }, \ >-+ { 0, 0, 0, \ >-+ { NULL, NULL } } \ >-+} >-+#endif /* _NET_IF_MEDIA_H_ */ > >Property changes on: files/patch-openbsd-compat_if_media.h >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-openbsd-compat_imsg-buffer.c >=================================================================== >--- files/patch-openbsd-compat_imsg-buffer.c (revision 500577) >+++ files/patch-openbsd-compat_imsg-buffer.c (nonexistent) >@@ -1,312 +0,0 @@ >-Index: openbsd-compat/imsg-buffer.c >-=================================================================== >-RCS file: openbsd-compat/imsg-buffer.c >-diff -N openbsd-compat/imsg-buffer.c >---- /dev/null 1 Jan 1970 00:00:00 -0000 >-+++ openbsd-compat/imsg-buffer.c 8 Dec 2012 20:17:59 -0000 1.2 >-@@ -0,0 +1,305 @@ >-+/* $OpenBSD: imsg-buffer.c,v 1.1 2010/05/26 16:44:32 nicm Exp $ */ >-+ >-+/* >-+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-+ * >-+ * Permission to use, copy, modify, and distribute this software for any >-+ * purpose with or without fee is hereby granted, provided that the above >-+ * copyright notice and this permission notice appear in all copies. >-+ * >-+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES >-+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF >-+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR >-+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES >-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN >-+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF >-+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >-+ */ >-+ >-+#include <sys/param.h> >-+#include <sys/queue.h> >-+#include <sys/socket.h> >-+#include <sys/uio.h> >-+ >-+#include <errno.h> >-+#include <stdlib.h> >-+#include <string.h> >-+#include <unistd.h> >-+ >-+#include "imsg.h" >-+ >-+int ibuf_realloc(struct ibuf *, size_t); >-+void ibuf_enqueue(struct msgbuf *, struct ibuf *); >-+void ibuf_dequeue(struct msgbuf *, struct ibuf *); >-+ >-+struct ibuf * >-+ibuf_open(size_t len) >-+{ >-+ struct ibuf *buf; >-+ >-+ if ((buf = calloc(1, sizeof(struct ibuf))) == NULL) >-+ return (NULL); >-+ if ((buf->buf = malloc(len)) == NULL) { >-+ free(buf); >-+ return (NULL); >-+ } >-+ buf->size = buf->max = len; >-+ buf->fd = -1; >-+ >-+ return (buf); >-+} >-+ >-+struct ibuf * >-+ibuf_dynamic(size_t len, size_t max) >-+{ >-+ struct ibuf *buf; >-+ >-+ if (max < len) >-+ return (NULL); >-+ >-+ if ((buf = ibuf_open(len)) == NULL) >-+ return (NULL); >-+ >-+ if (max > 0) >-+ buf->max = max; >-+ >-+ return (buf); >-+} >-+ >-+int >-+ibuf_realloc(struct ibuf *buf, size_t len) >-+{ >-+ u_char *b; >-+ >-+ /* on static buffers max is eq size and so the following fails */ >-+ if (buf->wpos + len > buf->max) { >-+ errno = ENOMEM; >-+ return (-1); >-+ } >-+ >-+ b = realloc(buf->buf, buf->wpos + len); >-+ if (b == NULL) >-+ return (-1); >-+ buf->buf = b; >-+ buf->size = buf->wpos + len; >-+ >-+ return (0); >-+} >-+ >-+int >-+ibuf_add(struct ibuf *buf, const void *data, size_t len) >-+{ >-+ if (buf->wpos + len > buf->size) >-+ if (ibuf_realloc(buf, len) == -1) >-+ return (-1); >-+ >-+ memcpy(buf->buf + buf->wpos, data, len); >-+ buf->wpos += len; >-+ return (0); >-+} >-+ >-+void * >-+ibuf_reserve(struct ibuf *buf, size_t len) >-+{ >-+ void *b; >-+ >-+ if (buf->wpos + len > buf->size) >-+ if (ibuf_realloc(buf, len) == -1) >-+ return (NULL); >-+ >-+ b = buf->buf + buf->wpos; >-+ buf->wpos += len; >-+ return (b); >-+} >-+ >-+void * >-+ibuf_seek(struct ibuf *buf, size_t pos, size_t len) >-+{ >-+ /* only allowed to seek in already written parts */ >-+ if (pos + len > buf->wpos) >-+ return (NULL); >-+ >-+ return (buf->buf + pos); >-+} >-+ >-+size_t >-+ibuf_size(struct ibuf *buf) >-+{ >-+ return (buf->wpos); >-+} >-+ >-+size_t >-+ibuf_left(struct ibuf *buf) >-+{ >-+ return (buf->max - buf->wpos); >-+} >-+ >-+void >-+ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf) >-+{ >-+ ibuf_enqueue(msgbuf, buf); >-+} >-+ >-+int >-+ibuf_write(struct msgbuf *msgbuf) >-+{ >-+ struct iovec iov[IOV_MAX]; >-+ struct ibuf *buf; >-+ unsigned int i = 0; >-+ ssize_t n; >-+ >-+ bzero(&iov, sizeof(iov)); >-+ TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { >-+ if (i >= IOV_MAX) >-+ break; >-+ iov[i].iov_base = buf->buf + buf->rpos; >-+ iov[i].iov_len = buf->wpos - buf->rpos; >-+ i++; >-+ } >-+ >-+again: >-+ if ((n = writev(msgbuf->fd, iov, i)) == -1) { >-+ if (errno == EAGAIN || errno == EINTR) >-+ goto again; >-+ if (errno == ENOBUFS) >-+ errno = EAGAIN; >-+ return (-1); >-+ } >-+ >-+ if (n == 0) { /* connection closed */ >-+ errno = 0; >-+ return (0); >-+ } >-+ >-+ msgbuf_drain(msgbuf, n); >-+ >-+ return (1); >-+} >-+ >-+void >-+ibuf_free(struct ibuf *buf) >-+{ >-+ free(buf->buf); >-+ free(buf); >-+} >-+ >-+void >-+msgbuf_init(struct msgbuf *msgbuf) >-+{ >-+ msgbuf->queued = 0; >-+ msgbuf->fd = -1; >-+ TAILQ_INIT(&msgbuf->bufs); >-+} >-+ >-+void >-+msgbuf_drain(struct msgbuf *msgbuf, size_t n) >-+{ >-+ struct ibuf *buf, *next; >-+ >-+ for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; >-+ buf = next) { >-+ next = TAILQ_NEXT(buf, entry); >-+ if (buf->rpos + n >= buf->wpos) { >-+ n -= buf->wpos - buf->rpos; >-+ ibuf_dequeue(msgbuf, buf); >-+ } else { >-+ buf->rpos += n; >-+ n = 0; >-+ } >-+ } >-+} >-+ >-+void >-+msgbuf_clear(struct msgbuf *msgbuf) >-+{ >-+ struct ibuf *buf; >-+ >-+ while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL) >-+ ibuf_dequeue(msgbuf, buf); >-+} >-+ >-+int >-+msgbuf_write(struct msgbuf *msgbuf) >-+{ >-+ struct iovec iov[IOV_MAX]; >-+ struct ibuf *buf; >-+ unsigned int i = 0; >-+ ssize_t n; >-+ struct msghdr msg; >-+ struct cmsghdr *cmsg; >-+ union { >-+ struct cmsghdr hdr; >-+ char buf[CMSG_SPACE(sizeof(int))]; >-+ } cmsgbuf; >-+ >-+ bzero(&iov, sizeof(iov)); >-+ bzero(&msg, sizeof(msg)); >-+ TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { >-+ if (i >= IOV_MAX) >-+ break; >-+ iov[i].iov_base = buf->buf + buf->rpos; >-+ iov[i].iov_len = buf->wpos - buf->rpos; >-+ i++; >-+ if (buf->fd != -1) >-+ break; >-+ } >-+ >-+ msg.msg_iov = iov; >-+ msg.msg_iovlen = i; >-+ >-+ if (buf != NULL && buf->fd != -1) { >-+ msg.msg_control = (caddr_t)&cmsgbuf.buf; >-+ msg.msg_controllen = sizeof(cmsgbuf.buf); >-+ cmsg = CMSG_FIRSTHDR(&msg); >-+ cmsg->cmsg_len = CMSG_LEN(sizeof(int)); >-+ cmsg->cmsg_level = SOL_SOCKET; >-+ cmsg->cmsg_type = SCM_RIGHTS; >-+ *(int *)CMSG_DATA(cmsg) = buf->fd; >-+ } >-+ >-+again: >-+ if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) { >-+ if (errno == EAGAIN || errno == EINTR) >-+ goto again; >-+ if (errno == ENOBUFS) >-+ errno = EAGAIN; >-+ return (-1); >-+ } >-+ >-+ if (n == 0) { /* connection closed */ >-+ errno = 0; >-+ return (0); >-+ } >-+ >-+ /* >-+ * assumption: fd got sent if sendmsg sent anything >-+ * this works because fds are passed one at a time >-+ */ >-+ if (buf != NULL && buf->fd != -1) { >-+ close(buf->fd); >-+ buf->fd = -1; >-+ } >-+ >-+ msgbuf_drain(msgbuf, n); >-+ >-+ return (1); >-+} >-+ >-+void >-+ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf) >-+{ >-+ TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry); >-+ msgbuf->queued++; >-+} >-+ >-+void >-+ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf) >-+{ >-+ TAILQ_REMOVE(&msgbuf->bufs, buf, entry); >-+ >-+ if (buf->fd != -1) >-+ close(buf->fd); >-+ >-+ msgbuf->queued--; >-+ ibuf_free(buf); >-+} > >Property changes on: files/patch-openbsd-compat_imsg-buffer.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-openbsd-compat_imsg.c >=================================================================== >--- files/patch-openbsd-compat_imsg.c (revision 500577) >+++ files/patch-openbsd-compat_imsg.c (nonexistent) >@@ -1,312 +0,0 @@ >-Index: openbsd-compat/imsg.c >-=================================================================== >-RCS file: openbsd-compat/imsg.c >-diff -N openbsd-compat/imsg.c >---- /dev/null 1 Jan 1970 00:00:00 -0000 >-+++ openbsd-compat/imsg.c 8 Dec 2012 20:17:59 -0000 1.2 >-@@ -0,0 +1,305 @@ >-+/* $OpenBSD: imsg.c,v 1.1 2010/05/26 16:44:32 nicm Exp $ */ >-+ >-+/* >-+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-+ * >-+ * Permission to use, copy, modify, and distribute this software for any >-+ * purpose with or without fee is hereby granted, provided that the above >-+ * copyright notice and this permission notice appear in all copies. >-+ * >-+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES >-+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF >-+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR >-+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES >-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN >-+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF >-+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >-+ */ >-+ >-+#include <sys/param.h> >-+#include <sys/queue.h> >-+#include <sys/socket.h> >-+#include <sys/uio.h> >-+ >-+#include <errno.h> >-+#include <stdlib.h> >-+#include <string.h> >-+#include <unistd.h> >-+ >-+#include "imsg.h" >-+ >-+int imsg_fd_overhead = 0; >-+ >-+int imsg_get_fd(struct imsgbuf *); >-+ >-+void >-+imsg_init(struct imsgbuf *ibuf, int fd) >-+{ >-+ msgbuf_init(&ibuf->w); >-+ bzero(&ibuf->r, sizeof(ibuf->r)); >-+ ibuf->fd = fd; >-+ ibuf->w.fd = fd; >-+ ibuf->pid = getpid(); >-+ TAILQ_INIT(&ibuf->fds); >-+} >-+ >-+ssize_t >-+imsg_read(struct imsgbuf *ibuf) >-+{ >-+ struct msghdr msg; >-+ struct cmsghdr *cmsg; >-+ union { >-+ struct cmsghdr hdr; >-+ char buf[CMSG_SPACE(sizeof(int) * 1)]; >-+ } cmsgbuf; >-+ struct iovec iov; >-+ ssize_t n = -1; >-+ int fd; >-+ struct imsg_fd *ifd; >-+ >-+ bzero(&msg, sizeof(msg)); >-+ >-+ iov.iov_base = ibuf->r.buf + ibuf->r.wpos; >-+ iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos; >-+ msg.msg_iov = &iov; >-+ msg.msg_iovlen = 1; >-+ msg.msg_control = &cmsgbuf.buf; >-+ msg.msg_controllen = sizeof(cmsgbuf.buf); >-+ >-+ if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) >-+ return (-1); >-+ >-+again: >-+#if defined(__FreeBSD__) >-+ if (imsg_fd_overhead + >-+#else >-+ if (getdtablecount() + imsg_fd_overhead + >-+#endif >-+ (CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int) >-+ >= getdtablesize()) { >-+ errno = EAGAIN; >-+ return (-1); >-+ } >-+ >-+ if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) { >-+ if (errno == EMSGSIZE) >-+ goto fail; >-+ if (errno != EINTR && errno != EAGAIN) >-+ goto fail; >-+ goto again; >-+ } >-+ >-+ ibuf->r.wpos += n; >-+ >-+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; >-+ cmsg = CMSG_NXTHDR(&msg, cmsg)) { >-+ if (cmsg->cmsg_level == SOL_SOCKET && >-+ cmsg->cmsg_type == SCM_RIGHTS) { >-+ int i; >-+ int j; >-+ >-+ /* >-+ * We only accept one file descriptor. Due to C >-+ * padding rules, our control buffer might contain >-+ * more than one fd, and we must close them. >-+ */ >-+ j = ((char *)cmsg + cmsg->cmsg_len - >-+ (char *)CMSG_DATA(cmsg)) / sizeof(int); >-+ for (i = 0; i < j; i++) { >-+ fd = ((int *)CMSG_DATA(cmsg))[i]; >-+ if (i == 0) { >-+ ifd->fd = fd; >-+ TAILQ_INSERT_TAIL(&ibuf->fds, ifd, >-+ entry); >-+ ifd = NULL; >-+ } else >-+ close(fd); >-+ } >-+ } >-+ /* we do not handle other ctl data level */ >-+ } >-+ >-+fail: >-+ if (ifd) >-+ free(ifd); >-+ return (n); >-+} >-+ >-+ssize_t >-+imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) >-+{ >-+ size_t av, left, datalen; >-+ >-+ av = ibuf->r.wpos; >-+ >-+ if (IMSG_HEADER_SIZE > av) >-+ return (0); >-+ >-+ memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr)); >-+ if (imsg->hdr.len < IMSG_HEADER_SIZE || >-+ imsg->hdr.len > MAX_IMSGSIZE) { >-+ errno = ERANGE; >-+ return (-1); >-+ } >-+ if (imsg->hdr.len > av) >-+ return (0); >-+ datalen = imsg->hdr.len - IMSG_HEADER_SIZE; >-+ ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE; >-+ if ((imsg->data = malloc(datalen)) == NULL) >-+ return (-1); >-+ >-+ if (imsg->hdr.flags & IMSGF_HASFD) >-+ imsg->fd = imsg_get_fd(ibuf); >-+ else >-+ imsg->fd = -1; >-+ >-+ memcpy(imsg->data, ibuf->r.rptr, datalen); >-+ >-+ if (imsg->hdr.len < av) { >-+ left = av - imsg->hdr.len; >-+ memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left); >-+ ibuf->r.wpos = left; >-+ } else >-+ ibuf->r.wpos = 0; >-+ >-+ return (datalen + IMSG_HEADER_SIZE); >-+} >-+ >-+int >-+imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, >-+ pid_t pid, int fd, void *data, u_int16_t datalen) >-+{ >-+ struct ibuf *wbuf; >-+ >-+ if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) >-+ return (-1); >-+ >-+ if (imsg_add(wbuf, data, datalen) == -1) >-+ return (-1); >-+ >-+ wbuf->fd = fd; >-+ >-+ imsg_close(ibuf, wbuf); >-+ >-+ return (1); >-+} >-+ >-+int >-+imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, >-+ pid_t pid, int fd, const struct iovec *iov, int iovcnt) >-+{ >-+ struct ibuf *wbuf; >-+ int i, datalen = 0; >-+ >-+ for (i = 0; i < iovcnt; i++) >-+ datalen += iov[i].iov_len; >-+ >-+ if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) >-+ return (-1); >-+ >-+ for (i = 0; i < iovcnt; i++) >-+ if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1) >-+ return (-1); >-+ >-+ wbuf->fd = fd; >-+ >-+ imsg_close(ibuf, wbuf); >-+ >-+ return (1); >-+} >-+ >-+/* ARGSUSED */ >-+struct ibuf * >-+imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, >-+ pid_t pid, u_int16_t datalen) >-+{ >-+ struct ibuf *wbuf; >-+ struct imsg_hdr hdr; >-+ >-+ datalen += IMSG_HEADER_SIZE; >-+ if (datalen > MAX_IMSGSIZE) { >-+ errno = ERANGE; >-+ return (NULL); >-+ } >-+ >-+ hdr.type = type; >-+ hdr.flags = 0; >-+ hdr.peerid = peerid; >-+ if ((hdr.pid = pid) == 0) >-+ hdr.pid = ibuf->pid; >-+ if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) { >-+ return (NULL); >-+ } >-+ if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1) >-+ return (NULL); >-+ >-+ return (wbuf); >-+} >-+ >-+int >-+imsg_add(struct ibuf *msg, void *data, u_int16_t datalen) >-+{ >-+ if (datalen) >-+ if (ibuf_add(msg, data, datalen) == -1) { >-+ ibuf_free(msg); >-+ return (-1); >-+ } >-+ return (datalen); >-+} >-+ >-+void >-+imsg_close(struct imsgbuf *ibuf, struct ibuf *msg) >-+{ >-+ struct imsg_hdr *hdr; >-+ >-+ hdr = (struct imsg_hdr *)msg->buf; >-+ >-+ hdr->flags &= ~IMSGF_HASFD; >-+ if (msg->fd != -1) >-+ hdr->flags |= IMSGF_HASFD; >-+ >-+ hdr->len = (u_int16_t)msg->wpos; >-+ >-+ ibuf_close(&ibuf->w, msg); >-+} >-+ >-+void >-+imsg_free(struct imsg *imsg) >-+{ >-+ free(imsg->data); >-+} >-+ >-+int >-+imsg_get_fd(struct imsgbuf *ibuf) >-+{ >-+ int fd; >-+ struct imsg_fd *ifd; >-+ >-+ if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL) >-+ return (-1); >-+ >-+ fd = ifd->fd; >-+ TAILQ_REMOVE(&ibuf->fds, ifd, entry); >-+ free(ifd); >-+ >-+ return (fd); >-+} >-+ >-+int >-+imsg_flush(struct imsgbuf *ibuf) >-+{ >-+ while (ibuf->w.queued) >-+ if (msgbuf_write(&ibuf->w) < 0) >-+ return (-1); >-+ return (0); >-+} >-+ >-+void >-+imsg_clear(struct imsgbuf *ibuf) >-+{ >-+ int fd; >-+ >-+ msgbuf_clear(&ibuf->w); >-+ while ((fd = imsg_get_fd(ibuf)) != -1) >-+ close(fd); >-+} > >Property changes on: files/patch-openbsd-compat_imsg.c >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-openbsd-compat_imsg.h >=================================================================== >--- files/patch-openbsd-compat_imsg.h (revision 500577) >+++ files/patch-openbsd-compat_imsg.h (nonexistent) >@@ -1,119 +0,0 @@ >-Index: openbsd-compat/imsg.h >-=================================================================== >-RCS file: openbsd-compat/imsg.h >-diff -N openbsd-compat/imsg.h >---- /dev/null 1 Jan 1970 00:00:00 -0000 >-+++ openbsd-compat/imsg.h 8 Dec 2012 20:17:59 -0000 1.2 >-@@ -0,0 +1,112 @@ >-+/* $OpenBSD: imsg.h,v 1.1 2010/05/26 16:44:32 nicm Exp $ */ >-+ >-+/* >-+ * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org> >-+ * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org> >-+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> >-+ * >-+ * Permission to use, copy, modify, and distribute this software for any >-+ * purpose with or without fee is hereby granted, provided that the above >-+ * copyright notice and this permission notice appear in all copies. >-+ * >-+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES >-+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF >-+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR >-+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES >-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN >-+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF >-+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >-+ */ >-+ >-+#ifndef _IMSG_H_ >-+#define _IMSG_H_ >-+ >-+#define IBUF_READ_SIZE 65535 >-+#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr) >-+#define MAX_IMSGSIZE 16384 >-+ >-+struct ibuf { >-+ TAILQ_ENTRY(ibuf) entry; >-+ u_char *buf; >-+ size_t size; >-+ size_t max; >-+ size_t wpos; >-+ size_t rpos; >-+ int fd; >-+}; >-+ >-+struct msgbuf { >-+ TAILQ_HEAD(, ibuf) bufs; >-+ u_int32_t queued; >-+ int fd; >-+}; >-+ >-+struct ibuf_read { >-+ u_char buf[IBUF_READ_SIZE]; >-+ u_char *rptr; >-+ size_t wpos; >-+}; >-+ >-+struct imsg_fd { >-+ TAILQ_ENTRY(imsg_fd) entry; >-+ int fd; >-+}; >-+ >-+struct imsgbuf { >-+ TAILQ_HEAD(, imsg_fd) fds; >-+ struct ibuf_read r; >-+ struct msgbuf w; >-+ int fd; >-+ pid_t pid; >-+}; >-+ >-+#define IMSGF_HASFD 1 >-+ >-+struct imsg_hdr { >-+ u_int32_t type; >-+ u_int16_t len; >-+ u_int16_t flags; >-+ u_int32_t peerid; >-+ u_int32_t pid; >-+}; >-+ >-+struct imsg { >-+ struct imsg_hdr hdr; >-+ int fd; >-+ void *data; >-+}; >-+ >-+ >-+/* buffer.c */ >-+struct ibuf *ibuf_open(size_t); >-+struct ibuf *ibuf_dynamic(size_t, size_t); >-+int ibuf_add(struct ibuf *, const void *, size_t); >-+void *ibuf_reserve(struct ibuf *, size_t); >-+void *ibuf_seek(struct ibuf *, size_t, size_t); >-+size_t ibuf_size(struct ibuf *); >-+size_t ibuf_left(struct ibuf *); >-+void ibuf_close(struct msgbuf *, struct ibuf *); >-+int ibuf_write(struct msgbuf *); >-+void ibuf_free(struct ibuf *); >-+void msgbuf_init(struct msgbuf *); >-+void msgbuf_clear(struct msgbuf *); >-+int msgbuf_write(struct msgbuf *); >-+void msgbuf_drain(struct msgbuf *, size_t); >-+ >-+/* imsg.c */ >-+void imsg_init(struct imsgbuf *, int); >-+ssize_t imsg_read(struct imsgbuf *); >-+ssize_t imsg_get(struct imsgbuf *, struct imsg *); >-+int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, >-+ int, void *, u_int16_t); >-+int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, >-+ int, const struct iovec *, int); >-+struct ibuf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, >-+ u_int16_t); >-+int imsg_add(struct ibuf *, void *, u_int16_t); >-+void imsg_close(struct imsgbuf *, struct ibuf *); >-+void imsg_free(struct imsg *); >-+int imsg_flush(struct imsgbuf *); >-+void imsg_clear(struct imsgbuf *); >-+ >-+#endif > >Property changes on: files/patch-openbsd-compat_imsg.h >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-openbsd-compat_openbsd-compat.h >=================================================================== >--- files/patch-openbsd-compat_openbsd-compat.h (revision 500577) >+++ files/patch-openbsd-compat_openbsd-compat.h (nonexistent) >@@ -1,98 +0,0 @@ >-Index: openbsd-compat/openbsd-compat.h >-=================================================================== >-RCS file: openbsd-compat/openbsd-compat.h >-diff -N openbsd-compat/openbsd-compat.h >---- /dev/null 1 Jan 1970 00:00:00 -0000 >-+++ openbsd-compat/openbsd-compat.h 13 Oct 2012 18:50:10 -0000 1.8 >-@@ -0,0 +1,91 @@ >-+/* >-+ * $hrs: openbgpd/openbsd-compat/openbsd-compat.h,v 1.8 2012/10/13 18:50:10 hrs Exp $ >-+ */ >-+ >-+#ifndef _OPENBSD_COMPAT_H >-+#define _OPENBSD_COMPAT_H >-+ >-+#define __dead >-+ >-+/* bgpctl/bgpctl.c */ >-+#include <sys/endian.h> >-+#include <inttypes.h> >-+#define betoh64(x) (be64toh(x)) >-+#ifndef IFT_CARP >-+#define IFT_CARP 0xf8 >-+#endif >-+ >-+/* bgpd/irrfilter.c */ >-+typedef unsigned long ulong; >-+ >-+/* bgpd/bgpd.c */ >-+#ifndef RTLABEL_LEN /* defined in net/pfvar.h */ >-+#define RTLABEL_LEN 32 >-+#endif >-+#define RTA_LABEL 0 >-+ >-+#define SIMPLEQ_FOREACH STAILQ_FOREACH >-+#define SIMPLEQ_FIRST STAILQ_FIRST >-+#define SIMPLEQ_REMOVE_HEAD STAILQ_REMOVE_HEAD >-+#define SIMPLEQ_INSERT_TAIL STAILQ_INSERT_TAIL >-+#define SIMPLEQ_ENTRY STAILQ_ENTRY >-+#define SIMPLEQ_HEAD STAILQ_HEAD >-+#define SIMPLEQ_INIT STAILQ_INIT >-+#define SIMPLEQ_HEAD_INITIALIZER STAILQ_HEAD_INITIALIZER >-+ >-+/* Routing priorities used by the different routing protocols */ >-+#define RTP_NONE 0 /* unset priority use sane default */ >-+#define RTP_CONNECTED 4 /* directly connected routes */ >-+#define RTP_STATIC 8 /* static routes base priority */ >-+#define RTP_OSPF 32 /* OSPF routes */ >-+#define RTP_ISIS 36 /* IS-IS routes */ >-+#define RTP_RIP 40 /* RIP routes */ >-+#define RTP_BGP 48 /* BGP routes */ >-+#define RTP_DEFAULT 56 /* routes that have nothing set */ >-+#define RTP_MAX 63 /* maximum priority */ >-+#define RTP_ANY 64 /* any of the above */ >-+#define RTP_MASK 0x7f >-+#define RTP_DOWN 0x80 /* route/link is down */ >-+ >-+/* missing LINK_STATE_* macros in net/if.h */ >-+#define LINK_STATE_INVALID LINK_STATE_UNKNOWN /* link invalid */ >-+#define LINK_STATE_KALIVE_DOWN 7 /* keepalive reports down */ >-+#define LINK_STATE_HALF_DUPLEX 5 /* link is up and half duplex */ >-+#define LINK_STATE_FULL_DUPLEX 6 /* link is up and full duplex */ >-+ >-+/* >-+ * Status bit descriptions for the various interface types. >-+ */ >-+struct if_status_description { >-+ unsigned char ifs_type; >-+ unsigned char ifs_state; >-+ const char *ifs_string; >-+}; >-+ >-+#define LINK_STATE_DESC_MATCH(_ifs, _t, _s) \ >-+ (((_ifs)->ifs_type == (_t) || (_ifs)->ifs_type == 0) && \ >-+ (_ifs)->ifs_state == (_s)) >-+ >-+#define LINK_STATE_DESCRIPTIONS { \ >-+ { IFT_ETHER, LINK_STATE_DOWN, "no carrier" }, \ >-+ \ >-+ { IFT_IEEE80211, LINK_STATE_DOWN, "no network" }, \ >-+ \ >-+ { IFT_PPP, LINK_STATE_DOWN, "no carrier" }, \ >-+ \ >-+ { IFT_CARP, LINK_STATE_DOWN, "backup" }, \ >-+ { IFT_CARP, LINK_STATE_UP, "master" }, \ >-+ { IFT_CARP, LINK_STATE_HALF_DUPLEX, "master" }, \ >-+ { IFT_CARP, LINK_STATE_FULL_DUPLEX, "master" }, \ >-+ \ >-+ { 0, LINK_STATE_UP, "active" }, \ >-+ { 0, LINK_STATE_HALF_DUPLEX, "active" }, \ >-+ { 0, LINK_STATE_FULL_DUPLEX, "active" }, \ >-+ \ >-+/* { 0, LINK_STATE_UNKNOWN, "unknown" }, */ \ >-+ { 0, LINK_STATE_INVALID, "invalid" }, \ >-+ { 0, LINK_STATE_DOWN, "down" }, \ >-+ { 0, LINK_STATE_KALIVE_DOWN, "keepalive down" }, \ >-+ { 0, 0, NULL } \ >-+} >-+#endif /* _OPENBSD_COMPAT_H */ > >Property changes on: files/patch-openbsd-compat_openbsd-compat.h >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: files/patch-openbsd-compat_util.h >=================================================================== >--- files/patch-openbsd-compat_util.h (revision 500577) >+++ files/patch-openbsd-compat_util.h (nonexistent) >@@ -1,126 +0,0 @@ >-Index: openbsd-compat/util.h >-=================================================================== >-RCS file: openbsd-compat/util.h >-diff -N openbsd-compat/util.h >---- /dev/null 1 Jan 1970 00:00:00 -0000 >-+++ openbsd-compat/util.h 30 Jun 2009 06:40:07 -0000 1.1 >-@@ -0,0 +1,119 @@ >-+/* $OpenBSD: util.h,v 1.27 2006/06/14 02:14:25 krw Exp $ */ >-+/* $NetBSD: util.h,v 1.2 1996/05/16 07:00:22 thorpej Exp $ */ >-+ >-+/*- >-+ * Copyright (c) 1995 >-+ * The Regents of the University of California. All rights reserved. >-+ * Portions Copyright (c) 1996, Jason Downs. All rights reserved. >-+ * >-+ * Redistribution and use in source and binary forms, with or without >-+ * modification, are permitted provided that the following conditions >-+ * are met: >-+ * 1. Redistributions of source code must retain the above copyright >-+ * notice, this list of conditions and the following disclaimer. >-+ * 2. Redistributions in binary form must reproduce the above copyright >-+ * notice, this list of conditions and the following disclaimer in the >-+ * documentation and/or other materials provided with the distribution. >-+ * 3. Neither the name of the University nor the names of its contributors >-+ * may be used to endorse or promote products derived from this software >-+ * without specific prior written permission. >-+ * >-+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND >-+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >-+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >-+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE >-+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >-+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS >-+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >-+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >-+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >-+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >-+ * SUCH DAMAGE. >-+ */ >-+ >-+#ifndef _UTIL_H_ >-+#define _UTIL_H_ >-+ >-+#include <sys/cdefs.h> >-+#include <sys/types.h> >-+ >-+/* >-+ * fparseln() specific operation flags. >-+ */ >-+#define FPARSELN_UNESCESC 0x01 >-+#define FPARSELN_UNESCCONT 0x02 >-+#define FPARSELN_UNESCCOMM 0x04 >-+#define FPARSELN_UNESCREST 0x08 >-+#define FPARSELN_UNESCALL 0x0f >-+ >-+/* >-+ * opendev() specific operation flags. >-+ */ >-+#define OPENDEV_PART 0x01 /* Try to open the raw partition. */ >-+#define OPENDEV_BLCK 0x04 /* Open block, not character device. */ >-+ >-+/* >-+ * uucplock(3) specific flags. >-+ */ >-+#define UU_LOCK_INUSE (1) >-+#define UU_LOCK_OK (0) >-+#define UU_LOCK_OPEN_ERR (-1) >-+#define UU_LOCK_READ_ERR (-2) >-+#define UU_LOCK_CREAT_ERR (-3) >-+#define UU_LOCK_WRITE_ERR (-4) >-+#define UU_LOCK_LINK_ERR (-5) >-+#define UU_LOCK_TRY_ERR (-6) >-+#define UU_LOCK_OWNER_ERR (-7) >-+ >-+/* >-+ * fmt_scaled(3) specific flags. >-+ */ >-+#define FMT_SCALED_STRSIZE 7 /* minus sign, 4 digits, suffix, null byte */ >-+ >-+/* >-+ * stub struct definitions. >-+ */ >-+struct __sFILE; >-+struct login_cap; >-+struct passwd; >-+struct termios; >-+struct utmp; >-+struct winsize; >-+ >-+__BEGIN_DECLS >-+char *fparseln(struct __sFILE *, size_t *, size_t *, const char[3], int); >-+void login(struct utmp *); >-+int login_tty(int); >-+int logout(const char *); >-+void logwtmp(const char *, const char *, const char *); >-+int opendev(char *, int, int, char **); >-+int pidfile(const char *); >-+void pw_setdir(const char *); >-+char *pw_file(const char *); >-+int pw_lock(int retries); >-+int pw_mkdb(char *, int); >-+int pw_abort(void); >-+void pw_init(void); >-+void pw_edit(int, const char *); >-+void pw_prompt(void); >-+void pw_copy(int, int, const struct passwd *, const struct passwd *); >-+int pw_scan(char *, struct passwd *, int *); >-+void pw_error(const char *, int, int); >-+int openpty(int *, int *, char *, struct termios *, struct winsize *); >-+int opendisk(const char *path, int flags, char *buf, size_t buflen, >-+ int iscooked); >-+pid_t forkpty(int *, char *, struct termios *, struct winsize *); >-+int getmaxpartitions(void); >-+int getrawpartition(void); >-+void login_fbtab(const char *, uid_t, gid_t); >-+int login_check_expire(struct __sFILE *, struct passwd *, char *, int); >-+char *readlabelfs(char *, int); >-+const char *uu_lockerr(int _uu_lockresult); >-+int uu_lock(const char *_ttyname); >-+int uu_lock_txfr(const char *_ttyname, pid_t _pid); >-+int uu_unlock(const char *_ttyname); >-+int fmt_scaled(long long number, char *result); >-+int scan_scaled(char *scaled, long long *result); >-+__END_DECLS >-+ >-+#endif /* !_UTIL_H_ */ > >Property changes on: files/patch-openbsd-compat_util.h >___________________________________________________________________ >Deleted: fbsd:nokeywords >## -1 +0,0 ## >-yes >\ No newline at end of property >Deleted: svn:eol-style >## -1 +0,0 ## >-native >\ No newline at end of property >Deleted: svn:mime-type >## -1 +0,0 ## >-text/plain >\ No newline at end of property >Index: pkg-plist >=================================================================== >--- pkg-plist (nonexistent) >+++ pkg-plist (working copy) >@@ -0,0 +1,6 @@ >+sbin/bgpctl >+sbin/bgpd >+man/man5/bgpd.conf.5.gz >+man/man8/bgpctl.8.gz >+man/man8/bgpd.8.gz >+@sample etc/bgpd.conf.sample > >Property changes on: pkg-plist >___________________________________________________________________ >Added: fbsd:nokeywords >## -0,0 +1 ## >+yes >\ No newline at end of property >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Added: svn:mime-type >## -0,0 +1 ## >+text/plain >\ No newline at end of property
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
koobs
:
maintainer-approval+
Actions:
View
|
Diff
Attachments on
bug 213445
: 204136 |
204404