aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/openbgpd/Makefile5
-rw-r--r--net/openbgpd/files/patch-bgpctl_Makefile11
-rw-r--r--net/openbgpd/files/patch-bgpctl_bgpctl.887
-rw-r--r--net/openbgpd/files/patch-bgpctl_bgpctl.c273
-rw-r--r--net/openbgpd/files/patch-bgpctl_irr_prefix.c11
-rw-r--r--net/openbgpd/files/patch-bgpctl_parser.c118
-rw-r--r--net/openbgpd/files/patch-bgpctl_parser.h26
-rw-r--r--net/openbgpd/files/patch-bgpd_Makefile26
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.874
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.c480
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.conf.5439
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.h324
-rw-r--r--net/openbgpd/files/patch-bgpd_buffer.c358
-rw-r--r--net/openbgpd/files/patch-bgpd_config.c83
-rw-r--r--net/openbgpd/files/patch-bgpd_control.c54
-rw-r--r--net/openbgpd/files/patch-bgpd_imsg.c296
-rw-r--r--net/openbgpd/files/patch-bgpd_imsg.h125
-rw-r--r--net/openbgpd/files/patch-bgpd_kroute.c2442
-rw-r--r--net/openbgpd/files/patch-bgpd_log.c51
-rw-r--r--net/openbgpd/files/patch-bgpd_mrt.c480
-rw-r--r--net/openbgpd/files/patch-bgpd_mrt.h53
-rw-r--r--net/openbgpd/files/patch-bgpd_parse.y753
-rw-r--r--net/openbgpd/files/patch-bgpd_pfkey.c86
-rw-r--r--net/openbgpd/files/patch-bgpd_printconf.c228
-rw-r--r--net/openbgpd/files/patch-bgpd_rde.c1016
-rw-r--r--net/openbgpd/files/patch-bgpd_rde.h79
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_attr.c145
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_decide.c14
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_filter.c87
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_rib.c134
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_update.c64
-rw-r--r--net/openbgpd/files/patch-bgpd_session.c499
-rw-r--r--net/openbgpd/files/patch-bgpd_session.h86
-rw-r--r--net/openbgpd/files/patch-bgpd_timer.c23
-rw-r--r--net/openbgpd/files/patch-bgpd_util.c86
-rw-r--r--net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c310
-rw-r--r--net/openbgpd/files/patch-openbsd-compat_imsg.c278
-rw-r--r--net/openbgpd/files/patch-openbsd-compat_imsg.h119
-rw-r--r--net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h4
-rw-r--r--net/openbgpd/files/patch-openbsd-compat_pfkey_compat.c9
-rw-r--r--net/openbgpd/pkg-install37
41 files changed, 8906 insertions, 967 deletions
diff --git a/net/openbgpd/Makefile b/net/openbgpd/Makefile
index 21feb49d6059..e97c0e3ae698 100644
--- a/net/openbgpd/Makefile
+++ b/net/openbgpd/Makefile
@@ -6,7 +6,7 @@
#
PORTNAME= openbgpd
-PORTVERSION= 4.7.20100410
+PORTVERSION= 4.9.20110612
CATEGORIES= net
MASTER_SITES= ${MASTER_SITE_OPENBSD}
MASTER_SITE_SUBDIR= OpenBGPD
@@ -33,6 +33,8 @@ MANCOMPRESSED= yes
USE_RC_SUBR= ${PORTNAME}.sh
PLIST_FILES= sbin/bgpctl sbin/bgpd
SUB_FILES= pkg-message
+USERS= _bgpd
+GROUPS= _bgpd
MAN5= bgpd.conf.5
MAN8= bgpctl.8 bgpd.8
@@ -48,7 +50,6 @@ post-patch:
${WRKSRC}/bgpctl/bgpctl.8
post-install:
- @${SH} ${PKGINSTALL} ${PKGNAME} POST-INSTALL
@${CAT} ${PKGMESSAGE}
.include <bsd.port.post.mk>
diff --git a/net/openbgpd/files/patch-bgpctl_Makefile b/net/openbgpd/files/patch-bgpctl_Makefile
index f39d97bcf14e..faca1083ecf9 100644
--- a/net/openbgpd/files/patch-bgpctl_Makefile
+++ b/net/openbgpd/files/patch-bgpctl_Makefile
@@ -2,10 +2,10 @@ Index: bgpctl/Makefile
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/Makefile,v
retrieving revision 1.1.1.1
-retrieving revision 1.2
-diff -u -p -r1.1.1.1 -r1.2
+retrieving revision 1.3
+diff -u -p -r1.1.1.1 -r1.3
--- bgpctl/Makefile 30 Jun 2009 05:46:15 -0000 1.1.1.1
-+++ bgpctl/Makefile 30 Jun 2009 06:40:05 -0000 1.2
++++ bgpctl/Makefile 2 Jul 2011 16:06:35 -0000 1.3
@@ -1,17 +1,18 @@
# $OpenBSD: Makefile,v 1.10 2007/12/20 17:08:48 henning Exp $
@@ -13,10 +13,11 @@ diff -u -p -r1.1.1.1 -r1.2
+.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 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+= fmt_scaled.c
++SRCS+= fmt_scaled.c imsg.c imsg-buffer.c
CFLAGS+= -Wall
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
CFLAGS+= -Wmissing-declarations
diff --git a/net/openbgpd/files/patch-bgpctl_bgpctl.8 b/net/openbgpd/files/patch-bgpctl_bgpctl.8
index 33875d1056c2..a5305b3061b1 100644
--- a/net/openbgpd/files/patch-bgpctl_bgpctl.8
+++ b/net/openbgpd/files/patch-bgpctl_bgpctl.8
@@ -2,10 +2,10 @@ Index: bgpctl/bgpctl.8
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/bgpctl.8,v
retrieving revision 1.1.1.6
-retrieving revision 1.4
-diff -u -p -r1.1.1.6 -r1.4
+retrieving revision 1.5
+diff -u -p -r1.1.1.6 -r1.5
--- bgpctl/bgpctl.8 14 Feb 2010 20:20:13 -0000 1.1.1.6
-+++ bgpctl/bgpctl.8 4 Feb 2010 16:22:26 -0000 1.4
++++ bgpctl/bgpctl.8 2 Jul 2011 16:06:35 -0000 1.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: bgpctl.8,v 1.49 2009/06/06 06:11:17 claudio Exp $
+.\" $OpenBSD: bgpctl.8,v 1.52 2009/11/03 08:09:15 jmc Exp $
@@ -17,11 +17,45 @@ diff -u -p -r1.1.1.6 -r1.4
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: June 6 2009 $
-+.Dd $Mdocdate: November 2 2009 $
++.Dd $Mdocdate: May 3 2010 $
.Dt BGPCTL 8
.Os
.Sh NAME
-@@ -79,7 +79,15 @@ The options are as follows:
+@@ -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.
@@ -37,7 +71,48 @@ diff -u -p -r1.1.1.6 -r1.4
.It Cm neighbor Ar peer Cm up
Take the BGP session to the specified neighbor up.
.Ar peer
-@@ -246,7 +254,7 @@ in a terse format.
+@@ -98,8 +113,10 @@ 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
+@@ -122,7 +139,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,6 +150,14 @@ 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.
+@@ -243,10 +268,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
diff --git a/net/openbgpd/files/patch-bgpctl_bgpctl.c b/net/openbgpd/files/patch-bgpctl_bgpctl.c
index a55bb3e66674..4497b055410f 100644
--- a/net/openbgpd/files/patch-bgpctl_bgpctl.c
+++ b/net/openbgpd/files/patch-bgpctl_bgpctl.c
@@ -2,10 +2,10 @@ Index: bgpctl/bgpctl.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/bgpctl.c,v
retrieving revision 1.1.1.7
-retrieving revision 1.7
-diff -u -p -r1.1.1.7 -r1.7
+retrieving revision 1.8
+diff -u -p -r1.1.1.7 -r1.8
--- bgpctl/bgpctl.c 14 Feb 2010 20:20:14 -0000 1.1.1.7
-+++ bgpctl/bgpctl.c 10 Apr 2010 12:17:18 -0000 1.7
++++ bgpctl/bgpctl.c 2 Jul 2011 16:06:35 -0000 1.8
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpctl.c,v 1.142 2009/06/06 06:33:15 eric Exp $ */
+/* $OpenBSD: bgpctl.c,v 1.157 2010/03/08 17:02:19 claudio Exp $ */
@@ -55,7 +55,7 @@ diff -u -p -r1.1.1.7 -r1.7
enum neighbor_views {
NV_DEFAULT,
NV_TIMERS
-@@ -50,7 +66,7 @@ int show_summary_msg(struct imsg *, in
+@@ -50,12 +66,13 @@ 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);
@@ -64,7 +64,13 @@ diff -u -p -r1.1.1.7 -r1.7
void print_neighbor_msgstats(struct peer *);
void print_timer(const char *, time_t);
static char *fmt_timeframe(time_t t);
-@@ -65,7 +81,7 @@ void show_interface_head(void);
+ 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 +82,7 @@ void show_interface_head(void);
int ift2ifm(int);
const char * get_media_descr(int);
const char * get_linkstate(int, int);
@@ -73,7 +79,7 @@ diff -u -p -r1.1.1.7 -r1.7
int show_interface_msg(struct imsg *);
void show_rib_summary_head(void);
void print_prefix(struct bgpd_addr *, u_int8_t, u_int8_t);
-@@ -74,7 +90,6 @@ void print_flags(u_int8_t, int);
+@@ -74,7 +91,6 @@ void print_flags(u_int8_t, int);
int show_rib_summary_msg(struct imsg *);
int show_rib_detail_msg(struct imsg *, int);
void show_community(u_char *, u_int16_t);
@@ -81,7 +87,7 @@ diff -u -p -r1.1.1.7 -r1.7
void show_ext_community(u_char *, u_int16_t);
char *fmt_mem(int64_t);
int show_rib_memory_msg(struct imsg *);
-@@ -98,7 +113,7 @@ int
+@@ -98,7 +114,7 @@ int
main(int argc, char *argv[])
{
struct sockaddr_un sun;
@@ -90,7 +96,7 @@ diff -u -p -r1.1.1.7 -r1.7
struct imsg imsg;
struct network_config net;
struct parse_result *res;
-@@ -128,8 +143,11 @@ main(int argc, char *argv[])
+@@ -128,8 +144,11 @@ main(int argc, char *argv[])
if ((res = parse(argc, argv)) == NULL)
exit(1);
@@ -103,19 +109,23 @@ diff -u -p -r1.1.1.7 -r1.7
memcpy(&neighbor.addr, &res->peeraddr, sizeof(neighbor.addr));
strlcpy(neighbor.descr, res->peerdesc, sizeof(neighbor.descr));
-@@ -164,15 +182,17 @@ main(int argc, char *argv[])
+@@ -164,24 +183,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 buf *msg;
++ struct ibuf *msg;
+ sa_family_t af;
-
++
+ af = aid2af(res->aid);
- if ((msg = imsg_create(ibuf, IMSG_CTL_KROUTE, 0, 0,
-- sizeof(res->flags) + sizeof(res->af))) == NULL)
-+ sizeof(res->flags) + sizeof(af))) == NULL)
++ 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 ||
@@ -124,7 +134,24 @@ diff -u -p -r1.1.1.7 -r1.7
errx(1, "imsg_add failure");
imsg_close(ibuf, msg);
} else
-@@ -192,7 +212,7 @@ main(int argc, char *argv[])
+- 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 +219,7 @@ main(int argc, char *argv[])
case SHOW_NEIGHBOR_TIMERS:
case SHOW_NEIGHBOR_TERSE:
neighbor.show_timers = (res->action == SHOW_NEIGHBOR_TIMERS);
@@ -133,7 +160,7 @@ diff -u -p -r1.1.1.7 -r1.7
imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1,
&neighbor, sizeof(neighbor));
else
-@@ -206,7 +226,7 @@ main(int argc, char *argv[])
+@@ -206,7 +233,7 @@ main(int argc, char *argv[])
memcpy(&ribreq.as, &res->as, sizeof(res->as));
type = IMSG_CTL_SHOW_RIB_AS;
}
@@ -142,7 +169,7 @@ diff -u -p -r1.1.1.7 -r1.7
memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr));
ribreq.prefixlen = res->prefixlen;
type = IMSG_CTL_SHOW_RIB_PREFIX;
-@@ -220,7 +240,7 @@ main(int argc, char *argv[])
+@@ -220,7 +247,7 @@ main(int argc, char *argv[])
memcpy(&ribreq.neighbor, &neighbor,
sizeof(ribreq.neighbor));
strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib));
@@ -151,7 +178,24 @@ diff -u -p -r1.1.1.7 -r1.7
ribreq.flags = res->flags;
imsg_compose(ibuf, type, 0, 0, -1, &ribreq, sizeof(ribreq));
if (!(res->flags & F_CTL_DETAIL))
-@@ -290,12 +310,21 @@ main(int argc, char *argv[])
+@@ -237,12 +264,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 +319,21 @@ main(int argc, char *argv[])
break;
case NETWORK_SHOW:
bzero(&ribreq, sizeof(ribreq));
@@ -174,7 +218,7 @@ diff -u -p -r1.1.1.7 -r1.7
}
while (ibuf->w.queued)
-@@ -304,13 +333,13 @@ main(int argc, char *argv[])
+@@ -304,13 +342,13 @@ main(int argc, char *argv[])
while (!done) {
if ((n = imsg_read(ibuf)) == -1)
@@ -190,7 +234,26 @@ diff -u -p -r1.1.1.7 -r1.7
if (n == 0)
break;
-@@ -373,6 +402,8 @@ main(int argc, char *argv[])
+@@ -329,6 +367,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 +396,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 +410,8 @@ main(int argc, char *argv[])
case NETWORK_REMOVE:
case NETWORK_FLUSH:
case IRRFILTER:
@@ -199,7 +262,7 @@ diff -u -p -r1.1.1.7 -r1.7
break;
}
imsg_free(&imsg);
-@@ -398,8 +429,8 @@ fmt_peer(const char *descr, const struct
+@@ -398,8 +437,8 @@ fmt_peer(const char *descr, const struct
}
ip = log_addr(remote_addr);
@@ -210,7 +273,7 @@ diff -u -p -r1.1.1.7 -r1.7
if (asprintf(&p, "%s/%u", ip, masklen) == -1)
err(1, NULL);
} else {
-@@ -521,13 +552,15 @@ show_neighbor_msg(struct imsg *imsg, enu
+@@ -521,13 +560,15 @@ show_neighbor_msg(struct imsg *imsg, enu
struct ctl_timer *t;
struct in_addr ina;
char buf[NI_MAXHOST], pbuf[NI_MAXSERV], *s;
@@ -228,7 +291,7 @@ diff -u -p -r1.1.1.7 -r1.7
p->conf.remote_masklen != 128)) {
if (asprintf(&s, "%s/%u",
log_addr(&p->conf.remote_addr),
-@@ -549,6 +582,10 @@ show_neighbor_msg(struct imsg *imsg, enu
+@@ -549,6 +590,10 @@ show_neighbor_msg(struct imsg *imsg, enu
printf(", Template");
if (p->conf.cloned)
printf(", Cloned");
@@ -239,7 +302,7 @@ diff -u -p -r1.1.1.7 -r1.7
printf("\n");
if (p->conf.descr[0])
printf(" Description: %s\n", p->conf.descr);
-@@ -563,17 +600,16 @@ show_neighbor_msg(struct imsg *imsg, enu
+@@ -563,17 +608,16 @@ 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);
@@ -266,7 +329,7 @@ diff -u -p -r1.1.1.7 -r1.7
}
if (p->capa.peer.refresh)
printf(" Route Refresh\n");
-@@ -633,20 +669,16 @@ show_neighbor_msg(struct imsg *imsg, enu
+@@ -633,20 +677,16 @@ show_neighbor_msg(struct imsg *imsg, enu
}
void
@@ -296,7 +359,7 @@ diff -u -p -r1.1.1.7 -r1.7
}
void
-@@ -680,7 +712,7 @@ print_neighbor_msgstats(struct peer *p)
+@@ -680,7 +720,7 @@ print_neighbor_msgstats(struct peer *p)
}
void
@@ -305,7 +368,95 @@ diff -u -p -r1.1.1.7 -r1.7
{
printf(" %-20s ", name);
-@@ -848,35 +880,70 @@ show_fib_msg(struct imsg *imsg)
+@@ -745,6 +785,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 +834,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;
++ kt = imsg->data;
+
+- show_fib_flags(k6->flags);
+-
+- 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 +882,70 @@ show_fib_msg(struct imsg *imsg)
void
show_nexthop_head(void)
{
@@ -385,7 +536,7 @@ diff -u -p -r1.1.1.7 -r1.7
+ } 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,
++ if (asprintf(&s, "%s (%s%s)", p->kif.ifname,
+ p->kif.flags & IFF_UP ? "UP" : "DOWN", s1) == -1)
+ err(1, NULL);
+ printf("%-15s", s);
@@ -394,7 +545,7 @@ diff -u -p -r1.1.1.7 -r1.7
}
printf("\n");
break;
-@@ -898,9 +965,8 @@ show_interface_head(void)
+@@ -898,9 +967,8 @@ show_interface_head(void)
"Link state");
}
@@ -406,7 +557,7 @@ diff -u -p -r1.1.1.7 -r1.7
const struct ifmedia_description
ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
-@@ -936,36 +1002,36 @@ get_media_descr(int media_type)
+@@ -936,36 +1004,36 @@ get_media_descr(int media_type)
const char *
get_linkstate(int media_type, int link_state)
{
@@ -465,7 +616,7 @@ diff -u -p -r1.1.1.7 -r1.7
}
int
-@@ -982,17 +1048,12 @@ show_interface_msg(struct imsg *imsg)
+@@ -982,17 +1050,12 @@ show_interface_msg(struct imsg *imsg)
printf("%-15s", k->flags & IFF_UP ? "UP" : "");
if ((ifms_type = ift2ifm(k->media_type)) != 0)
@@ -488,7 +639,7 @@ diff -u -p -r1.1.1.7 -r1.7
printf("\n");
break;
case IMSG_CTL_END:
-@@ -1011,7 +1072,7 @@ show_rib_summary_head(void)
+@@ -1011,7 +1074,7 @@ show_rib_summary_head(void)
printf(
"flags: * = Valid, > = Selected, I = via IBGP, A = Announced\n");
printf("origin: i = IGP, e = EGP, ? = Incomplete\n\n");
@@ -497,7 +648,42 @@ diff -u -p -r1.1.1.7 -r1.7
"gateway", "lpref", "med", "aspath origin");
}
-@@ -1085,7 +1146,7 @@ show_rib_summary_msg(struct imsg *imsg)
+@@ -1049,26 +1112,26 @@ 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_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_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");
+ }
+ }
+@@ -1085,7 +1148,7 @@ show_rib_summary_msg(struct imsg *imsg)
memcpy(&rib, imsg->data, sizeof(rib));
print_prefix(&rib.prefix, rib.prefixlen, rib.flags);
@@ -506,16 +692,18 @@ diff -u -p -r1.1.1.7 -r1.7
printf(" %5u %5u ", rib.local_pref, rib.med);
-@@ -1190,7 +1251,7 @@ show_rib_detail_msg(struct imsg *imsg, i
+@@ -1189,8 +1252,8 @@ show_rib_detail_msg(struct imsg *imsg, i
+ case ATTR_AGGREGATOR:
memcpy(&as, data, sizeof(as));
memcpy(&id, data + sizeof(as), sizeof(id));
- printf(" Aggregator: %s [%s]\n",
+- printf(" Aggregator: %s [%s]\n",
- log_as(htonl(as)), inet_ntoa(id));
++ printf(" Aggregator: %s [%s]\n",
+ log_as(ntohl(as)), inet_ntoa(id));
break;
case ATTR_ORIGINATOR_ID:
memcpy(&id, data, sizeof(id));
-@@ -1236,22 +1297,27 @@ fmt_mem(int64_t num)
+@@ -1236,22 +1299,27 @@ fmt_mem(int64_t num)
return (buf);
}
@@ -550,7 +738,7 @@ diff -u -p -r1.1.1.7 -r1.7
printf("%10lld rib entries using %s of memory\n",
(long long)stats.rib_cnt, fmt_mem(stats.rib_cnt *
sizeof(struct rib_entry)));
-@@ -1272,9 +1338,7 @@ show_rib_memory_msg(struct imsg *imsg)
+@@ -1272,9 +1340,7 @@ show_rib_memory_msg(struct imsg *imsg)
(long long)stats.attr_refs);
printf("%10lld BGP attributes using %s of memory\n",
(long long)stats.attr_dcnt, fmt_mem(stats.attr_data));
@@ -561,7 +749,7 @@ diff -u -p -r1.1.1.7 -r1.7
stats.prefix_cnt * sizeof(struct prefix) +
stats.rib_cnt * sizeof(struct rib_entry) +
stats.path_cnt * sizeof(struct rde_aspath) +
-@@ -1328,30 +1392,6 @@ show_community(u_char *data, u_int16_t l
+@@ -1328,30 +1394,6 @@ show_community(u_char *data, u_int16_t l
}
}
@@ -592,7 +780,7 @@ diff -u -p -r1.1.1.7 -r1.7
void
show_ext_community(u_char *data, u_int16_t len)
{
-@@ -1372,24 +1412,25 @@ show_ext_community(u_char *data, u_int16
+@@ -1372,28 +1414,29 @@ 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));
@@ -620,7 +808,12 @@ diff -u -p -r1.1.1.7 -r1.7
memcpy(&ext, data + i, sizeof(ext));
ext = betoh64(ext) & 0xffffffffffffLL;
- printf("%s 0x%llx", get_ext_subtype(subtype), ext);
-+ printf("%s 0x%llx", log_ext_subtype(subtype), ext);
++ printf("%s 0x%llx", log_ext_subtype(subtype), ext);
break;
default:
memcpy(&ext, data + i, sizeof(ext));
+- printf("0x%llx", betoh64(ext));
++ printf("0x%llx", betoh64(ext));
+ }
+ if (i + 8 < len)
+ printf(", ");
diff --git a/net/openbgpd/files/patch-bgpctl_irr_prefix.c b/net/openbgpd/files/patch-bgpctl_irr_prefix.c
index 2d1d5217c4cc..da541297f183 100644
--- a/net/openbgpd/files/patch-bgpctl_irr_prefix.c
+++ b/net/openbgpd/files/patch-bgpctl_irr_prefix.c
@@ -2,13 +2,13 @@ Index: bgpctl/irr_prefix.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_prefix.c,v
retrieving revision 1.1.1.5
-retrieving revision 1.1.1.6
-diff -u -p -r1.1.1.5 -r1.1.1.6
+retrieving revision 1.1.1.7
+diff -u -p -r1.1.1.5 -r1.1.1.7
--- bgpctl/irr_prefix.c 14 Feb 2010 20:20:14 -0000 1.1.1.5
-+++ bgpctl/irr_prefix.c 14 Feb 2010 20:27:21 -0000 1.1.1.6
++++ bgpctl/irr_prefix.c 12 Jun 2011 10:44:54 -0000 1.1.1.7
@@ -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 $ */
++/* $OpenBSD: irr_prefix.c,v 1.18 2010/05/10 02:00:50 krw Exp $ */
/*
* Copyright (c) 2007 Henning Brauer <henning@openbsd.org>
@@ -112,7 +112,8 @@ diff -u -p -r1.1.1.5 -r1.1.1.6
+ return (1);
+ }
- /* see wether we can fold them in one */
+- /* 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) ==
diff --git a/net/openbgpd/files/patch-bgpctl_parser.c b/net/openbgpd/files/patch-bgpctl_parser.c
index 5efa4ce8cd49..237c6ffc9b92 100644
--- a/net/openbgpd/files/patch-bgpctl_parser.c
+++ b/net/openbgpd/files/patch-bgpctl_parser.c
@@ -2,10 +2,10 @@ Index: bgpctl/parser.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/parser.c,v
retrieving revision 1.1.1.6
-retrieving revision 1.5
-diff -u -p -r1.1.1.6 -r1.5
+retrieving revision 1.6
+diff -u -p -r1.1.1.6 -r1.6
--- bgpctl/parser.c 14 Feb 2010 20:20:14 -0000 1.1.1.6
-+++ bgpctl/parser.c 10 Apr 2010 12:17:18 -0000 1.5
++++ bgpctl/parser.c 2 Jul 2011 16:06:35 -0000 1.6
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.c,v 1.54 2009/06/12 16:44:02 claudio Exp $ */
+/* $OpenBSD: parser.c,v 1.61 2010/03/08 17:02:19 claudio Exp $ */
@@ -23,15 +23,27 @@ diff -u -p -r1.1.1.6 -r1.5
#include <sys/types.h>
#include <sys/socket.h>
-@@ -97,6 +101,7 @@ static const struct token t_prepself[];
+@@ -52,7 +56,8 @@ enum token_type {
+ PREPSELF,
+ WEIGHT,
+ FAMILY,
+- GETOPT
++ GETOPT,
++ RTABLE
+ };
+
+ enum getopts {
+@@ -97,6 +102,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 +110,7 @@ static const struct token t_main[] = {
+@@ -105,6 +113,7 @@ static const struct token t_main[] = {
{ KEYWORD, "neighbor", NEIGHBOR, t_neighbor},
{ KEYWORD, "network", NONE, t_network},
{ KEYWORD, "irrfilter", IRRFILTER, t_irrfilter},
@@ -39,7 +51,47 @@ diff -u -p -r1.1.1.6 -r1.5
{ ENDTOKEN, "", NONE, NULL}
};
-@@ -311,6 +317,12 @@ static const struct token t_irrfilter_op
+@@ -116,6 +125,7 @@ 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},
+ { ENDTOKEN, "", NONE, NULL}
+@@ -128,14 +138,15 @@ 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[] = {
+@@ -187,6 +198,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}
+ };
+
+@@ -311,6 +323,22 @@ static const struct token t_irrfilter_op
{ ENDTOKEN, "", NONE, NULL}
};
@@ -49,10 +101,20 @@ diff -u -p -r1.1.1.6 -r1.5
+ { 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 +416,22 @@ match_token(int *argc, char **argv[], co
+@@ -404,15 +432,22 @@ match_token(int *argc, char **argv[], co
case FAMILY:
if (word == NULL)
break;
@@ -79,7 +141,25 @@ diff -u -p -r1.1.1.6 -r1.5
}
break;
case ADDRESS:
-@@ -584,7 +603,7 @@ show_valid_args(const struct token table
+@@ -485,6 +520,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++;
+@@ -577,6 +613,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,7 +623,7 @@ show_valid_args(const struct token table
fprintf(stderr, " <pftable>\n");
break;
case FAMILY:
@@ -88,7 +168,7 @@ diff -u -p -r1.1.1.6 -r1.5
break;
case GETOPT:
fprintf(stderr, " <options>\n");
-@@ -608,7 +627,7 @@ parse_addr(const char *word, struct bgpd
+@@ -608,7 +647,7 @@ parse_addr(const char *word, struct bgpd
bzero(&ina, sizeof(ina));
if (inet_net_pton(AF_INET, word, &ina, sizeof(ina)) != -1) {
@@ -97,7 +177,7 @@ diff -u -p -r1.1.1.6 -r1.5
addr->v4 = ina;
return (1);
}
-@@ -618,13 +637,7 @@ parse_addr(const char *word, struct bgpd
+@@ -618,13 +657,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) {
@@ -112,7 +192,7 @@ diff -u -p -r1.1.1.6 -r1.5
freeaddrinfo(r);
return (1);
}
-@@ -663,15 +676,15 @@ parse_prefix(const char *word, struct bg
+@@ -663,15 +696,15 @@ parse_prefix(const char *word, struct bg
if (parse_addr(word, addr) == 0)
return (0);
@@ -131,7 +211,7 @@ diff -u -p -r1.1.1.6 -r1.5
if (mask == -1)
mask = 128;
inet6applymask(&addr->v6, &addr->v6, mask);
-@@ -706,7 +719,7 @@ parse_asnum(const char *word, u_int32_t
+@@ -706,7 +739,7 @@ parse_asnum(const char *word, u_int32_t
if (errstr)
errx(1, "AS number is %s: %s", errstr, word);
} else {
@@ -140,7 +220,19 @@ diff -u -p -r1.1.1.6 -r1.5
if (errstr)
errx(1, "AS number is %s: %s", errstr, word);
}
-@@ -882,8 +895,14 @@ bgpctl_getopt(int *argc, char **argv[],
+@@ -730,6 +763,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 +920,14 @@ bgpctl_getopt(int *argc, char **argv[],
int ch;
optind = optreset = 1;
diff --git a/net/openbgpd/files/patch-bgpctl_parser.h b/net/openbgpd/files/patch-bgpctl_parser.h
index a3bb1fede7af..bf86d255a853 100644
--- a/net/openbgpd/files/patch-bgpctl_parser.h
+++ b/net/openbgpd/files/patch-bgpctl_parser.h
@@ -2,17 +2,25 @@ 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.7
-diff -u -p -r1.1.1.6 -r1.1.1.7
+retrieving revision 1.1.1.8
+diff -u -p -r1.1.1.6 -r1.1.1.8
--- bgpctl/parser.h 14 Feb 2010 20:20:14 -0000 1.1.1.6
-+++ bgpctl/parser.h 14 Feb 2010 20:27:21 -0000 1.1.1.7
++++ bgpctl/parser.h 12 Jun 2011 10:44:54 -0000 1.1.1.8
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.h,v 1.19 2009/06/06 06:05:41 claudio Exp $ */
-+/* $OpenBSD: parser.h,v 1.21 2010/01/10 00:16:23 claudio Exp $ */
++/* $OpenBSD: parser.h,v 1.22 2010/05/03 13:11:41 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
-@@ -37,6 +37,8 @@ enum actions {
+@@ -29,6 +29,7 @@ enum actions {
+ SHOW_NEIGHBOR_TIMERS,
+ SHOW_NEIGHBOR_TERSE,
+ SHOW_FIB,
++ SHOW_FIB_TABLES,
+ SHOW_RIB,
+ SHOW_RIB_MEM,
+ SHOW_NEXTHOP,
+@@ -37,6 +38,8 @@ enum actions {
FIB,
FIB_COUPLE,
FIB_DECOUPLE,
@@ -21,9 +29,13 @@ diff -u -p -r1.1.1.6 -r1.1.1.7
NEIGHBOR,
NEIGHBOR_UP,
NEIGHBOR_DOWN,
-@@ -61,7 +63,7 @@ struct parse_result {
+@@ -59,9 +62,10 @@ struct parse_result {
+ char rib[PEER_DESCR_LEN];
+ char *irr_outdir;
int flags;
- enum actions action;
+- enum actions action;
++ u_int rtableid;
++ enum actions action;
u_int8_t prefixlen;
- sa_family_t af;
+ u_int8_t aid;
diff --git a/net/openbgpd/files/patch-bgpd_Makefile b/net/openbgpd/files/patch-bgpd_Makefile
index a7289abf0dc4..9bc06ffb1090 100644
--- a/net/openbgpd/files/patch-bgpd_Makefile
+++ b/net/openbgpd/files/patch-bgpd_Makefile
@@ -2,25 +2,29 @@ Index: bgpd/Makefile
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/Makefile,v
retrieving revision 1.1.1.2
-retrieving revision 1.6
-diff -u -p -r1.1.1.2 -r1.6
+retrieving revision 1.8
+diff -u -p -r1.1.1.2 -r1.8
--- bgpd/Makefile 9 Jul 2009 16:49:54 -0000 1.1.1.2
-+++ bgpd/Makefile 9 Jul 2009 17:22:14 -0000 1.6
-@@ -1,15 +1,23 @@
- # $OpenBSD: Makefile,v 1.28 2009/06/25 14:14:54 deraadt Exp $
-
++++ bgpd/Makefile 3 Jul 2011 04:46:36 -0000 1.8
+@@ -1,15 +1,25 @@
+-# $OpenBSD: Makefile,v 1.28 2009/06/25 14:14:54 deraadt Exp $
++# $OpenBSD: Makefile,v 1.29 2010/05/26 16:44:32 nicm Exp $
++
+.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 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
+ control.c pfkey_compat.c rde_update.c rde_attr.c printconf.c \
- rde_filter.c pftable.c name2id.c util.c carp.c timer.c
--CFLAGS+= -Wall -I${.CURDIR}
-+CFLAGS+= -Wall -I${.CURDIR} -I${.CURDIR}/../openbsd-compat
++ 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
diff --git a/net/openbgpd/files/patch-bgpd_bgpd.8 b/net/openbgpd/files/patch-bgpd_bgpd.8
index aa748ec1035f..e666cb96d92c 100644
--- a/net/openbgpd/files/patch-bgpd_bgpd.8
+++ b/net/openbgpd/files/patch-bgpd_bgpd.8
@@ -2,10 +2,10 @@ Index: bgpd/bgpd.8
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.8,v
retrieving revision 1.1.1.8
-retrieving revision 1.8
-diff -u -p -r1.1.1.8 -r1.8
+retrieving revision 1.9
+diff -u -p -r1.1.1.8 -r1.9
--- bgpd/bgpd.8 14 Feb 2010 20:19:57 -0000 1.1.1.8
-+++ bgpd/bgpd.8 2 Mar 2010 05:48:19 -0000 1.8
++++ bgpd/bgpd.8 2 Jul 2011 16:06:38 -0000 1.9
@@ -1,4 +1,4 @@
-.\" $OpenBSD: bgpd.8,v 1.28 2009/01/13 23:01:36 sthen Exp $
+.\" $OpenBSD: bgpd.8,v 1.33 2009/12/16 15:40:55 claudio Exp $
@@ -17,24 +17,32 @@ diff -u -p -r1.1.1.8 -r1.8
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: January 13 2009 $
-+.Dd $Mdocdate: December 16 2009 $
++.Dd $Mdocdate: June 27 2010 $
.Dt BGPD 8
.Os
.Sh NAME
-@@ -24,9 +24,9 @@
+@@ -24,12 +24,8 @@
.Nm bgpd
.Bk -words
.Op Fl cdnv
-.Oo Xo
-.Fl D Ar macro Ns = Ns Ar value Oc
-.Xc
-+.Oo
-+.Fl D Ar macro Ns = Ns Ar value
-+.Oc
++.Op Fl D Ar macro Ns = Ns Ar value
.Op Fl f Ar file
- .Op Fl r Ar path
- .Op Fl s Ar path
-@@ -48,9 +48,9 @@ Please refer to that document for more i
+-.Op Fl r Ar path
+-.Op Fl s Ar path
+ .Ek
+ .Sh DESCRIPTION
+ .Nm
+@@ -42,15 +38,15 @@ concerning
+ with other BGP systems.
+ .Nm
+ uses the Border Gateway Protocol, Version 4,
+-as described in RFC 1771.
++as described in RFC 4271.
+ Please refer to that document for more information about BGP.
+ .Pp
.Nm
is usually started at boot time, and can be enabled by
setting the following in
@@ -46,7 +54,7 @@ diff -u -p -r1.1.1.8 -r1.8
.Pp
See
.Xr rc 8
-@@ -117,7 +117,7 @@ Use
+@@ -117,25 +113,16 @@ Use
.Ar file
as the configuration file,
instead of the default
@@ -55,7 +63,17 @@ diff -u -p -r1.1.1.8 -r1.8
.It Fl n
Configtest mode.
Only check the configuration file for validity.
-@@ -135,7 +135,7 @@ Produce more verbose output.
+-.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
@@ -64,7 +82,19 @@ diff -u -p -r1.1.1.8 -r1.8
default
.Nm
configuration file
-@@ -165,6 +165,11 @@ control socket
+@@ -150,9 +137,9 @@ control socket
+ .Xr bgplg 8 ,
+ .Xr bgplgsh 8
+ .Rs
+-.%R RFC 1771
++.%R RFC 4271
+ .%T "A Border Gateway Protocol 4 (BGP-4)"
+-.%D March 1995
++.%D January 2006
+ .Re
+ .Rs
+ .%R RFC 1997
+@@ -165,6 +152,11 @@ control socket
.%D August 1998
.Re
.Rs
@@ -76,7 +106,7 @@ diff -u -p -r1.1.1.8 -r1.8
.%R RFC 2796
.%T "BGP Route Reflection - An Alternative to Full Mesh IBGP"
.%D April 2000
-@@ -175,11 +180,6 @@ control socket
+@@ -175,11 +167,6 @@ control socket
.%D September 2000
.Re
.Rs
@@ -88,7 +118,7 @@ diff -u -p -r1.1.1.8 -r1.8
.%R RFC 3682
.%T "The Generalized TTL Security Mechanism (GTSM)"
.%D February 2004
-@@ -190,6 +190,16 @@ control socket
+@@ -190,6 +177,21 @@ control socket
.%D April 2004
.Re
.Rs
@@ -97,6 +127,11 @@ diff -u -p -r1.1.1.8 -r1.8
+.%D February 2006
+.Re
+.Rs
++.%R RFC 4364
++.%T "BGP/MPLS IP Virtual Private Networks (VPNs)"
++.%D February 2006
++.Re
++.Rs
+.%R RFC 4486
+.%T "BGP Cease Notification Message Subcodes"
+.%D April 2006
@@ -105,7 +140,7 @@ diff -u -p -r1.1.1.8 -r1.8
.%R RFC 4760
.%T "Multiprotocol Extensions for BGP-4"
.%D January 2007
-@@ -199,6 +209,16 @@ control socket
+@@ -199,6 +201,21 @@ control socket
.%T "BGP Support for Four-octet AS Number Space"
.%D May 2007
.Re
@@ -119,6 +154,11 @@ diff -u -p -r1.1.1.8 -r1.8
+.%T "Error Handling for Optional Transitive BGP Attributes"
+.%D April 2009
+.Re
++.Rs
++.%R draft-ietf-idr-fsm-subcode-00
++.%T "Subcodes for BGP Finite State Machine Error"
++.%D September 2010
++.Re
.Sh HISTORY
The
.Nm
diff --git a/net/openbgpd/files/patch-bgpd_bgpd.c b/net/openbgpd/files/patch-bgpd_bgpd.c
index 788b053a2d48..73190ce9b93f 100644
--- a/net/openbgpd/files/patch-bgpd_bgpd.c
+++ b/net/openbgpd/files/patch-bgpd_bgpd.c
@@ -2,26 +2,71 @@ 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.9
-diff -u -p -r1.1.1.7 -r1.1.1.9
+diff -u -p -r1.1.1.7 bgpd.c
--- bgpd/bgpd.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/bgpd.c 10 Apr 2010 12:13:04 -0000 1.1.1.9
++++ bgpd/bgpd.c 3 Jul 2011 04:34:14 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.148 2009/06/07 00:30:23 claudio Exp $ */
-+/* $OpenBSD: bgpd.c,v 1.156 2010/03/29 09:09:25 claudio Exp $ */
++/* $OpenBSD: bgpd.c,v 1.167 2011/05/01 10:42:28 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
-@@ -42,7 +42,7 @@ int main(int, char *[]);
+@@ -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,22 @@ 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;
-@@ -101,15 +101,10 @@ int
+-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;
+ 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 +85,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 +100,10 @@ int
main(int argc, char *argv[])
{
struct bgpd_config conf;
@@ -38,7 +83,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
struct pollfd pfd[POLL_MAX];
pid_t io_pid = 0, rde_pid = 0, pid;
char *conffile;
-@@ -125,13 +120,8 @@ main(int argc, char *argv[])
+@@ -125,17 +119,11 @@ main(int argc, char *argv[])
log_init(1); /* log to stderr until daemonized */
@@ -50,17 +95,28 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
- TAILQ_INIT(&net_l);
- TAILQ_INIT(rules_l);
peer_l = NULL;
- conf.csock = SOCKET_NAME;
+- conf.csock = SOCKET_NAME;
-@@ -158,6 +148,7 @@ main(int argc, char *argv[])
+- 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 +146,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;
- case 'r':
- conf.rcsock = optarg;
-@@ -176,14 +167,16 @@ main(int argc, char *argv[])
+ default:
+ usage();
+@@ -176,24 +159,22 @@ main(int argc, char *argv[])
if (argc > 0)
usage();
@@ -71,19 +127,31 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
-
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))
++ &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);
++ &mrt_l, &rdom_l);
else
fprintf(stderr, "configuration OK\n");
-@@ -225,13 +218,10 @@ main(int argc, char *argv[])
+ exit(0);
+ }
+- cflags = conf.flags;
+- connectset = &conf.connectset;
+- staticset = &conf.staticset;
+- connectset6 = &conf.connectset6;
+- staticset6 = &conf.staticset6;
+
+ if (geteuid())
+ errx(1, "need root privileges");
+@@ -225,13 +206,9 @@ main(int argc, char *argv[])
session_socket_blockmode(pipe_s2r_c[0], BM_NONBLOCK);
session_socket_blockmode(pipe_s2r_c[1], BM_NONBLOCK);
@@ -95,19 +163,19 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
- 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,
-+ conf.csock, conf.rcsock);
++ io_pid = session_main(pipe_m2s, pipe_s2r, pipe_m2r, pipe_s2r_c);
setproctitle("parent");
-@@ -254,33 +244,13 @@ main(int argc, char *argv[])
+@@ -254,33 +231,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);
-+ quit = reconfigure(conffile, &conf, &mrt_l, &peer_l);
- if ((rfd = kr_init(!(conf.flags & BGPD_FLAG_NO_FIB_UPDATE),
- conf.rtableid)) == -1)
+- 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;
@@ -135,7 +203,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
while (quit == 0) {
bzero(pfd, sizeof(pfd));
pfd[PFD_PIPE_SESSION].fd = ibuf_se->fd;
-@@ -336,8 +306,7 @@ main(int argc, char *argv[])
+@@ -336,8 +292,7 @@ main(int argc, char *argv[])
reconfig = 0;
log_info("rereading config");
@@ -145,7 +213,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
case -1: /* fatal error */
quit = 1;
break;
-@@ -389,13 +358,13 @@ main(int argc, char *argv[])
+@@ -389,13 +344,13 @@ main(int argc, char *argv[])
LIST_REMOVE(m, entry);
free(m);
}
@@ -165,7 +233,16 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
control_cleanup(conf.csock);
control_cleanup(conf.rcsock);
carp_demote_shutdown();
-@@ -452,18 +421,23 @@ send_filterset(struct imsgbuf *i, struct
+@@ -413,6 +368,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 +409,25 @@ send_filterset(struct imsgbuf *i, struct
int
reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l,
@@ -173,41 +250,168 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
+ struct peer **peer_l)
{
struct network_head net_l;
+- struct network *n;
++ struct rdomain_head rdom_l;
+ struct filter_head rules_l;
- struct network *n;
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 (parse_config(conffile, conf, mrt_l, peer_l, &net_l, &rules_l)) {
++ 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);
-+ while ((rr = SIMPLEQ_FIRST(&ribnames))) {
-+ SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
-+ free(rr);
-+ }
return (1);
}
-@@ -525,13 +499,13 @@ reconfigure(char *conffile, struct bgpd_
+ cflags = conf->flags;
+- connectset = &conf->connectset;
+- staticset = &conf->staticset;
+- connectset6 = &conf->connectset6;
+- staticset6 = &conf->staticset6;
+-
+ prepare_listeners(conf);
+
+ /* start reconfiguration */
+@@ -483,12 +438,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 +445,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);
-+ TAILQ_REMOVE(&rules_l, r, entry);
filterset_free(&r->set);
free(r);
}
-@@ -550,8 +524,8 @@ int
+
++ 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 +552,8 @@ int
dispatch_imsg(struct imsgbuf *ibuf, int idx)
{
struct imsg imsg;
@@ -218,7 +422,94 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
if ((n = imsg_read(ibuf)) == -1)
return (-1);
-@@ -692,6 +666,11 @@ dispatch_imsg(struct imsgbuf *ibuf, int
+@@ -573,46 +575,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)
+@@ -654,18 +649,19 @@ dispatch_imsg(struct imsgbuf *ibuf, int
+ 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 +688,11 @@ dispatch_imsg(struct imsgbuf *ibuf, int
carp_demote_set(msg->demote_group, msg->level);
}
break;
@@ -230,7 +521,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
default:
break;
}
-@@ -707,7 +686,7 @@ send_nexthop_update(struct kroute_nextho
+@@ -707,7 +708,7 @@ send_nexthop_update(struct kroute_nextho
{
char *gw = NULL;
@@ -239,7 +530,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
if (asprintf(&gw, ": via %s",
log_addr(&msg->gateway)) == -1) {
log_warn("send_nexthop_update");
-@@ -717,7 +696,7 @@ send_nexthop_update(struct kroute_nextho
+@@ -717,7 +718,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" : "",
@@ -248,23 +539,110 @@ diff -u -p -r1.1.1.7 -r1.1.1.9
free(gw);
-@@ -758,17 +737,16 @@ bgpd_redistribute(int type, struct krout
- fatalx("bgpd_redistribute: unable to redistribute v4 and v6"
- "together");
- if (kr != NULL) {
+@@ -733,56 +734,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.aid = AID_INET;
- net.prefix.v4.s_addr = kr->prefix.s_addr;
- net.prefixlen = kr->prefixlen;
- }
- if (kr6 != NULL) {
+- net.prefix.v4.s_addr = kr->prefix.s_addr;
+- net.prefixlen = kr->prefixlen;
+- }
+- if (kr6 != NULL) {
- net.prefix.af = AF_INET6;
-+ net.prefix.aid = AID_INET6;
- memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr));
- net.prefixlen = kr6->prefixlen;
- }
-
+- 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,
++ 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 +775,45 @@ bgpd_filternexthop(struct kroute *kr, st
+
+ return (1);
+ }
++
++int
++control_setup(struct bgpd_config *conf)
++{
++ int fd, restricted;
++
++ /* control socket is outside chroot */
++ if (!cname || strcmp(cname, conf->csock)) {
++ if (cname) {
++ control_cleanup(cname);
++ free(cname);
++ }
++ if ((cname = strdup(conf->csock)) == NULL)
++ fatal("strdup");
++ if ((fd = control_init(0, cname)) == -1)
++ fatalx("control socket setup failed");
++ restricted = 0;
++ if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd,
++ &restricted, sizeof(restricted)) == -1)
++ return (-1);
++ }
++ if (!conf->rcsock) {
++ /* remove restricted socket */
++ control_cleanup(rcname);
++ free(rcname);
++ rcname = NULL;
++ } else if (!rcname || strcmp(rcname, conf->rcsock)) {
++ if (rcname) {
++ control_cleanup(rcname);
++ free(rcname);
++ }
++ if ((rcname = strdup(conf->rcsock)) == NULL)
++ fatal("strdup");
++ if ((fd = control_init(1, rcname)) == -1)
++ fatalx("control socket setup failed");
++ restricted = 1;
++ if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd,
++ &restricted, sizeof(restricted)) == -1)
++ return (-1);
++ }
++ return (0);
++}
diff --git a/net/openbgpd/files/patch-bgpd_bgpd.conf.5 b/net/openbgpd/files/patch-bgpd_bgpd.conf.5
index 3c658e499a18..3b8afd260fd6 100644
--- a/net/openbgpd/files/patch-bgpd_bgpd.conf.5
+++ b/net/openbgpd/files/patch-bgpd_bgpd.conf.5
@@ -2,10 +2,10 @@ 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.7
-diff -u -p -r1.1.1.7 -r1.7
+retrieving revision 1.8
+diff -u -p -r1.1.1.7 -r1.8
--- bgpd/bgpd.conf.5 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/bgpd.conf.5 10 Apr 2010 12:16:23 -0000 1.7
++++ bgpd/bgpd.conf.5 2 Jul 2011 16:06:38 -0000 1.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: bgpd.conf.5,v 1.94 2009/06/07 00:31:22 claudio Exp $
+.\" $OpenBSD: bgpd.conf.5,v 1.104 2010/03/05 15:25:00 claudio Exp $
@@ -17,11 +17,29 @@ diff -u -p -r1.1.1.7 -r1.7
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: June 7 2009 $
-+.Dd $Mdocdate: December 16 2009 $
++.Dd $Mdocdate: October 23 2010 $
.Dt BGPD.CONF 5
.Os
.Sh NAME
-@@ -93,7 +93,7 @@ Set the local
+@@ -26,7 +26,7 @@
+ The
+ .Xr bgpd 8
+ daemon implements the Border Gateway Protocol version 4 as described
+-in RFC 1771.
++in RFC 4271.
+ .Sh SECTIONS
+ The
+ .Nm
+@@ -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
+@@ -93,7 +95,7 @@ Set the local
.Em autonomous system
number to
.Ar as-number .
@@ -30,16 +48,86 @@ diff -u -p -r1.1.1.7 -r1.7
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.
-@@ -313,7 +313,7 @@ is only compared between peers belonging
+@@ -143,13 +145,13 @@ 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
+ .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
+@@ -195,7 +197,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 +244,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 +280,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,7 +297,7 @@ 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 ,
+@@ -313,20 +315,31 @@ is only compared between peers belonging
.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
-@@ -321,7 +321,7 @@ flag.
+ 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
@@ -48,12 +136,189 @@ diff -u -p -r1.1.1.7 -r1.7
.Pp
.It Xo
.Ic rde
-@@ -483,6 +483,17 @@ Only routes for that address family and
+ .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 +352,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 +374,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 +400,111 @@ 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 Route Distinguishers uniquely identifies a set of VPN prefixes.
++Only prefixes matching the
++.Ic rd
++will be imported into the routing domain.
++The purpose of the
++.Ic rd
++is solely to allow one to create distinct routes to a common address prefix.
++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.
++.Pp
++.El
+ .Sh NEIGHBORS AND GROUPS
+ .Xr bgpd 8
+ establishes TCP connections to other BGP speakers called
+@@ -470,21 +599,35 @@ The default for IBGP peers is
+ .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
++.Pq Ic yes Ns | Ns Ic no
+.Xc
+If set to
+.Ic no ,
@@ -64,15 +329,18 @@ diff -u -p -r1.1.1.7 -r1.7
+.Pp
+.It Xo
.Ic announce capabilities
- .Pq Ic yes Ns \&| Ns Ic no
+-.Pq Ic yes Ns \&| Ns Ic no
++.Pq Ic yes Ns | Ns Ic no
.Xc
-@@ -493,6 +504,29 @@ This can be helpful to connect to old or
+ If set to
+ .Ic no ,
+@@ -493,6 +636,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
++.Pq Ic yes Ns | Ns Ic no
+.Xc
+If set to
+.Ic no ,
@@ -82,7 +350,7 @@ diff -u -p -r1.1.1.7 -r1.7
+.Pp
+.It Xo
+.Ic announce restart
-+.Pq Ic yes Ns \&| Ns Ic no
++.Pq Ic yes Ns | Ns Ic no
+.Xc
+If set to
+.Ic yes ,
@@ -96,7 +364,7 @@ diff -u -p -r1.1.1.7 -r1.7
.It Ic demote Ar group
Increase the
.Xr carp 4
-@@ -504,7 +538,7 @@ The demotion counter will be increased a
+@@ -504,7 +670,7 @@ The demotion counter will be increased a
.Xr bgpd 8
starts and decreased
60 seconds after the session went to state
@@ -105,7 +373,27 @@ diff -u -p -r1.1.1.7 -r1.7
For neighbors added at runtime, the demotion counter is only increased after
the session has been
.Em ESTABLISHED
-@@ -589,6 +623,12 @@ Inherited from the global configuration
+@@ -548,8 +714,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 +730,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 +755,16 @@ Inherited from the global configuration
Set the minimal acceptable holdtime.
Inherited from the global configuration if not given.
.Pp
@@ -117,8 +405,23 @@ diff -u -p -r1.1.1.7 -r1.7
+.Pp
.It Xo
.Ic ipsec
- .Pq Ic ah Ns \&| Ns Ic esp
-@@ -639,11 +679,11 @@ is responsible for managing the session
+-.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 +799,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 +811,11 @@ is responsible for managing the session
With
.Xr isakmpd 8 ,
it is sufficient to copy the peer's public key, found in
@@ -132,7 +435,7 @@ diff -u -p -r1.1.1.7 -r1.7
The local public key must be copied to the peer in the same way.
As
.Xr bgpd 8
-@@ -698,7 +738,7 @@ Do not attempt to actively open a TCP co
+@@ -698,7 +870,7 @@ 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
@@ -141,10 +444,51 @@ diff -u -p -r1.1.1.7 -r1.7
Bind the neighbor to the specified RIB.
.Pp
.It Ic route-reflector Op Ar address
-@@ -917,6 +957,31 @@ may be set to
+@@ -732,8 +904,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 +932,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 +944,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 +1021,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 +1093,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
@@ -170,10 +514,45 @@ diff -u -p -r1.1.1.7 -r1.7
+section for further information about the encoding.
+.Pp
+.It Xo
- .Pq Ic from Ns \&| Ns Ic to
++.Pq Ic from Ns | Ns Ic to
.Ar peer
.Xc
-@@ -1028,6 +1093,12 @@ matches a rule which has the
+ This rule applies only to
+@@ -945,7 +1146,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 +1154,24 @@ 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 Xo
+ .Ic prefix
+ .Ar address Ns Li / Ns Ar len
+@@ -1028,6 +1247,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
@@ -186,7 +565,7 @@ diff -u -p -r1.1.1.7 -r1.7
.It Ic set Ar attribute ...
All matching rules can set the
.Em AS path attributes
-@@ -1079,6 +1150,48 @@ Alternately, well-known communities may
+@@ -1079,6 +1304,48 @@ Alternately, well-known communities may
or
.Ic NO_PEER .
.Pp
@@ -235,7 +614,7 @@ diff -u -p -r1.1.1.7 -r1.7
.It Ic localpref Ar number
Set the
.Em LOCAL_PREF
-@@ -1108,6 +1221,20 @@ otherwise it will be set to
+@@ -1108,6 +1375,20 @@ otherwise it will be set to
.Ar number .
.Pp
.It Xo
@@ -256,7 +635,19 @@ diff -u -p -r1.1.1.7 -r1.7
.Ic nexthop
.Sm off
.Po Ar address \*(Ba
-@@ -1181,8 +1308,8 @@ For prefixes with equally long paths, th
+@@ -1157,9 +1438,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 +1461,8 @@ For prefixes with equally long paths, th
is selected.
.El
.Sh FILES
diff --git a/net/openbgpd/files/patch-bgpd_bgpd.h b/net/openbgpd/files/patch-bgpd_bgpd.h
index d522bad36b14..c374b981553c 100644
--- a/net/openbgpd/files/patch-bgpd_bgpd.h
+++ b/net/openbgpd/files/patch-bgpd_bgpd.h
@@ -2,17 +2,25 @@ Index: bgpd/bgpd.h
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.h,v
retrieving revision 1.1.1.8
-retrieving revision 1.11
-diff -u -p -r1.1.1.8 -r1.11
+retrieving revision 1.12
+diff -u -p -r1.1.1.8 -r1.12
--- bgpd/bgpd.h 14 Feb 2010 20:19:57 -0000 1.1.1.8
-+++ bgpd/bgpd.h 10 Apr 2010 12:16:23 -0000 1.11
++++ bgpd/bgpd.h 2 Jul 2011 16:06:38 -0000 1.12
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.241 2009/06/12 16:42:53 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.255 2010/04/06 13:25:08 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
-@@ -30,11 +30,16 @@
+@@ -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>
@@ -30,7 +38,7 @@ diff -u -p -r1.1.1.8 -r1.11
#define BGPD_USER "_bgpd"
#define PEER_DESCR_LEN 32
#define PFTABLE_LEN 16
-@@ -42,8 +47,6 @@
+@@ -42,8 +48,6 @@
#define IPSEC_ENC_KEY_LEN 32
#define IPSEC_AUTH_KEY_LEN 20
@@ -39,7 +47,30 @@ diff -u -p -r1.1.1.8 -r1.11
#define MAX_PKTSIZE 4096
#define MIN_HOLDTIME 3
#define READ_BUF_SIZE 65535
-@@ -109,18 +112,74 @@ enum reconf_action {
+@@ -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,6 +82,8 @@
+ #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
+@@ -109,18 +110,74 @@ enum reconf_action {
RECONF_DELETE
};
@@ -118,7 +149,25 @@ diff -u -p -r1.1.1.8 -r1.11
#define addr8 ba.addr8
#define addr16 ba.addr16
#define addr32 ba.addr32
-@@ -205,11 +264,10 @@ struct peer_auth {
+@@ -141,17 +198,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,11 +257,10 @@ struct peer_auth {
};
struct capabilities {
@@ -134,7 +183,7 @@ diff -u -p -r1.1.1.8 -r1.11
};
struct peer_config {
-@@ -248,6 +306,7 @@ struct peer_config {
+@@ -248,21 +299,31 @@ struct peer_config {
u_int8_t ttlsec; /* TTL security hack */
u_int8_t flags;
u_int8_t pad[3];
@@ -142,15 +191,119 @@ diff -u -p -r1.1.1.8 -r1.11
};
#define PEERFLAG_TRANS_AS 0x01
-@@ -292,6 +351,7 @@ enum imsg_type {
+
++enum network_type {
++ NETWORK_DEFAULT,
++ NETWORK_STATIC,
++ NETWORK_CONNECTED
++};
++
+ struct network_config {
+ struct bgpd_addr prefix;
+ struct filter_set_head attrset;
++ u_int rtableid;
++ enum network_type type;
+ u_int8_t prefixlen;
++ u_int8_t old; /* used for reloading */
+ };
+
+ 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 +337,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,10 +348,11 @@ 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_REMOVE,
IMSG_NETWORK_FLUSH,
-@@ -400,14 +460,12 @@ struct kroute6 {
+@@ -302,6 +363,11 @@ 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,
+@@ -313,8 +379,6 @@ enum imsg_type {
+ IMSG_MRT_CLOSE,
+ IMSG_KROUTE_CHANGE,
+ IMSG_KROUTE_DELETE,
+- IMSG_KROUTE6_CHANGE,
+- IMSG_KROUTE6_DELETE,
+ IMSG_NEXTHOP_ADD,
+ IMSG_NEXTHOP_REMOVE,
+ IMSG_NEXTHOP_UPDATE,
+@@ -379,9 +443,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 +498,12 @@ struct kroute6 {
};
struct kroute_nexthop {
@@ -167,7 +320,7 @@ diff -u -p -r1.1.1.8 -r1.11
};
struct kif {
-@@ -423,8 +481,7 @@ struct kif {
+@@ -423,8 +519,7 @@ struct kif {
struct session_up {
struct bgpd_addr local_addr;
struct bgpd_addr remote_addr;
@@ -177,7 +330,7 @@ diff -u -p -r1.1.1.8 -r1.11
u_int32_t remote_bgpid;
u_int16_t short_as;
};
-@@ -437,8 +494,13 @@ struct pftable_msg {
+@@ -437,8 +532,13 @@ struct pftable_msg {
struct ctl_show_nexthop {
struct bgpd_addr addr;
@@ -188,14 +341,66 @@ diff -u -p -r1.1.1.8 -r1.11
+ struct kroute6 kr6;
+ } kr;
+ u_int8_t valid;
-+ u_int8_t krvalid;;
++ u_int8_t krvalid;
};
struct ctl_neighbor {
-@@ -508,6 +570,28 @@ struct filter_community {
- int type;
+@@ -447,20 +547,10 @@ 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
+
+ struct ctl_show_rib {
+ struct bgpd_addr true_nexthop;
+@@ -498,16 +588,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;
@@ -215,13 +420,13 @@ diff -u -p -r1.1.1.8 -r1.11
+ } 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 +602,8 @@ struct ctl_show_rib_request {
+@@ -518,8 +644,8 @@ struct ctl_show_rib_request {
pid_t pid;
u_int16_t flags;
enum imsg_type type;
@@ -231,7 +436,7 @@ diff -u -p -r1.1.1.8 -r1.11
};
enum filter_actions {
-@@ -585,6 +669,28 @@ struct filter_peers {
+@@ -585,6 +711,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 */
@@ -260,7 +465,7 @@ diff -u -p -r1.1.1.8 -r1.11
struct filter_prefix {
-@@ -594,16 +700,17 @@ struct filter_prefix {
+@@ -594,16 +742,18 @@ struct filter_prefix {
struct filter_prefixlen {
enum comp_ops op;
@@ -278,12 +483,13 @@ diff -u -p -r1.1.1.8 -r1.11
+ struct filter_prefix prefix;
+ struct filter_prefixlen prefixlen;
+ 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 +742,13 @@ enum action_types {
+@@ -635,10 +785,13 @@ enum action_types {
ACTION_SET_NEXTHOP_SELF,
ACTION_SET_COMMUNITY,
ACTION_DEL_COMMUNITY,
@@ -298,7 +504,7 @@ diff -u -p -r1.1.1.8 -r1.11
};
struct filter_set {
-@@ -650,23 +760,31 @@ struct filter_set {
+@@ -650,23 +803,53 @@ struct filter_set {
int32_t relative;
struct bgpd_addr nexthop;
struct filter_community community;
@@ -313,15 +519,37 @@ diff -u -p -r1.1.1.8 -r1.11
-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
@@ -335,7 +563,7 @@ diff -u -p -r1.1.1.8 -r1.11
int64_t nexthop_cnt;
int64_t aspath_cnt;
int64_t aspath_size;
-@@ -677,28 +795,17 @@ struct rde_memstats {
+@@ -677,38 +860,29 @@ struct rde_memstats {
int64_t attr_dcnt;
};
@@ -375,7 +603,12 @@ diff -u -p -r1.1.1.8 -r1.11
/* prototypes */
/* bgpd.c */
-@@ -709,6 +816,7 @@ int bgpd_filternexthop(struct kroute *
+ 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);
@@ -383,7 +616,48 @@ diff -u -p -r1.1.1.8 -r1.11
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 *, ...);
-@@ -779,11 +887,20 @@ const char *log_addr(const struct bgpd_a
+@@ -726,19 +900,22 @@ int cmdline_symset(char *);
+ 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);
+
+@@ -772,6 +949,8 @@ void pftable_ref(u_int16_t);
+ /* 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 +958,20 @@ 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);
diff --git a/net/openbgpd/files/patch-bgpd_buffer.c b/net/openbgpd/files/patch-bgpd_buffer.c
index 875b789f68b3..7ca7a41c1438 100644
--- a/net/openbgpd/files/patch-bgpd_buffer.c
+++ b/net/openbgpd/files/patch-bgpd_buffer.c
@@ -1,39 +1,182 @@
Index: bgpd/buffer.c
===================================================================
-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/buffer.c,v
-retrieving revision 1.1.1.7
-retrieving revision 1.1.1.8
-diff -u -p -r1.1.1.7 -r1.1.1.8
+RCS file: bgpd/buffer.c
+diff -N bgpd/buffer.c
--- bgpd/buffer.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/buffer.c 14 Feb 2010 20:27:06 -0000 1.1.1.8
-@@ -1,4 +1,4 @@
++++ /dev/null 1 Jan 1970 00:00:00 -0000
+@@ -1,305 +0,0 @@
-/* $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];
+-
+-/*
+- * 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 buf_realloc(struct buf *, size_t);
+-void buf_enqueue(struct msgbuf *, struct buf *);
+-void buf_dequeue(struct msgbuf *, struct buf *);
+-
+-struct buf *
+-buf_open(size_t len)
+-{
+- struct buf *buf;
+-
+- if ((buf = calloc(1, sizeof(struct buf))) == NULL)
+- return (NULL);
+- if ((buf->buf = malloc(len)) == NULL) {
+- free(buf);
+- return (NULL);
+- }
+- buf->size = buf->max = len;
+- buf->fd = -1;
+-
+- return (buf);
+-}
+-
+-struct buf *
+-buf_dynamic(size_t len, size_t max)
+-{
+- struct buf *buf;
+-
+- if (max < len)
+- return (NULL);
+-
+- if ((buf = buf_open(len)) == NULL)
+- return (NULL);
+-
+- if (max > 0)
+- buf->max = max;
+-
+- return (buf);
+-}
+-
+-int
+-buf_realloc(struct buf *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
+-buf_add(struct buf *buf, const void *data, size_t len)
+-{
+- if (buf->wpos + len > buf->size)
+- if (buf_realloc(buf, len) == -1)
+- return (-1);
+-
+- memcpy(buf->buf + buf->wpos, data, len);
+- buf->wpos += len;
+- return (0);
+-}
+-
+-void *
+-buf_reserve(struct buf *buf, size_t len)
+-{
+- void *b;
+-
+- if (buf->wpos + len > buf->size)
+- if (buf_realloc(buf, len) == -1)
+- return (NULL);
+-
+- b = buf->buf + buf->wpos;
+- buf->wpos += len;
+- return (b);
+-}
+-
+-void *
+-buf_seek(struct buf *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
+-buf_size(struct buf *buf)
+-{
+- return (buf->wpos);
+-}
+-
+-size_t
+-buf_left(struct buf *buf)
+-{
+- return (buf->max - buf->wpos);
+-}
+-
+-void
+-buf_close(struct msgbuf *msgbuf, struct buf *buf)
+-{
+- buf_enqueue(msgbuf, buf);
+-}
+-
+-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;
+- 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->size - buf->rpos;
-+ iov[i].iov_len = buf->wpos - buf->rpos;
- i++;
- }
-
-@@ -170,17 +170,7 @@ buf_write(struct msgbuf *msgbuf)
- return (-2);
- }
-
+- i++;
+- }
+-
+- if ((n = writev(msgbuf->fd, iov, i)) == -1) {
+- if (errno == EAGAIN || errno == ENOBUFS ||
+- errno == EINTR) /* try later */
+- return (0);
+- else
+- return (-1);
+- }
+-
+- if (n == 0) { /* connection closed */
+- errno = 0;
+- return (-2);
+- }
+-
- for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
- buf = next) {
- next = TAILQ_NEXT(buf, entry);
@@ -45,48 +188,95 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
- 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];
+-
+- return (0);
+-}
+-
+-void
+-buf_free(struct buf *buf)
+-{
+- free(buf->buf);
+- free(buf);
+-}
+-
+-void
+-msgbuf_init(struct msgbuf *msgbuf)
+-{
+- msgbuf->queued = 0;
+- msgbuf->fd = -1;
+- TAILQ_INIT(&msgbuf->bufs);
+-}
+-
+-void
+-msgbuf_clear(struct msgbuf *msgbuf)
+-{
+- struct buf *buf;
+-
+- while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
+- buf_dequeue(msgbuf, buf);
+-}
+-
+-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;
- }
-
+- 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;
+- }
+-
+- if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
+- if (errno == EAGAIN || errno == ENOBUFS ||
+- errno == EINTR) /* try later */
+- return (0);
+- else
+- return (-1);
+- }
+-
+- if (n == 0) { /* connection closed */
+- errno = 0;
+- return (-2);
+- }
+-
+- /*
+- * 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;
+- }
+-
- for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
- buf = next) {
- next = TAILQ_NEXT(buf, entry);
@@ -98,7 +288,25 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
- n = 0;
- }
- }
-+ msgbuf_drain(msgbuf, n);
-
- return (0);
- }
+-
+- return (0);
+-}
+-
+-void
+-buf_enqueue(struct msgbuf *msgbuf, struct buf *buf)
+-{
+- TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
+- msgbuf->queued++;
+-}
+-
+-void
+-buf_dequeue(struct msgbuf *msgbuf, struct buf *buf)
+-{
+- TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
+-
+- if (buf->fd != -1)
+- close(buf->fd);
+-
+- msgbuf->queued--;
+- buf_free(buf);
+-}
diff --git a/net/openbgpd/files/patch-bgpd_config.c b/net/openbgpd/files/patch-bgpd_config.c
index 77598e255fa6..3df03c1b3795 100644
--- a/net/openbgpd/files/patch-bgpd_config.c
+++ b/net/openbgpd/files/patch-bgpd_config.c
@@ -2,17 +2,57 @@ Index: bgpd/config.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/config.c,v
retrieving revision 1.1.1.6
-retrieving revision 1.1.1.7
-diff -u -p -r1.1.1.6 -r1.1.1.7
+retrieving revision 1.2
+diff -u -p -r1.1.1.6 -r1.2
--- bgpd/config.c 14 Feb 2010 20:19:57 -0000 1.1.1.6
-+++ bgpd/config.c 14 Feb 2010 20:27:06 -0000 1.1.1.7
++++ bgpd/config.c 2 Jul 2011 16:06:38 -0000 1.2
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.51 2009/01/26 23:10:02 claudio Exp $ */
-+/* $OpenBSD: config.c,v 1.52 2009/12/01 14:28:05 claudio Exp $ */
++/* $OpenBSD: config.c,v 1.56 2010/10/24 17:20:08 deraadt Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
-@@ -208,7 +208,7 @@ host_v4(const char *s, struct bgpd_addr
+@@ -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);
}
@@ -21,7 +61,7 @@ diff -u -p -r1.1.1.6 -r1.1.1.7
h->v4.s_addr = ina.s_addr;
*len = bits;
-@@ -225,13 +225,7 @@ host_v6(const char *s, struct bgpd_addr
+@@ -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) {
@@ -36,3 +76,34 @@ diff -u -p -r1.1.1.6 -r1.1.1.7
freeaddrinfo(res);
return (1);
}
+@@ -317,3 +317,30 @@ prepare_listeners(struct bgpd_config *co
+ }
+ }
+ }
++
++int
++get_mpe_label(struct rdomain *r)
++{
++#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */
++ struct ifreq ifr;
++ struct shim_hdr shim;
++ int s;
++
++ s = socket(AF_INET, SOCK_DGRAM, 0);
++ if (s == -1)
++ return (-1);
++
++ bzero(&shim, sizeof(shim));
++ bzero(&ifr, sizeof(ifr));
++ strlcpy(ifr.ifr_name, r->ifmpe, sizeof(ifr.ifr_name));
++ ifr.ifr_data = (caddr_t)&shim;
++
++ if (ioctl(s, SIOCGETLABEL, (caddr_t)&ifr) == -1) {
++ close(s);
++ return (-1);
++ }
++ close(s);
++ r->label = shim.shim_label;
++#endif
++ return (0);
++}
diff --git a/net/openbgpd/files/patch-bgpd_control.c b/net/openbgpd/files/patch-bgpd_control.c
index 70b1dfd9393a..09c2ac85a831 100644
--- a/net/openbgpd/files/patch-bgpd_control.c
+++ b/net/openbgpd/files/patch-bgpd_control.c
@@ -2,13 +2,13 @@ Index: bgpd/control.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/control.c,v
retrieving revision 1.1.1.7
-retrieving revision 1.1.1.8
-diff -u -p -r1.1.1.7 -r1.1.1.8
+retrieving revision 1.1.1.9
+diff -u -p -r1.1.1.7 -r1.1.1.9
--- bgpd/control.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/control.c 14 Feb 2010 20:27:06 -0000 1.1.1.8
++++ bgpd/control.c 12 Jun 2011 10:44:24 -0000 1.1.1.9
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.61 2009/05/05 20:09:19 sthen Exp $ */
-+/* $OpenBSD: control.c,v 1.68 2010/01/13 06:02:37 claudio Exp $ */
++/* $OpenBSD: control.c,v 1.70 2010/10/29 12:51:53 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -32,8 +32,9 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
session_socket_blockmode(connfd, BM_NONBLOCK);
- if ((ctl_conn = malloc(sizeof(struct ctl_conn))) == NULL) {
+- 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);
@@ -48,7 +49,17 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
struct peer *p;
struct ctl_neighbor *neighbor;
struct ctl_show_rib_request *ribreq;
-@@ -328,13 +329,19 @@ control_dispatch_msg(struct pollfd *pfd,
+@@ -305,7 +306,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 +330,19 @@ control_dispatch_msg(struct pollfd *pfd,
control_result(c, CTL_RES_OK);
break;
case IMSG_CTL_NEIGHBOR_DOWN:
@@ -72,7 +83,30 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
control_result(c, CTL_RES_OK);
break;
case IMSG_CTL_NEIGHBOR_RREFRESH:
-@@ -370,7 +377,7 @@ control_dispatch_msg(struct pollfd *pfd,
+@@ -352,13 +360,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 +384,7 @@ control_dispatch_msg(struct pollfd *pfd,
neighbor->descr[PEER_DESCR_LEN - 1] = 0;
ribreq->peerid = 0;
p = NULL;
@@ -81,7 +115,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
p = getpeerbyaddr(&neighbor->addr);
if (p == NULL) {
control_result(c,
-@@ -397,8 +404,7 @@ control_dispatch_msg(struct pollfd *pfd,
+@@ -397,8 +411,7 @@ control_dispatch_msg(struct pollfd *pfd,
break;
}
if ((imsg.hdr.type == IMSG_CTL_SHOW_RIB_PREFIX)
@@ -91,7 +125,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
/* malformed request, must specify af */
control_result(c, CTL_RES_PARSE_ERROR);
break;
-@@ -425,6 +431,20 @@ control_dispatch_msg(struct pollfd *pfd,
+@@ -425,6 +438,20 @@ control_dispatch_msg(struct pollfd *pfd,
imsg_compose_rde(imsg.hdr.type, 0,
imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
break;
@@ -101,7 +135,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
+ break;
+
+ /* forward to other processes */
-+ imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid,
++ 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);
diff --git a/net/openbgpd/files/patch-bgpd_imsg.c b/net/openbgpd/files/patch-bgpd_imsg.c
index 0cd9ad061d24..0ae6c8a603e7 100644
--- a/net/openbgpd/files/patch-bgpd_imsg.c
+++ b/net/openbgpd/files/patch-bgpd_imsg.c
@@ -1,35 +1,275 @@
Index: bgpd/imsg.c
===================================================================
-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/imsg.c,v
-retrieving revision 1.1.1.6
-retrieving revision 1.1.1.8
-diff -u -p -r1.1.1.6 -r1.1.1.8
+RCS file: bgpd/imsg.c
+diff -N bgpd/imsg.c
--- bgpd/imsg.c 14 Feb 2010 20:19:57 -0000 1.1.1.6
-+++ bgpd/imsg.c 10 Apr 2010 12:13:04 -0000 1.1.1.8
-@@ -1,4 +1,4 @@
++++ /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 $ */
-+/* $OpenBSD: imsg.c,v 1.49 2010/04/07 18:09:39 nicm Exp $ */
-
- /*
- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
-@@ -79,7 +79,7 @@ imsg_read(struct imsgbuf *ibuf)
- cmsg->cmsg_type == SCM_RIGHTS) {
- fd = (*(int *)CMSG_DATA(cmsg));
- if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) {
+-
+-/*
+- * 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 */
-+ close(fd);
- return (-1);
- }
- ifd->fd = fd;
-@@ -263,6 +263,9 @@ imsg_flush(struct imsgbuf *ibuf)
- void
- imsg_clear(struct imsgbuf *ibuf)
- {
+- 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);
-+ int fd;
-+
-+ msgbuf_clear(&ibuf->w);
-+ while ((fd = imsg_get_fd(ibuf)) != -1)
-+ close(fd);
- }
+-}
diff --git a/net/openbgpd/files/patch-bgpd_imsg.h b/net/openbgpd/files/patch-bgpd_imsg.h
index a7b0c120c556..09fe037f51eb 100644
--- a/net/openbgpd/files/patch-bgpd_imsg.h
+++ b/net/openbgpd/files/patch-bgpd_imsg.h
@@ -1,16 +1,115 @@
Index: bgpd/imsg.h
===================================================================
-RCS file: /home/cvs/private/hrs/openbgpd/bgpd/imsg.h,v
-retrieving revision 1.1.1.5
-retrieving revision 1.1.1.6
-diff -u -p -r1.1.1.5 -r1.1.1.6
+RCS file: bgpd/imsg.h
+diff -N bgpd/imsg.h
--- bgpd/imsg.h 14 Feb 2010 20:19:57 -0000 1.1.1.5
-+++ bgpd/imsg.h 14 Feb 2010 20:27:06 -0000 1.1.1.6
-@@ -90,6 +90,7 @@ void buf_free(struct buf *);
- 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);
++++ /dev/null 1 Jan 1970 00:00:00 -0000
+@@ -1,108 +0,0 @@
+-/* $OpenBSD: imsg.h,v 1.3 2009/06/07 05:56:24 eric Exp $ */
+-
+-/*
+- * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
+- * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
+- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+- *
+- * Permission to use, copy, modify, and distribute this software for any
+- * purpose with or without fee is hereby granted, provided that the above
+- * copyright notice and this permission notice appear in all copies.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+- */
+-
+-#include <sys/tree.h>
+-
+-#define READ_BUF_SIZE 65535
+-#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
+-#define MAX_IMSGSIZE 16384
+-
+-struct buf {
+- TAILQ_ENTRY(buf) entry;
+- u_char *buf;
+- size_t size;
+- size_t max;
+- size_t wpos;
+- size_t rpos;
+- int fd;
+-};
+-
+-struct msgbuf {
+- TAILQ_HEAD(, buf) bufs;
+- u_int32_t queued;
+- int fd;
+-};
+-
+-struct buf_read {
+- u_char buf[READ_BUF_SIZE];
+- u_char *rptr;
+- size_t wpos;
+-};
+-
+-struct imsg_fd {
+- TAILQ_ENTRY(imsg_fd) entry;
+- int fd;
+-};
+-
+-struct imsgbuf {
+- TAILQ_HEAD(, imsg_fd) fds;
+- struct buf_read r;
+- struct msgbuf w;
+- int fd;
+- pid_t pid;
+-};
+-
+-#define IMSGF_HASFD 1
+-
+-struct imsg_hdr {
+- u_int32_t type;
+- u_int16_t len;
+- u_int16_t flags;
+- u_int32_t peerid;
+- u_int32_t pid;
+-};
+-
+-struct imsg {
+- struct imsg_hdr hdr;
+- int fd;
+- void *data;
+-};
+-
+-
+-/* buffer.c */
+-struct buf *buf_open(size_t);
+-struct buf *buf_dynamic(size_t, size_t);
+-int buf_add(struct buf *, const void *, size_t);
+-void *buf_reserve(struct buf *, size_t);
+-void *buf_seek(struct buf *, size_t, size_t);
+-size_t buf_size(struct buf *);
+-size_t buf_left(struct buf *);
+-void buf_close(struct msgbuf *, struct buf *);
+-int buf_write(struct msgbuf *);
+-void buf_free(struct buf *);
+-void msgbuf_init(struct msgbuf *);
+-void msgbuf_clear(struct msgbuf *);
+-int msgbuf_write(struct msgbuf *);
+-
+-/* imsg.c */
+-void imsg_init(struct imsgbuf *, int);
+-ssize_t imsg_read(struct imsgbuf *);
+-ssize_t imsg_get(struct imsgbuf *, struct imsg *);
+-int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
+- int, void *, u_int16_t);
+-int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
+- int, const struct iovec *, int);
+-struct buf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
+- u_int16_t);
+-int imsg_add(struct buf *, void *, u_int16_t);
+-void imsg_close(struct imsgbuf *, struct buf *);
+-void imsg_free(struct imsg *);
+-int imsg_flush(struct imsgbuf *);
+-void imsg_clear(struct imsgbuf *);
diff --git a/net/openbgpd/files/patch-bgpd_kroute.c b/net/openbgpd/files/patch-bgpd_kroute.c
index 08bb5eacbf50..6f93029d60cd 100644
--- a/net/openbgpd/files/patch-bgpd_kroute.c
+++ b/net/openbgpd/files/patch-bgpd_kroute.c
@@ -2,17 +2,912 @@ Index: bgpd/kroute.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/kroute.c,v
retrieving revision 1.1.1.7
-retrieving revision 1.9
-diff -u -p -r1.1.1.7 -r1.9
+retrieving revision 1.12
+diff -u -p -r1.1.1.7 -r1.12
--- bgpd/kroute.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/kroute.c 10 Apr 2010 12:16:23 -0000 1.9
++++ bgpd/kroute.c 3 Jul 2011 04:46:36 -0000 1.12
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.169 2009/06/25 15:54:22 claudio Exp $ */
+/* $OpenBSD: kroute.c,v 1.176 2010/04/06 13:25:08 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
-@@ -463,25 +463,30 @@ kr_nexthop_add(struct bgpd_addr *addr)
+@@ -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,15 @@ 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 *);
++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 +164,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 +185,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 +223,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));
++
++ 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;
+
+- rtlabel_unref(kl->kr.labelid);
++ 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 (kroute_remove(kr) == -1)
++ 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
++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 kroute6_label *kl)
++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 +758,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;
++
++ kt->fib_sync = 1;
+
+- 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_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,11 +824,16 @@ 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;
+@@ -463,25 +842,30 @@ kr_nexthop_add(struct bgpd_addr *addr)
bzero(&nh, sizeof(nh));
memcpy(&nh.nexthop, addr, sizeof(nh.nexthop));
nh.valid = 1;
@@ -49,25 +944,159 @@ diff -u -p -r1.1.1.7 -r1.9
}
send_nexthop_update(&nh);
-@@ -563,14 +568,14 @@ kr_show_route(struct imsg *imsg)
+@@ -492,7 +876,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 +884,25 @@ 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_add: 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 +911,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 +919,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(addr->v4.s_addr, 1);
++ 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->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(&addr->v6, 1);
++ kr6 = kroute6_match(kt, &addr->v6, 1);
if (kr6 != NULL)
- send_imsg_session(IMSG_CTL_KROUTE6,
-@@ -583,15 +588,21 @@ kr_show_route(struct imsg *imsg)
+- 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) {
@@ -92,7 +1121,407 @@ diff -u -p -r1.1.1.7 -r1.9
ifindex = kr6->r.ifindex;
break;
}
-@@ -846,26 +857,28 @@ kroute6_compare(struct kroute6_node *a,
+@@ -608,6 +1025,24 @@ 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;
+ }
+@@ -628,21 +1063,146 @@ kr_ifinfo(char *ifname)
+ }
+ }
+
+-struct redist_node {
+- LIST_ENTRY(redist_node) entry;
+- struct kroute *kr;
+- struct kroute6 *kr6;
+-};
++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;
++ }
++ }
++ return (NULL);
++}
++
++struct network *
++kr_net_match6(struct ktable *kt, struct kroute6 *kr6)
++{
++ struct network *xn;
++
++ 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;
++ }
++ }
++ return (NULL);
++}
++
++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 +1230,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 +1295,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 +1452,28 @@ kroute6_compare(struct kroute6_node *a,
int
knexthop_compare(struct knexthop_node *a, struct knexthop_node *b)
{
@@ -137,16 +1566,165 @@ diff -u -p -r1.1.1.7 -r1.9
}
return (0);
-@@ -945,7 +958,7 @@ kroute_insert(struct kroute_node *kr)
+@@ -883,7 +1491,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 +1501,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 +1536,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;
+@@ -944,10 +1553,10 @@ kroute_insert(struct kroute_node *kr)
+ if (kr->r.flags & F_KERNEL) {
mask = prefixlen2mask(kr->r.prefixlen);
ina = ntohl(kr->r.prefix.s_addr);
- RB_FOREACH(h, knexthop_tree, &knt)
+- 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(h);
++ knexthop_validate(kt, h);
+
+ if (kr->r.flags & F_CONNECTED)
+ if (kif_kr_insert(kr) == -1)
+@@ -955,19 +1564,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);
+ }
-@@ -1065,7 +1078,7 @@ kroute6_matchgw(struct kroute6_node *kr,
+
+ 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 +1584,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);
+@@ -1002,13 +1612,13 @@ 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)
++ 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 +1631,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 +1650,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);
+@@ -1065,7 +1676,7 @@ kroute6_matchgw(struct kroute6_node *kr,
memcpy(&nexthop, &sa_in6->sin6_addr, sizeof(nexthop));
while (kr) {
@@ -155,24 +1733,213 @@ diff -u -p -r1.1.1.7 -r1.9
return (kr);
kr = kr->next;
}
-@@ -1091,7 +1104,7 @@ kroute6_insert(struct kroute6_node *kr)
+@@ -1074,13 +1685,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;
+@@ -1090,12 +1701,12 @@ kroute6_insert(struct kroute6_node *kr)
+
if (kr->r.flags & F_KERNEL) {
inet6applymask(&ina, &kr->r.prefix, kr->r.prefixlen);
- RB_FOREACH(h, knexthop_tree, &knt)
+- 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)
-@@ -1184,6 +1197,7 @@ knexthop_find(struct bgpd_addr *addr)
+- knexthop_validate(h);
++ knexthop_validate(kt, h);
+ }
+
+ if (kr->r.flags & F_CONNECTED)
+@@ -1104,19 +1715,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 +1735,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);
+@@ -1152,13 +1764,13 @@ 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)
++ 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 +1783,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));
-@@ -1480,17 +1494,17 @@ knexthop_validate(struct knexthop_node *
+- 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 +1833,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 +1870,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 +1879,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,25 +2090,25 @@ kroute6_validate(struct kroute6 *kr)
+ }
+
+ void
+-knexthop_validate(struct knexthop_node *kn)
++knexthop_validate(struct ktable *kt, struct knexthop_node *kn)
+ {
+ struct kroute_node *kr;
+ struct kroute6_node *kr6;
struct kroute_nexthop n;
int was_valid = 0;
@@ -185,16 +1952,19 @@ diff -u -p -r1.1.1.7 -r1.9
bzero(&n, sizeof(n));
memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop));
- kroute_detach_nexthop(kn);
+- kroute_detach_nexthop(kn);
++ kroute_detach_nexthop(kt, kn);
- switch (kn->nexthop.af) {
- case AF_INET:
+- if ((kr = kroute_match(kn->nexthop.v4.s_addr, 0)) == NULL) {
+ switch (kn->nexthop.aid) {
+ case AID_INET:
- if ((kr = kroute_match(kn->nexthop.v4.s_addr, 0)) == NULL) {
++ if ((kr = kroute_match(kt, kn->nexthop.v4.s_addr, 0)) == NULL) {
if (was_valid)
send_nexthop_update(&n);
-@@ -1500,8 +1514,10 @@ knexthop_validate(struct knexthop_node *
+ } else { /* match */
+@@ -1500,8 +2117,10 @@ knexthop_validate(struct knexthop_node *
n.connected = kr->r.flags & F_CONNECTED;
if ((n.gateway.v4.s_addr =
kr->r.nexthop.s_addr) != 0)
@@ -207,16 +1977,18 @@ diff -u -p -r1.1.1.7 -r1.9
send_nexthop_update(&n);
} else /* down */
if (was_valid)
-@@ -1511,7 +1527,7 @@ knexthop_validate(struct knexthop_node *
+@@ -1511,8 +2130,8 @@ knexthop_validate(struct knexthop_node *
kr->r.flags |= F_NEXTHOP;
}
break;
- case AF_INET6:
+- if ((kr6 = kroute6_match(&kn->nexthop.v6, 0)) == NULL) {
+ case AID_INET6:
- if ((kr6 = kroute6_match(&kn->nexthop.v6, 0)) == NULL) {
++ if ((kr6 = kroute6_match(kt, &kn->nexthop.v6, 0)) == NULL) {
if (was_valid)
send_nexthop_update(&n);
-@@ -1521,11 +1537,14 @@ knexthop_validate(struct knexthop_node *
+ } else { /* match */
+@@ -1521,11 +2140,14 @@ knexthop_validate(struct knexthop_node *
n.connected = kr6->r.flags & F_CONNECTED;
if (memcmp(&kr6->r.nexthop, &in6addr_any,
sizeof(struct in6_addr)) != 0) {
@@ -233,15 +2005,31 @@ diff -u -p -r1.1.1.7 -r1.9
send_nexthop_update(&n);
} else /* down */
if (was_valid)
-@@ -1551,27 +1570,32 @@ knexthop_track(void *krn)
+@@ -1539,39 +2161,44 @@ knexthop_validate(struct knexthop_node *
+ }
+
+ void
+-knexthop_track(void *krn)
++knexthop_track(struct ktable *kt, void *krp)
+ {
+ struct knexthop_node *kn;
+ struct kroute_node *kr;
+ struct kroute6_node *kr6;
+ struct kroute_nexthop n;
+
+- RB_FOREACH(kn, knexthop_tree, &knt)
+- if (kn->kroute == krn) {
++ RB_FOREACH(kn, knexthop_tree, KT2KNT(kt))
++ if (kn->kroute == krp) {
bzero(&n, sizeof(n));
memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop));
- switch (kn->nexthop.af) {
- case AF_INET:
+- kr = krn;
+ switch (kn->nexthop.aid) {
+ case AID_INET:
- kr = krn;
++ kr = krp;
n.valid = 1;
n.connected = kr->r.flags & F_CONNECTED;
if ((n.gateway.v4.s_addr =
@@ -254,8 +2042,9 @@ diff -u -p -r1.1.1.7 -r1.9
+ n.netlen = kr->r.prefixlen;
break;
- case AF_INET6:
+- kr6 = krn;
+ case AID_INET6:
- kr6 = krn;
++ kr6 = krp;
n.valid = 1;
n.connected = kr6->r.flags & F_CONNECTED;
if (memcmp(&kr6->r.nexthop, &in6addr_any,
@@ -273,7 +2062,73 @@ diff -u -p -r1.1.1.7 -r1.9
break;
}
send_nexthop_update(&n);
-@@ -1645,12 +1669,12 @@ kroute_detach_nexthop(struct knexthop_no
+@@ -1579,7 +2206,7 @@ knexthop_track(void *krn)
+ }
+
+ 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 +2216,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 +2230,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 +2239,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,7 +2253,7 @@ 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;
+@@ -1640,17 +2267,17 @@ kroute_detach_nexthop(struct knexthop_no
+ if (kn->kroute == NULL)
+ return;
+
+- for (s = RB_MIN(knexthop_tree, &knt); s != NULL &&
+- s->kroute != kn->kroute; s = RB_NEXT(knexthop_tree, &knt, s))
++ for (s = RB_MIN(knexthop_tree, KT2KNT(kt)); s != NULL &&
++ s->kroute != kn->kroute; s = RB_NEXT(knexthop_tree, KT2KNT(kt), s))
; /* nothing */
if (s == NULL) {
@@ -289,7 +2144,16 @@ diff -u -p -r1.1.1.7 -r1.9
k6 = kn->kroute;
k6->r.flags &= ~F_NEXTHOP;
break;
-@@ -1675,7 +1699,7 @@ protect_lo(void)
+@@ -1665,7 +2292,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 +2302,11 @@ protect_lo(void)
log_warn("protect_lo");
return (-1);
}
@@ -298,16 +2162,56 @@ diff -u -p -r1.1.1.7 -r1.9
kr->r.prefixlen = 8;
kr->r.flags = F_KERNEL|F_CONNECTED;
-@@ -1689,7 +1713,7 @@ protect_lo(void)
+- 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 +2316,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, &krt6, kr6) != NULL)
++ if (RB_INSERT(kroute6_tree, &kt->krt6, kr6) != NULL)
free(kr6); /* kernel route already there, no problem */
-@@ -1788,7 +1812,7 @@ prefixlen2mask6(u_int8_t prefixlen)
+
+ return (0);
+@@ -1726,17 +2353,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 +2391,7 @@ mask2prefixlen6(struct sockaddr_in6 *sa_
+ case 0x00:
+ return (l);
+ default:
+- fatalx("non continguous inet6 netmask");
++ fatalx("non contiguous inet6 netmask");
+ }
+ }
+
+@@ -1788,7 +2415,7 @@ prefixlen2mask6(u_int8_t prefixlen)
}
#define ROUNDUP(a) \
@@ -316,7 +2220,35 @@ diff -u -p -r1.1.1.7 -r1.9
void
get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
-@@ -1849,10 +1873,11 @@ if_change(u_short ifindex, int flags, st
+@@ -1808,6 +2435,7 @@ 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;
+@@ -1833,13 +2461,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 (kt == NULL)
++ continue;
++
++ RB_FOREACH(n, knexthop_tree, KT2KNT(kt))
+ if (n->kroute == kkr->kr) {
+ bzero(&nh, sizeof(nh));
+ memcpy(&nh.nexthop, &n->nexthop,
+@@ -1849,10 +2482,11 @@ if_change(u_short ifindex, int flags, st
nh.connected = 1;
if ((nh.gateway.v4.s_addr =
kkr->kr->r.nexthop.s_addr) != 0)
@@ -331,7 +2263,18 @@ diff -u -p -r1.1.1.7 -r1.9
send_nexthop_update(&nh);
}
}
-@@ -1873,14 +1898,16 @@ if_change(u_short ifindex, int flags, st
+@@ -1862,7 +2496,9 @@ if_change(u_short ifindex, int flags, st
+ else
+ kkr6->kr->r.flags |= F_DOWN;
+
+- RB_FOREACH(n, knexthop_tree, &knt)
++ if (kt == NULL)
++ continue;
++ RB_FOREACH(n, knexthop_tree, KT2KNT(kt))
+ if (n->kroute == kkr6->kr) {
+ bzero(&nh, sizeof(nh));
+ memcpy(&nh.nexthop, &n->nexthop,
+@@ -1873,14 +2509,16 @@ if_change(u_short ifindex, int flags, st
if (memcmp(&kkr6->kr->r.nexthop,
&in6addr_any, sizeof(struct
in6_addr))) {
@@ -351,39 +2294,88 @@ diff -u -p -r1.1.1.7 -r1.9
send_nexthop_update(&nh);
}
}
-@@ -1924,7 +1951,9 @@ send_rtmsg(int fd, int action, struct kr
+@@ -1917,25 +2555,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)
-@@ -1934,8 +1963,13 @@ send_rtmsg(int fd, int action, struct kr
+- 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 = kr_state.rtableid;
++ hdr.rtm_tableid = kt->rtableid;
+#endif /* !defined(__FreeBSD__) */
-+ hdr.rtm_flags = RTF_PROTO1;
+#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 +2018,7 @@ send_rtmsg(int fd, int action, struct kr
+@@ -1984,6 +2635,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,6 +2031,7 @@ send_rtmsg(int fd, int action, struct kr
+@@ -1996,11 +2678,11 @@ send_rtmsg(int fd, int action, struct kr
iov[iovcnt].iov_base = &label;
iov[iovcnt++].iov_len = sizeof(label);
}
@@ -391,7 +2383,45 @@ diff -u -p -r1.1.1.7 -r1.9
retry:
if (writev(fd, iov, iovcnt) == -1) {
-@@ -2037,7 +2073,9 @@ send_rt6msg(int fd, int action, struct k
+- switch (errno) {
+- case ESRCH:
++ if (errno == ESRCH) {
+ if (hdr.rtm_type == RTM_CHANGE) {
+ hdr.rtm_type = RTM_ADD;
+ goto retry;
+@@ -2009,27 +2691,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 +2710,23 @@ send_rt6msg(int fd, int action, struct k
struct sockaddr_in6 addr;
char pad[sizeof(long)];
} prefix, nexthop, mask;
@@ -400,19 +2430,23 @@ diff -u -p -r1.1.1.7 -r1.9
+#endif /* !defined(__FreeBSD__) */
int iovcnt = 0;
- if (kr_state.fib_sync == 0)
-@@ -2047,7 +2085,10 @@ send_rt6msg(int fd, int action, struct k
+- 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;
-+#endif /* !defined(__FreeBSD__) */
++#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 +2141,7 @@ send_rt6msg(int fd, int action, struct k
+@@ -2100,6 +2779,7 @@ send_rt6msg(int fd, int action, struct k
iov[iovcnt].iov_base = &mask;
iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6));
@@ -420,7 +2454,7 @@ diff -u -p -r1.1.1.7 -r1.9
if (kroute->labelid) {
bzero(&label, sizeof(label));
label.sr_len = sizeof(label);
-@@ -2112,6 +2154,7 @@ send_rt6msg(int fd, int action, struct k
+@@ -2112,11 +2792,11 @@ send_rt6msg(int fd, int action, struct k
iov[iovcnt].iov_base = &label;
iov[iovcnt++].iov_len = sizeof(label);
}
@@ -428,42 +2462,104 @@ diff -u -p -r1.1.1.7 -r1.9
retry:
if (writev(fd, iov, iovcnt) == -1) {
-@@ -2147,8 +2190,8 @@ retry:
+- switch (errno) {
+- case ESRCH:
++ if (errno == ESRCH) {
+ if (hdr.rtm_type == RTM_CHANGE) {
+ hdr.rtm_type = RTM_ADD;
+ goto retry;
+@@ -2125,31 +2805,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(u_int rtableid, int connected_only)
++fetchtable(struct ktable *kt)
{
-- size_t len;
-- int mib[7];
-+ size_t len;
-+ int mib[6];
- char *buf, *next, *lim;
+ 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];
-@@ -2163,9 +2206,8 @@ fetchtable(u_int rtableid, int connected
+ struct sockaddr_in *sa_in;
+@@ -2163,22 +2838,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 (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) {
++#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) {
- if (rtableid != 0 && errno == EINVAL) /* table nonexistent */
++#endif
++ if (kt->rtableid != 0 && errno == EINVAL)
++ /* table nonexistent */
return (0);
log_warn("sysctl");
-@@ -2175,7 +2217,7 @@ fetchtable(u_int rtableid, int connected
- log_warn("fetchtable");
return (-1);
}
+- if ((buf = malloc(len)) == NULL) {
+- log_warn("fetchtable");
+- return (-1);
+- }
- if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) {
-+ if (sysctl(mib, 6, buf, &len, NULL, 0) == -1) {
- log_warn("sysctl");
- free(buf);
- return (-1);
-@@ -2186,7 +2228,11 @@ fetchtable(u_int rtableid, int connected
+- 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 +2874,11 @@ fetchtable(u_int rtableid, int connected
rtm = (struct rt_msghdr *)next;
if (rtm->rtm_version != RTM_VERSION)
continue;
-+#if !defined(__FreeBSD__) /* no rtm_hdrlen on FreeBSD */
++#if !defined(__FreeBSD__)
sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
+#else
+ sa = (struct sockaddr *)(next + sizeof(struct rt_msghdr));
@@ -471,7 +2567,7 @@ diff -u -p -r1.1.1.7 -r1.9
get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
if ((sa = rti_info[RTAX_DST]) == NULL)
-@@ -2205,7 +2251,11 @@ fetchtable(u_int rtableid, int connected
+@@ -2205,7 +2897,11 @@ fetchtable(u_int rtableid, int connected
}
kr->r.flags = F_KERNEL;
@@ -483,7 +2579,7 @@ diff -u -p -r1.1.1.7 -r1.9
kr->r.ifindex = rtm->rtm_index;
kr->r.prefix.s_addr =
((struct sockaddr_in *)sa)->sin_addr.s_addr;
-@@ -2223,8 +2273,12 @@ fetchtable(u_int rtableid, int connected
+@@ -2223,8 +2919,12 @@ fetchtable(u_int rtableid, int connected
break;
kr->r.prefixlen =
mask2prefixlen(sa_in->sin_addr.s_addr);
@@ -497,7 +2593,7 @@ diff -u -p -r1.1.1.7 -r1.9
else
kr->r.prefixlen =
prefixlen_classful(kr->r.prefix.s_addr);
-@@ -2238,7 +2292,11 @@ fetchtable(u_int rtableid, int connected
+@@ -2238,7 +2938,11 @@ fetchtable(u_int rtableid, int connected
}
kr6->r.flags = F_KERNEL;
@@ -509,7 +2605,7 @@ diff -u -p -r1.1.1.7 -r1.9
kr6->r.ifindex = rtm->rtm_index;
memcpy(&kr6->r.prefix,
&((struct sockaddr_in6 *)sa)->sin6_addr,
-@@ -2257,8 +2315,12 @@ fetchtable(u_int rtableid, int connected
+@@ -2257,8 +2961,12 @@ fetchtable(u_int rtableid, int connected
if (sa_in6->sin6_len == 0)
break;
kr6->r.prefixlen = mask2prefixlen6(sa_in6);
@@ -523,37 +2619,70 @@ diff -u -p -r1.1.1.7 -r1.9
else
fatalx("INET6 route without netmask");
break;
-@@ -2290,7 +2352,12 @@ fetchtable(u_int rtableid, int connected
+@@ -2290,23 +2998,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, &kr->r);
++ send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r);
free(kr);
- } else if (connected_only &&
-@@ -2299,7 +2366,12 @@ fetchtable(u_int rtableid, int connected
- else
- kroute_insert(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, &kr6->r);
++ send_rt6msg(kr_state.fd, RTM_DELETE, kt,
++ &kr6->r);
free(kr6);
- } else if (connected_only &&
-@@ -2418,7 +2490,11 @@ dispatch_rtmsg(void)
+- else
+- kroute6_insert(kr6);
++ } else
++ kroute6_insert(kt, kr6);
+ }
+ }
+ free(buf);
+@@ -2327,7 +3040,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 +3109,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 +3131,11 @@ dispatch_rtmsg(void)
case RTM_ADD:
case RTM_CHANGE:
case RTM_DELETE:
-+#if !defined(__FreeBSD__) /* no rtm_hdrlen on FreeBSD */
++#if !defined(__FreeBSD__)
sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
+#else
+ sa = (struct sockaddr *)(next + sizeof(struct rt_msghdr));
@@ -561,22 +2690,40 @@ diff -u -p -r1.1.1.7 -r1.9
get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
if (rtm->rtm_pid == kr_state.pid) /* cause by us */
-@@ -2431,12 +2507,14 @@ dispatch_rtmsg(void)
+@@ -2430,16 +3147,14 @@ dispatch_rtmsg(void)
+ if (rtm->rtm_flags & RTF_LLINFO) /* arp cache */
continue;
- connected_only = 0;
-+#if !defined(__FreeBSD__) /* XXX: FreeBSD has no multiple routing tables */
- if (rtm->rtm_tableid != kr_state.rtableid) {
- if (rtm->rtm_tableid == 0)
- connected_only = 1;
- else
- continue;
- }
-+#endif /* !defined(__FreeBSD__) */
+- 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 +3175,7 @@ dispatch_rtmsg(void)
- if (dispatch_rtmsg_addr(rtm, rti_info,
- connected_only) == -1)
-@@ -2494,31 +2572,44 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
+ 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;
+@@ -2494,31 +3209,44 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
mpath = 1;
#endif
@@ -625,7 +2772,7 @@ diff -u -p -r1.1.1.7 -r1.9
else
fatalx("in6 net addr without netmask");
break;
-@@ -2537,8 +2628,8 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
+@@ -2537,10 +3265,10 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
}
if (rtm->rtm_type == RTM_DELETE) {
@@ -634,18 +2781,45 @@ diff -u -p -r1.1.1.7 -r1.9
+ switch (prefix.aid) {
+ case AID_INET:
sa_in = (struct sockaddr_in *)sa;
- if ((kr = kroute_find(prefix.v4.s_addr,
+- if ((kr = kroute_find(prefix.v4.s_addr,
++ if ((kr = kroute_find(kt, prefix.v4.s_addr,
prefixlen, prio)) == NULL)
-@@ -2557,7 +2648,7 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
- if (kroute_remove(kr) == -1)
+ return (0);
+ if (!(kr->r.flags & F_KERNEL))
+@@ -2554,12 +3282,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(&prefix.v6, prefixlen,
++ if ((kr6 = kroute6_find(kt, &prefix.v6, prefixlen,
prio)) == NULL)
-@@ -2590,8 +2681,8 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
+ return (0);
+ if (!(kr6->r.flags & F_KERNEL))
+@@ -2574,26 +3302,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);
}
@@ -654,14 +2828,74 @@ diff -u -p -r1.1.1.7 -r1.9
+ 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(prefix.v4.s_addr, prefixlen,
++ if ((kr = kroute_find(kt, prefix.v4.s_addr, prefixlen,
prio)) != NULL) {
-@@ -2654,7 +2745,7 @@ add4:
- kroute_insert(kr);
+ if (kr->r.flags & F_KERNEL) {
+ /* get the correct route */
+@@ -2619,16 +3344,16 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
+ !(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);
++ knexthop_track(kt, kr);
+ }
+ } else if (rtm->rtm_type == RTM_CHANGE) {
+ log_warnx("change req for %s/%u: not in table",
+@@ -2651,12 +3376,13 @@ add4:
+ 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(&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 &&
+@@ -2685,16 +3411,16 @@ add4:
+ !(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);
++ knexthop_track(kt, kr6);
+ }
+ } else if (rtm->rtm_type == RTM_CHANGE) {
+ log_warnx("change req for %s/%u: not in table",
+@@ -2720,7 +3446,7 @@ add6:
+ kr6->r.ifindex = ifindex;
+ kr6->r.priority = prio;
+
+- kroute6_insert(kr6);
++ kroute6_insert(kt, kr6);
+ }
+ break;
+ }
diff --git a/net/openbgpd/files/patch-bgpd_log.c b/net/openbgpd/files/patch-bgpd_log.c
index 603711ce1158..ca58a9bcfa0c 100644
--- a/net/openbgpd/files/patch-bgpd_log.c
+++ b/net/openbgpd/files/patch-bgpd_log.c
@@ -2,13 +2,13 @@ Index: bgpd/log.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/log.c,v
retrieving revision 1.1.1.5
-retrieving revision 1.1.1.6
-diff -u -p -r1.1.1.5 -r1.1.1.6
+retrieving revision 1.1.1.7
+diff -u -p -r1.1.1.5 -r1.1.1.7
--- bgpd/log.c 14 Feb 2010 20:19:57 -0000 1.1.1.5
-+++ bgpd/log.c 14 Feb 2010 20:27:06 -0000 1.1.1.6
++++ bgpd/log.c 12 Jun 2011 10:44:25 -0000 1.1.1.7
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.c,v 1.50 2007/04/23 13:04:24 claudio Exp $ */
-+/* $OpenBSD: log.c,v 1.53 2009/12/03 19:20:35 claudio Exp $ */
++/* $OpenBSD: log.c,v 1.54 2010/11/18 12:51:24 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -62,7 +62,48 @@ diff -u -p -r1.1.1.5 -r1.1.1.6
va_start(ap, emsg);
vlog(LOG_DEBUG, emsg, ap);
va_end(ap);
-@@ -318,6 +327,9 @@ log_conn_attempt(const struct peer *peer
+@@ -250,7 +259,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;
+@@ -287,23 +296,22 @@ log_notification(const struct peer *peer
+ uk = 1;
+ 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 +326,9 @@ log_conn_attempt(const struct peer *peer
b = log_sockaddr(sa);
logit(LOG_INFO, "connection from non-peer %s refused", b);
} else {
diff --git a/net/openbgpd/files/patch-bgpd_mrt.c b/net/openbgpd/files/patch-bgpd_mrt.c
index c35359ac5f39..4b5248a73d4e 100644
--- a/net/openbgpd/files/patch-bgpd_mrt.c
+++ b/net/openbgpd/files/patch-bgpd_mrt.c
@@ -2,26 +2,228 @@ 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.8
-diff -u -p -r1.1.1.7 -r1.1.1.8
+retrieving revision 1.1.1.9
+diff -u -p -r1.1.1.7 -r1.1.1.9
--- bgpd/mrt.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/mrt.c 14 Feb 2010 20:27:06 -0000 1.1.1.8
++++ bgpd/mrt.c 12 Jun 2011 10:44:25 -0000 1.1.1.9
@@ -1,4 +1,4 @@
-/* $OpenBSD: mrt.c,v 1.63 2009/06/29 12:22:16 claudio Exp $ */
-+/* $OpenBSD: mrt.c,v 1.66 2009/12/01 14:28:05 claudio Exp $ */
++/* $OpenBSD: mrt.c,v 1.70 2010/09/02 14:03:21 sobrado Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
-@@ -194,7 +194,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
+@@ -32,20 +32,20 @@
+
+ #include "mrt.h"
+
+-int mrt_attr_dump(struct buf *, struct rde_aspath *, struct bgpd_addr *);
++int mrt_attr_dump(struct ibuf *, struct rde_aspath *, struct bgpd_addr *);
+ int mrt_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_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_warnx("mrt_dump1: ibuf_add error"); \
+ goto fail; \
+ } \
+ } while (0)
+@@ -54,8 +54,8 @@ int mrt_open(struct mrt *, time_t);
+ do { \
+ u_int16_t t; \
+ t = htons((s)); \
+- if (buf_add((x), &t, sizeof(t)) == -1) { \
+- log_warnx("mrt_dump2: buf_add error"); \
++ if (ibuf_add((x), &t, sizeof(t)) == -1) { \
++ log_warnx("mrt_dump2: ibuf_add error"); \
+ goto fail; \
+ } \
+ } while (0)
+@@ -64,8 +64,8 @@ int mrt_open(struct mrt *, time_t);
+ do { \
+ u_int32_t t; \
+ t = htonl((l)); \
+- if (buf_add((x), &t, sizeof(t)) == -1) { \
+- log_warnx("mrt_dump3: buf_add error"); \
++ if (ibuf_add((x), &t, sizeof(t)) == -1) { \
++ log_warnx("mrt_dump3: ibuf_add error"); \
+ goto fail; \
+ } \
+ } while (0)
+@@ -73,8 +73,8 @@ int mrt_open(struct mrt *, time_t);
+ #define DUMP_NLONG(x, l) \
+ do { \
+ u_int32_t t = (l); \
+- if (buf_add((x), &t, sizeof(t)) == -1) { \
+- log_warnx("mrt_dump4: buf_add error"); \
++ if (ibuf_add((x), &t, sizeof(t)) == -1) { \
++ log_warnx("mrt_dump4: ibuf_add error"); \
+ goto fail; \
+ } \
+ } while (0)
+@@ -83,55 +83,63 @@ 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) {
++ if (ibuf_add(buf, pkg, pkglen) == -1) {
+ log_warnx("mrt_dump_bgp_msg: buf_add error");
+- buf_free(buf);
++ 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)
+ {
+ 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, mpattr[21];
+
+ /* origin */
+ if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ORIGIN,
+@@ -141,11 +149,14 @@ 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 (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)
+@@ -173,12 +184,27 @@ mrt_attr_dump(struct buf *buf, struct rd
+ return (-1);
+ }
+
++ if (nexthop && nexthop->aid != AID_INET) {
++ if (aid2afi(nexthop->aid, &afi, &mpattr[2]))
++ return (-1);
++ afi = htons(afi);
++ memcpy(mpattr, &afi, sizeof(afi));
++ mpattr[3] = sizeof(struct in6_addr);
++ memcpy(&mpattr[4], &nexthop->v6, sizeof(struct in6_addr));
++ mpattr[20] = 0; /* Reserved must be 0 */
++ if (attr_writebuf(buf, ATTR_OPTIONAL, ATTR_MP_REACH_NLRI,
++ mpattr, sizeof(mpattr)) == -1)
++ return (-1);
++ }
++
+ 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,14 +215,14 @@ 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;
++ struct ibuf *buf, *hbuf = NULL, *h2buf = NULL;
+ void *bptr;
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) {
+- if ((buf = buf_dynamic(0, MAX_PKTSIZE)) == NULL) {
++ if ((buf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) {
+ log_warn("mrt_dump_entry_mp: buf_dynamic");
+ return (-1);
+ }
+@@ -205,9 +231,9 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
+ 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");
-@@ -219,14 +219,15 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
+@@ -219,25 +245,26 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
DUMP_SHORT(h2buf, /* ifindex */ 0);
/* XXX is this for peer self? */
@@ -39,9 +241,14 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
- case AF_INET6:
+ case AID_INET6:
DUMP_SHORT(h2buf, AFI_IPv6);
- if (buf_add(h2buf, &peer->local_v6_addr.v6,
+- if (buf_add(h2buf, &peer->local_v6_addr.v6,
++ if (ibuf_add(h2buf, &peer->local_v6_addr.v6,
sizeof(struct in6_addr)) == -1 ||
-@@ -237,7 +238,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
+- 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");
+ goto fail;
}
break;
default:
@@ -50,7 +257,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
goto fail;
}
-@@ -247,20 +248,20 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
+@@ -247,24 +274,24 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
if (p->aspath->nexthop == NULL) {
bzero(&nexthop, sizeof(struct bgpd_addr));
@@ -75,35 +282,153 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
DUMP_SHORT(h2buf, AFI_IPv6); /* afi */
DUMP_BYTE(h2buf, SAFI_UNICAST); /* safi */
DUMP_BYTE(h2buf, 16); /* nhlen */
-@@ -300,7 +301,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
+- if (buf_add(h2buf, &nh->v6, sizeof(struct in6_addr)) == -1) {
++ if (ibuf_add(h2buf, &nh->v6, sizeof(struct in6_addr)) == -1) {
+ log_warnx("mrt_dump_entry_mp: buf_add error");
+ goto fail;
+ }
+@@ -275,7 +302,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
+ }
+
+ p_len = PREFIX_SIZE(p->prefix->prefixlen);
+- if ((bptr = buf_reserve(h2buf, p_len)) == NULL) {
++ if ((bptr = ibuf_reserve(h2buf, p_len)) == NULL) {
+ log_warnx("mrt_dump_entry_mp: buf_reserve error");
+ goto fail;
+ }
+@@ -285,24 +312,24 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
+ }
+
+ 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);
+- buf_free(hbuf);
- if (h2buf);
+- buf_free(h2buf);
+- buf_free(buf);
++ ibuf_free(hbuf);
+ if (h2buf)
- buf_free(h2buf);
- buf_free(buf);
++ ibuf_free(h2buf);
++ ibuf_free(buf);
return (-1);
-@@ -314,7 +315,8 @@ mrt_dump_entry(struct mrt *mrt, struct p
+ }
+
+@@ -310,34 +337,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)
-+ if (p->prefix->aid != AID_INET &&
-+ peer->remote_addr.aid == AID_INET)
- /* only able to dump IPv4 */
+- /* 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);
-@@ -325,7 +327,7 @@ mrt_dump_entry(struct mrt *mrt, struct p
+- if ((buf = buf_dynamic(0, MAX_PKTSIZE)) == NULL) {
++ if ((buf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) {
+ log_warnx("mrt_dump_entry: buf_dynamic");
+ return (-1);
+ }
if (p->aspath->nexthop == NULL) {
bzero(&addr, sizeof(struct bgpd_addr));
- addr.af = AF_INET;
-+ addr.aid = AID_INET;
++ addr.aid = p->prefix->aid;
nh = &addr;
} else
nh = &p->aspath->nexthop->exit_nexthop;
-@@ -387,7 +389,7 @@ mrt_dump_upcall(struct rib_entry *re, vo
+ if (mrt_attr_dump(buf, p->aspath, nh) == -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 +375,44 @@ 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_warnx("mrt_dump_entry: buf_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_warnx("mrt_dump_entry: buf_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);
+ }
+
+@@ -387,7 +438,7 @@ mrt_dump_upcall(struct rib_entry *re, vo
}
void
@@ -112,11 +437,120 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
{
struct mrt *mrtbuf = ptr;
-@@ -541,6 +543,7 @@ mrt_write(struct mrt *mrt)
- if ((r = buf_write(&mrt->wbuf)) < 0) {
+@@ -395,12 +446,12 @@ 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");
+ return (-1);
+@@ -468,20 +519,20 @@ 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");
+ 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");
+ 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");
+@@ -493,17 +544,17 @@ 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");
+@@ -517,7 +568,15 @@ 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:
+ DUMP_LONG(*bp, len);
+@@ -525,11 +584,11 @@ mrt_dump_hdr_rde(struct buf **bp, u_int1
+ default:
+ log_warnx("mrt_dump_hdr_rde: unsupported type");
+ goto fail;
+- }
++ }
+ return (0);
+
+ fail:
+- buf_free(*bp);
++ ibuf_free(*bp);
+ return (-1);
+ }
+
+@@ -538,21 +597,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;
+ }
diff --git a/net/openbgpd/files/patch-bgpd_mrt.h b/net/openbgpd/files/patch-bgpd_mrt.h
index a2ef64adf59f..7bf1857d39eb 100644
--- a/net/openbgpd/files/patch-bgpd_mrt.h
+++ b/net/openbgpd/files/patch-bgpd_mrt.h
@@ -2,17 +2,60 @@ 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.7
-diff -u -p -r1.1.1.6 -r1.1.1.7
+retrieving revision 1.1.1.8
+diff -u -p -r1.1.1.6 -r1.1.1.8
--- bgpd/mrt.h 14 Feb 2010 20:19:57 -0000 1.1.1.6
-+++ bgpd/mrt.h 14 Feb 2010 20:27:06 -0000 1.1.1.7
++++ bgpd/mrt.h 12 Jun 2011 10:44:25 -0000 1.1.1.8
@@ -1,4 +1,4 @@
-/* $OpenBSD: mrt.h,v 1.23 2009/06/29 12:22:16 claudio Exp $ */
-+/* $OpenBSD: mrt.h,v 1.24 2009/10/26 09:27:58 claudio Exp $ */
++/* $OpenBSD: mrt.h,v 1.27 2010/06/04 10:13:00 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
-@@ -303,7 +303,7 @@ void mrt_dump_state(struct mrt *, u_in
+@@ -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
+ */
+
+@@ -75,8 +73,10 @@ enum MRT_BGP4MP_TYPES {
+ 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 */
+@@ -184,6 +184,7 @@ enum MRT_BGP4MP_TYPES {
+
+ /* size of the dump header until attr_len */
+ #define MRT_DUMP_HEADER_SIZE 22
++#define MRT_DUMP_HEADER_SIZE_V6 46
+
+ /*
+ * OLD MRT message headers. These structs are here for completion but
+@@ -235,7 +236,7 @@ enum MRT_BGP_TYPES {
+ * | new_state |
+ * +--------+--------+
+ *
+- * State are defined in RFC 1771.
++ * State are defined in RFC 1771/4271.
+ */
+
+ /*
+@@ -303,7 +304,7 @@ void mrt_dump_state(struct mrt *, u_in
struct peer *);
void mrt_clear_seq(void);
void mrt_dump_upcall(struct rib_entry *, void *);
diff --git a/net/openbgpd/files/patch-bgpd_parse.y b/net/openbgpd/files/patch-bgpd_parse.y
index fd81af9709ae..64e9081f287d 100644
--- a/net/openbgpd/files/patch-bgpd_parse.y
+++ b/net/openbgpd/files/patch-bgpd_parse.y
@@ -2,17 +2,42 @@ Index: bgpd/parse.y
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/parse.y,v
retrieving revision 1.1.1.8
-retrieving revision 1.8
-diff -u -p -r1.1.1.8 -r1.8
+diff -u -p -r1.1.1.8 parse.y
--- bgpd/parse.y 14 Feb 2010 20:19:57 -0000 1.1.1.8
-+++ bgpd/parse.y 10 Apr 2010 12:16:23 -0000 1.8
++++ bgpd/parse.y 3 Jul 2011 04:43:32 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.231 2009/06/06 01:10:29 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.250 2010/03/31 18:53:23 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
-@@ -105,7 +105,7 @@ struct filter_match_l {
+@@ -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>
+@@ -74,10 +77,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 +110,7 @@ struct filter_match_l {
struct filter_match m;
struct filter_prefix_l *prefix_l;
struct filter_as_l *as_l;
@@ -21,7 +46,23 @@ diff -u -p -r1.1.1.8 -r1.8
} fmopts;
struct peer *alloc_peer(void);
-@@ -128,7 +128,11 @@ void move_filterset(struct filter_set_
+@@ -113,8 +118,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 +128,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 *);
@@ -34,26 +75,30 @@ diff -u -p -r1.1.1.8 -r1.8
typedef struct {
union {
-@@ -161,9 +165,9 @@ typedef struct {
+@@ -159,29 +166,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
++%token DUMP IN OUT SOCKET RESTRICTED
%token LOG ROUTECOLL TRANSPARENT
%token TCP MD5SIG PASSWORD KEY TTLSECURITY
-@@ -171,17 +175,19 @@ typedef struct {
+ %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
++%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
@@ -64,13 +109,23 @@ diff -u -p -r1.1.1.8 -r1.8
+%token NE LE GE XRANGE
%token <v.string> STRING
%token <v.number> NUMBER
- %type <v.number> asnumber as4number optnumber yesno inout
+-%type <v.number> asnumber as4number optnumber yesno inout
-%type <v.number> espah family restart
-+%type <v.number> espah family restart origincode
++%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
-@@ -211,8 +217,12 @@ grammar : /* empty */
+@@ -204,6 +215,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 +223,12 @@ grammar : /* empty */
;
asnumber : NUMBER {
@@ -85,7 +140,7 @@ diff -u -p -r1.1.1.8 -r1.8
YYERROR;
}
}
-@@ -274,6 +284,8 @@ yesno : STRING {
+@@ -274,6 +290,8 @@ yesno : STRING {
else if (!strcmp($1, "no"))
$$ = 0;
else {
@@ -94,7 +149,7 @@ diff -u -p -r1.1.1.8 -r1.8
free($1);
YYERROR;
}
-@@ -318,7 +330,7 @@ conf_main : AS as4number {
+@@ -318,7 +336,7 @@ conf_main : AS as4number {
conf->short_as = $3;
}
| ROUTERID address {
@@ -103,7 +158,7 @@ diff -u -p -r1.1.1.8 -r1.8
yyerror("router-id must be an IPv4 address");
YYERROR;
}
-@@ -342,35 +354,13 @@ conf_main : AS as4number {
+@@ -342,42 +360,25 @@ conf_main : AS as4number {
}
| LISTEN ON address {
struct listen_addr *la;
@@ -140,19 +195,103 @@ diff -u -p -r1.1.1.8 -r1.8
TAILQ_INSERT_TAIL(listen_addrs, la, entry);
}
| FIBUPDATE yesno {
-@@ -397,7 +387,7 @@ conf_main : AS as4number {
++ 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 +387,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 +396,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, F_RIB_NOFIB | 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;
}
-@@ -459,18 +449,6 @@ conf_main : AS as4number {
+@@ -418,59 +437,7 @@ conf_main : AS as4number {
}
- free($4);
+ 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;
@@ -165,27 +304,99 @@ diff -u -p -r1.1.1.8 -r1.8
- move_filterset($3, &conf->connectset);
- free($3);
- }
++ | network
| DUMP STRING STRING optnumber {
int action;
-@@ -575,11 +553,16 @@ conf_main : AS as4number {
+@@ -575,11 +542,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
- if ($2 > RT_TABLEID_MAX || $2 < 0) {
- yyerror("invalid rtable id");
++ struct rde_rib *rr;
++ if (ktable_exists($2, NULL) != 1) {
++ yyerror("rtable id %lld does not exist", $2);
YYERROR;
}
- conf->rtableid = $2;
+- 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) {
-@@ -635,11 +618,11 @@ address : STRING {
+@@ -588,6 +564,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 +605,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 +657,11 @@ address : STRING {
}
free($1);
@@ -200,7 +411,25 @@ diff -u -p -r1.1.1.8 -r1.8
YYERROR;
}
}
-@@ -686,7 +669,7 @@ prefix : STRING '/' NUMBER {
+@@ -653,7 +675,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 +694,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 +708,7 @@ prefix : STRING '/' NUMBER {
addrspec : address {
memcpy(&$$.prefix, &$1, sizeof(struct bgpd_addr));
@@ -209,7 +438,144 @@ diff -u -p -r1.1.1.8 -r1.8
$$.len = 32;
else
$$.len = 128;
-@@ -710,9 +693,13 @@ neighbor : { curpeer = new_peer(); }
+@@ -705,14 +727,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;
@@ -225,7 +591,7 @@ diff -u -p -r1.1.1.8 -r1.8
if (get_id(curpeer)) {
yyerror("get_id failed");
YYERROR;
-@@ -802,6 +789,17 @@ peeropts : REMOTEAS as4number {
+@@ -802,6 +960,17 @@ peeropts : REMOTEAS as4number {
}
free($2);
}
@@ -243,7 +609,7 @@ diff -u -p -r1.1.1.8 -r1.8
| LOCALADDR address {
memcpy(&curpeer->conf.local_addr, &$2,
sizeof(curpeer->conf.local_addr));
-@@ -852,13 +850,17 @@ peeropts : REMOTEAS as4number {
+@@ -852,13 +1021,17 @@ peeropts : REMOTEAS as4number {
curpeer->conf.min_holdtime = $3;
}
| ANNOUNCE family STRING {
@@ -266,7 +632,7 @@ diff -u -p -r1.1.1.8 -r1.8
yyerror("unknown/unsupported SAFI \"%s\"",
$3);
free($3);
-@@ -866,25 +868,31 @@ peeropts : REMOTEAS as4number {
+@@ -866,25 +1039,31 @@ peeropts : REMOTEAS as4number {
}
free($3);
@@ -308,7 +674,7 @@ diff -u -p -r1.1.1.8 -r1.8
curpeer->conf.announce_type = ANNOUNCE_NONE;
else if (!strcmp($2, "all"))
curpeer->conf.announce_type = ANNOUNCE_ALL;
-@@ -1083,7 +1091,7 @@ peeropts : REMOTEAS as4number {
+@@ -1083,7 +1262,7 @@ peeropts : REMOTEAS as4number {
curpeer->conf.reflector_client = 1;
}
| REFLECTOR address {
@@ -317,7 +683,18 @@ diff -u -p -r1.1.1.8 -r1.8
yyerror("route reflector cluster-id must be "
"an IPv4 address");
YYERROR;
-@@ -1336,12 +1344,12 @@ filter_prefix_l : filter_prefix { $$
+@@ -1157,6 +1336,10 @@ family : IPV4 { $$ = AFI_IPv4; }
+ | IPV6 { $$ = AFI_IPv6; }
+ ;
+
++nettype : STATIC { $$ = 1; },
++ | CONNECTED { $$ = 0; }
++ ;
++
+ espah : ESP { $$ = 1; }
+ | AH { $$ = 0; }
+ ;
+@@ -1336,12 +1519,12 @@ filter_prefix_l : filter_prefix { $$
;
filter_prefix : prefix {
@@ -332,7 +709,20 @@ diff -u -p -r1.1.1.8 -r1.8
if (($$ = calloc(1, sizeof(struct filter_prefix_l))) ==
NULL)
fatal(NULL);
-@@ -1437,18 +1445,18 @@ filter_elm : filter_prefix_h {
+@@ -1410,6 +1593,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 +1626,18 @@ filter_elm : filter_prefix_h {
fmopts.prefix_l = $1;
}
| PREFIXLEN prefixlenop {
@@ -354,7 +744,37 @@ diff -u -p -r1.1.1.8 -r1.8
}
| filter_as_h {
if (fmopts.as_l != NULL) {
-@@ -1463,26 +1471,43 @@ filter_elm : filter_prefix_h {
+@@ -1457,32 +1646,73 @@ 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;
}
@@ -404,7 +824,7 @@ diff -u -p -r1.1.1.8 -r1.8
}
;
-@@ -1782,8 +1807,7 @@ filter_set_opt : LOCALPREF NUMBER {
+@@ -1782,8 +2012,7 @@ filter_set_opt : LOCALPREF NUMBER {
else
$$->type = ACTION_SET_COMMUNITY;
@@ -414,7 +834,7 @@ diff -u -p -r1.1.1.8 -r1.8
free($3);
free($$);
YYERROR;
-@@ -1796,40 +1820,62 @@ filter_set_opt : LOCALPREF NUMBER {
+@@ -1796,40 +2025,62 @@ filter_set_opt : LOCALPREF NUMBER {
free($$);
YYERROR;
}
@@ -497,7 +917,7 @@ diff -u -p -r1.1.1.8 -r1.8
;
%%
-@@ -1873,6 +1919,7 @@ lookup(char *s)
+@@ -1873,6 +2124,7 @@ lookup(char *s)
{ "allow", ALLOW},
{ "announce", ANNOUNCE},
{ "any", ANY},
@@ -505,15 +925,20 @@ diff -u -p -r1.1.1.8 -r1.8
{ "blackhole", BLACKHOLE},
{ "capabilities", CAPABILITIES},
{ "community", COMMUNITY},
-@@ -1889,6 +1936,7 @@ lookup(char *s)
+@@ -1889,16 +2141,22 @@ lookup(char *s)
{ "enforce", ENFORCE},
{ "esp", ESP},
{ "evaluate", EVALUATE},
++ { "export-target", EXPORTTRGT},
+ { "ext-community", EXTCOMMUNITY},
{ "fib-update", FIBUPDATE},
{ "from", FROM},
{ "group", GROUP},
-@@ -1899,6 +1947,9 @@ lookup(char *s)
+ { "holdtime", HOLDTIME},
+ { "ignore", IGNORE},
+ { "ike", IKE},
++ { "import-target", IMPORTTRGT},
+ { "in", IN},
{ "include", INCLUDE},
{ "inet", IPV4},
{ "inet6", IPV6},
@@ -523,7 +948,16 @@ diff -u -p -r1.1.1.8 -r1.8
{ "ipsec", IPSEC},
{ "key", KEY},
{ "listen", LISTEN},
-@@ -1918,6 +1969,7 @@ lookup(char *s)
+@@ -1906,6 +2164,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 +2178,7 @@ lookup(char *s)
{ "nexthop", NEXTHOP},
{ "no-modify", NOMODIFY},
{ "on", ON},
@@ -531,15 +965,43 @@ diff -u -p -r1.1.1.8 -r1.8
{ "out", OUT},
{ "passive", PASSIVE},
{ "password", PASSWORD},
-@@ -1930,6 +1982,7 @@ lookup(char *s)
+@@ -1929,10 +2190,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},
-@@ -2135,6 +2188,26 @@ top:
++ { "restricted", RESTRICTED},
+ { "rib", RIB},
+ { "route-collector", ROUTECOLL},
+ { "route-reflector", REFLECTOR},
+@@ -1941,6 +2206,7 @@ lookup(char *s)
+ { "rtlabel", RTLABEL},
+ { "self", SELF},
+ { "set", SET},
++ { "socket", SOCKET },
+ { "softreconfig", SOFTRECONFIG},
+ { "source-as", SOURCEAS},
+ { "spi", SPI},
+@@ -2117,9 +2383,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 +2402,26 @@ top:
if (yylval.v.string == NULL)
fatal("yylex: strdup");
return (STRING);
@@ -548,7 +1010,7 @@ diff -u -p -r1.1.1.8 -r1.8
+ if (next == '=')
+ return (NE);
+ lungetc(next);
-+ break;
++ break;
+ case '<':
+ next = lgetc(0);
+ if (next == '=')
@@ -566,7 +1028,104 @@ diff -u -p -r1.1.1.8 -r1.8
}
#define allowed_to_end_number(x) \
-@@ -2505,27 +2578,27 @@ getcommunity(char *s)
+@@ -2274,18 +2561,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 +2606,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 +2636,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 +2652,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 +2821,27 @@ getcommunity(char *s)
}
int
@@ -604,7 +1163,7 @@ diff -u -p -r1.1.1.8 -r1.8
return (0);
}
-@@ -2537,23 +2610,176 @@ parsecommunity(char *s, int *as, int *ty
+@@ -2537,23 +2853,176 @@ parsecommunity(char *s, int *as, int *ty
if ((i = getcommunity(s)) == COMMUNITY_ERROR)
return (-1);
@@ -784,7 +1343,7 @@ diff -u -p -r1.1.1.8 -r1.8
if ((p = calloc(1, sizeof(struct peer))) == NULL)
fatal("new_peer");
-@@ -2564,11 +2790,11 @@ alloc_peer(void)
+@@ -2564,11 +3033,11 @@ alloc_peer(void)
p->conf.distance = 1;
p->conf.announce_type = ANNOUNCE_UNDEF;
p->conf.announce_capa = 1;
@@ -799,7 +1358,7 @@ diff -u -p -r1.1.1.8 -r1.8
p->conf.local_as = conf->as;
p->conf.local_short_as = conf->short_as;
p->conf.softreconfig_in = 1;
-@@ -2592,6 +2818,9 @@ new_peer(void)
+@@ -2592,6 +3061,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");
@@ -809,7 +1368,72 @@ diff -u -p -r1.1.1.8 -r1.8
p->conf.groupid = curgroup->conf.id;
p->conf.local_as = curgroup->conf.local_as;
p->conf.local_short_as = curgroup->conf.local_short_as;
-@@ -2715,7 +2944,7 @@ get_id(struct peer *newpeer)
+@@ -2674,39 +3146,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 +3200,7 @@ get_id(struct peer *newpeer)
struct peer *p;
for (p = peer_l_old; p != NULL; p = p->next)
@@ -818,7 +1442,7 @@ diff -u -p -r1.1.1.8 -r1.8
if (!memcmp(&p->conf.remote_addr,
&newpeer->conf.remote_addr,
sizeof(p->conf.remote_addr))) {
-@@ -2856,9 +3085,11 @@ str2key(char *s, char *dest, size_t max_
+@@ -2856,9 +3341,11 @@ str2key(char *s, char *dest, size_t max_
int
neighbor_consistent(struct peer *p)
{
@@ -832,7 +1456,7 @@ diff -u -p -r1.1.1.8 -r1.8
yyerror("local-address and neighbor address "
"must be of the same address family");
return (-1);
-@@ -2869,7 +3100,7 @@ neighbor_consistent(struct peer *p)
+@@ -2869,7 +3356,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) &&
@@ -841,7 +1465,7 @@ diff -u -p -r1.1.1.8 -r1.8
yyerror("neighbors with any form of IPsec configured "
"need local-address to be specified");
return (-1);
-@@ -2889,10 +3120,6 @@ neighbor_consistent(struct peer *p)
+@@ -2889,10 +3376,6 @@ neighbor_consistent(struct peer *p)
return (-1);
}
@@ -852,7 +1476,7 @@ diff -u -p -r1.1.1.8 -r1.8
/* set default values if they where undefined */
p->conf.ebgp = (p->conf.remote_as != conf->as);
if (p->conf.announce_type == ANNOUNCE_UNDEF)
-@@ -2909,6 +3136,11 @@ neighbor_consistent(struct peer *p)
+@@ -2909,6 +3392,11 @@ neighbor_consistent(struct peer *p)
return (-1);
}
@@ -864,7 +1488,7 @@ diff -u -p -r1.1.1.8 -r1.8
return (0);
}
-@@ -2927,6 +3159,11 @@ merge_filterset(struct filter_set_head *
+@@ -2927,6 +3415,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");
@@ -876,7 +1500,7 @@ diff -u -p -r1.1.1.8 -r1.8
else
yyerror("redefining set parameter %s",
filterset_name(s->type));
-@@ -2953,9 +3190,18 @@ merge_filterset(struct filter_set_head *
+@@ -2953,9 +3446,18 @@ merge_filterset(struct filter_set_head *
return (0);
}
break;
@@ -897,3 +1521,26 @@ diff -u -p -r1.1.1.8 -r1.8
TAILQ_INSERT_BEFORE(t, s, entry);
return (0);
}
+@@ -2985,22 +3487,6 @@ copy_filterset(struct filter_set_head *s
+ }
+ }
+
+-void
+-move_filterset(struct filter_set_head *source, struct filter_set_head *dest)
+-{
+- struct filter_set *s;
+-
+- TAILQ_INIT(dest);
+-
+- if (source == NULL)
+- return;
+-
+- while ((s = TAILQ_FIRST(source)) != NULL) {
+- TAILQ_REMOVE(source, s, entry);
+- TAILQ_INSERT_TAIL(dest, s, entry);
+- }
+-}
+-
+ struct filter_rule *
+ get_rule(enum action_types type)
+ {
diff --git a/net/openbgpd/files/patch-bgpd_pfkey.c b/net/openbgpd/files/patch-bgpd_pfkey.c
index a7d261db35ea..f8e6845f1661 100644
--- a/net/openbgpd/files/patch-bgpd_pfkey.c
+++ b/net/openbgpd/files/patch-bgpd_pfkey.c
@@ -2,13 +2,13 @@ Index: bgpd/pfkey.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/pfkey.c,v
retrieving revision 1.1.1.6
-retrieving revision 1.1.1.7
-diff -u -p -r1.1.1.6 -r1.1.1.7
+retrieving revision 1.1.1.8
+diff -u -p -r1.1.1.6 -r1.1.1.8
--- bgpd/pfkey.c 14 Feb 2010 20:19:57 -0000 1.1.1.6
-+++ bgpd/pfkey.c 14 Feb 2010 20:27:06 -0000 1.1.1.7
++++ bgpd/pfkey.c 12 Jun 2011 10:44:25 -0000 1.1.1.8
@@ -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 $ */
++/* $OpenBSD: pfkey.c,v 1.41 2010/12/09 13:50:41 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -118,3 +118,81 @@ diff -u -p -r1.1.1.6 -r1.1.1.7
dmask.ss_len = sizeof(struct sockaddr_in6);
dmask.ss_family = AF_INET6;
memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr,
+@@ -411,6 +402,33 @@ pfkey_send(int sd, uint8_t satype, uint8
+ }
+
+ 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,23 +436,13 @@ pfkey_reply(int sd, u_int32_t *spip)
+ 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");
++ do {
++ rv = pfkey_read(sd, &hdr);
++ if (rv == -1)
+ 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");
+- return (-1);
+- }
+- }
++ } while (rv);
+
+ if (hdr.sadb_msg_errno != 0) {
+ errno = hdr.sadb_msg_errno;
+@@ -730,11 +738,9 @@ pfkey_init(struct bgpd_sysdep *sysdep)
+ if (errno == EPROTONOSUPPORT) {
+ log_warnx("PF_KEY not available, disabling ipsec");
+ sysdep->no_pfkey = 1;
+- return (0);
+- } else {
+- log_warn("PF_KEY socket");
+ return (-1);
+- }
++ } else
++ fatal("pfkey setup failed");
+ }
+- return (0);
++ return (fd);
+ }
diff --git a/net/openbgpd/files/patch-bgpd_printconf.c b/net/openbgpd/files/patch-bgpd_printconf.c
index ee5be19032af..82fb337ccb7b 100644
--- a/net/openbgpd/files/patch-bgpd_printconf.c
+++ b/net/openbgpd/files/patch-bgpd_printconf.c
@@ -2,17 +2,21 @@ Index: bgpd/printconf.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/printconf.c,v
retrieving revision 1.1.1.7
-retrieving revision 1.7
-diff -u -p -r1.1.1.7 -r1.7
+retrieving revision 1.8
+diff -u -p -r1.1.1.7 -r1.8
--- bgpd/printconf.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/printconf.c 10 Apr 2010 12:16:23 -0000 1.7
++++ bgpd/printconf.c 2 Jul 2011 16:06:38 -0000 1.8
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.70 2009/06/06 01:10:29 claudio Exp $ */
+/* $OpenBSD: printconf.c,v 1.79 2010/03/05 15:25:00 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
-@@ -19,6 +19,9 @@
+@@ -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>
@@ -22,7 +26,7 @@ diff -u -p -r1.1.1.7 -r1.7
#include "bgpd.h"
#include "mrt.h"
-@@ -27,6 +30,8 @@
+@@ -27,14 +31,19 @@
void print_op(enum comp_ops);
void print_community(int, int);
@@ -30,8 +34,11 @@ diff -u -p -r1.1.1.7 -r1.7
+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 *);
-@@ -34,7 +39,7 @@ void print_peer(struct peer_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);
@@ -40,7 +47,7 @@ diff -u -p -r1.1.1.7 -r1.7
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 +99,45 @@ print_community(int as, int type)
+@@ -94,6 +103,45 @@ print_community(int as, int type)
}
void
@@ -61,10 +68,10 @@ diff -u -p -r1.1.1.7 -r1.7
+ break;
+ case EXT_COMMUNITY_OPAQUE:
+ printf("%s 0x%llx ", log_ext_subtype(c->subtype),
-+ c->data.ext_opaq);
++ (long long unsigned int)c->data.ext_opaq);
+ break;
+ default:
-+ printf("0x%x 0x%llx ", c->type, c->data.ext_opaq);
++ printf("0x%x 0x%llx ", c->type, (long long unsigned int)c->data.ext_opaq);
+ break;
+ }
+}
@@ -86,7 +93,7 @@ diff -u -p -r1.1.1.7 -r1.7
print_set(struct filter_set_head *set)
{
struct filter_set *s;
-@@ -161,11 +205,23 @@ print_set(struct filter_set_head *set)
+@@ -161,11 +209,23 @@ print_set(struct filter_set_head *set)
case ACTION_RTLABEL:
printf("rtlabel %s ", s->action.rtlabel);
break;
@@ -110,16 +117,127 @@ diff -u -p -r1.1.1.7 -r1.7
}
}
printf("}");
-@@ -236,7 +292,7 @@ print_mainconf(struct bgpd_config *conf)
- print_set(&conf->connectset6);
+@@ -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->flags & BGPD_FLAG_REDIST_STATIC) {
-+ if (conf->flags & BGPD_FLAG_REDIST6_STATIC) {
- printf("network inet6 static");
- if (!TAILQ_EMPTY(&conf->staticset6))
- printf(" ");
-@@ -263,8 +319,8 @@ print_peer(struct peer_config *p, struct
+- 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;
@@ -130,7 +248,7 @@ diff -u -p -r1.1.1.7 -r1.7
printf("%sneighbor %s/%u {\n", c, log_addr(&p->remote_addr),
p->remote_masklen);
else
-@@ -281,7 +337,7 @@ print_peer(struct peer_config *p, struct
+@@ -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);
@@ -139,7 +257,7 @@ diff -u -p -r1.1.1.7 -r1.7
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 +351,12 @@ print_peer(struct peer_config *p, struct
+@@ -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);
@@ -152,7 +270,7 @@ diff -u -p -r1.1.1.7 -r1.7
if (p->announce_type == ANNOUNCE_SELF)
printf("%s\tannounce self\n", c);
else if (p->announce_type == ANNOUNCE_NONE)
-@@ -324,6 +386,10 @@ print_peer(struct peer_config *p, struct
+@@ -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);
@@ -163,7 +281,7 @@ diff -u -p -r1.1.1.7 -r1.7
if (p->auth.method == AUTH_MD5SIG)
printf("%s\ttcp md5sig\n", c);
-@@ -354,8 +420,7 @@ print_peer(struct peer_config *p, struct
+@@ -354,8 +447,7 @@ print_peer(struct peer_config *p, struct
if (p->ttlsec)
printf("%s\tttl-security yes\n", c);
@@ -173,7 +291,7 @@ diff -u -p -r1.1.1.7 -r1.7
if (p->softreconfig_in == 1)
printf("%s\tsoftreconfig in yes\n", c);
-@@ -399,17 +464,14 @@ print_enc_alg(u_int8_t alg)
+@@ -399,17 +491,14 @@ print_enc_alg(u_int8_t alg)
}
}
@@ -198,7 +316,7 @@ diff -u -p -r1.1.1.7 -r1.7
}
void
-@@ -455,14 +517,14 @@ print_rule(struct peer *peer_l, struct f
+@@ -455,14 +544,14 @@ print_rule(struct peer *peer_l, struct f
} else
printf("any ");
@@ -217,7 +335,17 @@ diff -u -p -r1.1.1.7 -r1.7
printf("inet6 ");
}
-@@ -497,6 +559,10 @@ print_rule(struct peer *peer_l, struct f
+@@ -492,11 +581,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);
}
@@ -228,3 +356,53 @@ diff -u -p -r1.1.1.7 -r1.7
print_set(&r->set);
+@@ -547,7 +645,7 @@ print_mrt(u_int32_t pid, u_int32_t gid,
+ else
+ printf("%s %s %d\n", mrt_type(m->type),
+ MRT2MC(m)->name,
+- MRT2MC(m)->ReopenTimerInterval);
++ (int)MRT2MC(m)->ReopenTimerInterval);
+ }
+ }
+
+@@ -612,26 +710,34 @@ peer_compare(const void *aa, const void
+ void
+ print_config(struct bgpd_config *conf, struct rib_names *rib_l,
+ struct network_head *net_l, struct peer *peer_l,
+- struct filter_head *rules_l, struct mrt_head *mrt_l)
++ struct filter_head *rules_l, struct mrt_head *mrt_l,
++ struct rdomain_head *rdom_l)
+ {
+ struct filter_rule *r;
+ struct network *n;
+ struct rde_rib *rr;
++ struct rdomain *rd;
+
+ xmrt_l = mrt_l;
+- printf("\n");
+ print_mainconf(conf);
+ printf("\n");
++ TAILQ_FOREACH(n, net_l, entry)
++ print_network(&n->net);
++ printf("\n");
++ SIMPLEQ_FOREACH(rd, rdom_l, entry)
++ print_rdomain(rd);
++ printf("\n");
+ SIMPLEQ_FOREACH(rr, rib_l, entry) {
+ if (rr->flags & F_RIB_NOEVALUATE)
+ printf("rde rib %s no evaluate\n", rr->name);
+- else
++ else if (rr->flags & F_RIB_NOFIB)
+ printf("rde rib %s\n", rr->name);
++ else
++ printf("rde rib %s rtable %u fib-update %s\n", rr->name,
++ rr->rtableid, rr->flags & F_RIB_NOFIBSYNC ?
++ "no" : "yes");
+ }
+ printf("\n");
+- TAILQ_FOREACH(n, net_l, entry)
+- print_network(&n->net);
+- printf("\n");
+ print_mrt(0, 0, "", "");
+ printf("\n");
+ print_groups(conf, peer_l);
diff --git a/net/openbgpd/files/patch-bgpd_rde.c b/net/openbgpd/files/patch-bgpd_rde.c
index 55e10012aa47..a62bcf26fdc7 100644
--- a/net/openbgpd/files/patch-bgpd_rde.c
+++ b/net/openbgpd/files/patch-bgpd_rde.c
@@ -2,17 +2,25 @@ Index: bgpd/rde.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde.c,v
retrieving revision 1.1.1.8
-retrieving revision 1.9
-diff -u -p -r1.1.1.8 -r1.9
+diff -u -p -r1.1.1.8 rde.c
--- bgpd/rde.c 14 Feb 2010 20:19:57 -0000 1.1.1.8
-+++ bgpd/rde.c 10 Apr 2010 12:16:23 -0000 1.9
++++ bgpd/rde.c 3 Jul 2011 04:43:59 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.264 2009/06/29 12:22:16 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.290 2010/03/30 15:43:30 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
-@@ -51,12 +51,16 @@ void rde_update_withdraw(struct rde_pe
+@@ -18,6 +18,8 @@
+
+ #include <sys/types.h>
+ #include <sys/socket.h>
++#include <sys/time.h>
++#include <sys/resource.h>
+
+ #include <errno.h>
+ #include <ifaddrs.h>
+@@ -51,12 +53,16 @@ void rde_update_withdraw(struct rde_pe
int rde_attr_parse(u_char *, u_int16_t, struct rde_peer *,
struct rde_aspath *, struct mpattr *);
u_int8_t rde_attr_missing(struct rde_aspath *, int, u_int16_t);
@@ -31,18 +39,24 @@ diff -u -p -r1.1.1.8 -r1.9
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,
-@@ -81,8 +85,9 @@ void rde_dump_done(void *);
+@@ -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,8 +96,8 @@ struct rde_peer *peer_add(u_int32_t, str
+@@ -91,10 +101,9 @@ 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);
@@ -51,9 +65,19 @@ diff -u -p -r1.1.1.8 -r1.9
+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_init(struct network_head *);
void network_add(struct network_config *, int);
-@@ -120,11 +125,12 @@ struct rde_dump_ctx {
+ void network_delete(struct network_config *, int);
+ void network_dump_upcall(struct rib_entry *, void *);
+@@ -108,6 +117,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 +130,12 @@ struct rde_dump_ctx {
};
struct rde_mrt_ctx {
@@ -69,7 +93,7 @@ diff -u -p -r1.1.1.8 -r1.9
u_int rde_mrt_cnt;
void
-@@ -144,24 +150,17 @@ u_int32_t attrhashsize = 512;
+@@ -144,24 +155,18 @@ u_int32_t attrhashsize = 512;
u_int32_t nexthophashsize = 64;
pid_t
@@ -80,6 +104,7 @@ diff -u -p -r1.1.1.8 -r1.9
+rde_main(int pipe_m2r[2], int pipe_s2r[2], int pipe_m2s[2], int pipe_s2rctl[2],
+ int debug)
{
++ struct rlimit rl;
pid_t pid;
struct passwd *pw;
- struct peer *p;
@@ -98,7 +123,7 @@ diff -u -p -r1.1.1.8 -r1.9
switch (pid = fork()) {
case -1:
-@@ -172,8 +171,6 @@ rde_main(struct bgpd_config *config, str
+@@ -172,8 +177,6 @@ rde_main(struct bgpd_config *config, str
return (pid);
}
@@ -107,7 +132,20 @@ diff -u -p -r1.1.1.8 -r1.9
if ((pw = getpwnam(BGPD_USER)) == NULL)
fatal("getpwnam");
-@@ -194,6 +191,8 @@ rde_main(struct bgpd_config *config, str
+@@ -185,6 +188,12 @@ rde_main(struct bgpd_config *config, str
+ setproctitle("route decision engine");
+ bgpd_process = PROC_RDE;
+
++ if (getrlimit(RLIMIT_DATA, &rl) == -1)
++ fatal("getrlimit");
++ rl.rlim_cur = rl.rlim_max;
++ if (setrlimit(RLIMIT_DATA, &rl) == -1)
++ fatal("setrlimit");
++
+ if (setgroups(1, &pw->pw_gid) ||
+ setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
+ setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
+@@ -194,6 +203,8 @@ rde_main(struct bgpd_config *config, str
signal(SIGINT, rde_sighdlr);
signal(SIGPIPE, SIG_IGN);
signal(SIGHUP, SIG_IGN);
@@ -116,7 +154,7 @@ diff -u -p -r1.1.1.8 -r1.9
close(pipe_s2r[0]);
close(pipe_s2rctl[0]);
-@@ -210,50 +209,21 @@ rde_main(struct bgpd_config *config, str
+@@ -210,50 +221,25 @@ rde_main(struct bgpd_config *config, str
imsg_init(ibuf_se_ctl, pipe_s2rctl[1]);
imsg_init(ibuf_main, pipe_m2r[1]);
@@ -156,7 +194,11 @@ diff -u -p -r1.1.1.8 -r1.9
+ if (rules_l == NULL)
+ fatal(NULL);
+ TAILQ_INIT(rules_l);
-+ if ((conf = malloc(sizeof(struct bgpd_config))) == NULL)
++ 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");
@@ -173,20 +215,29 @@ diff -u -p -r1.1.1.8 -r1.9
while (rde_quit == 0) {
if (pfd_elms < PFD_PIPE_COUNT + rde_mrt_cnt) {
if ((newp = realloc(pfd, sizeof(struct pollfd) *
-@@ -287,9 +257,9 @@ rde_main(struct bgpd_config *config, str
+@@ -287,11 +273,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;
-+ LIST_FOREACH(mctx, &rde_mrts, entry) {
++ 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 +295,26 @@ rde_main(struct bgpd_config *config, str
+ }
+
+@@ -325,24 +318,17 @@ rde_main(struct bgpd_config *config, str
if (pfd[PFD_PIPE_SESSION_CTL].revents & POLLIN)
rde_dispatch_imsg_session(ibuf_se_ctl);
@@ -196,7 +247,6 @@ diff -u -p -r1.1.1.8 -r1.9
- if (pfd[j].fd == mrt->wbuf.fd &&
+ for (j = PFD_PIPE_COUNT, mctx = LIST_FIRST(&rde_mrts);
+ j < i && mctx != 0; j++) {
-+ xmctx = LIST_NEXT(mctx, entry);
+ if (pfd[j].fd == mctx->mrt.wbuf.fd &&
pfd[j].revents & POLLOUT)
- mrt_write(mrt);
@@ -205,17 +255,11 @@ diff -u -p -r1.1.1.8 -r1.9
- close(mrt->wbuf.fd);
- LIST_REMOVE(mrt, entry);
- free(mrt);
-+ mrt_write(&mctx->mrt);
-+ if (mctx->mrt.wbuf.queued == 0 &&
-+ 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--;
- }
+- rde_mrt_cnt--;
+- }
- mrt = xmrt;
-+ mctx = xmctx;
++ mrt_write(&mctx->mrt);
++ mctx = LIST_NEXT(mctx, entry);
}
rde_update_queue_runner();
@@ -225,7 +269,7 @@ diff -u -p -r1.1.1.8 -r1.9
if (ibuf_se_ctl->w.queued <= 0)
rib_dump_runner();
}
-@@ -351,11 +323,12 @@ rde_main(struct bgpd_config *config, str
+@@ -351,11 +337,12 @@ rde_main(struct bgpd_config *config, str
if (debug)
rde_shutdown();
@@ -243,7 +287,7 @@ diff -u -p -r1.1.1.8 -r1.9
}
msgbuf_clear(&ibuf_se->w);
-@@ -378,13 +351,14 @@ rde_dispatch_imsg_session(struct imsgbuf
+@@ -378,13 +365,14 @@ rde_dispatch_imsg_session(struct imsgbuf
struct imsg imsg;
struct peer p;
struct peer_config pconf;
@@ -260,7 +304,7 @@ diff -u -p -r1.1.1.8 -r1.9
if ((n = imsg_read(ibuf)) == -1)
fatal("rde_dispatch_imsg_session: imsg_read error");
-@@ -423,12 +397,14 @@ rde_dispatch_imsg_session(struct imsgbuf
+@@ -423,12 +411,14 @@ rde_dispatch_imsg_session(struct imsgbuf
peer_down(imsg.hdr.peerid);
break;
case IMSG_REFRESH:
@@ -278,7 +322,7 @@ diff -u -p -r1.1.1.8 -r1.9
break;
case IMSG_NETWORK_ADD:
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
-@@ -446,13 +422,13 @@ rde_dispatch_imsg_session(struct imsgbuf
+@@ -446,13 +436,13 @@ rde_dispatch_imsg_session(struct imsgbuf
break;
}
session_set = NULL;
@@ -295,7 +339,7 @@ diff -u -p -r1.1.1.8 -r1.9
if (netconf_s.prefixlen > 128)
goto badnet;
network_add(&netconf_s, 0);
-@@ -544,6 +520,11 @@ badnet:
+@@ -544,6 +534,11 @@ badnet:
imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_RIB_MEM, 0,
imsg.hdr.pid, -1, &rdemem, sizeof(rdemem));
break;
@@ -307,28 +351,153 @@ diff -u -p -r1.1.1.8 -r1.9
default:
break;
}
-@@ -587,7 +568,7 @@ rde_dispatch_imsg_parent(struct imsgbuf
- fatal(NULL);
- memcpy(nconf, imsg.data, sizeof(struct bgpd_config));
- for (rid = 0; rid < rib_size; rid++)
-- ribs[rid].state = RIB_DELETE;
-+ ribs[rid].state = RECONF_DELETE;
+@@ -554,14 +549,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 +574,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));
-@@ -615,9 +596,9 @@ rde_dispatch_imsg_parent(struct imsgbuf
+ TAILQ_INIT(&netconf_p.attrset);
+ parent_set = &netconf_p.attrset;
+@@ -608,6 +598,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 +625,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);
-+ rib_new(rn.name, rn.flags);
- else
+- 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 !=
-@@ -644,9 +625,17 @@ rde_dispatch_imsg_parent(struct imsgbuf
+@@ -631,12 +658,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 +701,27 @@ rde_dispatch_imsg_parent(struct imsgbuf
nconf->flags &= ~BGPD_FLAG_NO_EVALUATE;
}
memcpy(conf, nconf, sizeof(struct bgpd_config));
@@ -338,19 +507,60 @@ diff -u -p -r1.1.1.8 -r1.9
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;
- prefix_network_clean(peerself, reloadtime, 0);
++
++ /* 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 */
-@@ -668,17 +657,29 @@ rde_dispatch_imsg_parent(struct imsgbuf
+ LIST_FOREACH(peer, &peerlist, peer_l) {
+@@ -655,30 +729,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)
@@ -360,7 +570,7 @@ diff -u -p -r1.1.1.8 -r1.9
+ rde_softreconfig_load, &ribs[rid],
+ AID_UNSPEC);
+ }
- /* sync local-RIB first */
++ /* sync local-RIBs first */
if (reconf_in)
rib_dump(&ribs[0], rde_softreconfig_in, NULL,
- AF_UNSPEC);
@@ -377,10 +587,17 @@ diff -u -p -r1.1.1.8 -r1.9
- 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,10 +689,6 @@ rde_dispatch_imsg_parent(struct imsgbuf
+@@ -688,16 +791,16 @@ rde_dispatch_imsg_parent(struct imsgbuf
}
free(rules_l);
rules_l = newrules;
@@ -388,10 +605,20 @@ diff -u -p -r1.1.1.8 -r1.9
- if (ribs[rid].state == RIB_DELETE)
- rib_free(&ribs[rid]);
- }
++
log_info("RDE reconfigured");
break;
case IMSG_NEXTHOP_UPDATE:
-@@ -744,6 +741,8 @@ rde_dispatch_imsg_parent(struct imsgbuf
+ 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");
+@@ -744,6 +847,8 @@ rde_dispatch_imsg_parent(struct imsgbuf
int
rde_update_dispatch(struct imsg *imsg)
{
@@ -400,7 +627,7 @@ diff -u -p -r1.1.1.8 -r1.9
struct rde_peer *peer;
struct rde_aspath *asp = NULL;
u_char *p, *mpp = NULL;
-@@ -752,9 +751,7 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -752,9 +857,8 @@ rde_update_dispatch(struct imsg *imsg)
u_int16_t withdrawn_len;
u_int16_t attrpath_len;
u_int16_t nlri_len;
@@ -408,10 +635,11 @@ diff -u -p -r1.1.1.8 -r1.9
- 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,14 +807,7 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -810,26 +914,21 @@ rde_update_dispatch(struct imsg *imsg)
goto done;
}
@@ -427,7 +655,28 @@ diff -u -p -r1.1.1.8 -r1.9
/* enforce remote AS if requested */
if (asp->flags & F_ATTR_ASPATH &&
-@@ -860,9 +850,9 @@ rde_update_dispatch(struct imsg *imsg)
+- 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 +959,9 @@ rde_update_dispatch(struct imsg *imsg)
p += pos;
len -= pos;
@@ -440,7 +689,7 @@ diff -u -p -r1.1.1.8 -r1.9
rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR,
NULL, 0);
goto done;
-@@ -892,15 +882,25 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -892,15 +991,25 @@ rde_update_dispatch(struct imsg *imsg)
afi = ntohs(afi);
safi = *mpp++;
mplen--;
@@ -475,7 +724,7 @@ diff -u -p -r1.1.1.8 -r1.9
while (mplen > 0) {
if ((pos = rde_update_get_prefix6(mpp, mplen,
&prefix, &prefixlen)) == -1) {
-@@ -926,6 +926,32 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -926,6 +1035,32 @@ rde_update_dispatch(struct imsg *imsg)
rde_update_withdraw(peer, &prefix, prefixlen);
}
break;
@@ -508,7 +757,7 @@ diff -u -p -r1.1.1.8 -r1.9
default:
/* silently ignore unsupported multiprotocol AF */
break;
-@@ -963,9 +989,9 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -963,9 +1098,9 @@ rde_update_dispatch(struct imsg *imsg)
p += pos;
nlri_len -= pos;
@@ -521,7 +770,7 @@ diff -u -p -r1.1.1.8 -r1.9
rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR,
NULL, 0);
goto done;
-@@ -995,6 +1021,22 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -995,6 +1130,22 @@ rde_update_dispatch(struct imsg *imsg)
safi = *mpp++;
mplen--;
@@ -544,7 +793,7 @@ diff -u -p -r1.1.1.8 -r1.9
/*
* this works because asp is not linked.
* But first unlock the previously locked nexthop.
-@@ -1004,8 +1046,8 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -1004,8 +1155,8 @@ rde_update_dispatch(struct imsg *imsg)
(void)nexthop_delete(asp->nexthop);
asp->nexthop = NULL;
}
@@ -555,7 +804,7 @@ diff -u -p -r1.1.1.8 -r1.9
rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR,
mpa.reach, mpa.reach_len);
goto done;
-@@ -1013,16 +1055,8 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -1013,16 +1164,8 @@ rde_update_dispatch(struct imsg *imsg)
mpp += pos;
mplen -= pos;
@@ -574,7 +823,7 @@ diff -u -p -r1.1.1.8 -r1.9
while (mplen > 0) {
if ((pos = rde_update_get_prefix6(mpp, mplen,
&prefix, &prefixlen)) == -1) {
-@@ -1058,6 +1092,42 @@ rde_update_dispatch(struct imsg *imsg)
+@@ -1058,6 +1201,42 @@ rde_update_dispatch(struct imsg *imsg)
}
break;
@@ -617,7 +866,7 @@ diff -u -p -r1.1.1.8 -r1.9
default:
/* silently ignore unsupported multiprotocol AF */
break;
-@@ -1085,7 +1155,8 @@ rde_update_update(struct rde_peer *peer,
+@@ -1085,7 +1264,8 @@ rde_update_update(struct rde_peer *peer,
struct bgpd_addr *prefix, u_int8_t prefixlen)
{
struct rde_aspath *fasp;
@@ -627,7 +876,7 @@ diff -u -p -r1.1.1.8 -r1.9
u_int16_t i;
peer->prefix_rcvd_update++;
-@@ -1095,18 +1166,24 @@ rde_update_update(struct rde_peer *peer,
+@@ -1095,18 +1275,24 @@ rde_update_update(struct rde_peer *peer,
for (i = 1; i < rib_size; i++) {
/* input filter */
@@ -659,7 +908,7 @@ diff -u -p -r1.1.1.8 -r1.9
/* free modified aspath */
if (fasp != asp)
path_put(fasp);
-@@ -1114,6 +1191,8 @@ done:
+@@ -1114,6 +1300,8 @@ done:
if (r)
peer->prefix_cnt++;
@@ -668,7 +917,42 @@ diff -u -p -r1.1.1.8 -r1.9
}
void
-@@ -1248,7 +1327,7 @@ bad_flags:
+@@ -1161,6 +1349,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 +1384,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 +1410,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 +1448,7 @@ bad_flags:
a->flags |= F_ATTR_NEXTHOP;
bzero(&nexthop, sizeof(nexthop));
@@ -677,7 +961,7 @@ diff -u -p -r1.1.1.8 -r1.9
UPD_READ(&nexthop.v4.s_addr, p, plen, 4);
/*
* Check if the nexthop is a valid IP address. We consider
-@@ -1305,9 +1384,19 @@ bad_flags:
+@@ -1305,9 +1505,21 @@ bad_flags:
goto optattr;
case ATTR_AGGREGATOR:
if ((!rde_as4byte(peer) && attr_len != 6) ||
@@ -692,6 +976,8 @@ diff -u -p -r1.1.1.8 -r1.9
+ */
+ if ((flags & ATTR_PARTIAL) == 0)
+ goto bad_len;
++ log_peer_warnx(&peer->conf, "bad AGGREGATOR, "
++ "partial attribute ignored");
+ plen += attr_len;
+ break;
+ }
@@ -700,13 +986,13 @@ diff -u -p -r1.1.1.8 -r1.9
goto bad_flags;
if (!rde_as4byte(peer)) {
/* need to inflate aggregator AS to 4-byte */
-@@ -1323,8 +1412,33 @@ bad_flags:
+@@ -1323,8 +1535,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 & 0x3) != 0) {
++ if (attr_len % 4 != 0) {
+ /*
+ * mark update as bad and withdraw all routes as per
+ * draft-ietf-idr-optional-transitive-00.txt
@@ -714,15 +1000,16 @@ diff -u -p -r1.1.1.8 -r1.9
+ */
+ if ((flags & ATTR_PARTIAL) == 0)
+ goto bad_len;
-+ else
-+ a->flags |= F_ATTR_PARSE_ERR;
++ 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 & 0x7) != 0) {
++ if (attr_len % 8 != 0) {
+ /*
+ * mark update as bad and withdraw all routes as per
+ * draft-ietf-idr-optional-transitive-00.txt
@@ -730,13 +1017,23 @@ diff -u -p -r1.1.1.8 -r1.9
+ */
+ if ((flags & ATTR_PARTIAL) == 0)
+ goto bad_len;
-+ else
-+ a->flags |= F_ATTR_PARSE_ERR;
++ 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;
-@@ -1370,8 +1484,14 @@ bad_flags:
+@@ -1336,7 +1575,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 +1609,15 @@ bad_flags:
plen += attr_len;
break;
case ATTR_AS4_AGGREGATOR:
@@ -746,14 +1043,20 @@ diff -u -p -r1.1.1.8 -r1.9
+ /* see ATTR_AGGREGATOR ... */
+ if ((flags & ATTR_PARTIAL) == 0)
+ goto bad_len;
-+ /* we should add a warning here */
++ 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;
-@@ -1385,13 +1505,21 @@ bad_flags:
+@@ -1381,17 +1627,28 @@ 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
@@ -767,11 +1070,14 @@ diff -u -p -r1.1.1.8 -r1.9
+ * 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;
-+ if (flags & ATTR_PARTIAL) {
++ 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,
@@ -781,7 +1087,7 @@ diff -u -p -r1.1.1.8 -r1.9
}
a->flags |= F_ATTR_AS4BYTE_NEW;
goto optattr;
-@@ -1440,8 +1568,8 @@ rde_attr_missing(struct rde_aspath *a, i
+@@ -1440,8 +1697,8 @@ rde_attr_missing(struct rde_aspath *a, i
}
int
@@ -792,7 +1098,7 @@ diff -u -p -r1.1.1.8 -r1.9
{
struct bgpd_addr nexthop;
u_int8_t totlen, nhlen;
-@@ -1457,8 +1585,9 @@ rde_get_mp_nexthop(u_char *data, u_int16
+@@ -1457,8 +1714,9 @@ rde_get_mp_nexthop(u_char *data, u_int16
return (-1);
bzero(&nexthop, sizeof(nexthop));
@@ -804,7 +1110,7 @@ diff -u -p -r1.1.1.8 -r1.9
/*
* RFC2545 describes that there may be a link-local
* address carried in nexthop. Yikes!
-@@ -1471,72 +1600,143 @@ rde_get_mp_nexthop(u_char *data, u_int16
+@@ -1471,72 +1729,143 @@ rde_get_mp_nexthop(u_char *data, u_int16
log_warnx("bad multiprotocol nexthop, bad size");
return (-1);
}
@@ -831,7 +1137,7 @@ diff -u -p -r1.1.1.8 -r1.9
- * cause a use after free error.
+ * Neither RFC4364 nor RFC3107 specify the format of the
+ * nexthop in an explicit way. The quality of RFC went down
-+ * the toilet the larger the the number got.
++ * the toilet the larger the 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
@@ -987,7 +1293,7 @@ diff -u -p -r1.1.1.8 -r1.9
if (len < 1)
return (-1);
-@@ -1546,18 +1746,43 @@ rde_update_get_prefix6(u_char *p, u_int1
+@@ -1546,25 +1875,50 @@ rde_update_get_prefix6(u_char *p, u_int1
plen = 1;
bzero(prefix, sizeof(struct bgpd_addr));
@@ -1041,7 +1347,15 @@ diff -u -p -r1.1.1.8 -r1.9
}
void
-@@ -1616,6 +1841,14 @@ rde_as4byte_fixup(struct rde_peer *peer,
+ 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 +1970,30 @@ rde_as4byte_fixup(struct rde_peer *peer,
struct attr *nasp, *naggr, *oaggr;
u_int32_t as;
@@ -1056,7 +1370,25 @@ diff -u -p -r1.1.1.8 -r1.9
/* first get the attributes */
nasp = attr_optget(a, ATTR_AS4_PATH);
naggr = attr_optget(a, ATTR_AS4_AGGREGATOR);
-@@ -1669,6 +1902,10 @@ rde_reflector(struct rde_peer *peer, str
+
+ 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 +2037,10 @@ rde_reflector(struct rde_peer *peer, str
u_int16_t len;
u_int32_t id;
@@ -1067,7 +1399,16 @@ diff -u -p -r1.1.1.8 -r1.9
/* 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) {
-@@ -1748,8 +1985,8 @@ rde_dump_rib_as(struct prefix *p, struct
+@@ -1724,7 +2096,7 @@ 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;
+ u_int8_t l;
+@@ -1748,23 +2120,23 @@ 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));
@@ -1078,7 +1419,54 @@ diff -u -p -r1.1.1.8 -r1.9
}
pt_getaddr(p->prefix, &rib.prefix);
rib.prefixlen = p->prefix->prefixlen;
-@@ -1836,7 +2073,7 @@ rde_dump_filter(struct prefix *p, struct
+ rib.origin = asp->origin;
+ rib.flags = 0;
+ if (p->rib->active == p)
+- rib.flags |= F_RIB_ACTIVE;
++ rib.flags |= F_PREF_ACTIVE;
+ if (asp->peer->conf.ebgp == 0)
+- rib.flags |= F_RIB_INTERNAL;
++ 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;
+ rib.aspath_len = aspath_length(asp->aspath);
+
+ if ((wbuf = imsg_create(ibuf_se_ctl, IMSG_CTL_SHOW_RIB, 0, pid,
+@@ -1784,13 +2156,13 @@ rde_dump_rib_as(struct prefix *p, struct
+ 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,15 +2200,15 @@ 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 &&
++ if (req->type == IMSG_CTL_SHOW_RIB_AS &&
!aspath_match(p->aspath->aspath, req->as.type, req->as.as))
return;
if (req->type == IMSG_CTL_SHOW_RIB_COMMUNITY &&
@@ -1087,7 +1475,7 @@ diff -u -p -r1.1.1.8 -r1.9
req->community.type))
return;
rde_dump_rib_as(p, p->aspath, req->pid, req->flags);
-@@ -1872,7 +2109,7 @@ rde_dump_prefix_upcall(struct rib_entry
+@@ -1872,7 +2244,7 @@ rde_dump_prefix_upcall(struct rib_entry
pt = re->prefix;
pt_getaddr(pt, &addr);
@@ -1096,7 +1484,15 @@ diff -u -p -r1.1.1.8 -r1.9
return;
if (ctx->req.prefixlen > pt->prefixlen)
return;
-@@ -1902,6 +2139,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req
+@@ -1889,6 +2261,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 +2275,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));
@@ -1104,7 +1500,27 @@ diff -u -p -r1.1.1.8 -r1.9
return;
}
-@@ -1937,7 +2175,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req
+@@ -1924,7 +2298,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 +2322,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req
}
ctx->ribctx.ctx_done = rde_dump_done;
ctx->ribctx.ctx_arg = ctx;
@@ -1113,7 +1529,7 @@ diff -u -p -r1.1.1.8 -r1.9
rib_dump_r(&ctx->ribctx);
}
-@@ -1974,10 +2212,10 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t
+@@ -1974,10 +2359,10 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t
ctx->ribctx.ctx_count = RDE_RUNNER_ROUNDS;
ctx->ribctx.ctx_rib = &ribs[id];
ctx->ribctx.ctx_upcall = mrt_dump_upcall;
@@ -1127,38 +1543,118 @@ diff -u -p -r1.1.1.8 -r1.9
rde_mrt_cnt++;
rib_dump_r(&ctx->ribctx);
}
-@@ -2011,8 +2249,8 @@ rde_send_kroute(struct prefix *new, stru
+@@ -1985,13 +2370,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 +2408,45 @@ 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_INET:
- bzero(&kl, sizeof(kl));
- kl.kr.prefix.s_addr = addr.v4.s_addr;
- kl.kr.prefixlen = p->prefix->prefixlen;
-@@ -2029,7 +2267,7 @@ rde_send_kroute(struct prefix *new, stru
- sizeof(kl)) == -1)
- fatal("imsg_compose error");
++ case AID_VPN_IPv4:
++ if (ribid != 1)
++ /* not Loc-RIB, no update for VPNs */
++ break;
++
++ SIMPLEQ_FOREACH(rd, rdomains_l, entry) {
++ if (addr.vpn4.rd != rd->rd)
++ continue;
++ if (!rde_rdomain_import(p->aspath, rd))
++ continue;
++ /* must send exit_nexthop so that correct MPLS tunnel
++ * 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:
-+ case AID_INET6:
- bzero(&kl6, sizeof(kl6));
- memcpy(&kl6.kr.prefix, &addr.v6, sizeof(struct in6_addr));
- kl6.kr.prefixlen = p->prefix->prefixlen;
-@@ -2050,6 +2288,10 @@ rde_send_kroute(struct prefix *new, stru
- sizeof(kl6)) == -1)
+- 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;
-+ case AID_VPN_IPv4:
-+ break;
-+ default:
-+ fatal("rde_send_kroute: unhandled AID");
}
- }
-
-@@ -2098,7 +2340,6 @@ rde_send_pftable_commit(void)
+@@ -2098,7 +2497,6 @@ rde_send_pftable_commit(void)
void
rde_send_nexthop(struct bgpd_addr *next, int valid)
{
@@ -1166,7 +1662,7 @@ diff -u -p -r1.1.1.8 -r1.9
int type;
if (valid)
-@@ -2106,8 +2347,6 @@ rde_send_nexthop(struct bgpd_addr *next,
+@@ -2106,8 +2504,6 @@ rde_send_nexthop(struct bgpd_addr *next,
else
type = IMSG_NEXTHOP_REMOVE;
@@ -1175,7 +1671,7 @@ diff -u -p -r1.1.1.8 -r1.9
if (imsg_compose(ibuf_main, type, 0, 0, -1, next,
sizeof(struct bgpd_addr)) == -1)
fatal("imsg_compose error");
-@@ -2201,6 +2440,10 @@ rde_softreconfig_in(struct rib_entry *re
+@@ -2201,6 +2597,10 @@ rde_softreconfig_in(struct rib_entry *re
continue;
for (i = 1; i < rib_size; i++) {
@@ -1186,7 +1682,7 @@ diff -u -p -r1.1.1.8 -r1.9
/* check if prefix changed */
oa = rde_filter(i, &oasp, rules_l, peer, asp, &addr,
pt->prefixlen, peer, DIR_IN);
-@@ -2228,7 +2471,7 @@ rde_softreconfig_in(struct rib_entry *re
+@@ -2228,7 +2628,7 @@ rde_softreconfig_in(struct rib_entry *re
if (path_compare(nasp, oasp) == 0)
goto done;
/* send update */
@@ -1195,7 +1691,7 @@ diff -u -p -r1.1.1.8 -r1.9
pt->prefixlen);
}
-@@ -2241,6 +2484,40 @@ done:
+@@ -2241,6 +2641,104 @@ done:
}
}
@@ -1233,10 +1729,92 @@ diff -u -p -r1.1.1.8 -r1.9
+ }
+}
+
++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
*/
-@@ -2286,7 +2563,7 @@ void
+@@ -2252,7 +2750,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 +2763,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 +2784,7 @@ void
rde_update_queue_runner(void)
{
struct rde_peer *peer;
@@ -1245,7 +1823,7 @@ diff -u -p -r1.1.1.8 -r1.9
u_int16_t len, wd_len, wpos;
len = sizeof(queue_buf) - MSGSIZE_HEADER;
-@@ -2300,7 +2577,7 @@ rde_update_queue_runner(void)
+@@ -2300,7 +2798,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,
@@ -1254,7 +1832,7 @@ diff -u -p -r1.1.1.8 -r1.9
wd_len = r;
/* write withdraws length filed */
wd_len = htons(wd_len);
-@@ -2310,31 +2587,49 @@ rde_update_queue_runner(void)
+@@ -2310,31 +2808,49 @@ rde_update_queue_runner(void)
/* now bgp path attributes */
r = up_dump_attrnlri(queue_buf + wpos, len - wpos,
peer);
@@ -1314,7 +1892,7 @@ diff -u -p -r1.1.1.8 -r1.9
u_int16_t len;
/* first withdraws ... */
-@@ -2346,7 +2641,7 @@ rde_update6_queue_runner(void)
+@@ -2346,7 +2862,7 @@ rde_update6_queue_runner(void)
if (peer->state != PEER_UP)
continue;
len = sizeof(queue_buf) - MSGSIZE_HEADER;
@@ -1323,7 +1901,7 @@ diff -u -p -r1.1.1.8 -r1.9
if (b == NULL)
continue;
-@@ -2369,10 +2664,18 @@ rde_update6_queue_runner(void)
+@@ -2369,10 +2885,18 @@ rde_update6_queue_runner(void)
if (peer->state != PEER_UP)
continue;
len = sizeof(queue_buf) - MSGSIZE_HEADER;
@@ -1333,19 +1911,19 @@ diff -u -p -r1.1.1.8 -r1.9
+ r = up_dump_mp_reach(queue_buf, &len, peer, aid);
+ switch (r) {
+ case -2:
- continue;
++ continue;
+ case -1:
+ peer_send_eor(peer, aid);
-+ continue;
+ continue;
+ default:
+ b = queue_buf + r;
+ break;
+ }
-+
++
/* finally send message to SE */
if (imsg_compose(ibuf_se, IMSG_UPDATE, peer->conf.id,
0, -1, b, len) == -1)
-@@ -2411,7 +2714,7 @@ rde_decisionflags(void)
+@@ -2411,7 +2935,7 @@ rde_decisionflags(void)
int
rde_as4byte(struct rde_peer *peer)
{
@@ -1354,7 +1932,7 @@ diff -u -p -r1.1.1.8 -r1.9
}
/*
-@@ -2429,7 +2732,6 @@ void
+@@ -2429,7 +2953,6 @@ void
peer_init(u_int32_t hashsize)
{
struct peer_config pc;
@@ -1362,7 +1940,7 @@ diff -u -p -r1.1.1.8 -r1.9
u_int32_t hs, i;
for (hs = 1; hs < hashsize; hs <<= 1)
-@@ -2445,17 +2747,13 @@ peer_init(u_int32_t hashsize)
+@@ -2445,17 +2968,13 @@ peer_init(u_int32_t hashsize)
peertable.peer_hashmask = hs - 1;
bzero(&pc, sizeof(pc));
@@ -1381,7 +1959,7 @@ diff -u -p -r1.1.1.8 -r1.9
}
void
-@@ -2534,14 +2832,10 @@ peer_localaddrs(struct rde_peer *peer, s
+@@ -2534,14 +3053,10 @@ peer_localaddrs(struct rde_peer *peer, s
if (ifa->ifa_addr->sa_family ==
match->ifa_addr->sa_family)
ifa = match;
@@ -1397,7 +1975,7 @@ diff -u -p -r1.1.1.8 -r1.9
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 +2853,7 @@ peer_localaddrs(struct rde_peer *peer, s
+@@ -2559,13 +3074,7 @@ peer_localaddrs(struct rde_peer *peer, s
&((struct sockaddr_in6 *)ifa->
ifa_addr)->sin6_addr))
continue;
@@ -1412,7 +1990,7 @@ diff -u -p -r1.1.1.8 -r1.9
break;
}
}
-@@ -2577,6 +2865,7 @@ void
+@@ -2577,6 +3086,7 @@ void
peer_up(u_int32_t id, struct session_up *sup)
{
struct rde_peer *peer;
@@ -1420,7 +1998,7 @@ diff -u -p -r1.1.1.8 -r1.9
peer = peer_get(id);
if (peer == NULL) {
-@@ -2590,10 +2879,7 @@ peer_up(u_int32_t id, struct session_up
+@@ -2590,10 +3100,7 @@ peer_up(u_int32_t id, struct session_up
peer->short_as = sup->short_as;
memcpy(&peer->remote_addr, &sup->remote_addr,
sizeof(peer->remote_addr));
@@ -1432,7 +2010,7 @@ diff -u -p -r1.1.1.8 -r1.9
peer_localaddrs(peer, &sup->local_addr);
-@@ -2607,7 +2893,10 @@ peer_up(u_int32_t id, struct session_up
+@@ -2607,7 +3114,10 @@ peer_up(u_int32_t id, struct session_up
*/
return;
@@ -1444,7 +2022,7 @@ diff -u -p -r1.1.1.8 -r1.9
}
void
-@@ -2642,42 +2931,32 @@ peer_down(u_int32_t id)
+@@ -2642,42 +3152,32 @@ peer_down(u_int32_t id)
}
void
@@ -1501,7 +2079,7 @@ diff -u -p -r1.1.1.8 -r1.9
u_char null[4];
bzero(&null, 4);
-@@ -2688,6 +2967,9 @@ peer_send_eor(struct rde_peer *peer, u_i
+@@ -2688,6 +3188,9 @@ peer_send_eor(struct rde_peer *peer, u_i
u_int16_t i;
u_char buf[10];
@@ -1511,50 +2089,178 @@ diff -u -p -r1.1.1.8 -r1.9
i = 0; /* v4 withdrawn len */
bcopy(&i, &buf[0], sizeof(i));
i = htons(6); /* path attr len */
-@@ -2737,7 +3019,7 @@ network_add(struct network_config *nc, i
+@@ -2709,25 +3212,43 @@ 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;
+
++ 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;
++ }
++ }
++ }
++
+ asp = path_get();
+ asp->aspath = aspath_get(NULL, 0);
+ asp->origin = ORIGIN_IGP;
+@@ -2737,7 +3258,9 @@ network_add(struct network_config *nc, i
if (!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);
-@@ -2772,9 +3054,10 @@ network_dump_upcall(struct rib_entry *re
+@@ -2749,12 +3272,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 +3316,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) {
-+ pt_getaddr(p->prefix, &addr);
-+ switch (addr.aid) {
-+ case AID_INET:
- bzero(&k, sizeof(k));
+- 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)
-@@ -2783,10 +3066,9 @@ network_dump_upcall(struct rib_entry *re
- ctx->req.pid, -1, &k, sizeof(k)) == -1)
- log_warnx("network_dump_upcall: "
- "imsg_compose error");
+- 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) {
-+ break;
-+ case AID_INET6:
- bzero(&k6, sizeof(k6));
+- 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)
-@@ -2795,6 +3077,7 @@ network_dump_upcall(struct rib_entry *re
- ctx->req.pid, -1, &k6, sizeof(k6)) == -1)
- log_warnx("network_dump_upcall: "
- "imsg_compose error");
-+ break;
- }
+- 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 +3124,10 @@ sa_cmp(struct bgpd_addr *a, struct socka
+
+@@ -2841,10 +3386,10 @@ sa_cmp(struct bgpd_addr *a, struct socka
struct sockaddr_in *in_b;
struct sockaddr_in6 *in6_b;
diff --git a/net/openbgpd/files/patch-bgpd_rde.h b/net/openbgpd/files/patch-bgpd_rde.h
index a19b053cac1d..22b372178ee9 100644
--- a/net/openbgpd/files/patch-bgpd_rde.h
+++ b/net/openbgpd/files/patch-bgpd_rde.h
@@ -2,13 +2,13 @@ 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.10
-diff -u -p -r1.1.1.8 -r1.1.1.10
+retrieving revision 1.1.1.11
+diff -u -p -r1.1.1.8 -r1.1.1.11
--- bgpd/rde.h 14 Feb 2010 20:19:57 -0000 1.1.1.8
-+++ bgpd/rde.h 10 Apr 2010 12:13:05 -0000 1.1.1.10
++++ bgpd/rde.h 12 Jun 2011 10:44:25 -0000 1.1.1.11
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.120 2009/06/06 01:10:29 claudio Exp $ */
-+/* $OpenBSD: rde.h,v 1.133 2010/03/29 09:24:07 claudio Exp $ */
++/* $OpenBSD: rde.h,v 1.138 2010/11/18 12:18:31 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -28,7 +28,21 @@ diff -u -p -r1.1.1.8 -r1.1.1.10
u_int64_t prefix_rcvd_update;
u_int64_t prefix_rcvd_withdraw;
u_int64_t prefix_sent_update;
-@@ -163,6 +160,7 @@ LIST_HEAD(prefix_head, prefix);
+@@ -77,10 +74,13 @@ struct rde_peer {
+ u_int16_t short_as;
+ 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);
+@@ -163,6 +163,7 @@ LIST_HEAD(prefix_head, prefix);
#define F_NEXTHOP_REJECT 0x02000
#define F_NEXTHOP_BLACKHOLE 0x04000
#define F_NEXTHOP_NOMODIFY 0x08000
@@ -36,7 +50,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10
#define F_ATTR_LINKED 0x20000
-@@ -220,14 +218,14 @@ struct nexthop {
+@@ -220,14 +221,14 @@ struct nexthop {
/* generic entry without address specific part */
struct pt_entry {
RB_ENTRY(pt_entry) pt_e;
@@ -53,7 +67,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10
u_int8_t prefixlen;
u_int16_t refcnt;
struct in_addr prefix4;
-@@ -235,12 +233,25 @@ struct pt_entry4 {
+@@ -235,12 +236,25 @@ struct pt_entry4 {
struct pt_entry6 {
RB_ENTRY(pt_entry) pt_e;
@@ -80,7 +94,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10
struct rib_context {
LIST_ENTRY(rib_context) entry;
struct rib_entry *ctx_re;
-@@ -250,7 +261,7 @@ struct rib_context {
+@@ -250,7 +264,7 @@ struct rib_context {
void (*ctx_wait)(void *);
void *ctx_arg;
unsigned int ctx_count;
@@ -89,7 +103,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10
};
struct rib_entry {
-@@ -262,16 +273,10 @@ struct rib_entry {
+@@ -262,23 +276,15 @@ struct rib_entry {
u_int16_t flags;
};
@@ -103,15 +117,50 @@ diff -u -p -r1.1.1.8 -r1.1.1.10
char name[PEER_DESCR_LEN];
struct rib_tree rib;
- enum rib_state state;
-+ enum reconf_action state;
++ u_int rtableid;
u_int16_t flags;
u_int16_t id;
++ enum reconf_action state;
};
-@@ -342,21 +347,29 @@ int aspath_loopfree(struct aspath *, u
+
+-#define F_RIB_ENTRYLOCK 0x0001
+-#define F_RIB_NOEVALUATE 0x0002
+-#define F_RIB_NOFIB 0x0004
+ #define RIB_FAILED 0xffff
+
+ struct prefix {
+@@ -293,7 +299,7 @@ extern struct rde_memstats rdemem;
+
+ /* prototypes */
+ /* rde.c */
+-void rde_send_kroute(struct prefix *, struct prefix *);
++void rde_send_kroute(struct prefix *, struct prefix *, u_int16_t);
+ void rde_send_nexthop(struct bgpd_addr *, int);
+ void rde_send_pftable(u_int16_t, struct bgpd_addr *,
+ u_int8_t, int);
+@@ -309,7 +315,7 @@ int rde_as4byte(struct rde_peer *);
+ /* 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 +333,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);
+@@ -342,21 +349,30 @@ int aspath_loopfree(struct aspath *, u
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);
@@ -129,7 +178,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10
extern struct rib *ribs;
-u_int16_t rib_new(int, char *, u_int16_t);
-+u_int16_t rib_new(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);
@@ -140,7 +189,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10
void rib_dump_r(struct rib_context *);
void rib_dump_runner(void);
int rib_dump_pending(void);
-@@ -395,7 +408,7 @@ void prefix_network_clean(struct rde_p
+@@ -395,7 +411,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 *,
@@ -149,7 +198,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10
void nexthop_link(struct rde_aspath *);
void nexthop_unlink(struct rde_aspath *);
int nexthop_delete(struct nexthop *);
-@@ -415,12 +428,15 @@ int up_generate(struct rde_peer *, str
+@@ -415,12 +431,15 @@ 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 *,
@@ -168,7 +217,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10
/* rde_prefix.c */
#define pt_empty(pt) ((pt)->refcnt == 0)
-@@ -452,8 +468,7 @@ enum filter_actions rde_filter(u_int16_t
+@@ -452,8 +471,7 @@ enum filter_actions rde_filter(u_int16_t
struct rde_aspath *, struct bgpd_addr *, u_int8_t,
struct rde_peer *, enum directions);
void rde_apply_set(struct rde_aspath *, struct filter_set_head *,
diff --git a/net/openbgpd/files/patch-bgpd_rde_attr.c b/net/openbgpd/files/patch-bgpd_rde_attr.c
index f62d59f083f0..eccdc1e36c27 100644
--- a/net/openbgpd/files/patch-bgpd_rde_attr.c
+++ b/net/openbgpd/files/patch-bgpd_rde_attr.c
@@ -2,17 +2,17 @@ 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.5
-diff -u -p -r1.1.1.6 -r1.5
+retrieving revision 1.6
+diff -u -p -r1.1.1.6 -r1.6
--- bgpd/rde_attr.c 14 Feb 2010 20:19:57 -0000 1.1.1.6
-+++ bgpd/rde_attr.c 10 Apr 2010 12:16:23 -0000 1.5
++++ bgpd/rde_attr.c 2 Jul 2011 16:06:38 -0000 1.6
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_attr.c,v 1.79 2009/03/19 06:52:59 claudio Exp $ */
+/* $OpenBSD: rde_attr.c,v 1.83 2010/03/29 09:24:07 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
-@@ -17,7 +17,11 @@
+@@ -17,14 +17,22 @@
*/
#include <sys/types.h>
@@ -24,7 +24,8 @@ diff -u -p -r1.1.1.6 -r1.5
#include <sys/queue.h>
#include <netinet/in.h>
-@@ -25,6 +29,9 @@
+
++#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -34,39 +35,143 @@ diff -u -p -r1.1.1.6 -r1.5
#include "bgpd.h"
#include "rde.h"
-@@ -971,15 +978,26 @@ aspath_match(struct aspath *a, enum as_s
+@@ -63,7 +71,7 @@ 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];
+@@ -80,9 +88,9 @@ attr_writebuf(struct buf *buf, u_int8_t
+ 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 */
+@@ -405,6 +416,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 +431,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 +451,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
+@@ -972,14 +992,62 @@ aspath_match(struct aspath *a, enum as_s
+ }
+
+ int
+-community_match(void *data, u_int16_t len, int as, int type)
++aspath_lenmatch(struct aspath *a, enum aslen_spec type, u_int aslen)
+ {
+- u_int8_t *p = data;
+- u_int16_t eas, etype;
++ u_int8_t *seg;
++ u_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 == ASLEN_MAX) {
++ if (aslen < aspath_count(a->data, a->len))
++ return (1);
++ else
++ return (0);
++ }
+
+- len >>= 2; /* divide by four */
++ /* 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;
+
+- for (; len > 0; len--) {
++ for (i = 0; i < seg_len; i++) {
++ /* 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)
++int
+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 +1018,6 @@ community_set(struct rde_aspath *asp, in
+@@ -1000,7 +1068,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;
@@ -74,7 +179,7 @@ diff -u -p -r1.1.1.6 -r1.5
attr = attr_optget(asp, ATTR_COMMUNITIES);
if (attr != NULL) {
-@@ -1017,7 +1034,7 @@ community_set(struct rde_aspath *asp, in
+@@ -1017,7 +1084,7 @@ community_set(struct rde_aspath *asp, in
p += 4;
}
@@ -83,7 +188,7 @@ diff -u -p -r1.1.1.6 -r1.5
/* overflow */
return (0);
-@@ -1032,11 +1049,10 @@ community_set(struct rde_aspath *asp, in
+@@ -1032,11 +1099,10 @@ community_set(struct rde_aspath *asp, in
if (attr != NULL) {
memcpy(p + 4, attr->data, attr->len);
f = attr->flags;
@@ -96,7 +201,7 @@ diff -u -p -r1.1.1.6 -r1.5
free(p);
return (1);
-@@ -1049,7 +1065,7 @@ community_delete(struct rde_aspath *asp,
+@@ -1049,7 +1115,7 @@ community_delete(struct rde_aspath *asp,
u_int8_t *p, *n;
u_int16_t l, len = 0;
u_int16_t eas, etype;
@@ -105,7 +210,7 @@ diff -u -p -r1.1.1.6 -r1.5
attr = attr_optget(asp, ATTR_COMMUNITIES);
if (attr == NULL)
-@@ -1100,10 +1116,250 @@ community_delete(struct rde_aspath *asp,
+@@ -1100,10 +1166,250 @@ community_delete(struct rde_aspath *asp,
}
f = attr->flags;
diff --git a/net/openbgpd/files/patch-bgpd_rde_decide.c b/net/openbgpd/files/patch-bgpd_rde_decide.c
index 84cafd11beef..3ed963b194dc 100644
--- a/net/openbgpd/files/patch-bgpd_rde_decide.c
+++ b/net/openbgpd/files/patch-bgpd_rde_decide.c
@@ -2,10 +2,9 @@ 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.2
-diff -u -p -r1.1.1.6 -r1.2
+diff -u -p -r1.1.1.6 rde_decide.c
--- bgpd/rde_decide.c 14 Feb 2010 20:19:57 -0000 1.1.1.6
-+++ bgpd/rde_decide.c 22 Oct 2009 15:12:21 -0000 1.2
++++ bgpd/rde_decide.c 3 Jul 2011 04:44:36 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_decide.c,v 1.58 2009/06/29 14:10:13 claudio Exp $ */
+/* $OpenBSD: rde_decide.c,v 1.59 2009/08/06 08:53:11 claudio Exp $ */
@@ -43,3 +42,12 @@ diff -u -p -r1.1.1.6 -r1.2
(xp->aspath->nexthop != NULL &&
xp->aspath->nexthop->state != NEXTHOP_REACH))
/* xp is ineligible */
+@@ -263,7 +269,7 @@ prefix_evaluate(struct prefix *p, struct
+ */
+ rde_generate_updates(re->ribid, xp, re->active);
+ if ((re->flags & F_RIB_NOFIB) == 0)
+- rde_send_kroute(xp, re->active);
++ rde_send_kroute(xp, re->active, re->ribid);
+
+ re->active = xp;
+ if (xp != NULL)
diff --git a/net/openbgpd/files/patch-bgpd_rde_filter.c b/net/openbgpd/files/patch-bgpd_rde_filter.c
index e3cd6712b9f6..b4fe8982b949 100644
--- a/net/openbgpd/files/patch-bgpd_rde_filter.c
+++ b/net/openbgpd/files/patch-bgpd_rde_filter.c
@@ -2,10 +2,10 @@ Index: bgpd/rde_filter.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_filter.c,v
retrieving revision 1.1.1.7
-retrieving revision 1.6
-diff -u -p -r1.1.1.7 -r1.6
+retrieving revision 1.7
+diff -u -p -r1.1.1.7 -r1.7
--- bgpd/rde_filter.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/rde_filter.c 10 Apr 2010 12:16:23 -0000 1.6
++++ bgpd/rde_filter.c 2 Jul 2011 16:06:38 -0000 1.7
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_filter.c,v 1.56 2009/06/06 01:10:29 claudio Exp $ */
+/* $OpenBSD: rde_filter.c,v 1.62 2010/03/05 15:25:00 claudio Exp $ */
@@ -18,10 +18,10 @@ diff -u -p -r1.1.1.7 -r1.6
+ if (asp->flags & F_ATTR_PARSE_ERR)
+ /*
-+ * don't try to filter bad updates but let them through
++ * don't try to filter bad updates just deny them
+ * so they act as implicit withdraws
+ */
-+ return (action);
++ return (ACTION_DENY);
+
TAILQ_FOREACH(f, rules, entry) {
if (dir != f->dir)
@@ -71,12 +71,51 @@ diff -u -p -r1.1.1.7 -r1.6
}
}
}
-@@ -281,12 +299,17 @@ rde_filter_match(struct filter_rule *f,
+@@ -251,11 +269,21 @@ int
+ rde_filter_match(struct filter_rule *f, struct rde_aspath *asp,
+ struct bgpd_addr *prefix, u_int8_t plen, struct rde_peer *peer)
+ {
+- 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, 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 +291,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 +309,17 @@ rde_filter_match(struct filter_rule *f,
break;
}
- if (rde_filter_community(asp, as, type) == 0)
-+ if (community_match(asp, as, type) == 0)
++ if (community_match(asp, cas, type) == 0)
return (0);
}
+ if (asp != NULL &&
@@ -92,7 +131,7 @@ diff -u -p -r1.1.1.7 -r1.6
/* don't use IPv4 rules for IPv6 and vice versa */
return (0);
-@@ -322,7 +345,7 @@ rde_filter_match(struct filter_rule *f,
+@@ -322,7 +355,7 @@ rde_filter_match(struct filter_rule *f,
} else if (f->match.prefixlen.op != OP_NONE) {
/* only prefixlen without a prefix */
@@ -101,7 +140,7 @@ diff -u -p -r1.1.1.7 -r1.6
/* don't use IPv4 rules for IPv6 and vice versa */
return (0);
-@@ -356,19 +379,6 @@ rde_filter_match(struct filter_rule *f,
+@@ -356,19 +389,6 @@ rde_filter_match(struct filter_rule *f,
}
int
@@ -121,7 +160,7 @@ diff -u -p -r1.1.1.7 -r1.6
rde_filter_equal(struct filter_head *a, struct filter_head *b,
struct rde_peer *peer, enum directions dir)
{
-@@ -476,6 +486,12 @@ filterset_cmp(struct filter_set *a, stru
+@@ -476,6 +496,12 @@ filterset_cmp(struct filter_set *a, stru
return (a->action.community.type - b->action.community.type);
}
@@ -134,7 +173,7 @@ diff -u -p -r1.1.1.7 -r1.6
if (a->type == ACTION_SET_NEXTHOP && b->type == ACTION_SET_NEXTHOP) {
/*
* This is the only interesting case, all others are considered
-@@ -483,7 +499,7 @@ filterset_cmp(struct filter_set *a, stru
+@@ -483,13 +509,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.
*/
@@ -143,7 +182,29 @@ diff -u -p -r1.1.1.7 -r1.6
}
/* equal */
-@@ -574,6 +590,19 @@ filterset_equal(struct filter_set_head *
+ 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 +616,19 @@ filterset_equal(struct filter_set_head *
if (strcmp(as, bs) == 0)
continue;
break;
@@ -163,7 +224,7 @@ diff -u -p -r1.1.1.7 -r1.6
}
/* compare failed */
return (0);
-@@ -616,7 +645,14 @@ filterset_name(enum action_types type)
+@@ -616,7 +671,14 @@ filterset_name(enum action_types type)
case ACTION_RTLABEL:
case ACTION_RTLABEL_ID:
return ("rtlabel");
diff --git a/net/openbgpd/files/patch-bgpd_rde_rib.c b/net/openbgpd/files/patch-bgpd_rde_rib.c
index edea241a977e..22d6f0ee0a48 100644
--- a/net/openbgpd/files/patch-bgpd_rde_rib.c
+++ b/net/openbgpd/files/patch-bgpd_rde_rib.c
@@ -2,10 +2,9 @@ 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.6
-diff -u -p -r1.1.1.7 -r1.6
+diff -u -p -r1.1.1.7 rde_rib.c
--- bgpd/rde_rib.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/rde_rib.c 10 Apr 2010 12:16:23 -0000 1.6
++++ bgpd/rde_rib.c 3 Jul 2011 04:45:31 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_rib.c,v 1.116 2009/06/29 14:13:48 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.125 2010/04/07 09:44:11 claudio Exp $ */
@@ -29,7 +28,7 @@ diff -u -p -r1.1.1.7 -r1.6
/* RIB specific functions */
u_int16_t
-rib_new(int id, char *name, u_int16_t flags)
-+rib_new(char *name, u_int16_t flags)
++rib_new(char *name, u_int rtableid, u_int16_t flags)
{
struct rib *xribs;
size_t newsize;
@@ -46,7 +45,7 @@ diff -u -p -r1.1.1.7 -r1.6
}
if (id == RIB_FAILED)
-@@ -78,7 +81,7 @@ rib_new(int id, char *name, u_int16_t fl
+@@ -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);
@@ -54,8 +53,11 @@ diff -u -p -r1.1.1.7 -r1.6
+ ribs[id].state = RECONF_REINIT;
ribs[id].id = id;
ribs[id].flags = flags;
++ ribs[id].rtableid = rtableid;
-@@ -173,15 +176,16 @@ rib_lookup(struct rib *rib, struct bgpd_
+ return (id);
+ }
+@@ -173,15 +177,16 @@ rib_lookup(struct rib *rib, struct bgpd_
struct rib_entry *re;
int i;
@@ -75,7 +77,15 @@ diff -u -p -r1.1.1.7 -r1.6
for (i = 128; i >= 0; i--) {
re = rib_get(rib, addr, i);
if (re != NULL)
-@@ -254,7 +258,7 @@ rib_empty(struct rib_entry *re)
+@@ -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 *),
@@ -84,7 +94,7 @@ diff -u -p -r1.1.1.7 -r1.6
{
struct rib_context *ctx;
-@@ -263,7 +267,7 @@ rib_dump(struct rib *rib, void (*upcall)
+@@ -263,7 +269,7 @@ rib_dump(struct rib *rib, void (*upcall)
ctx->ctx_rib = rib;
ctx->ctx_upcall = upcall;
ctx->ctx_arg = arg;
@@ -93,7 +103,7 @@ diff -u -p -r1.1.1.7 -r1.6
rib_dump_r(ctx);
}
-@@ -280,7 +284,8 @@ rib_dump_r(struct rib_context *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)) {
@@ -103,7 +113,7 @@ diff -u -p -r1.1.1.7 -r1.6
continue;
if (ctx->ctx_count && i++ >= ctx->ctx_count &&
(re->flags & F_RIB_ENTRYLOCK) == 0) {
-@@ -308,7 +313,7 @@ rib_restart(struct rib_context *ctx)
+@@ -308,7 +315,7 @@ rib_restart(struct rib_context *ctx)
re->flags &= ~F_RIB_ENTRYLOCK;
/* find first non empty element */
@@ -112,7 +122,7 @@ diff -u -p -r1.1.1.7 -r1.6
re = RB_NEXT(rib_tree, unused, re);
/* free the previously locked rib element if empty */
-@@ -632,11 +637,11 @@ prefix_compare(const struct bgpd_addr *a
+@@ -632,11 +639,11 @@ prefix_compare(const struct bgpd_addr *a
int i;
u_int8_t m;
@@ -128,7 +138,7 @@ diff -u -p -r1.1.1.7 -r1.6
if (prefixlen > 32)
fatalx("prefix_cmp: bad IPv4 prefixlen");
mask = htonl(prefixlen2mask(prefixlen));
-@@ -645,7 +650,7 @@ prefix_compare(const struct bgpd_addr *a
+@@ -645,7 +652,7 @@ prefix_compare(const struct bgpd_addr *a
if (aa != ba)
return (aa - ba);
return (0);
@@ -137,7 +147,7 @@ diff -u -p -r1.1.1.7 -r1.6
if (prefixlen > 128)
fatalx("prefix_cmp: bad IPv6 prefixlen");
for (i = 0; i < prefixlen / 8; i++)
-@@ -660,6 +665,24 @@ prefix_compare(const struct bgpd_addr *a
+@@ -660,6 +667,24 @@ prefix_compare(const struct bgpd_addr *a
(b->v6.s6_addr[prefixlen / 8] & m));
}
return (0);
@@ -162,7 +172,7 @@ diff -u -p -r1.1.1.7 -r1.6
default:
fatalx("prefix_cmp: unknown af");
}
-@@ -806,16 +829,33 @@ prefix_write(u_char *buf, int len, struc
+@@ -806,16 +831,33 @@ prefix_write(u_char *buf, int len, struc
{
int totlen;
@@ -203,7 +213,91 @@ diff -u -p -r1.1.1.7 -r1.6
}
/*
-@@ -1070,10 +1110,6 @@ nexthop_update(struct kroute_nexthop *ms
+@@ -861,7 +903,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;
+ }
+
+@@ -885,16 +927,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,7 +945,6 @@ 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);
+@@ -916,12 +953,8 @@ prefix_network_clean(struct rde_peer *pe
+ 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 +987,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 +999,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 +1008,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 +1105,6 @@ nexthop_update(struct kroute_nexthop *ms
return;
}
@@ -214,7 +308,7 @@ diff -u -p -r1.1.1.7 -r1.6
oldstate = nh->state;
if (msg->valid)
nh->state = NEXTHOP_REACH;
-@@ -1088,21 +1124,13 @@ nexthop_update(struct kroute_nexthop *ms
+@@ -1088,21 +1119,13 @@ nexthop_update(struct kroute_nexthop *ms
memcpy(&nh->true_nexthop, &msg->gateway,
sizeof(nh->true_nexthop));
@@ -243,7 +337,7 @@ diff -u -p -r1.1.1.7 -r1.6
if (rde_noevaluate())
/*
-@@ -1118,7 +1146,7 @@ nexthop_update(struct kroute_nexthop *ms
+@@ -1118,7 +1141,7 @@ nexthop_update(struct kroute_nexthop *ms
void
nexthop_modify(struct rde_aspath *asp, struct bgpd_addr *nexthop,
@@ -252,7 +346,7 @@ diff -u -p -r1.1.1.7 -r1.6
{
struct nexthop *nh;
-@@ -1138,7 +1166,7 @@ nexthop_modify(struct rde_aspath *asp, s
+@@ -1138,7 +1161,7 @@ nexthop_modify(struct rde_aspath *asp, s
asp->flags |= F_NEXTHOP_SELF;
return;
}
@@ -261,7 +355,7 @@ diff -u -p -r1.1.1.7 -r1.6
return;
nh = nexthop_get(nexthop);
-@@ -1233,17 +1261,17 @@ nexthop_compare(struct nexthop *na, stru
+@@ -1233,17 +1256,17 @@ nexthop_compare(struct nexthop *na, stru
a = &na->exit_nexthop;
b = &nb->exit_nexthop;
@@ -284,7 +378,7 @@ diff -u -p -r1.1.1.7 -r1.6
return (memcmp(&a->v6, &b->v6, sizeof(struct in6_addr)));
default:
fatalx("nexthop_cmp: unknown af");
-@@ -1269,14 +1297,14 @@ nexthop_hash(struct bgpd_addr *nexthop)
+@@ -1269,14 +1292,14 @@ nexthop_hash(struct bgpd_addr *nexthop)
{
u_int32_t h = 0;
diff --git a/net/openbgpd/files/patch-bgpd_rde_update.c b/net/openbgpd/files/patch-bgpd_rde_update.c
index bbd2c19ce25f..cbffb73387e5 100644
--- a/net/openbgpd/files/patch-bgpd_rde_update.c
+++ b/net/openbgpd/files/patch-bgpd_rde_update.c
@@ -2,17 +2,16 @@ 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.6
-diff -u -p -r1.1.1.7 -r1.6
+diff -u -p -r1.1.1.7 rde_update.c
--- bgpd/rde_update.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/rde_update.c 14 Feb 2010 19:53:36 -0000 1.6
++++ bgpd/rde_update.c 3 Jul 2011 04:45:50 -0000
@@ -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,26 @@
+@@ -17,19 +17,27 @@
*/
#include <sys/types.h>
#include <sys/queue.h>
@@ -22,6 +21,7 @@ diff -u -p -r1.1.1.7 -r1.6
#include <sys/hash.h>
+#endif /* defined(__FreeBSD__) */
++#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#if defined(__FreeBSD__) /* limits.h */
@@ -41,7 +41,7 @@ diff -u -p -r1.1.1.7 -r1.6
/* update stuff. */
struct update_prefix {
-@@ -65,10 +72,12 @@ RB_GENERATE(uptree_attr, update_attr, en
+@@ -65,10 +73,12 @@ RB_GENERATE(uptree_attr, update_attr, en
void
up_init(struct rde_peer *peer)
{
@@ -58,7 +58,7 @@ diff -u -p -r1.1.1.7 -r1.6
RB_INIT(&peer->up_prefix);
RB_INIT(&peer->up_attrs);
peer->up_pcnt = 0;
-@@ -103,8 +112,10 @@ up_clear(struct uplist_attr *updates, st
+@@ -103,8 +113,10 @@ up_clear(struct uplist_attr *updates, st
void
up_down(struct rde_peer *peer)
{
@@ -71,7 +71,7 @@ diff -u -p -r1.1.1.7 -r1.6
RB_INIT(&peer->up_prefix);
RB_INIT(&peer->up_attrs);
-@@ -120,19 +131,19 @@ up_prefix_cmp(struct update_prefix *a, s
+@@ -120,19 +132,19 @@ up_prefix_cmp(struct update_prefix *a, s
{
int i;
@@ -96,7 +96,7 @@ diff -u -p -r1.1.1.7 -r1.6
i = memcmp(&a->prefix.v6, &b->prefix.v6,
sizeof(struct in6_addr));
if (i > 0)
-@@ -140,6 +151,25 @@ up_prefix_cmp(struct update_prefix *a, s
+@@ -140,6 +152,25 @@ up_prefix_cmp(struct update_prefix *a, s
if (i < 0)
return (-1);
break;
@@ -122,7 +122,7 @@ diff -u -p -r1.1.1.7 -r1.6
default:
fatalx("pt_prefix_cmp: unknown af");
}
-@@ -174,18 +204,8 @@ up_add(struct rde_peer *peer, struct upd
+@@ -174,18 +205,8 @@ up_add(struct rde_peer *peer, struct upd
struct uplist_attr *upl = NULL;
struct uplist_prefix *wdl = NULL;
@@ -143,7 +143,7 @@ diff -u -p -r1.1.1.7 -r1.6
/* 1. search for attr */
if (a != NULL && (na = RB_FIND(uptree_attr, &peer->up_attrs, a)) ==
-@@ -270,21 +290,14 @@ up_test_update(struct rde_peer *peer, st
+@@ -270,21 +291,14 @@ up_test_update(struct rde_peer *peer, st
/* Do not send routes back to sender */
return (0);
@@ -169,7 +169,7 @@ diff -u -p -r1.1.1.7 -r1.6
if (p->aspath->peer->conf.ebgp == 0 && peer->conf.ebgp == 0) {
/*
-@@ -325,13 +338,13 @@ up_test_update(struct rde_peer *peer, st
+@@ -325,13 +339,13 @@ up_test_update(struct rde_peer *peer, st
}
/* well known communities */
@@ -186,7 +186,7 @@ diff -u -p -r1.1.1.7 -r1.6
COMMUNITY_WELLKNOWN, COMMUNITY_NO_EXPSUBCONFED))
return (0);
-@@ -362,7 +375,7 @@ up_generate(struct rde_peer *peer, struc
+@@ -362,7 +376,7 @@ up_generate(struct rde_peer *peer, struc
if (ua == NULL)
fatal("up_generate");
@@ -195,7 +195,7 @@ diff -u -p -r1.1.1.7 -r1.6
log_warnx("generation of bgp path attributes failed");
free(ua);
return (-1);
-@@ -444,18 +457,12 @@ up_generate_updates(struct filter_head *
+@@ -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,
@@ -216,7 +216,7 @@ diff -u -p -r1.1.1.7 -r1.6
return;
asp = path_get();
-@@ -471,7 +478,7 @@ up_generate_default(struct filter_head *
+@@ -471,7 +479,7 @@ up_generate_default(struct filter_head *
/* filter as usual */
bzero(&addr, sizeof(addr));
@@ -225,7 +225,7 @@ diff -u -p -r1.1.1.7 -r1.6
if (rde_filter(peer->ribid, &fasp, rules, peer, asp, &addr, 0, NULL,
DIR_OUT) == ACTION_DENY) {
-@@ -491,6 +498,43 @@ up_generate_default(struct filter_head *
+@@ -491,6 +499,43 @@ up_generate_default(struct filter_head *
path_put(asp);
}
@@ -269,7 +269,7 @@ diff -u -p -r1.1.1.7 -r1.6
u_char up_attr_buf[4096];
/* only for IPv4 */
-@@ -551,28 +595,41 @@ up_get_nexthop(struct rde_peer *peer, st
+@@ -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,
@@ -319,7 +319,7 @@ diff -u -p -r1.1.1.7 -r1.6
&peer->remote_addr.v6, sizeof(struct in6_addr))))
memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6,
sizeof(struct in6_addr));
-@@ -603,6 +660,68 @@ up_generate_mp_reach(struct rde_peer *pe
+@@ -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);
@@ -388,7 +388,7 @@ diff -u -p -r1.1.1.7 -r1.6
default:
break;
}
-@@ -611,7 +730,7 @@ up_generate_mp_reach(struct rde_peer *pe
+@@ -611,7 +731,7 @@ up_generate_mp_reach(struct rde_peer *pe
int
up_generate_attr(struct rde_peer *peer, struct update_attr *upa,
@@ -397,7 +397,7 @@ diff -u -p -r1.1.1.7 -r1.6
{
struct attr *oa, *newaggr = NULL;
u_char *pdata;
-@@ -643,8 +762,8 @@ up_generate_attr(struct rde_peer *peer,
+@@ -643,8 +763,8 @@ up_generate_attr(struct rde_peer *peer,
wlen += r; len -= r;
free(pdata);
@@ -408,7 +408,7 @@ diff -u -p -r1.1.1.7 -r1.6
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 +778,11 @@ up_generate_attr(struct rde_peer *peer,
+@@ -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.
@@ -421,7 +421,7 @@ diff -u -p -r1.1.1.7 -r1.6
tmp32 = htonl(a->med);
if ((r = attr_write(up_attr_buf + wlen, len, ATTR_OPTIONAL,
ATTR_MED, &tmp32, 4)) == -1)
-@@ -791,7 +912,7 @@ up_generate_attr(struct rde_peer *peer,
+@@ -791,7 +913,7 @@ up_generate_attr(struct rde_peer *peer,
/* write mp attribute to different buffer */
if (ismp)
@@ -430,7 +430,7 @@ diff -u -p -r1.1.1.7 -r1.6
return (-1);
/* the bgp path attributes are now stored in the global buf */
-@@ -810,6 +931,7 @@ up_dump_prefix(u_char *buf, int len, str
+@@ -810,6 +932,7 @@ up_dump_prefix(u_char *buf, int len, str
{
struct update_prefix *upp;
int r, wpos = 0;
@@ -438,7 +438,7 @@ diff -u -p -r1.1.1.7 -r1.6
while ((upp = TAILQ_FIRST(prefix_head)) != NULL) {
if ((r = prefix_write(buf + wpos, len - wpos,
-@@ -820,13 +942,14 @@ up_dump_prefix(u_char *buf, int len, str
+@@ -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--;
@@ -460,7 +460,7 @@ diff -u -p -r1.1.1.7 -r1.6
}
free(upp);
}
-@@ -844,16 +967,21 @@ up_dump_attrnlri(u_char *buf, int len, s
+@@ -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.
*/
@@ -484,7 +484,7 @@ diff -u -p -r1.1.1.7 -r1.6
} else
break;
-@@ -884,7 +1012,7 @@ up_dump_attrnlri(u_char *buf, int len, s
+@@ -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.");
@@ -493,7 +493,7 @@ diff -u -p -r1.1.1.7 -r1.6
free(upa->attr);
free(upa->mpattr);
free(upa);
-@@ -895,12 +1023,13 @@ up_dump_attrnlri(u_char *buf, int len, s
+@@ -895,12 +1024,13 @@ up_dump_attrnlri(u_char *buf, int len, s
}
u_char *
@@ -509,7 +509,7 @@ diff -u -p -r1.1.1.7 -r1.6
/*
* reserve space for withdraw len, attr len, the attribute header
-@@ -912,7 +1041,7 @@ up_dump_mp_unreach(u_char *buf, u_int16_
+@@ -912,7 +1042,7 @@ up_dump_mp_unreach(u_char *buf, u_int16_
return (NULL);
datalen = up_dump_prefix(buf + wpos, *len - wpos,
@@ -518,7 +518,7 @@ diff -u -p -r1.1.1.7 -r1.6
if (datalen == 0)
return (NULL);
-@@ -920,9 +1049,11 @@ up_dump_mp_unreach(u_char *buf, u_int16_
+@@ -920,9 +1050,11 @@ up_dump_mp_unreach(u_char *buf, u_int16_
/* prepend header, need to do it reverse */
/* safi & afi */
@@ -532,7 +532,7 @@ diff -u -p -r1.1.1.7 -r1.6
memcpy(buf + wpos, &tmp, sizeof(u_int16_t));
/* attribute length */
-@@ -959,33 +1090,39 @@ up_dump_mp_unreach(u_char *buf, u_int16_
+@@ -959,33 +1091,39 @@ up_dump_mp_unreach(u_char *buf, u_int16_
return (buf + wpos);
}
@@ -578,7 +578,7 @@ diff -u -p -r1.1.1.7 -r1.6
/*
* reserve space for attr len, the attributes, the
-@@ -993,12 +1130,12 @@ up_dump_mp_reach(u_char *buf, u_int16_t
+@@ -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)
@@ -593,7 +593,7 @@ diff -u -p -r1.1.1.7 -r1.6
if (upa->mpattr_len == 0 || upa->mpattr == NULL)
fatalx("mulitprotocol update without MP attrs");
-@@ -1038,7 +1175,7 @@ up_dump_mp_reach(u_char *buf, u_int16_t
+@@ -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.");
@@ -602,7 +602,7 @@ diff -u -p -r1.1.1.7 -r1.6
free(upa->attr);
free(upa->mpattr);
free(upa);
-@@ -1046,6 +1183,5 @@ up_dump_mp_reach(u_char *buf, u_int16_t
+@@ -1046,6 +1184,5 @@ up_dump_mp_reach(u_char *buf, u_int16_t
}
*len = datalen + 4;
diff --git a/net/openbgpd/files/patch-bgpd_session.c b/net/openbgpd/files/patch-bgpd_session.c
index b6659f236a79..6b29252645e7 100644
--- a/net/openbgpd/files/patch-bgpd_session.c
+++ b/net/openbgpd/files/patch-bgpd_session.c
@@ -2,40 +2,52 @@ Index: bgpd/session.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/session.c,v
retrieving revision 1.1.1.8
-retrieving revision 1.7
-diff -u -p -r1.1.1.8 -r1.7
+retrieving revision 1.8
+diff -u -p -r1.1.1.8 -r1.8
--- bgpd/session.c 14 Feb 2010 20:19:57 -0000 1.1.1.8
-+++ bgpd/session.c 14 Feb 2010 19:53:36 -0000 1.7
++++ bgpd/session.c 2 Jul 2011 16:06:38 -0000 1.8
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.293 2009/06/07 05:56:24 eric Exp $ */
+/* $OpenBSD: session.c,v 1.304 2010/01/05 08:49:57 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
-@@ -52,6 +52,10 @@
+@@ -21,6 +21,8 @@
+
+ #include <sys/mman.h>
+ #include <sys/socket.h>
++#include <sys/time.h>
++#include <sys/resource.h>
+ #include <sys/un.h>
+ #include <net/if_types.h>
+ #include <netinet/in.h>
+@@ -50,7 +52,12 @@
+ #define PFD_PIPE_ROUTE_CTL 2
+ #define PFD_SOCK_CTL 3
#define PFD_SOCK_RCTL 4
- #define PFD_LISTENERS_START 5
-
+-#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 *);
- void init_conf(struct bgpd_config *);
-@@ -65,9 +69,8 @@ void session_accept(int);
+@@ -65,9 +72,8 @@ 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 buf *, u_int8_t, u_int8_t);
-+int session_capa_add_mp(struct buf *, 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);
struct bgp_msg *session_newmsg(enum msg_type, u_int16_t);
int session_sendmsg(struct bgp_msg *, struct peer *);
void session_open(struct peer *);
-@@ -75,7 +78,7 @@ void session_keepalive(struct peer *);
+@@ -75,7 +81,7 @@ 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);
@@ -44,7 +56,7 @@ diff -u -p -r1.1.1.8 -r1.7
int session_dispatch_msg(struct pollfd *, struct peer *);
int parse_header(struct peer *, u_char *, u_int16_t *, u_int8_t *);
int parse_open(struct peer *);
-@@ -83,22 +86,22 @@ int parse_update(struct peer *);
+@@ -83,22 +89,22 @@ 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 *);
@@ -76,7 +88,7 @@ diff -u -p -r1.1.1.8 -r1.7
int csock = -1, rcsock = -1;
u_int peer_cnt;
struct imsgbuf *ibuf_rde;
-@@ -175,10 +178,8 @@ setup_listeners(u_int *la_cnt)
+@@ -175,12 +181,11 @@ setup_listeners(u_int *la_cnt)
}
pid_t
@@ -84,12 +96,16 @@ diff -u -p -r1.1.1.8 -r1.7
- 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], char *cname, char *rcname)
++session_main(int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2],
++ int pipe_s2rctl[2])
{
- int nfds, timeout;
+- int nfds, timeout;
++ struct rlimit rl;
++ int nfds, timeout, pfkeysock;
unsigned int i, j, idx_peers, idx_listeners, idx_mrts;
-@@ -189,19 +190,13 @@ session_main(struct bgpd_config *config,
+ pid_t pid;
+ u_int pfd_elms = 0, peer_l_elms = 0, mrt_l_elms = 0;
+@@ -189,19 +194,13 @@ session_main(struct bgpd_config *config,
u_int32_t ctl_queued;
struct passwd *pw;
struct peer *p, **peer_l = NULL, *last, *next;
@@ -110,20 +126,36 @@ diff -u -p -r1.1.1.8 -r1.7
switch (pid = fork()) {
case -1:
fatal("cannot fork");
-@@ -212,10 +207,9 @@ session_main(struct bgpd_config *config,
+@@ -211,13 +210,6 @@ session_main(struct bgpd_config *config,
+ return (pid);
}
- /* control socket is outside chroot */
+- /* control socket is outside chroot */
- if ((csock = control_init(0, conf->csock)) == -1)
-+ if ((csock = control_init(0, cname)) == -1)
- fatalx("control socket setup failed");
+- fatalx("control socket setup failed");
- if (conf->rcsock != NULL &&
- (rcsock = control_init(1, conf->rcsock)) == -1)
-+ if (rcname != NULL && (rcsock = control_init(1, rcname)) == -1)
- fatalx("control socket setup failed");
-
+- fatalx("control socket setup failed");
+-
if ((pw = getpwnam(BGPD_USER)) == NULL)
-@@ -237,20 +231,18 @@ session_main(struct bgpd_config *config,
+ fatal(NULL);
+
+@@ -229,28 +221,31 @@ session_main(struct bgpd_config *config,
+ setproctitle("session engine");
+ bgpd_process = PROC_SE;
+
+- if (pfkey_init(&sysdep) == -1)
+- fatalx("pfkey setup failed");
++ if (getrlimit(RLIMIT_NOFILE, &rl) == -1)
++ fatal("getrlimit");
++ rl.rlim_cur = rl.rlim_max;
++ if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
++ fatal("setrlimit");
++
++ pfkeysock = pfkey_init(&sysdep);
+
+ if (setgroups(1, &pw->pw_gid) ||
+ 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");
@@ -147,14 +179,14 @@ diff -u -p -r1.1.1.8 -r1.7
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 +250,23 @@ session_main(struct bgpd_config *config,
+@@ -258,37 +253,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);
+- control_listen(csock);
+- control_listen(rcsock);
LIST_INIT(&mrthead);
+ listener_cnt = 0;
peer_cnt = 0;
@@ -173,7 +205,7 @@ diff -u -p -r1.1.1.8 -r1.7
- filterset_free(&net->net.attrset);
- free(net);
- }
-+ if ((conf = malloc(sizeof(struct bgpd_config))) == NULL)
++ if ((conf = calloc(1, sizeof(struct bgpd_config))) == NULL)
+ fatal(NULL);
+ if ((conf->listen_addrs = calloc(1, sizeof(struct listen_addrs))) ==
+ NULL)
@@ -194,7 +226,7 @@ diff -u -p -r1.1.1.8 -r1.7
while (session_quit == 0) {
/* check for peers to be initialized or deleted */
-@@ -308,8 +286,9 @@ session_main(struct bgpd_config *config,
+@@ -308,8 +287,9 @@ session_main(struct bgpd_config *config,
/* reinit due? */
if (p->conf.reconf_action == RECONF_REINIT) {
@@ -206,7 +238,7 @@ diff -u -p -r1.1.1.8 -r1.7
}
/* deletion due? */
-@@ -317,7 +296,7 @@ session_main(struct bgpd_config *config,
+@@ -317,7 +297,7 @@ session_main(struct bgpd_config *config,
if (p->demoted)
session_demote(p, -1);
p->conf.demote_group[0] = 0;
@@ -215,7 +247,7 @@ diff -u -p -r1.1.1.8 -r1.7
log_peer_warnx(&p->conf, "removed");
if (last != NULL)
last->next = next;
-@@ -346,9 +325,17 @@ session_main(struct bgpd_config *config,
+@@ -346,9 +326,17 @@ session_main(struct bgpd_config *config,
}
mrt_cnt = 0;
@@ -234,7 +266,39 @@ diff -u -p -r1.1.1.8 -r1.7
if (mrt_cnt > mrt_l_elms) {
if ((newp = realloc(mrt_l, sizeof(struct mrt *) *
-@@ -557,7 +544,7 @@ session_main(struct bgpd_config *config,
+@@ -394,13 +382,15 @@ 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;
++ pfd[PFD_SOCK_PFKEY].fd = pfkeysock;
++ pfd[PFD_SOCK_PFKEY].events = POLLIN;
+
+ i = PFD_LISTENERS_START;
+ TAILQ_FOREACH(la, conf->listen_addrs, entry) {
+@@ -534,6 +524,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) {
+@@ -557,7 +555,7 @@ session_main(struct bgpd_config *config,
while ((p = peers) != NULL) {
peers = p->next;
@@ -243,7 +307,19 @@ diff -u -p -r1.1.1.8 -r1.7
pfkey_remove(p);
free(p);
}
-@@ -746,7 +733,6 @@ bgp_fsm(struct peer *peer, enum session_
+@@ -643,10 +641,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 +743,6 @@ bgp_fsm(struct peer *peer, enum session_
/* ignore */
break;
case EVNT_STOP:
@@ -251,7 +327,17 @@ diff -u -p -r1.1.1.8 -r1.7
change_state(peer, STATE_IDLE, event);
break;
case EVNT_CON_CLOSED:
-@@ -791,7 +777,6 @@ bgp_fsm(struct peer *peer, enum session_
+@@ -780,7 +776,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 +788,6 @@ bgp_fsm(struct peer *peer, enum session_
/* ignore */
break;
case EVNT_STOP:
@@ -259,7 +345,17 @@ diff -u -p -r1.1.1.8 -r1.7
change_state(peer, STATE_IDLE, event);
break;
case EVNT_CON_CLOSED:
-@@ -826,7 +811,6 @@ bgp_fsm(struct peer *peer, enum session_
+@@ -815,7 +811,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 +823,6 @@ bgp_fsm(struct peer *peer, enum session_
/* ignore */
break;
case EVNT_STOP:
@@ -267,7 +363,17 @@ diff -u -p -r1.1.1.8 -r1.7
change_state(peer, STATE_IDLE, event);
break;
case EVNT_CON_CLOSED:
-@@ -923,6 +907,7 @@ change_state(struct peer *peer, enum ses
+@@ -856,7 +852,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;
+ }
+@@ -923,6 +920,7 @@ change_state(struct peer *peer, enum ses
timer_stop(peer, Timer_ConnectRetry);
timer_stop(peer, Timer_Keepalive);
timer_stop(peer, Timer_Hold);
@@ -275,7 +381,7 @@ diff -u -p -r1.1.1.8 -r1.7
timer_stop(peer, Timer_IdleHoldReset);
session_close_connection(peer);
msgbuf_clear(&peer->wbuf);
-@@ -1069,7 +1054,7 @@ session_connect(struct peer *peer)
+@@ -1069,7 +1067,7 @@ session_connect(struct peer *peer)
if (peer->fd != -1)
return (-1);
@@ -284,7 +390,7 @@ diff -u -p -r1.1.1.8 -r1.7
IPPROTO_TCP)) == -1) {
log_peer_warn(&peer->conf, "session_connect socket");
bgp_fsm(peer, EVNT_CON_OPENFAIL);
-@@ -1100,8 +1085,7 @@ session_connect(struct peer *peer)
+@@ -1100,8 +1098,7 @@ session_connect(struct peer *peer)
peer->wbuf.fd = peer->fd;
/* if update source is set we need to bind() */
@@ -294,7 +400,7 @@ diff -u -p -r1.1.1.8 -r1.7
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 +1123,50 @@ session_setup_socket(struct peer *p)
+@@ -1139,42 +1136,50 @@ session_setup_socket(struct peer *p)
int nodelay = 1;
int bsize;
@@ -375,7 +481,7 @@ diff -u -p -r1.1.1.8 -r1.7
}
/* set TCP_NODELAY */
-@@ -1185,14 +1177,6 @@ session_setup_socket(struct peer *p)
+@@ -1185,14 +1190,6 @@ session_setup_socket(struct peer *p)
return (-1);
}
@@ -390,7 +496,7 @@ diff -u -p -r1.1.1.8 -r1.7
/* only increase bufsize (and thus window) if md5 or ipsec is in use */
if (p->conf.auth.method != AUTH_NONE) {
/* try to increase bufsize. no biggie if it fails */
-@@ -1244,36 +1228,28 @@ session_tcp_established(struct peer *pee
+@@ -1244,40 +1241,32 @@ session_tcp_established(struct peer *pee
void
session_capa_ann_none(struct peer *peer)
{
@@ -405,7 +511,7 @@ diff -u -p -r1.1.1.8 -r1.7
int
-session_capa_add(struct peer *p, struct buf *opb, u_int8_t capa_code,
- u_int8_t capa_len, u_int8_t *optparamlen)
-+session_capa_add(struct buf *opb, u_int8_t capa_code, u_int8_t capa_len)
++session_capa_add(struct ibuf *opb, u_int8_t capa_code, u_int8_t capa_len)
{
- u_int8_t op_type, op_len, tot_len, errs = 0;
+ int errs = 0;
@@ -415,15 +521,17 @@ diff -u -p -r1.1.1.8 -r1.7
- 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));
+- errs += buf_add(opb, &capa_code, sizeof(capa_code));
+- errs += buf_add(opb, &capa_len, sizeof(capa_len));
- *optparamlen += tot_len;
++ 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 buf *buf, u_int8_t aid)
++session_capa_add_mp(struct ibuf *buf, u_int8_t aid)
{
- u_int8_t pad = 0;
+ u_int8_t safi, pad = 0;
@@ -433,19 +541,72 @@ diff -u -p -r1.1.1.8 -r1.7
+ if (aid2afi(aid, &afi, &safi) == -1)
+ fatalx("session_capa_add_mp: bad afi/safi pair");
afi = htons(afi);
- errs += buf_add(buf, &afi, sizeof(afi));
- errs += buf_add(buf, &pad, sizeof(pad));
-@@ -1341,36 +1317,34 @@ session_open(struct peer *p)
- struct buf *opb;
+- errs += buf_add(buf, &afi, sizeof(afi));
+- errs += buf_add(buf, &pad, sizeof(pad));
+- errs += buf_add(buf, &safi, sizeof(safi));
++ errs += ibuf_add(buf, &afi, sizeof(afi));
++ errs += ibuf_add(buf, &pad, sizeof(pad));
++ errs += ibuf_add(buf, &safi, sizeof(safi));
+
+ return (errs);
+ }
+@@ -1287,23 +1276,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 +1317,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 +1326,38 @@ 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;
- u_int errs = 0;
++ int errs = 0;
- if ((opb = buf_dynamic(0, MAX_PKTSIZE - MSGSIZE_OPEN_MIN)) == NULL) {
-+ if ((opb = buf_dynamic(0, UCHAR_MAX - sizeof(op_type) -
++ if ((opb = ibuf_dynamic(0, UCHAR_MAX - sizeof(op_type) -
+ sizeof(optparamlen))) == NULL) {
bgp_fsm(p, EVNT_CON_FATAL);
return;
@@ -478,65 +639,120 @@ diff -u -p -r1.1.1.8 -r1.7
- 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);
+ c[1] = 0;
+ errs += session_capa_add(opb, CAPA_RESTART, 2);
- errs += buf_add(opb, &c, 2);
++ errs += ibuf_add(opb, &c, 2);
}
-@@ -1379,10 +1353,14 @@ session_open(struct peer *p)
+ /* 4-bytes AS numbers, draft-ietf-idr-as4bytes-13 */
+@@ -1379,13 +1365,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 += buf_add(opb, &nas, sizeof(nas));
++ errs += ibuf_add(opb, &nas, sizeof(nas));
}
-+ if (buf_size(opb))
-+ optparamlen = buf_size(opb) + sizeof(op_type) +
++ 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);
-@@ -1405,8 +1383,13 @@ session_open(struct peer *p)
- errs += buf_add(buf->buf, &msg.bgpid, sizeof(msg.bgpid));
- errs += buf_add(buf->buf, &msg.optparamlen, sizeof(msg.optparamlen));
-
+- buf_free(opb);
++ ibuf_free(opb);
+ bgp_fsm(p, EVNT_CON_FATAL);
+ return;
+ }
+@@ -1399,19 +1389,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 = buf_size(opb);
-+ errs += buf_add(buf->buf, &op_type, sizeof(op_type));
-+ errs += buf_add(buf->buf, &optparamlen, sizeof(optparamlen));
-+ errs += buf_add(buf->buf, opb->buf, buf_size(opb));
++ 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);
+- 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 +1454,8 @@ session_update(u_int32_t peerid, void *d
+ return;
+ }
-@@ -1481,7 +1464,6 @@ session_notification(struct peer *p, u_i
+- 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 +1475,27 @@ session_notification(struct peer *p, u_i
+ void *data, ssize_t datalen)
{
struct bgp_msg *buf;
- u_int errs = 0;
+- u_int errs = 0;
- u_int8_t null8 = 0;
++ int errs = 0;
if (p->stats.last_sent_errcode) /* some notification already sent */
return;
-@@ -1493,10 +1475,7 @@ session_notification(struct peer *p, u_i
+
++ 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));
+- 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 += 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);
-@@ -1521,23 +1500,29 @@ session_notification(struct peer *p, u_i
+- 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 +1514,29 @@ session_notification(struct peer *p, u_i
int
session_neighbor_rrefresh(struct peer *p)
{
@@ -572,7 +788,25 @@ diff -u -p -r1.1.1.8 -r1.7
if ((buf = session_newmsg(RREFRESH, MSGSIZE_RREFRESH)) == NULL) {
bgp_fsm(p, EVNT_CON_FATAL);
-@@ -1853,12 +1838,6 @@ parse_open(struct peer *peer)
+@@ -1545,12 +1544,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;
+@@ -1853,12 +1852,6 @@ parse_open(struct peer *peer)
p += sizeof(short_as);
as = peer->short_as = ntohs(short_as);
@@ -585,7 +819,7 @@ diff -u -p -r1.1.1.8 -r1.7
memcpy(&oholdtime, p, sizeof(oholdtime));
p += sizeof(oholdtime);
-@@ -1966,6 +1945,15 @@ parse_open(struct peer *peer)
+@@ -1966,6 +1959,15 @@ parse_open(struct peer *peer)
}
}
@@ -601,7 +835,7 @@ diff -u -p -r1.1.1.8 -r1.7
if (peer->conf.remote_as != as) {
log_peer_warnx(&peer->conf, "peer sent wrong AS %s",
log_as(as));
-@@ -1974,6 +1962,14 @@ parse_open(struct peer *peer)
+@@ -1974,6 +1976,14 @@ parse_open(struct peer *peer)
return (-1);
}
@@ -616,7 +850,7 @@ diff -u -p -r1.1.1.8 -r1.7
return (0);
}
-@@ -2008,24 +2004,35 @@ int
+@@ -2008,24 +2018,35 @@ int
parse_refresh(struct peer *peer)
{
u_char *p;
@@ -658,7 +892,7 @@ diff -u -p -r1.1.1.8 -r1.7
return (-1);
return (0);
-@@ -2035,11 +2042,12 @@ int
+@@ -2035,11 +2056,12 @@ int
parse_notification(struct peer *peer)
{
u_char *p;
@@ -672,7 +906,16 @@ diff -u -p -r1.1.1.8 -r1.7
/* just log */
p = peer->rbuf->rptr;
-@@ -2094,8 +2102,8 @@ parse_notification(struct peer *peer)
+@@ -2059,7 +2081,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 +2116,8 @@ parse_notification(struct peer *peer)
datalen -= capa_len;
switch (capa_code) {
case CAPA_MP:
@@ -683,7 +926,7 @@ diff -u -p -r1.1.1.8 -r1.7
log_peer_warnx(&peer->conf,
"disabling multiprotocol capability");
break;
-@@ -2139,13 +2147,14 @@ parse_notification(struct peer *peer)
+@@ -2139,13 +2161,14 @@ parse_notification(struct peer *peer)
int
parse_capabilities(struct peer *peer, u_char *d, u_int16_t dlen, u_int32_t *as)
{
@@ -702,7 +945,7 @@ diff -u -p -r1.1.1.8 -r1.7
len = dlen;
while (len > 0) {
-@@ -2182,29 +2191,16 @@ parse_capabilities(struct peer *peer, u_
+@@ -2182,29 +2205,16 @@ parse_capabilities(struct peer *peer, u_
"expect len 4, len is %u", capa_len);
return (-1);
}
@@ -740,7 +983,7 @@ diff -u -p -r1.1.1.8 -r1.7
break;
case CAPA_REFRESH:
peer->capa.peer.refresh = 1;
-@@ -2232,6 +2228,37 @@ parse_capabilities(struct peer *peer, u_
+@@ -2232,6 +2242,37 @@ parse_capabilities(struct peer *peer, u_
return (0);
}
@@ -778,13 +1021,48 @@ diff -u -p -r1.1.1.8 -r1.7
void
session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
{
-@@ -2337,10 +2364,16 @@ session_dispatch_imsg(struct imsgbuf *ib
+@@ -2244,7 +2285,7 @@ session_dispatch_imsg(struct imsgbuf *ib
+ struct kif *kif;
+ u_char *data;
+ enum reconf_action reconf;
+- int n, depend_ok;
++ int n, depend_ok, restricted;
+ u_int8_t errcode, subcode;
+
+ if ((n = imsg_read(ibuf)) == -1)
+@@ -2332,15 +2373,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->rtableid = nconf->rtableid;
+ conf->bgpid = nconf->bgpid;
+ conf->clusterid = nconf->clusterid;
conf->as = nconf->as;
@@ -796,7 +1074,7 @@ diff -u -p -r1.1.1.8 -r1.7
/* add new peers */
for (p = npeers; p != NULL; p = next) {
-@@ -2408,7 +2441,8 @@ session_dispatch_imsg(struct imsgbuf *ib
+@@ -2408,7 +2476,8 @@ session_dispatch_imsg(struct imsgbuf *ib
bgp_fsm(p, EVNT_START);
} else if (!depend_ok && p->depend_ok) {
p->depend_ok = depend_ok;
@@ -806,7 +1084,27 @@ diff -u -p -r1.1.1.8 -r1.7
}
}
break;
-@@ -2612,29 +2646,23 @@ getpeerbydesc(const char *descr)
+@@ -2456,10 +2525,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 +2538,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");
+@@ -2612,29 +2680,23 @@ getpeerbydesc(const char *descr)
struct peer *
getpeerbyip(struct sockaddr *ip)
{
@@ -843,7 +1141,7 @@ diff -u -p -r1.1.1.8 -r1.7
if (loose == NULL || loose->conf.remote_masklen <
p->conf.remote_masklen)
loose = p;
-@@ -2653,21 +2681,19 @@ getpeerbyip(struct sockaddr *ip)
+@@ -2653,21 +2715,19 @@ getpeerbyip(struct sockaddr *ip)
break;
}
}
@@ -872,7 +1170,7 @@ diff -u -p -r1.1.1.8 -r1.7
newpeer->rbuf = NULL;
init_peer(newpeer);
bgp_fsm(newpeer, EVNT_START);
-@@ -2680,40 +2706,24 @@ getpeerbyip(struct sockaddr *ip)
+@@ -2680,40 +2740,24 @@ getpeerbyip(struct sockaddr *ip)
}
int
@@ -924,7 +1222,7 @@ diff -u -p -r1.1.1.8 -r1.7
return (0);
}
-@@ -2733,6 +2743,7 @@ getpeerbyid(u_int32_t peerid)
+@@ -2733,6 +2777,7 @@ getpeerbyid(u_int32_t peerid)
void
session_down(struct peer *peer)
{
@@ -932,7 +1230,7 @@ diff -u -p -r1.1.1.8 -r1.7
peer->stats.last_updown = time(NULL);
if (imsg_compose(ibuf_rde, IMSG_SESSION_DOWN, peer->conf.id, 0, -1,
NULL, 0) == -1)
-@@ -2748,35 +2759,12 @@ session_up(struct peer *p)
+@@ -2748,35 +2793,12 @@ session_up(struct peer *p)
&p->conf, sizeof(p->conf)) == -1)
fatalx("imsg_compose error");
@@ -971,7 +1269,20 @@ diff -u -p -r1.1.1.8 -r1.7
p->stats.last_updown = time(NULL);
if (imsg_compose(ibuf_rde, IMSG_SESSION_UP, p->conf.id, 0, -1,
&sup, sizeof(sup)) == -1)
-@@ -2795,34 +2783,6 @@ imsg_compose_rde(int type, pid_t pid, vo
+@@ -2784,9 +2806,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 +2818,6 @@ imsg_compose_rde(int type, pid_t pid, vo
return (imsg_compose(ibuf_rde, type, 0, pid, -1, data, datalen));
}
@@ -1006,7 +1317,7 @@ diff -u -p -r1.1.1.8 -r1.7
void
session_demote(struct peer *p, int level)
{
-@@ -2837,3 +2797,19 @@ session_demote(struct peer *p, int level
+@@ -2837,3 +2832,19 @@ session_demote(struct peer *p, int level
p->demoted += level;
}
diff --git a/net/openbgpd/files/patch-bgpd_session.h b/net/openbgpd/files/patch-bgpd_session.h
index 2d855c2e8b3a..4eb8dbce5f6b 100644
--- a/net/openbgpd/files/patch-bgpd_session.h
+++ b/net/openbgpd/files/patch-bgpd_session.h
@@ -2,17 +2,40 @@ 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.8
-diff -u -p -r1.1.1.7 -r1.1.1.8
+retrieving revision 1.1.1.9
+diff -u -p -r1.1.1.7 -r1.1.1.9
--- bgpd/session.h 14 Feb 2010 20:19:57 -0000 1.1.1.7
-+++ bgpd/session.h 14 Feb 2010 20:27:06 -0000 1.1.1.8
++++ bgpd/session.h 12 Jun 2011 10:44:25 -0000 1.1.1.9
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.h,v 1.101 2009/06/05 20:26:38 claudio Exp $ */
-+/* $OpenBSD: session.h,v 1.104 2009/12/31 15:34:02 claudio Exp $ */
++/* $OpenBSD: session.h,v 1.111 2010/12/09 13:50:41 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
-@@ -189,6 +189,7 @@ struct peer {
+@@ -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;
+ };
+@@ -189,6 +196,7 @@ struct peer {
struct {
struct capabilities ann;
struct capabilities peer;
@@ -20,7 +43,16 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
} capa;
struct {
struct bgpd_addr local_addr;
-@@ -217,7 +218,7 @@ struct peer {
+@@ -201,7 +209,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,7 +225,7 @@ struct peer {
u_int8_t passive;
};
@@ -29,7 +61,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
struct ctl_timer {
enum Timer type;
-@@ -226,16 +227,14 @@ struct ctl_timer {
+@@ -226,38 +234,36 @@ struct ctl_timer {
/* session.c */
void session_socket_blockmode(int, enum blockmodes);
@@ -37,19 +69,36 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
- struct network_head *, struct filter_head *,
- struct mrt_head *, struct rib_names *,
- int[2], int[2], int[2], int[2]);
-+pid_t session_main(int[2], int[2], int[2], int[2], char *, char *);
++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, pid_t, void *, u_int16_t);
+-int imsg_compose_parent(int, pid_t, void *, u_int16_t);
++int imsg_compose_parent(int, u_int32_t, pid_t, void *, u_int16_t);
int imsg_compose_rde(int, pid_t, void *, u_int16_t);
+void session_stop(struct peer *, u_int8_t);
/* log.c */
char *log_fmt_peer(const struct peer_config *);
-@@ -255,9 +254,7 @@ int merge_config(struct bgpd_config *,
+ void log_statechange(struct peer *, enum session_state,
+ enum session_events);
+ void log_notification(const struct peer *, u_int8_t, u_int8_t,
+- u_char *, u_int16_t);
++ u_char *, u_int16_t, const char *);
+ void log_conn_attempt(const struct peer *, struct sockaddr *);
+
+ /* parse.y */
+ int parse_config(char *, struct bgpd_config *, struct mrt_head *,
+- struct peer **, struct network_head *, struct filter_head *);
++ struct peer **, struct network_head *, struct filter_head *,
++ struct rdomain_head *);
+
+ /* config.c */
+ int merge_config(struct bgpd_config *, struct bgpd_config *,
+ struct peer *, struct listen_addrs *);
void prepare_listeners(struct bgpd_config *);
++int get_mpe_label(struct rdomain *);
/* rde.c */
-pid_t rde_main(struct bgpd_config *, struct peer *, struct network_head *,
@@ -59,3 +108,20 @@ diff -u -p -r1.1.1.7 -r1.1.1.8
/* control.c */
int control_init(int, char *);
+@@ -267,6 +273,7 @@ int control_dispatch_msg(struct pollfd *
+ unsigned int control_accept(int, int);
+
+ /* pfkey.c */
++int pfkey_read(int, struct sadb_msg *);
+ int pfkey_establish(struct peer *);
+ int pfkey_remove(struct peer *);
+ int pfkey_init(struct bgpd_sysdep *);
+@@ -274,7 +281,7 @@ int pfkey_init(struct bgpd_sysdep *);
+ /* 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);
diff --git a/net/openbgpd/files/patch-bgpd_timer.c b/net/openbgpd/files/patch-bgpd_timer.c
new file mode 100644
index 000000000000..1bace94e1998
--- /dev/null
+++ b/net/openbgpd/files/patch-bgpd_timer.c
@@ -0,0 +1,23 @@
+Index: bgpd/timer.c
+===================================================================
+RCS file: /home/cvs/private/hrs/openbgpd/bgpd/timer.c,v
+retrieving revision 1.1.1.2
+retrieving revision 1.1.1.3
+diff -u -p -r1.1.1.2 -r1.1.1.3
+--- bgpd/timer.c 9 Jul 2009 16:49:54 -0000 1.1.1.2
++++ bgpd/timer.c 12 Jun 2011 10:44:25 -0000 1.1.1.3
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: timer.c,v 1.13 2009/01/21 20:32:53 henning Exp $ */
++/* $OpenBSD: timer.c,v 1.14 2010/10/24 17:20:08 deraadt Exp $ */
+
+ /*
+ * Copyright (c) 2003-2007 Henning Brauer <henning@openbsd.org>
+@@ -43,7 +43,7 @@ timer_get(struct peer *p, enum Timer tim
+
+ TAILQ_FOREACH(pt, &p->timers, entry)
+ if (pt->type == timer)
+- break;
++ break;
+
+ return (pt);
+ }
diff --git a/net/openbgpd/files/patch-bgpd_util.c b/net/openbgpd/files/patch-bgpd_util.c
index 88c95a8423d8..213c90a2276e 100644
--- a/net/openbgpd/files/patch-bgpd_util.c
+++ b/net/openbgpd/files/patch-bgpd_util.c
@@ -2,10 +2,10 @@ Index: bgpd/util.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/util.c,v
retrieving revision 1.1.1.6
-retrieving revision 1.5
-diff -u -p -r1.1.1.6 -r1.5
+retrieving revision 1.6
+diff -u -p -r1.1.1.6 -r1.6
--- bgpd/util.c 14 Feb 2010 20:19:57 -0000 1.1.1.6
-+++ bgpd/util.c 10 Apr 2010 12:16:23 -0000 1.5
++++ bgpd/util.c 2 Jul 2011 16:06:38 -0000 1.6
@@ -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 $ */
@@ -22,7 +22,13 @@ diff -u -p -r1.1.1.6 -r1.5
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
-@@ -32,11 +35,24 @@ const char *
+@@ -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];
@@ -50,7 +56,7 @@ diff -u -p -r1.1.1.6 -r1.5
}
const char *
-@@ -90,6 +106,64 @@ log_as(u_int32_t as)
+@@ -90,6 +108,96 @@ log_as(u_int32_t as)
return (buf);
}
@@ -107,15 +113,81 @@ diff -u -p -r1.1.1.6 -r1.5
+ case EXT_COMMUNITY_BGP_COLLECT:
+ return ("bdc"); /* bgp data collection */
+ default:
-+ snprintf(etype, sizeof(etype), "[%i]", (int)subtype);
++ 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)
{
-@@ -276,3 +350,115 @@ inet6applymask(struct in6_addr *dest, co
+@@ -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)
+@@ -276,3 +376,115 @@ inet6applymask(struct in6_addr *dest, co
for (i = 0; i < 16; i++)
dest->s6_addr[i] = src->s6_addr[i] & mask.s6_addr[i];
}
diff --git a/net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c b/net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c
new file mode 100644
index 000000000000..7d807d2259d9
--- /dev/null
+++ b/net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c
@@ -0,0 +1,310 @@
+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 2 Jul 2011 16:06:38 -0000 1.1
+@@ -0,0 +1,303 @@
++/* $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++;
++ }
++
++ if ((n = writev(msgbuf->fd, iov, i)) == -1) {
++ if (errno == EAGAIN || errno == ENOBUFS ||
++ errno == EINTR) /* try later */
++ return (0);
++ else
++ return (-1);
++ }
++
++ if (n == 0) { /* connection closed */
++ errno = 0;
++ return (-2);
++ }
++
++ msgbuf_drain(msgbuf, n);
++
++ return (0);
++}
++
++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;
++ }
++
++ if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
++ if (errno == EAGAIN || errno == ENOBUFS ||
++ errno == EINTR) /* try later */
++ return (0);
++ else
++ return (-1);
++ }
++
++ if (n == 0) { /* connection closed */
++ errno = 0;
++ return (-2);
++ }
++
++ /*
++ * 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 (0);
++}
++
++void
++ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
++{
++ TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
++ msgbuf->queued++;
++}
++
++void
++ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
++{
++ TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
++
++ if (buf->fd != -1)
++ close(buf->fd);
++
++ msgbuf->queued--;
++ ibuf_free(buf);
++}
diff --git a/net/openbgpd/files/patch-openbsd-compat_imsg.c b/net/openbgpd/files/patch-openbsd-compat_imsg.c
new file mode 100644
index 000000000000..183a46ba6697
--- /dev/null
+++ b/net/openbgpd/files/patch-openbsd-compat_imsg.c
@@ -0,0 +1,278 @@
+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 2 Jul 2011 16:06:38 -0000 1.1
+@@ -0,0 +1,271 @@
++/* $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_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) {
++ close(fd);
++ 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 ibuf *wbuf;
++
++ if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
++ return (-1);
++
++ if (imsg_add(wbuf, data, datalen) == -1)
++ return (-1);
++
++ wbuf->fd = fd;
++
++ imsg_close(ibuf, wbuf);
++
++ return (1);
++}
++
++int
++imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
++ pid_t pid, int fd, const struct iovec *iov, int iovcnt)
++{
++ struct ibuf *wbuf;
++ int i, datalen = 0;
++
++ for (i = 0; i < iovcnt; i++)
++ datalen += iov[i].iov_len;
++
++ if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
++ return (-1);
++
++ for (i = 0; i < iovcnt; i++)
++ if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
++ return (-1);
++
++ wbuf->fd = fd;
++
++ imsg_close(ibuf, wbuf);
++
++ return (1);
++}
++
++/* ARGSUSED */
++struct ibuf *
++imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
++ pid_t pid, u_int16_t datalen)
++{
++ struct ibuf *wbuf;
++ struct imsg_hdr hdr;
++
++ datalen += IMSG_HEADER_SIZE;
++ if (datalen > MAX_IMSGSIZE) {
++ errno = ERANGE;
++ return (NULL);
++ }
++
++ hdr.type = type;
++ hdr.flags = 0;
++ hdr.peerid = peerid;
++ if ((hdr.pid = pid) == 0)
++ hdr.pid = ibuf->pid;
++ if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
++ return (NULL);
++ }
++ if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
++ return (NULL);
++
++ return (wbuf);
++}
++
++int
++imsg_add(struct ibuf *msg, void *data, u_int16_t datalen)
++{
++ if (datalen)
++ if (ibuf_add(msg, data, datalen) == -1) {
++ ibuf_free(msg);
++ return (-1);
++ }
++ return (datalen);
++}
++
++void
++imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
++{
++ struct imsg_hdr *hdr;
++
++ hdr = (struct imsg_hdr *)msg->buf;
++
++ hdr->flags &= ~IMSGF_HASFD;
++ if (msg->fd != -1)
++ hdr->flags |= IMSGF_HASFD;
++
++ hdr->len = (u_int16_t)msg->wpos;
++
++ ibuf_close(&ibuf->w, msg);
++}
++
++void
++imsg_free(struct imsg *imsg)
++{
++ free(imsg->data);
++}
++
++int
++imsg_get_fd(struct imsgbuf *ibuf)
++{
++ int fd;
++ struct imsg_fd *ifd;
++
++ if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
++ return (-1);
++
++ fd = ifd->fd;
++ TAILQ_REMOVE(&ibuf->fds, ifd, entry);
++ free(ifd);
++
++ return (fd);
++}
++
++int
++imsg_flush(struct imsgbuf *ibuf)
++{
++ while (ibuf->w.queued)
++ if (msgbuf_write(&ibuf->w) < 0)
++ return (-1);
++ return (0);
++}
++
++void
++imsg_clear(struct imsgbuf *ibuf)
++{
++ int fd;
++
++ msgbuf_clear(&ibuf->w);
++ while ((fd = imsg_get_fd(ibuf)) != -1)
++ close(fd);
++}
diff --git a/net/openbgpd/files/patch-openbsd-compat_imsg.h b/net/openbgpd/files/patch-openbsd-compat_imsg.h
new file mode 100644
index 000000000000..80ce85487aef
--- /dev/null
+++ b/net/openbgpd/files/patch-openbsd-compat_imsg.h
@@ -0,0 +1,119 @@
+Index: openbsd-compat/imsg.h
+===================================================================
+RCS file: openbsd-compat/imsg.h
+diff -N openbsd-compat/imsg.h
+--- /dev/null 1 Jan 1970 00:00:00 -0000
++++ openbsd-compat/imsg.h 2 Jul 2011 16:06:38 -0000 1.1
+@@ -0,0 +1,112 @@
++/* $OpenBSD: imsg.h,v 1.2 2010/06/23 07:53:55 nicm Exp $ */
++
++/*
++ * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
++ * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
++ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#ifndef _IMSG_H_
++#define _IMSG_H_
++
++#define IBUF_READ_SIZE 65535
++#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
++#define MAX_IMSGSIZE 16384
++
++struct ibuf {
++ TAILQ_ENTRY(ibuf) entry;
++ u_char *buf;
++ size_t size;
++ size_t max;
++ size_t wpos;
++ size_t rpos;
++ int fd;
++};
++
++struct msgbuf {
++ TAILQ_HEAD(, ibuf) bufs;
++ u_int32_t queued;
++ int fd;
++};
++
++struct ibuf_read {
++ u_char buf[IBUF_READ_SIZE];
++ u_char *rptr;
++ size_t wpos;
++};
++
++struct imsg_fd {
++ TAILQ_ENTRY(imsg_fd) entry;
++ int fd;
++};
++
++struct imsgbuf {
++ TAILQ_HEAD(, imsg_fd) fds;
++ struct ibuf_read r;
++ struct msgbuf w;
++ int fd;
++ pid_t pid;
++};
++
++#define IMSGF_HASFD 1
++
++struct imsg_hdr {
++ u_int32_t type;
++ u_int16_t len;
++ u_int16_t flags;
++ u_int32_t peerid;
++ u_int32_t pid;
++};
++
++struct imsg {
++ struct imsg_hdr hdr;
++ int fd;
++ void *data;
++};
++
++
++/* buffer.c */
++struct ibuf *ibuf_open(size_t);
++struct ibuf *ibuf_dynamic(size_t, size_t);
++int ibuf_add(struct ibuf *, const void *, size_t);
++void *ibuf_reserve(struct ibuf *, size_t);
++void *ibuf_seek(struct ibuf *, size_t, size_t);
++size_t ibuf_size(struct ibuf *);
++size_t ibuf_left(struct ibuf *);
++void ibuf_close(struct msgbuf *, struct ibuf *);
++int ibuf_write(struct msgbuf *);
++void ibuf_free(struct ibuf *);
++void msgbuf_init(struct msgbuf *);
++void msgbuf_clear(struct msgbuf *);
++int msgbuf_write(struct msgbuf *);
++void msgbuf_drain(struct msgbuf *, size_t);
++
++/* imsg.c */
++void imsg_init(struct imsgbuf *, int);
++ssize_t imsg_read(struct imsgbuf *);
++ssize_t imsg_get(struct imsgbuf *, struct imsg *);
++int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
++ int, void *, u_int16_t);
++int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
++ int, const struct iovec *, int);
++struct ibuf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
++ u_int16_t);
++int imsg_add(struct ibuf *, void *, u_int16_t);
++void imsg_close(struct imsgbuf *, struct ibuf *);
++void imsg_free(struct imsg *);
++int imsg_flush(struct imsgbuf *);
++void imsg_clear(struct imsgbuf *);
++
++#endif
diff --git a/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h b/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h
index 1339f1f1a772..312906fefe60 100644
--- a/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h
+++ b/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h
@@ -3,10 +3,10 @@ Index: openbsd-compat/openbsd-compat.h
RCS file: openbsd-compat/openbsd-compat.h
diff -N openbsd-compat/openbsd-compat.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
-+++ openbsd-compat/openbsd-compat.h 4 Feb 2010 16:22:51 -0000 1.4
++++ openbsd-compat/openbsd-compat.h 3 Jul 2011 04:46:38 -0000 1.6
@@ -0,0 +1,87 @@
+/*
-+ * $hrs: openbgpd/openbsd-compat/openbsd-compat.h,v 1.4 2010/02/04 16:22:51 hrs Exp $
++ * $hrs: openbgpd/openbsd-compat/openbsd-compat.h,v 1.6 2011/07/03 04:46:38 hrs Exp $
+ */
+
+#ifndef _OPENBSD_COMPAT_H
diff --git a/net/openbgpd/files/patch-openbsd-compat_pfkey_compat.c b/net/openbgpd/files/patch-openbsd-compat_pfkey_compat.c
index d7754e350646..6e2a53f6d341 100644
--- a/net/openbgpd/files/patch-openbsd-compat_pfkey_compat.c
+++ b/net/openbgpd/files/patch-openbsd-compat_pfkey_compat.c
@@ -3,8 +3,8 @@ Index: openbsd-compat/pfkey_compat.c
RCS file: openbsd-compat/pfkey_compat.c
diff -N openbsd-compat/pfkey_compat.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
-+++ openbsd-compat/pfkey_compat.c 30 Jun 2009 06:40:07 -0000 1.1
-@@ -0,0 +1,27 @@
++++ openbsd-compat/pfkey_compat.c 2 Jul 2011 16:06:38 -0000 1.2
+@@ -0,0 +1,32 @@
+#include "bgpd.h"
+#include "session.h"
+
@@ -32,3 +32,8 @@ diff -N openbsd-compat/pfkey_compat.c
+ return (0);
+}
+
++int
++pfkey_read(int sd, struct sadb_msg *h)
++{
++ return (1);
++}
diff --git a/net/openbgpd/pkg-install b/net/openbgpd/pkg-install
deleted file mode 100644
index f5996af787be..000000000000
--- a/net/openbgpd/pkg-install
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-case $2 in
-POST-INSTALL)
- USER=_bgpd
- GROUP=${USER}
- UID=130
- GID=${UID}
- PW=/usr/sbin/pw
-
- if ${PW} group show "${GROUP}" 2>/dev/null; then
- echo "You already have a group \"${GROUP}\", so I will use it."
- else
- if ${PW} groupadd ${GROUP} -g ${GID}; then
- echo "Added group \"${GROUP}\"."
- else
- echo "Adding group \"${GROUP}\" failed..."
- exit 1
- fi
- fi
-
- if ${PW} user show "${USER}" 2>/dev/null; then
- echo "You already have a user \"${USER}\", so I will use it."
- else
- if ${PW} useradd ${USER} -u ${UID} -g ${GROUP} -h - \
- -d "/var/empty" -s /sbin/nologin -c "BGP Daemon"
- then
- echo "Added user \"${USER}\"."
- else
- echo "Adding user \"${USER}\" failed..."
- exit 1
- fi
- fi
- exit 0
- ;;
-esac