diff options
46 files changed, 6464 insertions, 1341 deletions
diff --git a/net/openbgpd/Makefile b/net/openbgpd/Makefile index c4793d40fffc..cdf52e324282 100644 --- a/net/openbgpd/Makefile +++ b/net/openbgpd/Makefile @@ -1,13 +1,8 @@ -# New ports collection makefile for: openbgpd -# Date created: May 10 2005 -# Whom: Florent Thoumie <flz@FreeBSD.org> -# +# Created by: Florent Thoumie <flz@FreeBSD.org> # $FreeBSD$ -# PORTNAME= openbgpd -PORTVERSION= 4.9.20110612 -PORTREVISION= 1 +PORTVERSION= 5.2.20121014 CATEGORIES= net MASTER_SITES= ${MASTER_SITE_OPENBSD} MASTER_SITE_SUBDIR= OpenBGPD @@ -20,8 +15,9 @@ COMMENT= Free implementation of the Border Gateway Protocol, Version 4 CONFLICTS= zebra-[0-9]* quagga-[0-9]* -OPTIONS= IPV6LLPEER \ - "Support nexthop using IPv6 link-local address" on +OPTIONS_DEFINE= IPV6LLPEER +OPTIONS_DEFAULT=IPV6LLPEER +IPV6LLPEER_DESC=Support nexthop using IPv6 link-local address .include <bsd.port.pre.mk> diff --git a/net/openbgpd/files/patch-bgpctl_Makefile b/net/openbgpd/files/patch-bgpctl_Makefile index faca1083ecf9..572c0fcb8362 100644 --- a/net/openbgpd/files/patch-bgpctl_Makefile +++ b/net/openbgpd/files/patch-bgpctl_Makefile @@ -2,10 +2,10 @@ Index: bgpctl/Makefile =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/Makefile,v retrieving revision 1.1.1.1 -retrieving revision 1.3 -diff -u -p -r1.1.1.1 -r1.3 +retrieving revision 1.4 +diff -u -p -r1.1.1.1 -r1.4 --- bgpctl/Makefile 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpctl/Makefile 2 Jul 2011 16:06:35 -0000 1.3 ++++ bgpctl/Makefile 13 Oct 2012 18:35:56 -0000 1.4 @@ -1,17 +1,18 @@ # $OpenBSD: Makefile,v 1.10 2007/12/20 17:08:48 henning Exp $ @@ -16,7 +16,8 @@ diff -u -p -r1.1.1.1 -r1.3 -SRCS= bgpctl.c parser.c buffer.c imsg.c util.c timer.c +SRCS= bgpctl.c parser.c util.c timer.c SRCS+= irrfilter.c whois.c irr_asset.c irr_prefix.c irr_output.c - SRCS+= irr_parser.c +-SRCS+= irr_parser.c ++SRCS+= irr_parser.c mrtparser.c +SRCS+= fmt_scaled.c imsg.c imsg-buffer.c CFLAGS+= -Wall CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes diff --git a/net/openbgpd/files/patch-bgpctl_bgpctl.8 b/net/openbgpd/files/patch-bgpctl_bgpctl.8 index a5305b3061b1..2e08c575981e 100644 --- a/net/openbgpd/files/patch-bgpctl_bgpctl.8 +++ b/net/openbgpd/files/patch-bgpctl_bgpctl.8 @@ -2,13 +2,13 @@ Index: bgpctl/bgpctl.8 =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/bgpctl.8,v retrieving revision 1.1.1.6 -retrieving revision 1.5 -diff -u -p -r1.1.1.6 -r1.5 +retrieving revision 1.6 +diff -u -p -r1.1.1.6 -r1.6 --- bgpctl/bgpctl.8 14 Feb 2010 20:20:13 -0000 1.1.1.6 -+++ bgpctl/bgpctl.8 2 Jul 2011 16:06:35 -0000 1.5 ++++ bgpctl/bgpctl.8 13 Oct 2012 18:35:56 -0000 1.6 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bgpctl.8,v 1.49 2009/06/06 06:11:17 claudio Exp $ -+.\" $OpenBSD: bgpctl.8,v 1.52 2009/11/03 08:09:15 jmc Exp $ ++.\" $OpenBSD: bgpctl.8,v 1.59 2012/05/27 20:49:42 jmc Exp $ .\" .\" Copyright (c) 2003 Henning Brauer <henning@openbsd.org> .\" @@ -17,7 +17,7 @@ diff -u -p -r1.1.1.6 -r1.5 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: June 6 2009 $ -+.Dd $Mdocdate: May 3 2010 $ ++.Dd $Mdocdate: May 27 2012 $ .Dt BGPCTL 8 .Os .Sh NAME @@ -71,7 +71,7 @@ diff -u -p -r1.1.1.6 -r1.5 .It Cm neighbor Ar peer Cm up Take the BGP session to the specified neighbor up. .Ar peer -@@ -98,8 +113,10 @@ Note that the neighbor is not obliged to +@@ -98,12 +113,21 @@ Note that the neighbor is not obliged to all, even if it announced the route refresh capability. .Ar peer may be the neighbor's address or description. @@ -83,7 +83,18 @@ diff -u -p -r1.1.1.6 -r1.5 .It Cm network delete Ar prefix Remove the specified prefix from the list of announced networks. .It Cm network flush -@@ -122,7 +139,7 @@ view of the Forwarding Information Base. + Remove all dynamically added prefixes from the list of announced networks. ++.It Cm network mrt file Ar file filter ++Import networks from an MRT table dump for debugging purposes. ++.Ar filter ++can be specified similarly to the ++.Ar show mrt ++command. ++Only networks matching the filter will be imported. + .It Cm network show Ar family + Show all announced networks. + .Ar family , +@@ -122,7 +146,7 @@ view of the Forwarding Information Base. can be an IP address, in which case the route to this address is shown, or a flag: .Pp @@ -92,7 +103,7 @@ diff -u -p -r1.1.1.6 -r1.5 .It Cm connected Show only connected routes. .It Cm static -@@ -133,6 +150,14 @@ Show only routes originating from +@@ -133,9 +157,81 @@ Show only routes originating from itself. .It Cm nexthop Show only routes required to reach a BGP nexthop. @@ -107,7 +118,138 @@ diff -u -p -r1.1.1.6 -r1.5 .El .It Cm show interfaces Show the interface states. -@@ -243,10 +268,12 @@ and message counters. ++.It Xo ++.Cm show mrt ++.Op Ar options ++.Ar filter ++.Xc ++Show routes from an MRT table dump file. ++.Ar filter ++can be an IP address, a CIDR prefix, an AS filter, a combination or nothing: ++.Pp ++.Bl -tag -width "address/len all" -compact ++.It Ar address ++Show best matching route for address. ++.It Ar address Ns Li / Ns Ar len ++Show RIB entry for this CIDR prefix. ++.It Xo ++.Ar address Ns Li / Ns Ar len ++.Cm all ++.Xc ++Show all entries in the specified range. ++.\".It Ar address/len Cm longer-prefixes ++.It Cm as Ar as ++Show all entries with ++.Ar as ++anywhere in the AS path. ++.It Cm empty-as ++Show all entries that are internal routes with no AS's in the AS path. ++.It Cm neighbor Ar ip ++Show only entries from the specified peer. ++.It Cm peer-as Ar as ++Show all entries with ++.Ar as ++as leftmost AS. ++.It Cm source-as Ar as ++Show all entries with ++.Ar as ++as rightmost AS. ++.It Cm transit-as Ar as ++Show all entries with ++.Ar as ++anywhere but rightmost. ++.El ++.Pp ++Additionally, the following ++.Ar options ++are defined: ++.Pp ++.Bl -tag -width "file name" -compact ++.It Cm detail ++Show more detailed output for matching routes. ++.It Ar family ++Limit the output to the given address family. ++.It Cm file Ar name ++Read the MRT dump from file ++.Ar name ++instead of using stdin. ++.El ++.Pp ++Multiple options and filters can be used at the same time. ++.It Cm show summary ++Show a list of all neighbors, including information about the session state ++and message counters. ++.It Cm show summary terse ++Show a list of all neighbors, including information about the session state, ++in a terse format. + .It Cm show neighbor Ar peer modifier + Show detailed information about the neighbor identified by + .Ar peer , +@@ -183,33 +279,33 @@ Show all entries in the specified range. + Show all entries with + .Ar as + anywhere in the AS path. +-.It Cm source-as Ar as +-Show all entries with +-.Ar as +-as rightmost AS. +-.It Cm transit-as Ar as +-Show all entries with +-.Ar as +-anywhere but rightmost. +-.It Cm peer-as Ar as +-Show all entries with +-.Ar as +-as leftmost AS. +-.It Cm empty-as +-Show all entries that are internal routes with no AS's in the AS path. + .It Cm community Ar community + Show all entries with community + .Ar community . ++.It Cm empty-as ++Show all entries that are internal routes with no AS's in the AS path. ++.It Cm memory ++Show RIB memory statistics. + .It Cm neighbor Ar peer + Show only entries from the specified peer. +-.It Cm table Ar rib +-Show only entries from the specified RIB table. ++.It Cm peer-as Ar as ++Show all entries with ++.Ar as ++as leftmost AS. ++.It Cm source-as Ar as ++Show all entries with ++.Ar as ++as rightmost AS. + .It Cm summary + This is the same as the + .Ic show summary + command. +-.It Cm memory +-Show RIB memory statistics. ++.It Cm table Ar rib ++Show only entries from the specified RIB table. ++.It Cm transit-as Ar as ++Show all entries with ++.Ar as ++anywhere but rightmost. + .El + .Pp + Additionally, the following +@@ -217,8 +313,10 @@ Additionally, the following + are defined: + .Pp + .Bl -tag -width "detail" -compact ++.It Cm selected ++Show only selected routes. + .It Cm detail +-Show more detailed output for matched routes. ++Show more detailed output for matching routes. + .It Ar family + Limit the output to the given address family. + .It Cm in +@@ -243,10 +341,12 @@ and message counters. .It Cm show summary terse Show a list of all neighbors, including information about the session state, in a terse format. @@ -121,3 +263,25 @@ diff -u -p -r1.1.1.6 -r1.5 default .Xr bgpd 8 configuration file +@@ -260,10 +360,19 @@ control socket + .Xr bgpd 8 , + .Xr bgplg 8 , + .Xr bgplgsh 8 ++.Sh STANDARDS + .Rs +-.%R RFC 2622 +-.%T "Routing Policy Specification Language (RPSL)" ++.%A C. Alaettinoglu ++.%A C. Villamizar ++.%A E. Gerich ++.%A D. Kessens ++.%A D. Meyer ++.%A T. Bates ++.%A D. Karrenberg ++.%A M. Terpstra + .%D June 1999 ++.%R RFC 2622 ++.%T Routing Policy Specification Language (RPSL) + .Re + .Sh HISTORY + The diff --git a/net/openbgpd/files/patch-bgpctl_bgpctl.c b/net/openbgpd/files/patch-bgpctl_bgpctl.c index 4497b055410f..54006c76dff3 100644 --- a/net/openbgpd/files/patch-bgpctl_bgpctl.c +++ b/net/openbgpd/files/patch-bgpctl_bgpctl.c @@ -2,13 +2,12 @@ Index: bgpctl/bgpctl.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/bgpctl.c,v retrieving revision 1.1.1.7 -retrieving revision 1.8 -diff -u -p -r1.1.1.7 -r1.8 +diff -u -p -r1.1.1.7 bgpctl.c --- bgpctl/bgpctl.c 14 Feb 2010 20:20:14 -0000 1.1.1.7 -+++ bgpctl/bgpctl.c 2 Jul 2011 16:06:35 -0000 1.8 ++++ bgpctl/bgpctl.c 13 Oct 2012 18:49:31 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpctl.c,v 1.142 2009/06/06 06:33:15 eric Exp $ */ -+/* $OpenBSD: bgpctl.c,v 1.157 2010/03/08 17:02:19 claudio Exp $ */ ++/* $OpenBSD: bgpctl.c,v 1.165 2012/09/12 05:57:10 claudio Exp $ */ /* * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> @@ -44,23 +43,25 @@ diff -u -p -r1.1.1.7 -r1.8 #include "bgpd.h" #include "session.h" -@@ -38,6 +50,10 @@ +@@ -37,6 +49,11 @@ + #include "log.h" #include "parser.h" #include "irrfilter.h" - ++#include "mrtparser.h" ++ +#if defined(__FreeBSD__) /* FreeBSD has no LINK_STATE_IS_UP macro. */ +#define LINK_STATE_IS_UP(_s) ((_s) >= LINK_STATE_UP) +#endif /* defined(__FreeBSD__) */ -+ + enum neighbor_views { NV_DEFAULT, - NV_TIMERS -@@ -50,12 +66,13 @@ int show_summary_msg(struct imsg *, in +@@ -50,12 +67,14 @@ int show_summary_msg(struct imsg *, in int show_summary_terse_msg(struct imsg *, int); int show_neighbor_terse(struct imsg *); int show_neighbor_msg(struct imsg *, enum neighbor_views); -void print_neighbor_capa_mp_safi(u_int8_t); +void print_neighbor_capa_mp(struct peer *); ++void print_neighbor_capa_restart(struct peer *); void print_neighbor_msgstats(struct peer *); void print_timer(const char *, time_t); static char *fmt_timeframe(time_t t); @@ -70,7 +71,7 @@ diff -u -p -r1.1.1.7 -r1.8 void show_network_head(void); void show_fib_flags(u_int16_t); int show_fib_msg(struct imsg *); -@@ -65,7 +82,7 @@ void show_interface_head(void); +@@ -65,7 +84,7 @@ void show_interface_head(void); int ift2ifm(int); const char * get_media_descr(int); const char * get_linkstate(int, int); @@ -79,15 +80,34 @@ diff -u -p -r1.1.1.7 -r1.8 int show_interface_msg(struct imsg *); void show_rib_summary_head(void); void print_prefix(struct bgpd_addr *, u_int8_t, u_int8_t); -@@ -74,7 +91,6 @@ void print_flags(u_int8_t, int); +@@ -73,16 +92,25 @@ const char * print_origin(u_int8_t, int + void print_flags(u_int8_t, int); int show_rib_summary_msg(struct imsg *); int show_rib_detail_msg(struct imsg *, int); ++void show_rib_brief(struct ctl_show_rib *, u_char *); ++void show_rib_detail(struct ctl_show_rib *, u_char *, int); ++void show_attr(void *, u_int16_t); void show_community(u_char *, u_int16_t); -const char *get_ext_subtype(u_int8_t); void show_ext_community(u_char *, u_int16_t); char *fmt_mem(int64_t); int show_rib_memory_msg(struct imsg *); -@@ -98,7 +114,7 @@ int + void send_filterset(struct imsgbuf *, struct filter_set_head *); + static const char *get_errstr(u_int8_t, u_int8_t); + int show_result(struct imsg *); ++void show_mrt_dump(struct mrt_rib *, struct mrt_peer *, void *); ++void network_mrt_dump(struct mrt_rib *, struct mrt_peer *, void *); ++void show_mrt_state(struct mrt_bgp_state *, void *); ++void show_mrt_msg(struct mrt_bgp_msg *, void *); ++void mrt_to_bgpd_addr(union mrt_addr *, struct bgpd_addr *); + + struct imsgbuf *ibuf; ++struct mrt_parser show_mrt = { show_mrt_dump, show_mrt_state, show_mrt_msg }; ++struct mrt_parser net_mrt = { network_mrt_dump, NULL, NULL }; + + __dead void + usage(void) +@@ -98,7 +126,7 @@ int main(int argc, char *argv[]) { struct sockaddr_un sun; @@ -96,7 +116,7 @@ diff -u -p -r1.1.1.7 -r1.8 struct imsg imsg; struct network_config net; struct parse_result *res; -@@ -128,8 +144,11 @@ main(int argc, char *argv[]) +@@ -128,8 +156,11 @@ main(int argc, char *argv[]) if ((res = parse(argc, argv)) == NULL) exit(1); @@ -109,7 +129,16 @@ diff -u -p -r1.1.1.7 -r1.8 memcpy(&neighbor.addr, &res->peeraddr, sizeof(neighbor.addr)); strlcpy(neighbor.descr, res->peerdesc, sizeof(neighbor.descr)); -@@ -164,24 +183,32 @@ main(int argc, char *argv[]) +@@ -154,7 +185,7 @@ main(int argc, char *argv[]) + case NONE: + case IRRFILTER: + usage(); +- /* not reached */ ++ /* NOTREACHED */ + case SHOW: + case SHOW_SUMMARY: + imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1, NULL, 0); +@@ -164,24 +195,32 @@ main(int argc, char *argv[]) imsg_compose(ibuf, IMSG_CTL_SHOW_TERSE, 0, 0, -1, NULL, 0); break; case SHOW_FIB: @@ -151,7 +180,7 @@ diff -u -p -r1.1.1.7 -r1.8 show_nexthop_head(); break; case SHOW_INTERFACE: -@@ -192,7 +219,7 @@ main(int argc, char *argv[]) +@@ -192,7 +231,7 @@ main(int argc, char *argv[]) case SHOW_NEIGHBOR_TIMERS: case SHOW_NEIGHBOR_TERSE: neighbor.show_timers = (res->action == SHOW_NEIGHBOR_TIMERS); @@ -160,7 +189,7 @@ diff -u -p -r1.1.1.7 -r1.8 imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1, &neighbor, sizeof(neighbor)); else -@@ -206,7 +233,7 @@ main(int argc, char *argv[]) +@@ -206,7 +245,7 @@ main(int argc, char *argv[]) memcpy(&ribreq.as, &res->as, sizeof(res->as)); type = IMSG_CTL_SHOW_RIB_AS; } @@ -169,16 +198,46 @@ diff -u -p -r1.1.1.7 -r1.8 memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr)); ribreq.prefixlen = res->prefixlen; type = IMSG_CTL_SHOW_RIB_PREFIX; -@@ -220,7 +247,7 @@ main(int argc, char *argv[]) - memcpy(&ribreq.neighbor, &neighbor, - sizeof(ribreq.neighbor)); +@@ -217,15 +256,35 @@ main(int argc, char *argv[]) + sizeof(res->community)); + type = IMSG_CTL_SHOW_RIB_COMMUNITY; + } +- memcpy(&ribreq.neighbor, &neighbor, +- sizeof(ribreq.neighbor)); ++ memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor)); strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib)); - ribreq.af = res->af; + ribreq.aid = res->aid; ribreq.flags = res->flags; imsg_compose(ibuf, type, 0, 0, -1, &ribreq, sizeof(ribreq)); if (!(res->flags & F_CTL_DETAIL)) -@@ -237,12 +264,14 @@ main(int argc, char *argv[]) + show_rib_summary_head(); + break; ++ case SHOW_MRT: ++ close(fd); ++ bzero(&ribreq, sizeof(ribreq)); ++ if (res->as.type != AS_NONE) ++ memcpy(&ribreq.as, &res->as, sizeof(res->as)); ++ if (res->addr.aid) { ++ memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr)); ++ ribreq.prefixlen = res->prefixlen; ++ } ++ if (res->community.as != COMMUNITY_UNSET && ++ res->community.type != COMMUNITY_UNSET) ++ memcpy(&ribreq.community, &res->community, ++ sizeof(res->community)); ++ memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor)); ++ ribreq.aid = res->aid; ++ ribreq.flags = res->flags; ++ show_mrt.arg = &ribreq; ++ if (!(res->flags & F_CTL_DETAIL)) ++ show_rib_summary_head(); ++ mrt_parse(res->mrtfd, &show_mrt, 1); ++ exit(0); + case SHOW_RIB_MEM: + imsg_compose(ibuf, IMSG_CTL_SHOW_RIB_MEM, 0, 0, -1, NULL, 0); + break; +@@ -237,12 +296,14 @@ main(int argc, char *argv[]) errx(1, "action==FIB"); break; case FIB_COUPLE: @@ -195,7 +254,7 @@ diff -u -p -r1.1.1.7 -r1.8 printf("decouple request sent.\n"); done = 1; break; -@@ -290,12 +319,21 @@ main(int argc, char *argv[]) +@@ -290,12 +351,40 @@ main(int argc, char *argv[]) break; case NETWORK_SHOW: bzero(&ribreq, sizeof(ribreq)); @@ -206,6 +265,25 @@ diff -u -p -r1.1.1.7 -r1.8 &ribreq, sizeof(ribreq)); show_network_head(); break; ++ case NETWORK_MRT: ++ bzero(&ribreq, sizeof(ribreq)); ++ if (res->as.type != AS_NONE) ++ memcpy(&ribreq.as, &res->as, sizeof(res->as)); ++ if (res->addr.aid) { ++ memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr)); ++ ribreq.prefixlen = res->prefixlen; ++ } ++ if (res->community.as != COMMUNITY_UNSET && ++ res->community.type != COMMUNITY_UNSET) ++ memcpy(&ribreq.community, &res->community, ++ sizeof(res->community)); ++ memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor)); ++ ribreq.aid = res->aid; ++ ribreq.flags = res->flags; ++ net_mrt.arg = &ribreq; ++ mrt_parse(res->mrtfd, &net_mrt, 1); ++ done = 1; ++ break; + case LOG_VERBOSE: + verbose = 1; + /* FALLTHROUGH */ @@ -218,7 +296,7 @@ diff -u -p -r1.1.1.7 -r1.8 } while (ibuf->w.queued) -@@ -304,13 +342,13 @@ main(int argc, char *argv[]) +@@ -304,13 +393,13 @@ main(int argc, char *argv[]) while (!done) { if ((n = imsg_read(ibuf)) == -1) @@ -234,7 +312,7 @@ diff -u -p -r1.1.1.7 -r1.8 if (n == 0) break; -@@ -329,6 +367,8 @@ main(int argc, char *argv[]) +@@ -329,6 +418,8 @@ main(int argc, char *argv[]) done = show_summary_terse_msg(&imsg, nodescr); break; case SHOW_FIB: @@ -243,7 +321,7 @@ diff -u -p -r1.1.1.7 -r1.8 done = show_fib_msg(&imsg); break; case SHOW_NEXTHOP: -@@ -356,9 +396,6 @@ main(int argc, char *argv[]) +@@ -356,9 +447,6 @@ main(int argc, char *argv[]) case SHOW_RIB_MEM: done = show_rib_memory_msg(&imsg); break; @@ -253,16 +331,18 @@ diff -u -p -r1.1.1.7 -r1.8 case NEIGHBOR: case NEIGHBOR_UP: case NEIGHBOR_DOWN: -@@ -373,6 +410,8 @@ main(int argc, char *argv[]) +@@ -373,6 +461,10 @@ main(int argc, char *argv[]) case NETWORK_REMOVE: case NETWORK_FLUSH: case IRRFILTER: + case LOG_VERBOSE: + case LOG_BRIEF: ++ case SHOW_MRT: ++ case NETWORK_MRT: break; } imsg_free(&imsg); -@@ -398,8 +437,8 @@ fmt_peer(const char *descr, const struct +@@ -398,8 +490,8 @@ fmt_peer(const char *descr, const struct } ip = log_addr(remote_addr); @@ -273,7 +353,27 @@ diff -u -p -r1.1.1.7 -r1.8 if (asprintf(&p, "%s/%u", ip, masklen) == -1) err(1, NULL); } else { -@@ -521,13 +560,15 @@ show_neighbor_msg(struct imsg *imsg, enu +@@ -430,7 +522,7 @@ show_summary_msg(struct imsg *imsg, int + p->conf.remote_masklen, nodescr); + if (strlen(s) >= 20) + s[20] = 0; +- printf("%-20s %8s %10llu %10llu %5u %-8s ", ++ printf("%-20s %8s %10" PRIu64 " %10" PRIu64 " %5u %-8s ", + s, log_as(p->conf.remote_as), + p->stats.msg_rcvd_open + p->stats.msg_rcvd_notification + + p->stats.msg_rcvd_update + p->stats.msg_rcvd_keepalive + +@@ -492,8 +584,8 @@ show_neighbor_terse(struct imsg *imsg) + switch (imsg->hdr.type) { + case IMSG_CTL_SHOW_NEIGHBOR: + p = imsg->data; +- printf("%llu %llu %llu %llu %llu %llu %llu " +- "%llu %llu %llu %u %u %llu %llu %llu %llu\n", ++ printf("%" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " " ++ "%" PRIu64 " %" PRIu64 " %" PRIu64 " %u %u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", + p->stats.msg_sent_open, p->stats.msg_rcvd_open, + p->stats.msg_sent_notification, + p->stats.msg_rcvd_notification, +@@ -521,13 +613,15 @@ show_neighbor_msg(struct imsg *imsg, enu struct ctl_timer *t; struct in_addr ina; char buf[NI_MAXHOST], pbuf[NI_MAXSERV], *s; @@ -291,7 +391,7 @@ diff -u -p -r1.1.1.7 -r1.8 p->conf.remote_masklen != 128)) { if (asprintf(&s, "%s/%u", log_addr(&p->conf.remote_addr), -@@ -549,6 +590,10 @@ show_neighbor_msg(struct imsg *imsg, enu +@@ -549,6 +643,10 @@ show_neighbor_msg(struct imsg *imsg, enu printf(", Template"); if (p->conf.cloned) printf(", Cloned"); @@ -302,7 +402,7 @@ diff -u -p -r1.1.1.7 -r1.8 printf("\n"); if (p->conf.descr[0]) printf(" Description: %s\n", p->conf.descr); -@@ -563,17 +608,16 @@ show_neighbor_msg(struct imsg *imsg, enu +@@ -563,22 +661,24 @@ show_neighbor_msg(struct imsg *imsg, enu printf(" Last read %s, holdtime %us, keepalive interval %us\n", fmt_timeframe(p->stats.last_read), p->holdtime, p->holdtime/3); @@ -313,7 +413,7 @@ diff -u -p -r1.1.1.7 -r1.8 + if (p->capa.peer.mp[i]) + hascapamp = 1; + if (hascapamp || p->capa.peer.refresh || -+ p->capa.peer.restart || p->capa.peer.as4byte) { ++ p->capa.peer.grestart.restart || p->capa.peer.as4byte) { printf(" Neighbor capabilities:\n"); - if (p->capa.peer.mp_v4) { - printf(" Multiprotocol extensions: IPv4"); @@ -329,7 +429,17 @@ diff -u -p -r1.1.1.7 -r1.8 } if (p->capa.peer.refresh) printf(" Route Refresh\n"); -@@ -633,20 +677,16 @@ show_neighbor_msg(struct imsg *imsg, enu +- if (p->capa.peer.restart) +- printf(" Graceful Restart\n"); ++ if (p->capa.peer.grestart.restart) { ++ printf(" Graceful Restart"); ++ print_neighbor_capa_restart(p); ++ printf("\n"); ++ } + if (p->capa.peer.as4byte) + printf(" 4-byte AS numbers\n"); + } +@@ -633,20 +733,38 @@ show_neighbor_msg(struct imsg *imsg, enu } void @@ -356,10 +466,67 @@ diff -u -p -r1.1.1.7 -r1.8 + printf("%s%s", comma ? ", " : "", aid2str(i)); + comma = 1; + } ++} ++ ++void ++print_neighbor_capa_restart(struct peer *p) ++{ ++ int comma; ++ u_int8_t i; ++ ++ if (p->capa.peer.grestart.timeout) ++ printf(": Timeout: %d, ", p->capa.peer.grestart.timeout); ++ for (i = 0, comma = 0; i < AID_MAX; i++) ++ if (p->capa.peer.grestart.flags[i] & CAPA_GR_PRESENT) { ++ if (!comma && ++ p->capa.peer.grestart.flags[i] & CAPA_GR_RESTART) ++ printf("restarted, "); ++ if (comma) ++ printf(", "); ++ printf("%s", aid2str(i)); ++ if (p->capa.peer.grestart.flags[i] & CAPA_GR_FORWARD) ++ printf(" (preserved)"); ++ comma = 1; ++ } } void -@@ -680,7 +720,7 @@ print_neighbor_msgstats(struct peer *p) +@@ -654,17 +772,17 @@ print_neighbor_msgstats(struct peer *p) + { + printf(" Message statistics:\n"); + printf(" %-15s %-10s %-10s\n", "", "Sent", "Received"); +- printf(" %-15s %10llu %10llu\n", "Opens", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Opens", + p->stats.msg_sent_open, p->stats.msg_rcvd_open); +- printf(" %-15s %10llu %10llu\n", "Notifications", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Notifications", + p->stats.msg_sent_notification, p->stats.msg_rcvd_notification); +- printf(" %-15s %10llu %10llu\n", "Updates", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Updates", + p->stats.msg_sent_update, p->stats.msg_rcvd_update); +- printf(" %-15s %10llu %10llu\n", "Keepalives", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Keepalives", + p->stats.msg_sent_keepalive, p->stats.msg_rcvd_keepalive); +- printf(" %-15s %10llu %10llu\n", "Route Refresh", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Route Refresh", + p->stats.msg_sent_rrefresh, p->stats.msg_rcvd_rrefresh); +- printf(" %-15s %10llu %10llu\n\n", "Total", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n\n", "Total", + p->stats.msg_sent_open + p->stats.msg_sent_notification + + p->stats.msg_sent_update + p->stats.msg_sent_keepalive + + p->stats.msg_sent_rrefresh, +@@ -673,14 +791,16 @@ print_neighbor_msgstats(struct peer *p) + p->stats.msg_rcvd_rrefresh); + printf(" Update statistics:\n"); + printf(" %-15s %-10s %-10s\n", "", "Sent", "Received"); +- printf(" %-15s %10llu %10llu\n", "Updates", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Updates", + p->stats.prefix_sent_update, p->stats.prefix_rcvd_update); +- printf(" %-15s %10llu %10llu\n", "Withdraws", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Withdraws", + p->stats.prefix_sent_withdraw, p->stats.prefix_rcvd_withdraw); ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "End-of-Rib", ++ p->stats.prefix_sent_eor, p->stats.prefix_rcvd_eor); } void @@ -368,7 +535,7 @@ diff -u -p -r1.1.1.7 -r1.8 { printf(" %-20s ", name); -@@ -745,6 +785,12 @@ show_fib_head(void) +@@ -745,6 +865,12 @@ show_fib_head(void) } void @@ -381,7 +548,7 @@ diff -u -p -r1.1.1.7 -r1.8 show_network_head(void) { printf("flags: S = Static\n"); -@@ -788,56 +834,44 @@ show_fib_flags(u_int16_t flags) +@@ -788,56 +914,44 @@ show_fib_flags(u_int16_t flags) int show_fib_msg(struct imsg *imsg) { @@ -456,7 +623,7 @@ diff -u -p -r1.1.1.7 -r1.8 default: break; } -@@ -848,35 +882,70 @@ show_fib_msg(struct imsg *imsg) +@@ -848,35 +962,70 @@ show_fib_msg(struct imsg *imsg) void show_nexthop_head(void) { @@ -545,7 +712,7 @@ diff -u -p -r1.1.1.7 -r1.8 } printf("\n"); break; -@@ -898,9 +967,8 @@ show_interface_head(void) +@@ -898,9 +1047,8 @@ show_interface_head(void) "Link state"); } @@ -557,7 +724,7 @@ diff -u -p -r1.1.1.7 -r1.8 const struct ifmedia_description ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; -@@ -936,36 +1004,36 @@ get_media_descr(int media_type) +@@ -936,36 +1084,36 @@ get_media_descr(int media_type) const char * get_linkstate(int media_type, int link_state) { @@ -566,9 +733,7 @@ diff -u -p -r1.1.1.7 -r1.8 - - if (link_state == LINK_STATE_UNKNOWN) - return ("unknown"); -+ const struct if_status_description *p; -+ static char buf[8]; - +- - for (i = 0; ifm_status_valid_list[i] != 0; i++) - for (p = ifm_status_descriptions; p->ifms_valid != 0; p++) { - if (p->ifms_type != media_type || @@ -578,7 +743,9 @@ diff -u -p -r1.1.1.7 -r1.8 - return (p->ifms_string[1]); - return (p->ifms_string[0]); - } -- ++ const struct if_status_description *p; ++ static char buf[8]; + - return ("unknown link state"); + for (p = if_status_descriptions; p->ifs_string != NULL; p++) { + if (LINK_STATE_DESC_MATCH(p, media_type, link_state)) @@ -597,26 +764,26 @@ diff -u -p -r1.1.1.7 -r1.8 + if (baudrate > IF_Gbps(1)) - printf("%llu GBit/s", baudrate / IF_Gbps(1)); -+ snprintf(bbuf, sizeof(bbuf), "%llu G%s", ++ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " G%s", + baudrate / IF_Gbps(1), unit); else if (baudrate > IF_Mbps(1)) - printf("%llu MBit/s", baudrate / IF_Mbps(1)); -+ snprintf(bbuf, sizeof(bbuf), "%llu M%s", ++ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " M%s", + baudrate / IF_Mbps(1), unit); else if (baudrate > IF_Kbps(1)) - printf("%llu KBit/s", baudrate / IF_Kbps(1)); -+ snprintf(bbuf, sizeof(bbuf), "%llu K%s", ++ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " K%s", + baudrate / IF_Kbps(1), unit); else - printf("%llu Bit/s", baudrate); -+ snprintf(bbuf, sizeof(bbuf), "%llu %s", ++ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " %s", + baudrate, unit); + + return (bbuf); } int -@@ -982,17 +1050,12 @@ show_interface_msg(struct imsg *imsg) +@@ -982,17 +1130,12 @@ show_interface_msg(struct imsg *imsg) printf("%-15s", k->flags & IFF_UP ? "UP" : ""); if ((ifms_type = ift2ifm(k->media_type)) != 0) @@ -639,16 +806,21 @@ diff -u -p -r1.1.1.7 -r1.8 printf("\n"); break; case IMSG_CTL_END: -@@ -1011,7 +1074,7 @@ show_rib_summary_head(void) - printf( - "flags: * = Valid, > = Selected, I = via IBGP, A = Announced\n"); +@@ -1008,10 +1151,10 @@ show_interface_msg(struct imsg *imsg) + void + show_rib_summary_head(void) + { +- printf( +- "flags: * = Valid, > = Selected, I = via IBGP, A = Announced\n"); ++ printf("flags: * = Valid, > = Selected, I = via IBGP, A = Announced, " ++ "S = Stale\n"); printf("origin: i = IGP, e = EGP, ? = Incomplete\n\n"); - printf("%-5s %-20s%-15s %5s %5s %s\n", "flags", "destination", + printf("%-5s %-20s %-15s %5s %5s %s\n", "flags", "destination", "gateway", "lpref", "med", "aspath origin"); } -@@ -1049,26 +1112,26 @@ print_flags(u_int8_t flags, int sum) +@@ -1049,26 +1192,30 @@ print_flags(u_int8_t flags, int sum) char *p = flagstr; if (sum) { @@ -659,6 +831,8 @@ diff -u -p -r1.1.1.7 -r1.8 + if (flags & F_PREF_INTERNAL) *p++ = 'I'; - if (flags & F_RIB_ELIGIBLE) ++ if (flags & F_PREF_STALE) ++ *p++ = 'S'; + if (flags & F_PREF_ELIGIBLE) *p++ = '*'; - if (flags & F_RIB_ACTIVE) @@ -673,6 +847,8 @@ diff -u -p -r1.1.1.7 -r1.8 else printf("external"); - if (flags & F_RIB_ELIGIBLE) ++ if (flags & F_PREF_STALE) ++ printf(", stale"); + if (flags & F_PREF_ELIGIBLE) printf(", valid"); - if (flags & F_RIB_ACTIVE) @@ -683,43 +859,192 @@ diff -u -p -r1.1.1.7 -r1.8 printf(", announced"); } } -@@ -1085,7 +1148,7 @@ show_rib_summary_msg(struct imsg *imsg) - memcpy(&rib, imsg->data, sizeof(rib)); +@@ -1077,27 +1224,14 @@ int + show_rib_summary_msg(struct imsg *imsg) + { + struct ctl_show_rib rib; +- char *aspath; + u_char *asdata; - print_prefix(&rib.prefix, rib.prefixlen, rib.flags); + switch (imsg->hdr.type) { + case IMSG_CTL_SHOW_RIB: + memcpy(&rib, imsg->data, sizeof(rib)); +- +- print_prefix(&rib.prefix, rib.prefixlen, rib.flags); - printf("%-15s ", log_addr(&rib.exit_nexthop)); -+ printf(" %-15s ", log_addr(&rib.exit_nexthop)); - - printf(" %5u %5u ", rib.local_pref, rib.med); +- +- printf(" %5u %5u ", rib.local_pref, rib.med); +- + asdata = imsg->data; + asdata += sizeof(struct ctl_show_rib); +- if (aspath_asprint(&aspath, asdata, rib.aspath_len) == -1) +- err(1, NULL); +- if (strlen(aspath) > 0) +- printf("%s ", aspath); +- free(aspath); +- +- printf("%s\n", print_origin(rib.origin, 1)); ++ show_rib_brief(&rib, asdata); + break; + case IMSG_CTL_END: + return (1); +@@ -1112,108 +1246,21 @@ int + show_rib_detail_msg(struct imsg *imsg, int nodescr) + { + struct ctl_show_rib rib; +- struct in_addr id; +- char *aspath, *s; +- u_char *data; +- u_int32_t as; +- u_int16_t ilen, alen, ioff; +- u_int8_t flags, type; +- time_t now; ++ u_char *asdata; ++ u_int16_t ilen; -@@ -1189,8 +1252,8 @@ show_rib_detail_msg(struct imsg *imsg, i - case ATTR_AGGREGATOR: - memcpy(&as, data, sizeof(as)); - memcpy(&id, data + sizeof(as), sizeof(id)); + switch (imsg->hdr.type) { + case IMSG_CTL_SHOW_RIB: + memcpy(&rib, imsg->data, sizeof(rib)); +- +- printf("\nBGP routing table entry for %s/%u\n", +- log_addr(&rib.prefix), rib.prefixlen); +- +- data = imsg->data; +- data += sizeof(struct ctl_show_rib); +- if (aspath_asprint(&aspath, data, rib.aspath_len) == -1) +- err(1, NULL); +- if (strlen(aspath) > 0) +- printf(" %s\n", aspath); +- free(aspath); +- +- s = fmt_peer(rib.descr, &rib.remote_addr, -1, nodescr); +- printf(" Nexthop %s ", log_addr(&rib.exit_nexthop)); +- printf("(via %s) from %s (", log_addr(&rib.true_nexthop), s); +- free(s); +- id.s_addr = htonl(rib.remote_id); +- printf("%s)\n", inet_ntoa(id)); +- +- printf(" Origin %s, metric %u, localpref %u, ", +- print_origin(rib.origin, 0), rib.med, rib.local_pref); +- print_flags(rib.flags, 0); +- +- now = time(NULL); +- if (now > rib.lastchange) +- now -= rib.lastchange; +- else +- now = 0; +- +- printf("\n Last update: %s ago\n", +- fmt_timeframe_core(now)); ++ asdata = imsg->data; ++ asdata += sizeof(struct ctl_show_rib); ++ show_rib_detail(&rib, asdata, nodescr); + break; + case IMSG_CTL_SHOW_RIB_ATTR: + ilen = imsg->hdr.len - IMSG_HEADER_SIZE; + if (ilen < 3) + errx(1, "bad IMSG_CTL_SHOW_RIB_ATTR received"); +- data = imsg->data; +- flags = data[0]; +- type = data[1]; +- +- /* get the attribute length */ +- if (flags & ATTR_EXTLEN) { +- if (ilen < 4) +- errx(1, "bad IMSG_CTL_SHOW_RIB_ATTR received"); +- memcpy(&alen, data+2, sizeof(u_int16_t)); +- alen = ntohs(alen); +- data += 4; +- ilen -= 4; +- } else { +- alen = data[2]; +- data += 3; +- ilen -= 3; +- } +- /* bad imsg len how can that happen!? */ +- if (alen != ilen) +- errx(1, "bad IMSG_CTL_SHOW_RIB_ATTR received"); +- +- switch (type) { +- case ATTR_COMMUNITIES: +- printf(" Communities: "); +- show_community(data, alen); +- printf("\n"); +- break; +- case ATTR_AGGREGATOR: +- memcpy(&as, data, sizeof(as)); +- memcpy(&id, data + sizeof(as), sizeof(id)); - printf(" Aggregator: %s [%s]\n", - log_as(htonl(as)), inet_ntoa(id)); -+ printf(" Aggregator: %s [%s]\n", -+ log_as(ntohl(as)), inet_ntoa(id)); - break; - case ATTR_ORIGINATOR_ID: - memcpy(&id, data, sizeof(id)); -@@ -1236,22 +1299,27 @@ fmt_mem(int64_t num) - return (buf); +- break; +- case ATTR_ORIGINATOR_ID: +- memcpy(&id, data, sizeof(id)); +- printf(" Originator Id: %s\n", inet_ntoa(id)); +- break; +- case ATTR_CLUSTER_LIST: +- printf(" Cluster ID List:"); +- for (ioff = 0; ioff + sizeof(id) <= ilen; +- ioff += sizeof(id)) { +- memcpy(&id, data + ioff, sizeof(id)); +- printf(" %s", inet_ntoa(id)); +- } +- printf("\n"); +- break; +- case ATTR_EXT_COMMUNITIES: +- printf(" Ext. communities: "); +- show_ext_community(data, alen); +- printf("\n"); +- break; +- default: +- /* ignore unknown attributes */ +- break; +- } ++ show_attr(imsg->data, ilen); + break; + case IMSG_CTL_END: + printf("\n"); +@@ -1225,67 +1272,128 @@ show_rib_detail_msg(struct imsg *imsg, i + return (0); } -+size_t pt_sizes[AID_MAX] = AID_PTSIZE; +-char * +-fmt_mem(int64_t num) ++void ++show_rib_brief(struct ctl_show_rib *r, u_char *asdata) + { +- static char buf[16]; ++ char *aspath; + +- if (fmt_scaled(num, buf) == -1) +- snprintf(buf, sizeof(buf), "%lldB", (long long)num); ++ print_prefix(&r->prefix, r->prefixlen, r->flags); ++ printf(" %-15s ", log_addr(&r->exit_nexthop)); ++ printf(" %5u %5u ", r->local_pref, r->med); + +- return (buf); ++ if (aspath_asprint(&aspath, asdata, r->aspath_len) == -1) ++ err(1, NULL); ++ if (strlen(aspath) > 0) ++ printf("%s ", aspath); ++ free(aspath); + - int - show_rib_memory_msg(struct imsg *imsg) ++ printf("%s\n", print_origin(r->origin, 1)); + } + +-int +-show_rib_memory_msg(struct imsg *imsg) ++void ++show_rib_detail(struct ctl_show_rib *r, u_char *asdata, int nodescr) { - struct rde_memstats stats; -+ size_t pts = 0; -+ int i; +- struct rde_memstats stats; ++ struct in_addr id; ++ char *aspath, *s; ++ time_t now; - switch (imsg->hdr.type) { - case IMSG_CTL_SHOW_RIB_MEM: - memcpy(&stats, imsg->data, sizeof(stats)); - printf("RDE memory statistics\n"); +- switch (imsg->hdr.type) { +- case IMSG_CTL_SHOW_RIB_MEM: +- memcpy(&stats, imsg->data, sizeof(stats)); +- printf("RDE memory statistics\n"); - printf("%10lld IPv4 network entries using %s of memory\n", - (long long)stats.pt4_cnt, fmt_mem(stats.pt4_cnt * - sizeof(struct pt_entry4))); @@ -727,29 +1052,137 @@ diff -u -p -r1.1.1.7 -r1.8 - printf("%10lld IPv6 network entries using " - "%s of memory\n", (long long)stats.pt6_cnt, - fmt_mem(stats.pt6_cnt * sizeof(struct pt_entry6))); -+ for (i = 0; i < AID_MAX; i++) { -+ if (stats.pt_cnt[i] == 0) -+ continue; -+ pts += stats.pt_cnt[i] * pt_sizes[i]; -+ printf("%10lld %s network entries using %s of memory\n", -+ (long long)stats.pt_cnt[i], aid_vals[i].name, -+ fmt_mem(stats.pt_cnt[i] * pt_sizes[i])); -+ } - printf("%10lld rib entries using %s of memory\n", - (long long)stats.rib_cnt, fmt_mem(stats.rib_cnt * - sizeof(struct rib_entry))); -@@ -1272,9 +1340,7 @@ show_rib_memory_msg(struct imsg *imsg) - (long long)stats.attr_refs); - printf("%10lld BGP attributes using %s of memory\n", - (long long)stats.attr_dcnt, fmt_mem(stats.attr_data)); +- printf("%10lld rib entries using %s of memory\n", +- (long long)stats.rib_cnt, fmt_mem(stats.rib_cnt * +- sizeof(struct rib_entry))); +- printf("%10lld prefix entries using %s of memory\n", +- (long long)stats.prefix_cnt, fmt_mem(stats.prefix_cnt * +- sizeof(struct prefix))); +- printf("%10lld BGP path attribute entries using %s of memory\n", +- (long long)stats.path_cnt, fmt_mem(stats.path_cnt * +- sizeof(struct rde_aspath))); +- printf("%10lld BGP AS-PATH attribute entries using " +- "%s of memory,\n\t and holding %lld references\n", +- (long long)stats.aspath_cnt, fmt_mem(stats.aspath_size), +- (long long)stats.aspath_refs); +- printf("%10lld BGP attributes entries using %s of memory\n", +- (long long)stats.attr_cnt, fmt_mem(stats.attr_cnt * +- sizeof(struct attr))); +- printf("\t and holding %lld references\n", +- (long long)stats.attr_refs); +- printf("%10lld BGP attributes using %s of memory\n", +- (long long)stats.attr_dcnt, fmt_mem(stats.attr_data)); - printf("RIB using %s of memory\n", fmt_mem( - stats.pt4_cnt * sizeof(struct pt_entry4) + - stats.pt6_cnt * sizeof(struct pt_entry6) + -+ printf("RIB using %s of memory\n", fmt_mem(pts + - stats.prefix_cnt * sizeof(struct prefix) + - stats.rib_cnt * sizeof(struct rib_entry) + - stats.path_cnt * sizeof(struct rde_aspath) + -@@ -1328,30 +1394,6 @@ show_community(u_char *data, u_int16_t l +- stats.prefix_cnt * sizeof(struct prefix) + +- stats.rib_cnt * sizeof(struct rib_entry) + +- stats.path_cnt * sizeof(struct rde_aspath) + +- stats.aspath_size + stats.attr_cnt * sizeof(struct attr) + +- stats.attr_data)); ++ printf("\nBGP routing table entry for %s/%u\n", ++ log_addr(&r->prefix), r->prefixlen); ++ ++ if (aspath_asprint(&aspath, asdata, r->aspath_len) == -1) ++ err(1, NULL); ++ if (strlen(aspath) > 0) ++ printf(" %s\n", aspath); ++ free(aspath); ++ ++ s = fmt_peer(r->descr, &r->remote_addr, -1, nodescr); ++ printf(" Nexthop %s ", log_addr(&r->exit_nexthop)); ++ printf("(via %s) from %s (", log_addr(&r->true_nexthop), s); ++ free(s); ++ id.s_addr = htonl(r->remote_id); ++ printf("%s)\n", inet_ntoa(id)); ++ ++ printf(" Origin %s, metric %u, localpref %u, weight %u, ", ++ print_origin(r->origin, 0), r->med, r->local_pref, r->weight); ++ print_flags(r->flags, 0); ++ ++ now = time(NULL); ++ if (now > r->lastchange) ++ now -= r->lastchange; ++ else ++ now = 0; ++ ++ printf("\n Last update: %s ago\n", fmt_timeframe_core(now)); ++} ++ ++void ++show_attr(void *b, u_int16_t len) ++{ ++ char *data = b; ++ struct in_addr id; ++ u_int32_t as; ++ u_int16_t alen, ioff; ++ u_int8_t flags, type; ++ ++ data = b; ++ if (len < 3) ++ errx(1, "show_attr: too short bgp attr"); ++ ++ flags = data[0]; ++ type = data[1]; ++ ++ /* get the attribute length */ ++ if (flags & ATTR_EXTLEN) { ++ if (len < 4) ++ errx(1, "show_attr: too short bgp attr"); ++ memcpy(&alen, data+2, sizeof(u_int16_t)); ++ alen = ntohs(alen); ++ data += 4; ++ len -= 4; ++ } else { ++ alen = data[2]; ++ data += 3; ++ len -= 3; ++ } ++ ++ /* bad imsg len how can that happen!? */ ++ if (alen > len) ++ errx(1, "show_attr: bad length"); ++ ++ switch (type) { ++ case ATTR_COMMUNITIES: ++ printf(" Communities: "); ++ show_community(data, alen); ++ printf("\n"); ++ break; ++ case ATTR_AGGREGATOR: ++ memcpy(&as, data, sizeof(as)); ++ memcpy(&id, data + sizeof(as), sizeof(id)); ++ printf(" Aggregator: %s [%s]\n", ++ log_as(ntohl(as)), inet_ntoa(id)); ++ break; ++ case ATTR_ORIGINATOR_ID: ++ memcpy(&id, data, sizeof(id)); ++ printf(" Originator Id: %s\n", inet_ntoa(id)); ++ break; ++ case ATTR_CLUSTER_LIST: ++ printf(" Cluster ID List:"); ++ for (ioff = 0; ioff + sizeof(id) <= alen; ++ ioff += sizeof(id)) { ++ memcpy(&id, data + ioff, sizeof(id)); ++ printf(" %s", inet_ntoa(id)); ++ } ++ printf("\n"); ++ break; ++ case ATTR_EXT_COMMUNITIES: ++ printf(" Ext. communities: "); ++ show_ext_community(data, alen); ++ printf("\n"); + break; + default: ++ /* ignore unknown attributes */ + break; + } +- +- return (1); + } + + void +@@ -1328,30 +1436,6 @@ show_community(u_char *data, u_int16_t l } } @@ -780,7 +1213,7 @@ diff -u -p -r1.1.1.7 -r1.8 void show_ext_community(u_char *data, u_int16_t len) { -@@ -1372,28 +1414,29 @@ show_ext_community(u_char *data, u_int16 +@@ -1372,34 +1456,101 @@ show_ext_community(u_char *data, u_int16 case EXT_COMMUNITY_TWO_AS: memcpy(&as2, data + i + 2, sizeof(as2)); memcpy(&u32, data + i + 4, sizeof(u32)); @@ -808,12 +1241,278 @@ diff -u -p -r1.1.1.7 -r1.8 memcpy(&ext, data + i, sizeof(ext)); ext = betoh64(ext) & 0xffffffffffffLL; - printf("%s 0x%llx", get_ext_subtype(subtype), ext); -+ printf("%s 0x%llx", log_ext_subtype(subtype), ext); ++ printf("%s 0x%" PRIx64, log_ext_subtype(subtype), ext); break; default: memcpy(&ext, data + i, sizeof(ext)); - printf("0x%llx", betoh64(ext)); -+ printf("0x%llx", betoh64(ext)); ++ printf("0x%" PRIx64, betoh64(ext)); } if (i + 8 < len) printf(", "); + } + } + ++char * ++fmt_mem(int64_t num) ++{ ++ static char buf[16]; ++ ++ if (fmt_scaled(num, buf) == -1) ++ snprintf(buf, sizeof(buf), "%lldB", (long long)num); ++ ++ return (buf); ++} ++ ++size_t pt_sizes[AID_MAX] = AID_PTSIZE; ++ ++int ++show_rib_memory_msg(struct imsg *imsg) ++{ ++ struct rde_memstats stats; ++ size_t pts = 0; ++ int i; ++ ++ switch (imsg->hdr.type) { ++ case IMSG_CTL_SHOW_RIB_MEM: ++ memcpy(&stats, imsg->data, sizeof(stats)); ++ printf("RDE memory statistics\n"); ++ for (i = 0; i < AID_MAX; i++) { ++ if (stats.pt_cnt[i] == 0) ++ continue; ++ pts += stats.pt_cnt[i] * pt_sizes[i]; ++ printf("%10lld %s network entries using %s of memory\n", ++ (long long)stats.pt_cnt[i], aid_vals[i].name, ++ fmt_mem(stats.pt_cnt[i] * pt_sizes[i])); ++ } ++ printf("%10lld rib entries using %s of memory\n", ++ (long long)stats.rib_cnt, fmt_mem(stats.rib_cnt * ++ sizeof(struct rib_entry))); ++ printf("%10lld prefix entries using %s of memory\n", ++ (long long)stats.prefix_cnt, fmt_mem(stats.prefix_cnt * ++ sizeof(struct prefix))); ++ printf("%10lld BGP path attribute entries using %s of memory\n", ++ (long long)stats.path_cnt, fmt_mem(stats.path_cnt * ++ sizeof(struct rde_aspath))); ++ printf("%10lld BGP AS-PATH attribute entries using " ++ "%s of memory,\n\t and holding %lld references\n", ++ (long long)stats.aspath_cnt, fmt_mem(stats.aspath_size), ++ (long long)stats.aspath_refs); ++ printf("%10lld BGP attributes entries using %s of memory\n", ++ (long long)stats.attr_cnt, fmt_mem(stats.attr_cnt * ++ sizeof(struct attr))); ++ printf("\t and holding %lld references\n", ++ (long long)stats.attr_refs); ++ printf("%10lld BGP attributes using %s of memory\n", ++ (long long)stats.attr_dcnt, fmt_mem(stats.attr_data)); ++ printf("RIB using %s of memory\n", fmt_mem(pts + ++ stats.prefix_cnt * sizeof(struct prefix) + ++ stats.rib_cnt * sizeof(struct rib_entry) + ++ stats.path_cnt * sizeof(struct rde_aspath) + ++ stats.aspath_size + stats.attr_cnt * sizeof(struct attr) + ++ stats.attr_data)); ++ break; ++ default: ++ break; ++ } ++ ++ return (1); ++} ++ + void + send_filterset(struct imsgbuf *i, struct filter_set_head *set) + { +@@ -1469,6 +1620,183 @@ show_result(struct imsg *imsg) + return (1); + } + ++void ++show_mrt_dump(struct mrt_rib *mr, struct mrt_peer *mp, void *arg) ++{ ++ struct ctl_show_rib ctl; ++ struct ctl_show_rib_request *req = arg; ++ struct mrt_rib_entry *mre; ++ u_int16_t i, j; ++ ++ for (i = 0; i < mr->nentries; i++) { ++ mre = &mr->entries[i]; ++ bzero(&ctl, sizeof(ctl)); ++ mrt_to_bgpd_addr(&mr->prefix, &ctl.prefix); ++ ctl.prefixlen = mr->prefixlen; ++ ctl.lastchange = mre->originated; ++ mrt_to_bgpd_addr(&mre->nexthop, &ctl.true_nexthop); ++ mrt_to_bgpd_addr(&mre->nexthop, &ctl.exit_nexthop); ++ ctl.origin = mre->origin; ++ ctl.local_pref = mre->local_pref; ++ ctl.med = mre->med; ++ /* weight is not part of the mrt dump so it can't be set */ ++ ctl.aspath_len = mre->aspath_len; ++ ++ if (mre->peer_idx < mp->npeers) { ++ mrt_to_bgpd_addr(&mp->peers[mre->peer_idx].addr, ++ &ctl.remote_addr); ++ ctl.remote_id = mp->peers[mre->peer_idx].bgp_id; ++ } ++ ++ /* filter by neighbor */ ++ if (req->neighbor.addr.aid != AID_UNSPEC && ++ memcmp(&req->neighbor.addr, &ctl.remote_addr, ++ sizeof(ctl.remote_addr)) != 0) ++ continue; ++ /* filter by AF */ ++ if (req->aid && req->aid != ctl.prefix.aid) ++ return; ++ /* filter by prefix */ ++ if (req->prefix.aid != AID_UNSPEC) { ++ if (!prefix_compare(&req->prefix, &ctl.prefix, ++ req->prefixlen)) { ++ if (req->flags & F_LONGER) { ++ if (req->prefixlen > ctl.prefixlen) ++ return; ++ } else if (req->prefixlen != ctl.prefixlen) ++ return; ++ } else ++ return; ++ } ++ /* filter by AS */ ++ if (req->as.type != AS_NONE && ++ !aspath_match(mre->aspath, mre->aspath_len, ++ req->as.type, req->as.as)) ++ continue; ++ ++ if (req->flags & F_CTL_DETAIL) { ++ show_rib_detail(&ctl, mre->aspath, 1); ++ for (j = 0; j < mre->nattrs; j++) ++ show_attr(mre->attrs[j].attr, ++ mre->attrs[j].attr_len); ++ } else ++ show_rib_brief(&ctl, mre->aspath); ++ } ++} ++ ++void ++network_mrt_dump(struct mrt_rib *mr, struct mrt_peer *mp, void *arg) ++{ ++ struct ctl_show_rib ctl; ++ struct network_config net; ++ struct ctl_show_rib_request *req = arg; ++ struct mrt_rib_entry *mre; ++ struct ibuf *msg; ++ u_int16_t i, j; ++ ++ for (i = 0; i < mr->nentries; i++) { ++ mre = &mr->entries[i]; ++ bzero(&ctl, sizeof(ctl)); ++ mrt_to_bgpd_addr(&mr->prefix, &ctl.prefix); ++ ctl.prefixlen = mr->prefixlen; ++ ctl.lastchange = mre->originated; ++ mrt_to_bgpd_addr(&mre->nexthop, &ctl.true_nexthop); ++ mrt_to_bgpd_addr(&mre->nexthop, &ctl.exit_nexthop); ++ ctl.origin = mre->origin; ++ ctl.local_pref = mre->local_pref; ++ ctl.med = mre->med; ++ ctl.aspath_len = mre->aspath_len; ++ ++ if (mre->peer_idx < mp->npeers) { ++ mrt_to_bgpd_addr(&mp->peers[mre->peer_idx].addr, ++ &ctl.remote_addr); ++ ctl.remote_id = mp->peers[mre->peer_idx].bgp_id; ++ } ++ ++ /* filter by neighbor */ ++ if (req->neighbor.addr.aid != AID_UNSPEC && ++ memcmp(&req->neighbor.addr, &ctl.remote_addr, ++ sizeof(ctl.remote_addr)) != 0) ++ continue; ++ /* filter by AF */ ++ if (req->aid && req->aid != ctl.prefix.aid) ++ return; ++ /* filter by prefix */ ++ if (req->prefix.aid != AID_UNSPEC) { ++ if (!prefix_compare(&req->prefix, &ctl.prefix, ++ req->prefixlen)) { ++ if (req->flags & F_LONGER) { ++ if (req->prefixlen > ctl.prefixlen) ++ return; ++ } else if (req->prefixlen != ctl.prefixlen) ++ return; ++ } else ++ return; ++ } ++ /* filter by AS */ ++ if (req->as.type != AS_NONE && ++ !aspath_match(mre->aspath, mre->aspath_len, ++ req->as.type, req->as.as)) ++ continue; ++ ++ bzero(&net, sizeof(net)); ++ memcpy(&net.prefix, &ctl.prefix, sizeof(net.prefix)); ++ net.prefixlen = ctl.prefixlen; ++ net.type = NETWORK_MRTCLONE; ++ /* XXX rtableid */ ++ ++ imsg_compose(ibuf, IMSG_NETWORK_ADD, 0, 0, -1, ++ &net, sizeof(net)); ++ if ((msg = imsg_create(ibuf, IMSG_NETWORK_ASPATH, ++ 0, 0, sizeof(ctl) + mre->aspath_len)) == NULL) ++ errx(1, "imsg_create failure"); ++ if (imsg_add(msg, &ctl, sizeof(ctl)) == -1 || ++ imsg_add(msg, mre->aspath, mre->aspath_len) == -1) ++ errx(1, "imsg_add failure"); ++ imsg_close(ibuf, msg); ++ for (j = 0; j < mre->nattrs; j++) ++ imsg_compose(ibuf, IMSG_NETWORK_ATTR, 0, 0, -1, ++ mre->attrs[j].attr, mre->attrs[j].attr_len); ++ imsg_compose(ibuf, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0); ++ ++ while (ibuf->w.queued) { ++ if (msgbuf_write(&ibuf->w) < 0) ++ err(1, "write error"); ++ } ++ } ++} ++ ++void ++show_mrt_state(struct mrt_bgp_state *ms, void *arg) ++{ ++ printf("show_mrt_state\n"); ++} ++ ++void ++show_mrt_msg(struct mrt_bgp_msg *mm, void *arg) ++{ ++ printf("show_mrt_msg\n"); ++} ++ ++void ++mrt_to_bgpd_addr(union mrt_addr *ma, struct bgpd_addr *ba) ++{ ++ switch (ma->sa.sa_family) { ++ case AF_INET: ++ case AF_INET6: ++ sa2addr(&ma->sa, ba); ++ break; ++ case AF_VPNv4: ++ bzero(ba, sizeof(*ba)); ++ ba->aid = AID_VPN_IPv4; ++ ba->vpn4.rd = ma->svpn4.sv_rd; ++ ba->vpn4.addr.s_addr = ma->svpn4.sv_addr.s_addr; ++ memcpy(ba->vpn4.labelstack, ma->svpn4.sv_label, ++ sizeof(ba->vpn4.labelstack)); ++ break; ++ } ++} ++ + /* following functions are necessary for imsg framework */ + void + log_warnx(const char *emsg, ...) +@@ -1495,3 +1823,9 @@ fatal(const char *emsg) + { + err(1, emsg); + } ++ ++void ++fatalx(const char *emsg) ++{ ++ errx(1, emsg); ++} diff --git a/net/openbgpd/files/patch-bgpctl_irr_asset.c b/net/openbgpd/files/patch-bgpctl_irr_asset.c new file mode 100644 index 000000000000..cf0e4a449c66 --- /dev/null +++ b/net/openbgpd/files/patch-bgpctl_irr_asset.c @@ -0,0 +1,14 @@ +Index: bgpctl/irr_asset.c +=================================================================== +RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_asset.c,v +retrieving revision 1.1.1.2 +retrieving revision 1.1.1.3 +diff -u -p -r1.1.1.2 -r1.1.1.3 +--- bgpctl/irr_asset.c 9 Jul 2009 16:49:55 -0000 1.1.1.2 ++++ bgpctl/irr_asset.c 13 Oct 2012 18:22:52 -0000 1.1.1.3 +@@ -1,4 +1,4 @@ +-/* $OpenBSD: irr_asset.c,v 1.8 2009/04/14 21:10:54 jj Exp $ */ ++/* $OpenBSD: irr_asset.c,v 1.7 2007/03/31 12:46:55 henning Exp $ */ + + /* + * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> diff --git a/net/openbgpd/files/patch-bgpctl_irr_output.c b/net/openbgpd/files/patch-bgpctl_irr_output.c new file mode 100644 index 000000000000..b611216c1928 --- /dev/null +++ b/net/openbgpd/files/patch-bgpctl_irr_output.c @@ -0,0 +1,14 @@ +Index: bgpctl/irr_output.c +=================================================================== +RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_output.c,v +retrieving revision 1.1.1.1 +retrieving revision 1.1.1.2 +diff -u -p -r1.1.1.1 -r1.1.1.2 +--- bgpctl/irr_output.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 ++++ bgpctl/irr_output.c 13 Oct 2012 18:22:52 -0000 1.1.1.2 +@@ -1,4 +1,4 @@ +-/* $OpenBSD: irr_output.c,v 1.13 2007/03/05 17:28:21 henning Exp $ */ ++/* $OpenBSD: irr_output.c,v 1.12 2007/03/05 15:02:05 henning Exp $ */ + + /* + * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> diff --git a/net/openbgpd/files/patch-bgpctl_irr_parser.c b/net/openbgpd/files/patch-bgpctl_irr_parser.c index af140f8b0f82..2e445ea37809 100644 --- a/net/openbgpd/files/patch-bgpctl_irr_parser.c +++ b/net/openbgpd/files/patch-bgpctl_irr_parser.c @@ -2,10 +2,10 @@ Index: bgpctl/irr_parser.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_parser.c,v retrieving revision 1.1.1.5 -retrieving revision 1.4 -diff -u -p -r1.1.1.5 -r1.4 +retrieving revision 1.5 +diff -u -p -r1.1.1.5 -r1.5 --- bgpctl/irr_parser.c 14 Feb 2010 20:20:14 -0000 1.1.1.5 -+++ bgpctl/irr_parser.c 4 Feb 2010 16:22:26 -0000 1.4 ++++ bgpctl/irr_parser.c 13 Oct 2012 18:35:56 -0000 1.5 @@ -1,4 +1,4 @@ -/* $OpenBSD: irr_parser.c,v 1.8 2007/03/05 22:34:08 henning Exp $ */ +/* $OpenBSD: irr_parser.c,v 1.9 2009/09/08 15:40:25 claudio Exp $ */ @@ -29,7 +29,7 @@ diff -u -p -r1.1.1.5 -r1.4 &errstr); if (errstr) errx(1, "peering spec \"%s\": format " -@@ -407,7 +408,8 @@ parse_asset(char *key, char *val) +@@ -407,11 +408,13 @@ parse_asset(char *key, char *val) int parse_route(char *key, char *val) { @@ -38,4 +38,11 @@ diff -u -p -r1.1.1.5 -r1.4 + /* ignore everything else */ return (0); - /* route is single-value, but seen trailing , in the wild */ +- /* route is single-value, but seen trailing , in the wild */ +- if (strlen(val) > 0 && val[strlen(val) - 1] == ',') ++ /* route is single-value, but seen trailing , and \r in the wild */ ++ if (strlen(val) > 0 && (val[strlen(val) - 1] == ',' || ++ val[strlen(val) - 1] == '\r')) + val[strlen(val) - 1] = '\0'; + + return (prefixset_addmember(val)); diff --git a/net/openbgpd/files/patch-bgpctl_irr_prefix.c b/net/openbgpd/files/patch-bgpctl_irr_prefix.c index da541297f183..4c97de2a4c7d 100644 --- a/net/openbgpd/files/patch-bgpctl_irr_prefix.c +++ b/net/openbgpd/files/patch-bgpctl_irr_prefix.c @@ -2,13 +2,13 @@ Index: bgpctl/irr_prefix.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_prefix.c,v retrieving revision 1.1.1.5 -retrieving revision 1.1.1.7 -diff -u -p -r1.1.1.5 -r1.1.1.7 +retrieving revision 1.1.1.8 +diff -u -p -r1.1.1.5 -r1.1.1.8 --- bgpctl/irr_prefix.c 14 Feb 2010 20:20:14 -0000 1.1.1.5 -+++ bgpctl/irr_prefix.c 12 Jun 2011 10:44:54 -0000 1.1.1.7 ++++ bgpctl/irr_prefix.c 13 Oct 2012 18:22:52 -0000 1.1.1.8 @@ -1,4 +1,4 @@ -/* $OpenBSD: irr_prefix.c,v 1.15 2007/05/27 18:54:25 henning Exp $ */ -+/* $OpenBSD: irr_prefix.c,v 1.18 2010/05/10 02:00:50 krw Exp $ */ ++/* $OpenBSD: irr_prefix.c,v 1.17 2009/09/08 16:11:36 sthen Exp $ */ /* * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> diff --git a/net/openbgpd/files/patch-bgpctl_irrfilter.c b/net/openbgpd/files/patch-bgpctl_irrfilter.c index 458351db3f29..79c31fc722aa 100644 --- a/net/openbgpd/files/patch-bgpctl_irrfilter.c +++ b/net/openbgpd/files/patch-bgpctl_irrfilter.c @@ -2,10 +2,16 @@ Index: bgpctl/irrfilter.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irrfilter.c,v retrieving revision 1.1.1.1 -retrieving revision 1.2 -diff -u -p -r1.1.1.1 -r1.2 +retrieving revision 1.3 +diff -u -p -r1.1.1.1 -r1.3 --- bgpctl/irrfilter.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpctl/irrfilter.c 30 Jun 2009 06:40:06 -0000 1.2 ++++ bgpctl/irrfilter.c 13 Oct 2012 18:35:56 -0000 1.3 +@@ -1,4 +1,4 @@ +-/* $OpenBSD: irrfilter.c,v 1.4 2007/05/28 23:31:53 henning Exp $ */ ++/* $OpenBSD: irrfilter.c,v 1.3 2007/03/06 16:45:34 henning Exp $ */ + + /* + * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> @@ -15,6 +15,9 @@ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/net/openbgpd/files/patch-bgpctl_irrfilter.h b/net/openbgpd/files/patch-bgpctl_irrfilter.h index cc9b1df0799a..485b97320e58 100644 --- a/net/openbgpd/files/patch-bgpctl_irrfilter.h +++ b/net/openbgpd/files/patch-bgpctl_irrfilter.h @@ -2,13 +2,13 @@ Index: bgpctl/irrfilter.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irrfilter.h,v retrieving revision 1.1.1.5 -retrieving revision 1.3 -diff -u -p -r1.1.1.5 -r1.3 +retrieving revision 1.4 +diff -u -p -r1.1.1.5 -r1.4 --- bgpctl/irrfilter.h 14 Feb 2010 20:20:14 -0000 1.1.1.5 -+++ bgpctl/irrfilter.h 4 Feb 2010 16:22:26 -0000 1.3 ++++ bgpctl/irrfilter.h 13 Oct 2012 18:35:56 -0000 1.4 @@ -1,4 +1,4 @@ -/* $OpenBSD: irrfilter.h,v 1.7 2007/03/06 16:45:34 henning Exp $ */ -+/* $OpenBSD: irrfilter.h,v 1.9 2009/09/08 16:11:36 sthen Exp $ */ ++/* $OpenBSD: irrfilter.h,v 1.8 2009/09/08 15:40:25 claudio Exp $ */ /* * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> diff --git a/net/openbgpd/files/patch-bgpctl_mrtparser.c b/net/openbgpd/files/patch-bgpctl_mrtparser.c new file mode 100644 index 000000000000..0d463c0064ef --- /dev/null +++ b/net/openbgpd/files/patch-bgpctl_mrtparser.c @@ -0,0 +1,977 @@ +Index: bgpctl/mrtparser.c +=================================================================== +RCS file: bgpctl/mrtparser.c +diff -N bgpctl/mrtparser.c +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ bgpctl/mrtparser.c 13 Oct 2012 18:22:53 -0000 1.1.1.1 +@@ -0,0 +1,970 @@ ++/* $OpenBSD: mrtparser.c,v 1.2 2012/03/06 07:52:32 claudio Exp $ */ ++/* ++ * Copyright (c) 2011 Claudio Jeker <claudio@openbsd.org> ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include <sys/types.h> ++#include <sys/socket.h> ++#include <netinet/in.h> ++#include <err.h> ++#include <errno.h> ++#include <limits.h> ++#include <stdlib.h> ++#include <stdio.h> ++#include <string.h> ++#include <unistd.h> ++ ++#include "mrt.h" ++#include "mrtparser.h" ++ ++void *mrt_read_msg(int, struct mrt_hdr *); ++size_t mrt_read_buf(int, void *, size_t); ++ ++struct mrt_peer *mrt_parse_v2_peer(struct mrt_hdr *, void *); ++struct mrt_rib *mrt_parse_v2_rib(struct mrt_hdr *, void *); ++int mrt_parse_dump(struct mrt_hdr *, void *, struct mrt_peer **, ++ struct mrt_rib **); ++int mrt_parse_dump_mp(struct mrt_hdr *, void *, struct mrt_peer **, ++ struct mrt_rib **); ++int mrt_extract_attr(struct mrt_rib_entry *, u_char *, int, sa_family_t, ++ int); ++ ++void mrt_free_peers(struct mrt_peer *); ++void mrt_free_rib(struct mrt_rib *); ++void mrt_free_bgp_state(struct mrt_bgp_state *); ++void mrt_free_bgp_msg(struct mrt_bgp_msg *); ++ ++u_char *mrt_aspath_inflate(void *, u_int16_t, u_int16_t *); ++int mrt_extract_addr(void *, u_int, union mrt_addr *, sa_family_t); ++ ++void * ++mrt_read_msg(int fd, struct mrt_hdr *hdr) ++{ ++ void *buf; ++ ++ bzero(hdr, sizeof(*hdr)); ++ if (mrt_read_buf(fd, hdr, sizeof(*hdr)) != sizeof(*hdr)) ++ return (NULL); ++ ++ if ((buf = malloc(ntohl(hdr->length))) == NULL) ++ err(1, "malloc(%d)", hdr->length); ++ ++ if (mrt_read_buf(fd, buf, ntohl(hdr->length)) != ntohl(hdr->length)) { ++ free(buf); ++ return (NULL); ++ } ++ return (buf); ++} ++ ++size_t ++mrt_read_buf(int fd, void *buf, size_t len) ++{ ++ char *b = buf; ++ ssize_t n; ++ ++ while (len > 0) { ++ if ((n = read(fd, b, len)) == -1) { ++ if (errno == EINTR) ++ continue; ++ err(1, "read"); ++ } ++ if (n == 0) ++ break; ++ b += n; ++ len -= n; ++ } ++ ++ return (b - (char *)buf); ++} ++ ++void ++mrt_parse(int fd, struct mrt_parser *p, int verbose) ++{ ++ struct mrt_hdr h; ++ struct mrt_peer *pctx = NULL; ++ struct mrt_rib *r; ++ void *msg; ++ ++ while ((msg = mrt_read_msg(fd, &h))) { ++ switch (ntohs(h.type)) { ++ case MSG_NULL: ++ case MSG_START: ++ case MSG_DIE: ++ case MSG_I_AM_DEAD: ++ case MSG_PEER_DOWN: ++ case MSG_PROTOCOL_BGP: ++ case MSG_PROTOCOL_IDRP: ++ case MSG_PROTOCOL_BGP4PLUS: ++ case MSG_PROTOCOL_BGP4PLUS1: ++ if (verbose) ++ printf("deprecated MRT type %d\n", ++ ntohs(h.type)); ++ break; ++ case MSG_PROTOCOL_RIP: ++ case MSG_PROTOCOL_RIPNG: ++ case MSG_PROTOCOL_OSPF: ++ case MSG_PROTOCOL_ISIS_ET: ++ case MSG_PROTOCOL_ISIS: ++ case MSG_PROTOCOL_OSPFV3_ET: ++ case MSG_PROTOCOL_OSPFV3: ++ if (verbose) ++ printf("unsuported MRT type %d\n", ++ ntohs(h.type)); ++ break; ++ case MSG_TABLE_DUMP: ++ switch (ntohs(h.subtype)) { ++ case MRT_DUMP_AFI_IP: ++ case MRT_DUMP_AFI_IPv6: ++ if (p->dump == NULL) ++ break; ++ if (mrt_parse_dump(&h, msg, &pctx, &r) == 0) { ++ p->dump(r, pctx, p->arg); ++ mrt_free_rib(r); ++ } ++ break; ++ default: ++ if (verbose) ++ printf("unknown AFI %d in table dump\n", ++ ntohs(h.subtype)); ++ break; ++ } ++ break; ++ case MSG_TABLE_DUMP_V2: ++ switch (ntohs(h.subtype)) { ++ case MRT_DUMP_V2_PEER_INDEX_TABLE: ++ if (p->dump == NULL) ++ break; ++ if (pctx) ++ mrt_free_peers(pctx); ++ pctx = mrt_parse_v2_peer(&h, msg); ++ break; ++ case MRT_DUMP_V2_RIB_IPV4_UNICAST: ++ case MRT_DUMP_V2_RIB_IPV4_MULTICAST: ++ case MRT_DUMP_V2_RIB_IPV6_UNICAST: ++ case MRT_DUMP_V2_RIB_IPV6_MULTICAST: ++ case MRT_DUMP_V2_RIB_GENERIC: ++ if (p->dump == NULL) ++ break; ++ r = mrt_parse_v2_rib(&h, msg); ++ if (r) { ++ p->dump(r, pctx, p->arg); ++ mrt_free_rib(r); ++ } ++ break; ++ default: ++ if (verbose) ++ printf("unhandled BGP4MP subtype %d\n", ++ ntohs(h.subtype)); ++ break; ++ } ++ break; ++ case MSG_PROTOCOL_BGP4MP_ET: ++ /* currently just ignore the microsec field */ ++ msg = (char *)msg + sizeof(u_int32_t); ++ h.length -= sizeof(u_int32_t); ++ /* FALLTHROUGH */ ++ case MSG_PROTOCOL_BGP4MP: ++ switch (ntohs(h.subtype)) { ++ case BGP4MP_STATE_CHANGE: ++ case BGP4MP_STATE_CHANGE_AS4: ++ /* XXX p->state(s, p->arg); */ ++ errx(1, "BGP4MP subtype not yet implemented"); ++ break; ++ case BGP4MP_MESSAGE: ++ case BGP4MP_MESSAGE_AS4: ++ case BGP4MP_MESSAGE_LOCAL: ++ case BGP4MP_MESSAGE_AS4_LOCAL: ++ /* XXX p->message(m, p->arg); */ ++ errx(1, "BGP4MP subtype not yet implemented"); ++ break; ++ case BGP4MP_ENTRY: ++ if (p->dump == NULL) ++ break; ++ if (mrt_parse_dump_mp(&h, msg, &pctx, &r) == ++ 0) { ++ p->dump(r, pctx, p->arg); ++ mrt_free_rib(r); ++ } ++ break; ++ default: ++ if (verbose) ++ printf("unhandled BGP4MP subtype %d\n", ++ ntohs(h.subtype)); ++ break; ++ } ++ break; ++ default: ++ if (verbose) ++ printf("unknown MRT type %d\n", ntohs(h.type)); ++ break; ++ } ++ free(msg); ++ } ++ if (pctx) ++ mrt_free_peers(pctx); ++} ++ ++struct mrt_peer * ++mrt_parse_v2_peer(struct mrt_hdr *hdr, void *msg) ++{ ++ struct mrt_peer_entry *peers; ++ struct mrt_peer *p; ++ u_int8_t *b = msg; ++ u_int32_t bid, as4; ++ u_int16_t cnt, i, as2; ++ u_int len = ntohl(hdr->length); ++ ++ if (len < 8) /* min msg size */ ++ return NULL; ++ ++ p = calloc(1, sizeof(struct mrt_peer)); ++ if (p == NULL) ++ err(1, "calloc"); ++ ++ /* collector bgp id */ ++ memcpy(&bid, b, sizeof(bid)); ++ b += sizeof(bid); ++ len -= sizeof(bid); ++ p->bgp_id = ntohl(bid); ++ ++ /* view name length */ ++ memcpy(&cnt, b, sizeof(cnt)); ++ b += sizeof(cnt); ++ len -= sizeof(cnt); ++ cnt = ntohs(cnt); ++ ++ /* view name */ ++ if (cnt > len) ++ goto fail; ++ if (cnt != 0) { ++ if ((p->view = malloc(cnt + 1)) == NULL) ++ err(1, "malloc"); ++ memcpy(p->view, b, cnt); ++ p->view[cnt] = 0; ++ } else ++ if ((p->view = strdup("")) == NULL) ++ err(1, "strdup"); ++ b += cnt; ++ len -= cnt; ++ ++ /* peer_count */ ++ if (len < sizeof(cnt)) ++ goto fail; ++ memcpy(&cnt, b, sizeof(cnt)); ++ b += sizeof(cnt); ++ len -= sizeof(cnt); ++ cnt = ntohs(cnt); ++ ++ /* peer entries */ ++ if ((peers = calloc(cnt, sizeof(struct mrt_peer_entry))) == NULL) ++ err(1, "calloc"); ++ for (i = 0; i < cnt; i++) { ++ u_int8_t type; ++ ++ if (len < sizeof(u_int8_t) + sizeof(u_int32_t)) ++ goto fail; ++ type = *b++; ++ len -= 1; ++ memcpy(&bid, b, sizeof(bid)); ++ b += sizeof(bid); ++ len -= sizeof(bid); ++ peers[i].bgp_id = ntohl(bid); ++ ++ if (type & MRT_DUMP_V2_PEER_BIT_I) { ++ if (mrt_extract_addr(b, len, &peers[i].addr, ++ AF_INET6) == -1) ++ goto fail; ++ b += sizeof(struct in6_addr); ++ len -= sizeof(struct in6_addr); ++ } else { ++ if (mrt_extract_addr(b, len, &peers[i].addr, ++ AF_INET) == -1) ++ goto fail; ++ b += sizeof(struct in_addr); ++ len -= sizeof(struct in_addr); ++ } ++ ++ if (type & MRT_DUMP_V2_PEER_BIT_A) { ++ memcpy(&as4, b, sizeof(as4)); ++ b += sizeof(as4); ++ len -= sizeof(as4); ++ as4 = ntohl(as4); ++ } else { ++ memcpy(&as2, b, sizeof(as2)); ++ b += sizeof(as2); ++ len -= sizeof(as2); ++ as4 = ntohs(as2); ++ } ++ peers[i].asnum = as4; ++ } ++ p->peers = peers; ++ p->npeers = cnt; ++ return (p); ++fail: ++ mrt_free_peers(p); ++ return (NULL); ++} ++ ++struct mrt_rib * ++mrt_parse_v2_rib(struct mrt_hdr *hdr, void *msg) ++{ ++ struct mrt_rib_entry *entries; ++ struct mrt_rib *r; ++ u_int8_t *b = msg; ++ u_int len = ntohl(hdr->length); ++ u_int32_t snum; ++ u_int16_t cnt, i; ++ u_int8_t plen; ++ ++ if (len < sizeof(snum) + 1) ++ return NULL; ++ ++ r = calloc(1, sizeof(struct mrt_rib)); ++ if (r == NULL) ++ err(1, "calloc"); ++ ++ /* seq_num */ ++ memcpy(&snum, b, sizeof(snum)); ++ b += sizeof(snum); ++ len -= sizeof(snum); ++ r->seqnum = ntohl(snum); ++ ++ switch (ntohs(hdr->subtype)) { ++ case MRT_DUMP_V2_RIB_IPV4_UNICAST: ++ case MRT_DUMP_V2_RIB_IPV4_MULTICAST: ++ plen = *b++; ++ len -= 1; ++ if (len < MRT_PREFIX_LEN(plen)) ++ goto fail; ++ r->prefix.sin.sin_family = AF_INET; ++ r->prefix.sin.sin_len = sizeof(struct sockaddr_in); ++ memcpy(&r->prefix.sin.sin_addr, b, MRT_PREFIX_LEN(plen)); ++ b += MRT_PREFIX_LEN(plen); ++ len -= MRT_PREFIX_LEN(plen); ++ r->prefixlen = plen; ++ break; ++ case MRT_DUMP_V2_RIB_IPV6_UNICAST: ++ case MRT_DUMP_V2_RIB_IPV6_MULTICAST: ++ plen = *b++; ++ len -= 1; ++ if (len < MRT_PREFIX_LEN(plen)) ++ goto fail; ++ r->prefix.sin6.sin6_family = AF_INET6; ++ r->prefix.sin6.sin6_len = sizeof(struct sockaddr_in6); ++ memcpy(&r->prefix.sin6.sin6_addr, b, MRT_PREFIX_LEN(plen)); ++ b += MRT_PREFIX_LEN(plen); ++ len -= MRT_PREFIX_LEN(plen); ++ r->prefixlen = plen; ++ break; ++ case MRT_DUMP_V2_RIB_GENERIC: ++ /* XXX unhandled */ ++ errx(1, "MRT_DUMP_V2_RIB_GENERIC subtype not yet implemented"); ++ goto fail; ++ } ++ ++ /* entries count */ ++ if (len < sizeof(cnt)) ++ goto fail; ++ memcpy(&cnt, b, sizeof(cnt)); ++ b += sizeof(cnt); ++ len -= sizeof(cnt); ++ cnt = ntohs(cnt); ++ r->nentries = cnt; ++ ++ /* entries */ ++ if ((entries = calloc(cnt, sizeof(struct mrt_rib_entry))) == NULL) ++ err(1, "calloc"); ++ for (i = 0; i < cnt; i++) { ++ u_int32_t otm; ++ u_int16_t pix, alen; ++ if (len < 2 * sizeof(u_int16_t) + sizeof(u_int32_t)) ++ goto fail; ++ /* peer index */ ++ memcpy(&pix, b, sizeof(pix)); ++ b += sizeof(pix); ++ len -= sizeof(pix); ++ entries[i].peer_idx = ntohs(pix); ++ ++ /* originated */ ++ memcpy(&otm, b, sizeof(otm)); ++ b += sizeof(otm); ++ len -= sizeof(otm); ++ entries[i].originated = ntohl(otm); ++ ++ /* attr_len */ ++ memcpy(&alen, b, sizeof(alen)); ++ b += sizeof(alen); ++ len -= sizeof(alen); ++ alen = ntohs(alen); ++ ++ /* attr */ ++ if (len < alen) ++ goto fail; ++ if (mrt_extract_attr(&entries[i], b, alen, ++ r->prefix.sa.sa_family, 1) == -1) ++ goto fail; ++ b += alen; ++ len -= alen; ++ } ++ r->entries = entries; ++ return (r); ++fail: ++ mrt_free_rib(r); ++ return (NULL); ++} ++ ++int ++mrt_parse_dump(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp, ++ struct mrt_rib **rp) ++{ ++ struct mrt_peer *p; ++ struct mrt_rib *r; ++ struct mrt_rib_entry *re; ++ u_int8_t *b = msg; ++ u_int len = ntohl(hdr->length); ++ u_int16_t asnum, alen; ++ ++ if (*pp == NULL) { ++ *pp = calloc(1, sizeof(struct mrt_peer)); ++ if (*pp == NULL) ++ err(1, "calloc"); ++ (*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry)); ++ if ((*pp)->peers == NULL) ++ err(1, "calloc"); ++ (*pp)->npeers = 1; ++ } ++ p = *pp; ++ ++ *rp = r = calloc(1, sizeof(struct mrt_rib)); ++ if (r == NULL) ++ err(1, "calloc"); ++ re = calloc(1, sizeof(struct mrt_rib_entry)); ++ if (re == NULL) ++ err(1, "calloc"); ++ r->nentries = 1; ++ r->entries = re; ++ ++ if (len < 2 * sizeof(u_int16_t)) ++ goto fail; ++ /* view */ ++ b += sizeof(u_int16_t); ++ len -= sizeof(u_int16_t); ++ /* seqnum */ ++ memcpy(&r->seqnum, b, sizeof(u_int16_t)); ++ b += sizeof(u_int16_t); ++ len -= sizeof(u_int16_t); ++ r->seqnum = ntohs(r->seqnum); ++ ++ switch (ntohs(hdr->subtype)) { ++ case MRT_DUMP_AFI_IP: ++ if (mrt_extract_addr(b, len, &r->prefix, AF_INET) == -1) ++ goto fail; ++ b += sizeof(struct in_addr); ++ len -= sizeof(struct in_addr); ++ break; ++ case MRT_DUMP_AFI_IPv6: ++ if (mrt_extract_addr(b, len, &r->prefix, AF_INET6) == -1) ++ goto fail; ++ b += sizeof(struct in6_addr); ++ len -= sizeof(struct in6_addr); ++ break; ++ } ++ if (len < 2 * sizeof(u_int32_t) + 2 * sizeof(u_int16_t) + 2) ++ goto fail; ++ r->prefixlen = *b++; ++ len -= 1; ++ /* status */ ++ b += 1; ++ len -= 1; ++ /* originated */ ++ memcpy(&re->originated, b, sizeof(u_int32_t)); ++ b += sizeof(u_int32_t); ++ len -= sizeof(u_int32_t); ++ re->originated = ntohl(re->originated); ++ /* peer ip */ ++ switch (ntohs(hdr->subtype)) { ++ case MRT_DUMP_AFI_IP: ++ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET) == -1) ++ goto fail; ++ b += sizeof(struct in_addr); ++ len -= sizeof(struct in_addr); ++ break; ++ case MRT_DUMP_AFI_IPv6: ++ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET6) == -1) ++ goto fail; ++ b += sizeof(struct in6_addr); ++ len -= sizeof(struct in6_addr); ++ break; ++ } ++ memcpy(&asnum, b, sizeof(asnum)); ++ b += sizeof(asnum); ++ len -= sizeof(asnum); ++ p->peers->asnum = ntohs(asnum); ++ ++ memcpy(&alen, b, sizeof(alen)); ++ b += sizeof(alen); ++ len -= sizeof(alen); ++ alen = ntohs(alen); ++ ++ /* attr */ ++ if (len < alen) ++ goto fail; ++ if (mrt_extract_attr(re, b, alen, r->prefix.sa.sa_family, 0) == -1) ++ goto fail; ++ b += alen; ++ len -= alen; ++ ++ return (0); ++fail: ++ mrt_free_rib(r); ++ return (-1); ++} ++ ++int ++mrt_parse_dump_mp(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp, ++ struct mrt_rib **rp) ++{ ++ struct mrt_peer *p; ++ struct mrt_rib *r; ++ struct mrt_rib_entry *re; ++ u_int8_t *b = msg; ++ u_int len = ntohl(hdr->length); ++ u_int16_t asnum, alen, afi; ++ u_int8_t safi, nhlen; ++ sa_family_t af; ++ ++ if (*pp == NULL) { ++ *pp = calloc(1, sizeof(struct mrt_peer)); ++ if (*pp == NULL) ++ err(1, "calloc"); ++ (*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry)); ++ if ((*pp)->peers == NULL) ++ err(1, "calloc"); ++ (*pp)->npeers = 1; ++ } ++ p = *pp; ++ ++ *rp = r = calloc(1, sizeof(struct mrt_rib)); ++ if (r == NULL) ++ err(1, "calloc"); ++ re = calloc(1, sizeof(struct mrt_rib_entry)); ++ if (re == NULL) ++ err(1, "calloc"); ++ r->nentries = 1; ++ r->entries = re; ++ ++ if (len < 4 * sizeof(u_int16_t)) ++ goto fail; ++ /* source AS */ ++ b += sizeof(u_int16_t); ++ len -= sizeof(u_int16_t); ++ /* dest AS */ ++ memcpy(&asnum, b, sizeof(asnum)); ++ b += sizeof(asnum); ++ len -= sizeof(asnum); ++ p->peers->asnum = ntohs(asnum); ++ /* iface index */ ++ b += sizeof(u_int16_t); ++ len -= sizeof(u_int16_t); ++ /* afi */ ++ memcpy(&afi, b, sizeof(afi)); ++ b += sizeof(afi); ++ len -= sizeof(afi); ++ afi = ntohs(afi); ++ ++ /* source + dest ip */ ++ switch (afi) { ++ case MRT_DUMP_AFI_IP: ++ if (len < 2 * sizeof(struct in_addr)) ++ goto fail; ++ /* source IP */ ++ b += sizeof(struct in_addr); ++ len -= sizeof(struct in_addr); ++ /* dest IP */ ++ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET) == -1) ++ goto fail; ++ b += sizeof(struct in_addr); ++ len -= sizeof(struct in_addr); ++ break; ++ case MRT_DUMP_AFI_IPv6: ++ if (len < 2 * sizeof(struct in6_addr)) ++ goto fail; ++ /* source IP */ ++ b += sizeof(struct in6_addr); ++ len -= sizeof(struct in6_addr); ++ /* dest IP */ ++ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET6) == -1) ++ goto fail; ++ b += sizeof(struct in6_addr); ++ len -= sizeof(struct in6_addr); ++ break; ++ } ++ ++ if (len < 2 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t)) ++ goto fail; ++ /* view + status */ ++ b += 2 * sizeof(u_int16_t); ++ len -= 2 * sizeof(u_int16_t); ++ /* originated */ ++ memcpy(&re->originated, b, sizeof(u_int32_t)); ++ b += sizeof(u_int32_t); ++ len -= sizeof(u_int32_t); ++ re->originated = ntohl(re->originated); ++ ++ /* afi */ ++ memcpy(&afi, b, sizeof(afi)); ++ b += sizeof(afi); ++ len -= sizeof(afi); ++ afi = ntohs(afi); ++ ++ /* safi */ ++ safi = *b++; ++ len -= 1; ++ ++ switch (afi) { ++ case MRT_DUMP_AFI_IP: ++ if (safi == 1 || safi == 2) { ++ af = AF_INET; ++ break; ++ } else if (safi == 128) { ++ af = AF_VPNv4; ++ break; ++ } ++ goto fail; ++ case MRT_DUMP_AFI_IPv6: ++ if (safi != 1 && safi != 2) ++ goto fail; ++ af = AF_INET6; ++ break; ++ default: ++ goto fail; ++ } ++ ++ /* nhlen */ ++ nhlen = *b++; ++ len -= 1; ++ ++ /* nexthop */ ++ if (mrt_extract_addr(b, len, &re->nexthop, af) == -1) ++ goto fail; ++ if (len < nhlen) ++ goto fail; ++ b += nhlen; ++ len -= nhlen; ++ ++ if (len < 1) ++ goto fail; ++ r->prefixlen = *b++; ++ len -= 1; ++ ++ /* prefix */ ++ switch (af) { ++ case AF_INET: ++ if (len < MRT_PREFIX_LEN(r->prefixlen)) ++ goto fail; ++ r->prefix.sin.sin_family = AF_INET; ++ r->prefix.sin.sin_len = sizeof(struct sockaddr_in); ++ memcpy(&r->prefix.sin.sin_addr, b, ++ MRT_PREFIX_LEN(r->prefixlen)); ++ b += MRT_PREFIX_LEN(r->prefixlen); ++ len -= MRT_PREFIX_LEN(r->prefixlen); ++ break; ++ case AF_INET6: ++ if (len < MRT_PREFIX_LEN(r->prefixlen)) ++ goto fail; ++ r->prefix.sin6.sin6_family = AF_INET6; ++ r->prefix.sin6.sin6_len = sizeof(struct sockaddr_in6); ++ memcpy(&r->prefix.sin6.sin6_addr, b, ++ MRT_PREFIX_LEN(r->prefixlen)); ++ b += MRT_PREFIX_LEN(r->prefixlen); ++ len -= MRT_PREFIX_LEN(r->prefixlen); ++ break; ++ case AF_VPNv4: ++ if (len < MRT_PREFIX_LEN(r->prefixlen)) ++ goto fail; ++ errx(1, "AF_VPNv4 handling not yet implemented"); ++ goto fail; ++ } ++ ++ memcpy(&alen, b, sizeof(alen)); ++ b += sizeof(alen); ++ len -= sizeof(alen); ++ alen = ntohs(alen); ++ ++ /* attr */ ++ if (len < alen) ++ goto fail; ++ if (mrt_extract_attr(re, b, alen, r->prefix.sa.sa_family, 0) == -1) ++ goto fail; ++ b += alen; ++ len -= alen; ++ ++ return (0); ++fail: ++ mrt_free_rib(r); ++ return (-1); ++} ++ ++int ++mrt_extract_attr(struct mrt_rib_entry *re, u_char *a, int alen, sa_family_t af, ++ int as4) ++{ ++ struct mrt_attr *ap; ++ u_int32_t tmp; ++ u_int16_t attr_len; ++ u_int8_t type, flags, *attr; ++ ++ do { ++ if (alen < 3) ++ return (-1); ++ attr = a; ++ flags = *a++; ++ alen -= 1; ++ type = *a++; ++ alen -= 1; ++ ++ if (flags & MRT_ATTR_EXTLEN) { ++ if (alen < 2) ++ return (-1); ++ memcpy(&attr_len, a, sizeof(attr_len)); ++ attr_len = ntohs(attr_len); ++ a += sizeof(attr_len); ++ alen -= sizeof(attr_len); ++ } else { ++ attr_len = *a++; ++ alen -= 1; ++ } ++ switch (type) { ++ case MRT_ATTR_ORIGIN: ++ if (attr_len != 1) ++ return (-1); ++ re->origin = *a; ++ break; ++ case MRT_ATTR_ASPATH: ++ if (as4) { ++ re->aspath_len = attr_len; ++ if ((re->aspath = malloc(attr_len)) == NULL) ++ err(1, "malloc"); ++ memcpy(re->aspath, a, attr_len); ++ } else { ++ re->aspath = mrt_aspath_inflate(a, attr_len, ++ &re->aspath_len); ++ if (re->aspath == NULL) ++ return (-1); ++ } ++ break; ++ case MRT_ATTR_NEXTHOP: ++ if (attr_len != 4) ++ return (-1); ++ if (af != AF_INET) ++ break; ++ memcpy(&tmp, a, sizeof(tmp)); ++ re->nexthop.sin.sin_len = sizeof(struct sockaddr_in); ++ re->nexthop.sin.sin_family = AF_INET; ++ re->nexthop.sin.sin_addr.s_addr = tmp; ++ break; ++ case MRT_ATTR_MED: ++ if (attr_len != 4) ++ return (-1); ++ memcpy(&tmp, a, sizeof(tmp)); ++ re->med = ntohl(tmp); ++ break; ++ case MRT_ATTR_LOCALPREF: ++ if (attr_len != 4) ++ return (-1); ++ memcpy(&tmp, a, sizeof(tmp)); ++ re->local_pref = ntohl(tmp); ++ break; ++ case MRT_ATTR_MP_REACH_NLRI: ++ /* ++ * XXX horrible hack: ++ * Once again IETF and the real world differ in the ++ * implementation. In short the abbreviated MP_NLRI ++ * hack in the standard is not used in real life. ++ * Detect the two cases by looking at the first byte ++ * of the payload (either the nexthop addr length (RFC) ++ * or the high byte of the AFI (old form)). If the ++ * first byte matches the expected nexthop length it ++ * is expected to be the RFC 6396 encoding. ++ */ ++ if (*a != attr_len - 1) { ++ a += 3; ++ alen -= 3; ++ attr_len -= 3; ++ } ++ switch (af) { ++ case AF_INET6: ++ if (attr_len < sizeof(struct in6_addr) + 1) ++ return (-1); ++ re->nexthop.sin6.sin6_len = ++ sizeof(struct sockaddr_in6); ++ re->nexthop.sin6.sin6_family = AF_INET6; ++ memcpy(&re->nexthop.sin6.sin6_addr, a + 1, ++ sizeof(struct in6_addr)); ++ break; ++ case AF_VPNv4: ++ if (attr_len < sizeof(u_int64_t) + ++ sizeof(struct in_addr)) ++ return (-1); ++ re->nexthop.svpn4.sv_len = ++ sizeof(struct sockaddr_vpn4); ++ re->nexthop.svpn4.sv_family = AF_VPNv4; ++ memcpy(&tmp, a + 1 + sizeof(u_int64_t), ++ sizeof(tmp)); ++ re->nexthop.svpn4.sv_addr.s_addr = tmp; ++ break; ++ } ++ break; ++ case MRT_ATTR_AS4PATH: ++ if (!as4) { ++ if (re->aspath) ++ free(re->aspath); ++ re->aspath_len = attr_len; ++ if ((re->aspath = malloc(attr_len)) == NULL) ++ err(1, "malloc"); ++ memcpy(re->aspath, a, attr_len); ++ break; ++ } ++ /* FALLTHROUGH */ ++ default: ++ re->nattrs++; ++ if (re->nattrs >= UCHAR_MAX) ++ err(1, "too many attributes"); ++ ap = realloc(re->attrs, ++ re->nattrs * sizeof(struct mrt_attr)); ++ if (ap == NULL) ++ err(1, "realloc"); ++ re->attrs = ap; ++ ap = re->attrs + re->nattrs - 1; ++ ap->attr_len = a + attr_len - attr; ++ if ((ap->attr = malloc(ap->attr_len)) == NULL) ++ err(1, "malloc"); ++ memcpy(ap->attr, attr, ap->attr_len); ++ break; ++ } ++ a += attr_len; ++ alen -= attr_len; ++ } while (alen > 0); ++ ++ return (0); ++} ++ ++void ++mrt_free_peers(struct mrt_peer *p) ++{ ++ free(p->peers); ++ free(p->view); ++ free(p); ++} ++ ++void ++mrt_free_rib(struct mrt_rib *r) ++{ ++ u_int16_t i, j; ++ ++ for (i = 0; i < r->nentries && r->entries; i++) { ++ for (j = 0; j < r->entries[i].nattrs; j++) ++ free(r->entries[i].attrs[j].attr); ++ free(r->entries[i].attrs); ++ free(r->entries[i].aspath); ++ } ++ ++ free(r->entries); ++ free(r); ++} ++ ++void ++mrt_free_bgp_state(struct mrt_bgp_state *s) ++{ ++ free(s); ++} ++ ++void ++mrt_free_bgp_msg(struct mrt_bgp_msg *m) ++{ ++ free(m->msg); ++ free(m); ++} ++ ++u_char * ++mrt_aspath_inflate(void *data, u_int16_t len, u_int16_t *newlen) ++{ ++ u_int8_t *seg, *nseg, *ndata; ++ u_int16_t seg_size, olen, nlen; ++ u_int8_t seg_len; ++ ++ /* first calculate the length of the aspath */ ++ seg = data; ++ nlen = 0; ++ for (olen = len; olen > 0; olen -= seg_size, seg += seg_size) { ++ seg_len = seg[1]; ++ seg_size = 2 + sizeof(u_int16_t) * seg_len; ++ nlen += 2 + sizeof(u_int32_t) * seg_len; ++ ++ if (seg_size > olen) ++ return NULL; ++ } ++ ++ *newlen = nlen; ++ if ((ndata = malloc(nlen)) == NULL) ++ err(1, "malloc"); ++ ++ /* then copy the aspath */ ++ seg = data; ++ for (nseg = ndata; nseg < ndata + nlen; ) { ++ *nseg++ = *seg++; ++ *nseg++ = seg_len = *seg++; ++ for (; seg_len > 0; seg_len--) { ++ *nseg++ = 0; ++ *nseg++ = 0; ++ *nseg++ = *seg++; ++ *nseg++ = *seg++; ++ } ++ } ++ ++ return (ndata); ++} ++ ++int ++mrt_extract_addr(void *msg, u_int len, union mrt_addr *addr, sa_family_t af) ++{ ++ u_int8_t *b = msg; ++ ++ switch (af) { ++ case AF_INET: ++ if (len < sizeof(struct in_addr)) ++ return (-1); ++ addr->sin.sin_family = AF_INET; ++ addr->sin.sin_len = sizeof(struct sockaddr_in); ++ memcpy(&addr->sin.sin_addr, b, sizeof(struct in_addr)); ++ return sizeof(struct in_addr); ++ case AF_INET6: ++ if (len < sizeof(struct in6_addr)) ++ return (-1); ++ addr->sin6.sin6_family = AF_INET6; ++ addr->sin6.sin6_len = sizeof(struct sockaddr_in6); ++ memcpy(&addr->sin6.sin6_addr, b, sizeof(struct in6_addr)); ++ return sizeof(struct in6_addr); ++ case AF_VPNv4: ++ if (len < sizeof(u_int64_t) + sizeof(struct in_addr)) ++ return (-1); ++ addr->svpn4.sv_len = sizeof(struct sockaddr_vpn4); ++ addr->svpn4.sv_family = AF_VPNv4; ++ memcpy(&addr->svpn4.sv_addr, b + sizeof(u_int64_t), ++ sizeof(struct in_addr)); ++ return (sizeof(u_int64_t) + sizeof(struct in_addr)); ++ default: ++ return (-1); ++ } ++} diff --git a/net/openbgpd/files/patch-bgpctl_mrtparser.h b/net/openbgpd/files/patch-bgpctl_mrtparser.h new file mode 100644 index 000000000000..2f11567e54f1 --- /dev/null +++ b/net/openbgpd/files/patch-bgpctl_mrtparser.h @@ -0,0 +1,122 @@ +Index: bgpctl/mrtparser.h +=================================================================== +RCS file: bgpctl/mrtparser.h +diff -N bgpctl/mrtparser.h +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ bgpctl/mrtparser.h 13 Oct 2012 18:22:53 -0000 1.1.1.1 +@@ -0,0 +1,115 @@ ++/* $OpenBSD$ */ ++/* ++ * Copyright (c) 2011 Claudio Jeker <claudio@openbsd.org> ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++struct sockaddr_vpn4 { ++ u_int8_t sv_len; ++ sa_family_t sv_family; ++ u_int8_t sv_labellen; ++ u_int8_t sv_pad; ++ struct in_addr sv_addr; ++ u_int64_t sv_rd; ++ u_int8_t sv_label[21]; ++ u_int8_t sv_pad2[3]; ++}; ++ ++#define AF_VPNv4 250 /* XXX high enough to not cause issues */ ++ ++union mrt_addr { ++ struct sockaddr_in6 sin6; ++ struct sockaddr_in sin; ++ struct sockaddr_vpn4 svpn4; ++ struct sockaddr sa; ++}; ++ ++/* data structures for the MSG_TABLE_DUMP_V2 format */ ++struct mrt_peer_entry { ++ union mrt_addr addr; ++ u_int32_t bgp_id; ++ u_int32_t asnum; ++}; ++ ++struct mrt_peer { ++ char *view; ++ struct mrt_peer_entry *peers; ++ u_int32_t bgp_id; ++ u_int16_t npeers; ++}; ++ ++struct mrt_attr { ++ void *attr; ++ size_t attr_len; ++}; ++ ++struct mrt_rib_entry { ++ void *aspath; ++ struct mrt_attr *attrs; ++ union mrt_addr nexthop; ++ time_t originated; ++ u_int32_t local_pref; ++ u_int32_t med; ++ u_int16_t peer_idx; ++ u_int16_t aspath_len; ++ u_int16_t nattrs; ++ u_int8_t origin; ++}; ++ ++struct mrt_rib { ++ struct mrt_rib_entry *entries; ++ union mrt_addr prefix; ++ u_int32_t seqnum; ++ u_int16_t nentries; ++ u_int8_t prefixlen; ++}; ++ ++/* data structures for the BGP4MP MESSAGE and STATE types */ ++struct mrt_bgp_state { ++ union mrt_addr src; ++ union mrt_addr dst; ++ u_int32_t src_as; ++ u_int32_t dst_as; ++ u_int16_t old_state; ++ u_int16_t new_state; ++}; ++ ++struct mrt_bgp_msg { ++ union mrt_addr src; ++ union mrt_addr dst; ++ u_int32_t src_as; ++ u_int32_t dst_as; ++ u_int16_t msg_len; ++ void *msg; ++}; ++ ++#define MRT_ATTR_ORIGIN 1 ++#define MRT_ATTR_ASPATH 2 ++#define MRT_ATTR_NEXTHOP 3 ++#define MRT_ATTR_MED 4 ++#define MRT_ATTR_LOCALPREF 5 ++#define MRT_ATTR_MP_REACH_NLRI 14 ++#define MRT_ATTR_AS4PATH 17 ++#define MRT_ATTR_EXTLEN 0x10 ++ ++#define MRT_PREFIX_LEN(x) ((((u_int)x) + 7) / 8) ++ ++struct mrt_parser { ++ void (*dump)(struct mrt_rib *, struct mrt_peer *, void *); ++ void (*state)(struct mrt_bgp_state *, void *); ++ void (*message)(struct mrt_bgp_msg *, void *); ++ void *arg; ++}; ++ ++void mrt_parse(int, struct mrt_parser *, int); diff --git a/net/openbgpd/files/patch-bgpctl_parser.c b/net/openbgpd/files/patch-bgpctl_parser.c index 237c6ffc9b92..0ce85818b1eb 100644 --- a/net/openbgpd/files/patch-bgpctl_parser.c +++ b/net/openbgpd/files/patch-bgpctl_parser.c @@ -2,17 +2,17 @@ Index: bgpctl/parser.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/parser.c,v retrieving revision 1.1.1.6 -retrieving revision 1.6 -diff -u -p -r1.1.1.6 -r1.6 +retrieving revision 1.7 +diff -u -p -r1.1.1.6 -r1.7 --- bgpctl/parser.c 14 Feb 2010 20:20:14 -0000 1.1.1.6 -+++ bgpctl/parser.c 2 Jul 2011 16:06:35 -0000 1.6 ++++ bgpctl/parser.c 13 Oct 2012 18:35:56 -0000 1.7 @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.c,v 1.54 2009/06/12 16:44:02 claudio Exp $ */ -+/* $OpenBSD: parser.c,v 1.61 2010/03/08 17:02:19 claudio Exp $ */ ++/* $OpenBSD: parser.c,v 1.64 2012/03/27 18:24:11 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -16,6 +16,10 @@ +@@ -16,11 +16,16 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ @@ -23,17 +23,44 @@ diff -u -p -r1.1.1.6 -r1.6 #include <sys/types.h> #include <sys/socket.h> -@@ -52,7 +56,8 @@ enum token_type { + #include <err.h> + #include <errno.h> ++#include <fcntl.h> + #include <limits.h> + #include <netdb.h> + #include <stdio.h> +@@ -52,7 +57,9 @@ enum token_type { PREPSELF, WEIGHT, FAMILY, - GETOPT + GETOPT, -+ RTABLE ++ RTABLE, ++ FILENAME }; enum getopts { -@@ -97,6 +102,9 @@ static const struct token t_prepself[]; +@@ -72,14 +79,18 @@ static const struct token t_show[]; + static const struct token t_show_summary[]; + static const struct token t_show_fib[]; + static const struct token t_show_rib[]; ++static const struct token t_show_mrt[]; ++static const struct token t_show_mrt_file[]; + static const struct token t_show_rib_neigh[]; ++static const struct token t_show_mrt_neigh[]; + static const struct token t_show_rib_rib[]; + static const struct token t_show_neighbor[]; + static const struct token t_show_neighbor_modifiers[]; + static const struct token t_fib[]; + static const struct token t_neighbor[]; + static const struct token t_neighbor_modifiers[]; +-static const struct token t_show_as[]; ++static const struct token t_show_rib_as[]; ++static const struct token t_show_mrt_as[]; + static const struct token t_show_prefix[]; + static const struct token t_show_ip[]; + static const struct token t_show_community[]; +@@ -97,6 +108,9 @@ static const struct token t_prepself[]; static const struct token t_weight[]; static const struct token t_irrfilter[]; static const struct token t_irrfilter_opts[]; @@ -43,7 +70,7 @@ diff -u -p -r1.1.1.6 -r1.6 static const struct token t_main[] = { { KEYWORD, "reload", RELOAD, NULL}, -@@ -105,6 +113,7 @@ static const struct token t_main[] = { +@@ -105,6 +119,7 @@ static const struct token t_main[] = { { KEYWORD, "neighbor", NEIGHBOR, t_neighbor}, { KEYWORD, "network", NONE, t_network}, { KEYWORD, "irrfilter", IRRFILTER, t_irrfilter}, @@ -51,15 +78,18 @@ diff -u -p -r1.1.1.6 -r1.6 { ENDTOKEN, "", NONE, NULL} }; -@@ -116,6 +125,7 @@ static const struct token t_show[] = { +@@ -116,8 +131,10 @@ static const struct token t_show[] = { { KEYWORD, "network", NETWORK_SHOW, t_network_show}, { KEYWORD, "nexthop", SHOW_NEXTHOP, NULL}, { KEYWORD, "rib", SHOW_RIB, t_show_rib}, + { KEYWORD, "tables", SHOW_FIB_TABLES, NULL}, { KEYWORD, "ip", NONE, t_show_ip}, { KEYWORD, "summary", SHOW_SUMMARY, t_show_summary}, ++ { KEYWORD, "mrt", SHOW_MRT, t_show_mrt}, { ENDTOKEN, "", NONE, NULL} -@@ -128,14 +138,15 @@ static const struct token t_show_summary + }; + +@@ -128,24 +145,26 @@ static const struct token t_show_summary }; static const struct token t_show_fib[] = { @@ -83,7 +113,61 @@ diff -u -p -r1.1.1.6 -r1.6 }; static const struct token t_show_rib[] = { -@@ -187,6 +198,7 @@ static const struct token t_show_neighbo + { NOTOKEN, "", NONE, NULL}, +- { ASTYPE, "as", AS_ALL, t_show_as}, +- { ASTYPE, "source-as", AS_SOURCE, t_show_as}, +- { ASTYPE, "transit-as", AS_TRANSIT, t_show_as}, +- { ASTYPE, "peer-as", AS_PEER, t_show_as}, ++ { ASTYPE, "as", AS_ALL, t_show_rib_as}, ++ { ASTYPE, "source-as", AS_SOURCE, t_show_rib_as}, ++ { ASTYPE, "transit-as", AS_TRANSIT, t_show_rib_as}, ++ { ASTYPE, "peer-as", AS_PEER, t_show_rib_as}, + { ASTYPE, "empty-as", AS_EMPTY, t_show_rib}, + { KEYWORD, "community", NONE, t_show_community}, ++ { FLAG, "selected", F_CTL_ACTIVE, t_show_rib}, + { FLAG, "detail", F_CTL_DETAIL, t_show_rib}, + { FLAG, "in", F_CTL_ADJ_IN, t_show_rib}, + { FLAG, "out", F_CTL_ADJ_OUT, t_show_rib}, +@@ -158,12 +177,38 @@ static const struct token t_show_rib[] = + { ENDTOKEN, "", NONE, NULL} + }; + ++ ++static const struct token t_show_mrt[] = { ++ { NOTOKEN, "", NONE, NULL}, ++ { ASTYPE, "as", AS_ALL, t_show_mrt_as}, ++ { ASTYPE, "source-as", AS_SOURCE, t_show_mrt_as}, ++ { ASTYPE, "transit-as", AS_TRANSIT, t_show_mrt_as}, ++ { ASTYPE, "peer-as", AS_PEER, t_show_mrt_as}, ++ { ASTYPE, "empty-as", AS_EMPTY, t_show_mrt}, ++ { FLAG, "detail", F_CTL_DETAIL, t_show_mrt}, ++ { KEYWORD, "neighbor", NONE, t_show_mrt_neigh}, ++ { KEYWORD, "file", NONE, t_show_mrt_file}, ++ { FAMILY, "", NONE, t_show_mrt}, ++ { PREFIX, "", NONE, t_show_prefix}, ++ { ENDTOKEN, "", NONE, NULL} ++}; ++ ++static const struct token t_show_mrt_file[] = { ++ { FILENAME, "", NONE, t_show_mrt}, ++ { ENDTOKEN, "", NONE, NULL} ++}; ++ + static const struct token t_show_rib_neigh[] = { + { PEERADDRESS, "", NONE, t_show_rib}, + { PEERDESC, "", NONE, t_show_rib}, + { ENDTOKEN, "", NONE, NULL} + }; + ++static const struct token t_show_mrt_neigh[] = { ++ { PEERADDRESS, "", NONE, t_show_mrt}, ++ { ENDTOKEN, "", NONE, NULL} ++}; ++ + static const struct token t_show_rib_rib[] = { + { RIBNAME, "", NONE, t_show_rib}, + { ENDTOKEN, "", NONE, NULL} +@@ -187,6 +232,7 @@ static const struct token t_show_neighbo static const struct token t_fib[] = { { KEYWORD, "couple", FIB_COUPLE, NULL}, { KEYWORD, "decouple", FIB_DECOUPLE, NULL}, @@ -91,7 +175,33 @@ diff -u -p -r1.1.1.6 -r1.6 { ENDTOKEN, "", NONE, NULL} }; -@@ -311,6 +323,22 @@ static const struct token t_irrfilter_op +@@ -204,11 +250,16 @@ static const struct token t_neighbor_mod + { ENDTOKEN, "", NONE, NULL} + }; + +-static const struct token t_show_as[] = { ++static const struct token t_show_rib_as[] = { + { ASNUM, "", NONE, t_show_rib}, + { ENDTOKEN, "", NONE, NULL} + }; + ++static const struct token t_show_mrt_as[] = { ++ { ASNUM, "", NONE, t_show_mrt}, ++ { ENDTOKEN, "", NONE, NULL} ++}; ++ + static const struct token t_show_prefix[] = { + { NOTOKEN, "", NONE, NULL}, + { FLAG, "all", F_LONGER, NULL}, +@@ -231,6 +282,7 @@ static const struct token t_network[] = + { KEYWORD, "delete", NETWORK_REMOVE, t_prefix}, + { KEYWORD, "flush", NETWORK_FLUSH, NULL}, + { KEYWORD, "show", NETWORK_SHOW, t_network_show}, ++ { KEYWORD, "mrt", NETWORK_MRT, t_show_mrt}, + { ENDTOKEN, "", NONE, NULL} + }; + +@@ -311,6 +363,22 @@ static const struct token t_irrfilter_op { ENDTOKEN, "", NONE, NULL} }; @@ -114,34 +224,34 @@ diff -u -p -r1.1.1.6 -r1.6 static struct parse_result res; const struct token *match_token(int *argc, char **argv[], -@@ -404,15 +432,22 @@ match_token(int *argc, char **argv[], co +@@ -404,15 +472,22 @@ match_token(int *argc, char **argv[], co case FAMILY: if (word == NULL) break; - if (!strcmp(word, "inet") || !strcmp(word, "IPv4")) { + if (!strcmp(word, "inet") || + !strcasecmp(word, "IPv4")) { -+ match++; -+ t = &table[i]; -+ res.aid = AID_INET; -+ } -+ if (!strcmp(word, "inet6") || -+ !strcasecmp(word, "IPv6")) { match++; t = &table[i]; - res.af = AF_INET; -+ res.aid = AID_INET6; ++ res.aid = AID_INET; } - if (!strcmp(word, "inet6") || !strcmp(word, "IPv6")) { -+ if (!strcasecmp(word, "VPNv4")) { ++ if (!strcmp(word, "inet6") || ++ !strcasecmp(word, "IPv6")) { match++; t = &table[i]; - res.af = AF_INET6; ++ res.aid = AID_INET6; ++ } ++ if (!strcasecmp(word, "VPNv4")) { ++ match++; ++ t = &table[i]; + res.aid = AID_VPN_IPv4; } break; case ADDRESS: -@@ -485,6 +520,7 @@ match_token(int *argc, char **argv[], co +@@ -485,6 +560,7 @@ match_token(int *argc, char **argv[], co case PREPNBR: case PREPSELF: case WEIGHT: @@ -149,7 +259,31 @@ diff -u -p -r1.1.1.6 -r1.6 if (word != NULL && strlen(word) > 0 && parse_number(word, &res, table[i].type)) { match++; -@@ -577,6 +613,9 @@ show_valid_args(const struct token table +@@ -518,6 +594,23 @@ match_token(int *argc, char **argv[], co + t = &table[i]; + } + break; ++ case FILENAME: ++ if (word != NULL && strlen(word) > 0) { ++ if ((res.mrtfd = open(word, O_RDONLY)) == -1) { ++ /* ++ * ignore error if path has no / and ++ * does not exist. In hope to print ++ * usage. ++ */ ++ if (errno == ENOENT && ++ !strchr(word, '/')) ++ break; ++ err(1, "mrt open(%s)", word); ++ } ++ match++; ++ t = &table[i]; ++ } ++ break; + case ENDTOKEN: + break; + } +@@ -577,6 +670,9 @@ show_valid_args(const struct token table case WEIGHT: fprintf(stderr, " <number>\n"); break; @@ -159,7 +293,7 @@ diff -u -p -r1.1.1.6 -r1.6 case NEXTHOP: fprintf(stderr, " <address>\n"); break; -@@ -584,7 +623,7 @@ show_valid_args(const struct token table +@@ -584,11 +680,14 @@ show_valid_args(const struct token table fprintf(stderr, " <pftable>\n"); break; case FAMILY: @@ -168,7 +302,14 @@ diff -u -p -r1.1.1.6 -r1.6 break; case GETOPT: fprintf(stderr, " <options>\n"); -@@ -608,7 +647,7 @@ parse_addr(const char *word, struct bgpd + break; ++ case FILENAME: ++ fprintf(stderr, " <filename>\n"); ++ break; + case ENDTOKEN: + break; + } +@@ -608,7 +707,7 @@ parse_addr(const char *word, struct bgpd bzero(&ina, sizeof(ina)); if (inet_net_pton(AF_INET, word, &ina, sizeof(ina)) != -1) { @@ -177,7 +318,7 @@ diff -u -p -r1.1.1.6 -r1.6 addr->v4 = ina; return (1); } -@@ -618,13 +657,7 @@ parse_addr(const char *word, struct bgpd +@@ -618,13 +717,7 @@ parse_addr(const char *word, struct bgpd hints.ai_socktype = SOCK_DGRAM; /*dummy*/ hints.ai_flags = AI_NUMERICHOST; if (getaddrinfo(word, "0", &hints, &r) == 0) { @@ -192,7 +333,16 @@ diff -u -p -r1.1.1.6 -r1.6 freeaddrinfo(r); return (1); } -@@ -663,15 +696,15 @@ parse_prefix(const char *word, struct bg +@@ -647,7 +740,7 @@ parse_prefix(const char *word, struct bg + if ((p = strrchr(word, '/')) != NULL) { + mask = strtonum(p + 1, 0, 128, &errstr); + if (errstr) +- errx(1, "invalid netmask: %s", errstr); ++ errx(1, "netmask %s", errstr); + + if ((ps = malloc(strlen(word) - strlen(p) + 1)) == NULL) + err(1, "parse_prefix: malloc"); +@@ -663,15 +756,15 @@ parse_prefix(const char *word, struct bg if (parse_addr(word, addr) == 0) return (0); @@ -211,7 +361,7 @@ diff -u -p -r1.1.1.6 -r1.6 if (mask == -1) mask = 128; inet6applymask(&addr->v6, &addr->v6, mask); -@@ -706,7 +739,7 @@ parse_asnum(const char *word, u_int32_t +@@ -706,7 +799,7 @@ parse_asnum(const char *word, u_int32_t if (errstr) errx(1, "AS number is %s: %s", errstr, word); } else { @@ -220,7 +370,7 @@ diff -u -p -r1.1.1.6 -r1.6 if (errstr) errx(1, "AS number is %s: %s", errstr, word); } -@@ -730,6 +763,11 @@ parse_number(const char *word, struct pa +@@ -730,6 +823,11 @@ parse_number(const char *word, struct pa errx(1, "number is %s: %s", errstr, word); /* number was parseable */ @@ -232,7 +382,7 @@ diff -u -p -r1.1.1.6 -r1.6 if ((fs = calloc(1, sizeof(struct filter_set))) == NULL) err(1, NULL); switch (type) { -@@ -882,8 +920,14 @@ bgpctl_getopt(int *argc, char **argv[], +@@ -882,8 +980,14 @@ bgpctl_getopt(int *argc, char **argv[], int ch; optind = optreset = 1; diff --git a/net/openbgpd/files/patch-bgpctl_parser.h b/net/openbgpd/files/patch-bgpctl_parser.h index bf86d255a853..1d570c747a7c 100644 --- a/net/openbgpd/files/patch-bgpctl_parser.h +++ b/net/openbgpd/files/patch-bgpctl_parser.h @@ -2,25 +2,27 @@ Index: bgpctl/parser.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/parser.h,v retrieving revision 1.1.1.6 -retrieving revision 1.1.1.8 -diff -u -p -r1.1.1.6 -r1.1.1.8 +retrieving revision 1.1.1.9 +diff -u -p -r1.1.1.6 -r1.1.1.9 --- bgpctl/parser.h 14 Feb 2010 20:20:14 -0000 1.1.1.6 -+++ bgpctl/parser.h 12 Jun 2011 10:44:54 -0000 1.1.1.8 ++++ bgpctl/parser.h 13 Oct 2012 18:22:53 -0000 1.1.1.9 @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.h,v 1.19 2009/06/06 06:05:41 claudio Exp $ */ -+/* $OpenBSD: parser.h,v 1.22 2010/05/03 13:11:41 claudio Exp $ */ ++/* $OpenBSD: parser.h,v 1.23 2011/09/21 10:37:51 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -29,6 +29,7 @@ enum actions { +@@ -29,7 +29,9 @@ enum actions { SHOW_NEIGHBOR_TIMERS, SHOW_NEIGHBOR_TERSE, SHOW_FIB, + SHOW_FIB_TABLES, SHOW_RIB, ++ SHOW_MRT, SHOW_RIB_MEM, SHOW_NEXTHOP, -@@ -37,6 +38,8 @@ enum actions { + SHOW_INTERFACE, +@@ -37,6 +39,8 @@ enum actions { FIB, FIB_COUPLE, FIB_DECOUPLE, @@ -29,7 +31,15 @@ diff -u -p -r1.1.1.6 -r1.1.1.8 NEIGHBOR, NEIGHBOR_UP, NEIGHBOR_DOWN, -@@ -59,9 +62,10 @@ struct parse_result { +@@ -46,6 +50,7 @@ enum actions { + NETWORK_REMOVE, + NETWORK_FLUSH, + NETWORK_SHOW, ++ NETWORK_MRT, + IRRFILTER + }; + +@@ -59,9 +64,11 @@ struct parse_result { char rib[PEER_DESCR_LEN]; char *irr_outdir; int flags; @@ -39,6 +49,7 @@ diff -u -p -r1.1.1.6 -r1.1.1.8 u_int8_t prefixlen; - sa_family_t af; + u_int8_t aid; ++ int mrtfd; }; __dead void usage(void); diff --git a/net/openbgpd/files/patch-bgpctl_whois.c b/net/openbgpd/files/patch-bgpctl_whois.c index 3ae7685e7cc1..0e4b86c84b6e 100644 --- a/net/openbgpd/files/patch-bgpctl_whois.c +++ b/net/openbgpd/files/patch-bgpctl_whois.c @@ -2,16 +2,10 @@ Index: bgpctl/whois.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/whois.c,v retrieving revision 1.1.1.5 -retrieving revision 1.1.1.6 -diff -u -p -r1.1.1.5 -r1.1.1.6 +retrieving revision 1.1.1.7 +diff -u -p -r1.1.1.5 -r1.1.1.7 --- bgpctl/whois.c 14 Feb 2010 20:20:14 -0000 1.1.1.5 -+++ bgpctl/whois.c 14 Feb 2010 20:27:21 -0000 1.1.1.6 -@@ -1,4 +1,4 @@ --/* $OpenBSD: whois.c,v 1.3 2007/03/05 16:43:24 henning Exp $ */ -+/* $OpenBSD: whois.c,v 1.4 2009/09/08 15:40:25 claudio Exp $ */ - - /* - * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> ++++ bgpctl/whois.c 13 Oct 2012 18:22:54 -0000 1.1.1.7 @@ -68,7 +68,8 @@ char *qtype_opts[] = { "", "-T aut-num", diff --git a/net/openbgpd/files/patch-bgpd_Makefile b/net/openbgpd/files/patch-bgpd_Makefile index 9bc06ffb1090..f946c920b826 100644 --- a/net/openbgpd/files/patch-bgpd_Makefile +++ b/net/openbgpd/files/patch-bgpd_Makefile @@ -2,18 +2,17 @@ Index: bgpd/Makefile =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/Makefile,v retrieving revision 1.1.1.2 -retrieving revision 1.8 -diff -u -p -r1.1.1.2 -r1.8 +retrieving revision 1.9 +diff -u -p -r1.1.1.2 -r1.9 --- bgpd/Makefile 9 Jul 2009 16:49:54 -0000 1.1.1.2 -+++ bgpd/Makefile 3 Jul 2011 04:46:36 -0000 1.8 ++++ bgpd/Makefile 13 Oct 2012 18:36:00 -0000 1.9 @@ -1,15 +1,25 @@ --# $OpenBSD: Makefile,v 1.28 2009/06/25 14:14:54 deraadt Exp $ -+# $OpenBSD: Makefile,v 1.29 2010/05/26 16:44:32 nicm Exp $ -+ + # $OpenBSD: Makefile,v 1.28 2009/06/25 14:14:54 deraadt Exp $ + +.PATH: ${.CURDIR}/.. ${.CURDIR}/../openbsd-compat + +CONFFILE?= ${PREFIX}/etc/bgpd.conf - ++ PROG= bgpd -SRCS= bgpd.c buffer.c session.c log.c parse.y config.c imsg.c \ +SRCS= bgpd.c session.c log.c parse.y config.c \ diff --git a/net/openbgpd/files/patch-bgpd_bgpd.8 b/net/openbgpd/files/patch-bgpd_bgpd.8 index e666cb96d92c..f59cd5269f2c 100644 --- a/net/openbgpd/files/patch-bgpd_bgpd.8 +++ b/net/openbgpd/files/patch-bgpd_bgpd.8 @@ -2,13 +2,13 @@ Index: bgpd/bgpd.8 =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.8,v retrieving revision 1.1.1.8 -retrieving revision 1.9 -diff -u -p -r1.1.1.8 -r1.9 +retrieving revision 1.10 +diff -u -p -r1.1.1.8 -r1.10 --- bgpd/bgpd.8 14 Feb 2010 20:19:57 -0000 1.1.1.8 -+++ bgpd/bgpd.8 2 Jul 2011 16:06:38 -0000 1.9 ++++ bgpd/bgpd.8 13 Oct 2012 18:36:00 -0000 1.10 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bgpd.8,v 1.28 2009/01/13 23:01:36 sthen Exp $ -+.\" $OpenBSD: bgpd.8,v 1.33 2009/12/16 15:40:55 claudio Exp $ ++.\" $OpenBSD: bgpd.8,v 1.45 2012/08/24 20:13:03 jmc Exp $ .\" .\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> .\" @@ -17,7 +17,7 @@ diff -u -p -r1.1.1.8 -r1.9 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: January 13 2009 $ -+.Dd $Mdocdate: June 27 2010 $ ++.Dd $Mdocdate: August 24 2012 $ .Dt BGPD 8 .Os .Sh NAME @@ -35,13 +35,105 @@ diff -u -p -r1.1.1.8 -r1.9 .Ek .Sh DESCRIPTION .Nm -@@ -42,15 +38,15 @@ concerning +@@ -42,15 +38,106 @@ concerning with other BGP systems. .Nm uses the Border Gateway Protocol, Version 4, -as described in RFC 1771. +-Please refer to that document for more information about BGP. +as described in RFC 4271. - Please refer to that document for more information about BGP. ++.Pp ++BGP is an exterior gateway protocol using a multiple step decision process ++to find the best path. ++Advanced filtering can be used to influence the route ++decision for traffic engineering. ++The session engine of ++.Nm ++is responsible for maintaining the TCP session with each neighbor. ++Updates are passed to the Route Decision Engine (RDE) where the paths ++are filtered and used to compute a Routing Information Base (RIB). ++The parent process is responsible for keeping the RIB in sync with ++the kernel routing table. ++.Pp ++The route decision process selects the best path by evaluating all paths to ++the same destination. ++The decision process continues to the next step if paths have equal attributes. ++Paths that are less preferred are taken out of consideration until there is ++only one path left. ++.Bl -enum -width 42 -offset bula ++.It ++All paths with errors or loops are not eligible. ++.It ++Paths with an unreachable nexthop are not eligible. ++After this step all remaining paths are valid. ++.It ++The path with the highest ++.Em LOCAL_PREF ++is selected. ++.It ++The path with the shortest ++.Em AS path ++attribute is selected. ++.It ++The ++.Em ORIGIN ++attribute is compared. ++The order is IGP before EGP before incomplete origins. ++.It ++The path with the lowest ++.Em MULTI_EXIT_DISC ++metric is selected. ++Normally, this value is only considered when choosing between multiple ++routes sent by the same neighbouring AS. ++However, if ++.Dq Li rde med compare always ++is set in the configuration, the metric is compared for routes sent by any AS. ++.It ++Comparison of the BGP session type. ++Paths learned over an external (EBGP) session are preferred over those ++learned via an internal (IBGP) session. ++.It ++The path with the lowest local ++.Em weight ++is selected. ++.It ++If ++.Dq Li rde route-age evaluate ++is set then the oldest path is selected. ++.It ++The path coming from the neighbor with the lowest ++.Em BGP ID ++wins. ++If the ++.Em ORIGINATOR_ID ++attribute is present that value will be used in the comparison instead. ++.It ++The path with the shortest ++.Em CLUSTER_LIST ++attribute is selected. ++If it is not present then a length of 0 is used in the comparison. ++.It ++The path coming from the peer with the lowest IP address is selected. ++IPv4 sessions will be preferred over IPv6 ones. ++.It ++In case of locally announced prefixes ++.Nm ++will prefer statically set prefixes over dynamically inserted ones. ++.El ++.Pp ++Attributes set by filters can be used to tip the decision process to prefer ++particular paths over others. ++This can be achieved by changing the ++.Em localpref , ++.Em med , ++or ++.Em weight ++attributes. ++AS path prepending or changing the ++.Em med ++or ++.Em origin ++attribute can be used to influencing the routing behaviour on remote systems. .Pp .Nm is usually started at boot time, and can be enabled by @@ -54,7 +146,7 @@ diff -u -p -r1.1.1.8 -r1.9 .Pp See .Xr rc 8 -@@ -117,25 +113,16 @@ Use +@@ -117,25 +204,16 @@ Use .Ar file as the configuration file, instead of the default @@ -82,83 +174,175 @@ diff -u -p -r1.1.1.8 -r1.9 default .Nm configuration file -@@ -150,9 +137,9 @@ control socket +@@ -149,55 +227,144 @@ control socket + .Xr bgpctl 8 , .Xr bgplg 8 , .Xr bgplgsh 8 ++.Sh STANDARDS .Rs -.%R RFC 1771 -+.%R RFC 4271 - .%T "A Border Gateway Protocol 4 (BGP-4)" +-.%T "A Border Gateway Protocol 4 (BGP-4)" -.%D March 1995 -+.%D January 2006 +-.Re +-.Rs +-.%R RFC 1997 +-.%T "BGP Communities Attribute" ++.%A R. Chandra ++.%A P. Traina ++.%A "T. Li" + .%D August 1996 ++.%R RFC 1997 ++.%T BGP Communities Attribute .Re ++.Pp .Rs - .%R RFC 1997 -@@ -165,6 +152,11 @@ control socket +-.%R RFC 2385 +-.%T "Protection of BGP Sessions via the TCP MD5 Signature Option" ++.%A A. Heffernan .%D August 1998 ++.%R RFC 2385 ++.%T Protection of BGP Sessions via the TCP MD5 Signature Option .Re ++.Pp .Rs -+.%R RFC 2545 -+.%T "Use of BGP-4 Multiprotocol Extensions for IPv6 Inter-Domain Routing" +-.%R RFC 2796 +-.%T "BGP Route Reflection - An Alternative to Full Mesh IBGP" +-.%D April 2000 ++.%A P. Marques ++.%A F. Dupont +.%D March 1999 -+.Re -+.Rs - .%R RFC 2796 - .%T "BGP Route Reflection - An Alternative to Full Mesh IBGP" - .%D April 2000 -@@ -175,11 +167,6 @@ control socket ++.%R RFC 2545 ++.%T Use of BGP-4 Multiprotocol Extensions for IPv6 Inter-Domain Routing + .Re ++.Pp + .Rs +-.%R RFC 2918 +-.%T "Route Refresh Capability for BGP-4" ++.%A E. Chen .%D September 2000 ++.%R RFC 2918 ++.%T Route Refresh Capability for BGP-4 .Re ++.Pp .Rs -.%R RFC 3392 -.%T "Capabilities Advertisement with BGP-4" -.%D January 1999 --.Re --.Rs - .%R RFC 3682 - .%T "The Generalized TTL Security Mechanism (GTSM)" - .%D February 2004 -@@ -190,6 +177,21 @@ control socket - .%D April 2004 ++.%A G. Huston ++.%D April 2004 ++.%R RFC 3765 ++.%T NOPEER Community for Border Gateway Protocol (BGP) Route Scope Control .Re ++.Pp .Rs +-.%R RFC 3682 +-.%T "The Generalized TTL Security Mechanism (GTSM)" +-.%D February 2004 ++.%A Y. Rekhter ++.%A "T. Li" ++.%A S. Hares ++.%D January 2006 ++.%R RFC 4271 ++.%T A Border Gateway Protocol 4 (BGP-4) + .Re ++.Pp + .Rs +-.%R RFC 3765 +-.%T "NOPEER Community for Border Gateway Protocol" +-.%D April 2004 ++.%A S. Sangli ++.%A D. Tappan ++.%A Y. Rekhter ++.%D February 2006 +.%R RFC 4360 -+.%T "BGP Extended Communities Attribute" ++.%T BGP Extended Communities Attribute + .Re ++.Pp + .Rs +-.%R RFC 4760 +-.%T "Multiprotocol Extensions for BGP-4" ++.%A E. Rosen ++.%A Y. Rekhter +.%D February 2006 ++.%R RFC 4364 ++.%T BGP/MPLS IP Virtual Private Networks (VPNs) +.Re ++.Pp +.Rs -+.%R RFC 4364 -+.%T "BGP/MPLS IP Virtual Private Networks (VPNs)" -+.%D February 2006 ++.%A T. Bates ++.%A E. Chen ++.%A R. Chandra ++.%D April 2006 ++.%R RFC 4456 ++.%T "BGP Route Reflection: An Alternative to Full Mesh Internal BGP (IBGP)" +.Re ++.Pp +.Rs -+.%R RFC 4486 -+.%T "BGP Cease Notification Message Subcodes" ++.%A E. Chen ++.%A V. Gillet +.%D April 2006 ++.%R RFC 4486 ++.%T Subcodes for BGP Cease Notification Message +.Re ++.Pp +.Rs - .%R RFC 4760 - .%T "Multiprotocol Extensions for BGP-4" ++.%A T. Bates ++.%A R. Chandra ++.%A D. Katz ++.%A Y. Rekhter .%D January 2007 -@@ -199,6 +201,21 @@ control socket - .%T "BGP Support for Four-octet AS Number Space" - .%D May 2007 ++.%R RFC 4760 ++.%T Multiprotocol Extensions for BGP-4 .Re ++.Pp + .Rs +-.%R RFC 4893 +-.%T "BGP Support for Four-octet AS Number Space" ++.%A Q. Vohra ++.%A E. Chen + .%D May 2007 ++.%R RFC 4893 ++.%T BGP Support for Four-octet AS Number Space ++.Re ++.Pp +.Rs -+.%R RFC 5492 -+.%T "Capabilities Advertisement with BGP-4" ++.%A V. Gill ++.%A J. Heasley ++.%A D. Meyer ++.%A P. Savola ++.%A C. Pignatoro ++.%D October 2007 ++.%R RFC 5082 ++.%T The Generalized TTL Security Mechanism (GTSM) ++.Re ++.Pp ++.Rs ++.%A J. Scudder ++.%A R. Chandra +.%D February 2009 ++.%R RFC 5492 ++.%T Capabilities Advertisement with BGP-4 +.Re ++.Pp +.Rs -+.%R draft-ietf-idr-optional-transitive-00 -+.%T "Error Handling for Optional Transitive BGP Attributes" +.%D April 2009 ++.%R draft-ietf-idr-optional-transitive-00 ++.%T Error Handling for Optional Transitive BGP Attributes +.Re ++.Pp +.Rs -+.%R draft-ietf-idr-fsm-subcode-00 -+.%T "Subcodes for BGP Finite State Machine Error" -+.%D September 2010 ++.%D August 2011 ++.%R draft-ietf-grow-mrt-17 ++.%T MRT routing information export format +.Re ++.Pp ++.Rs ++.%A J. Dong ++.%A M. Chen ++.%A A. Suryanarayana ++.%D May 2012 ++.%R RFC 6608 ++.%T Subcodes for BGP Finite State Machine Error + .Re .Sh HISTORY The - .Nm diff --git a/net/openbgpd/files/patch-bgpd_bgpd.c b/net/openbgpd/files/patch-bgpd_bgpd.c index 73190ce9b93f..43fb3eb010a2 100644 --- a/net/openbgpd/files/patch-bgpd_bgpd.c +++ b/net/openbgpd/files/patch-bgpd_bgpd.c @@ -2,12 +2,13 @@ Index: bgpd/bgpd.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.c,v retrieving revision 1.1.1.7 -diff -u -p -r1.1.1.7 bgpd.c +retrieving revision 1.1.1.11 +diff -u -p -r1.1.1.7 -r1.1.1.11 --- bgpd/bgpd.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/bgpd.c 3 Jul 2011 04:34:14 -0000 ++++ bgpd/bgpd.c 13 Oct 2012 18:22:38 -0000 1.1.1.11 @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.c,v 1.148 2009/06/07 00:30:23 claudio Exp $ */ -+/* $OpenBSD: bgpd.c,v 1.167 2011/05/01 10:42:28 claudio Exp $ */ ++/* $OpenBSD: bgpd.c,v 1.168 2011/08/20 19:02:28 sthen Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -21,7 +22,7 @@ diff -u -p -r1.1.1.7 bgpd.c #include "session.h" void sighdlr(int); -@@ -42,23 +42,22 @@ int main(int, char *[]); +@@ -42,23 +42,23 @@ int main(int, char *[]); int check_child(pid_t, const char *); int send_filterset(struct imsgbuf *, struct filter_set_head *); int reconfigure(char *, struct bgpd_config *, struct mrt_head *, @@ -47,6 +48,7 @@ diff -u -p -r1.1.1.7 bgpd.c +volatile sig_atomic_t sigchld; +volatile sig_atomic_t reconfig; +pid_t reconfpid; ++int reconfpending; struct imsgbuf *ibuf_se; struct imsgbuf *ibuf_rde; struct rib_names ribnames = SIMPLEQ_HEAD_INITIALIZER(ribnames); @@ -55,7 +57,7 @@ diff -u -p -r1.1.1.7 bgpd.c void sighdlr(int sig) -@@ -86,8 +85,8 @@ usage(void) +@@ -86,8 +86,8 @@ usage(void) { extern char *__progname; @@ -66,7 +68,7 @@ diff -u -p -r1.1.1.7 bgpd.c exit(1); } -@@ -101,15 +100,10 @@ int +@@ -101,15 +101,10 @@ int main(int argc, char *argv[]) { struct bgpd_config conf; @@ -83,13 +85,15 @@ diff -u -p -r1.1.1.7 bgpd.c struct pollfd pfd[POLL_MAX]; pid_t io_pid = 0, rde_pid = 0, pid; char *conffile; -@@ -125,17 +119,11 @@ main(int argc, char *argv[]) +@@ -124,18 +119,13 @@ main(int argc, char *argv[]) + bgpd_process = PROC_MAIN; log_init(1); /* log to stderr until daemonized */ - +- - if ((rules_l = calloc(1, sizeof(struct filter_head))) == NULL) - err(1, NULL); -- ++ log_verbose(1); + bzero(&conf, sizeof(conf)); LIST_INIT(&mrt_l); - TAILQ_INIT(&net_l); @@ -102,7 +106,7 @@ diff -u -p -r1.1.1.7 bgpd.c switch (ch) { case 'c': conf.opts |= BGPD_OPT_FORCE_DEMOTE; -@@ -158,12 +146,7 @@ main(int argc, char *argv[]) +@@ -158,12 +148,7 @@ main(int argc, char *argv[]) if (conf.opts & BGPD_OPT_VERBOSE) conf.opts |= BGPD_OPT_VERBOSE2; conf.opts |= BGPD_OPT_VERBOSE; @@ -116,7 +120,7 @@ diff -u -p -r1.1.1.7 bgpd.c break; default: usage(); -@@ -176,24 +159,22 @@ main(int argc, char *argv[]) +@@ -176,24 +161,22 @@ main(int argc, char *argv[]) if (argc > 0) usage(); @@ -151,7 +155,15 @@ diff -u -p -r1.1.1.7 bgpd.c if (geteuid()) errx(1, "need root privileges"); -@@ -225,13 +206,9 @@ main(int argc, char *argv[]) +@@ -202,6 +185,7 @@ main(int argc, char *argv[]) + errx(1, "unknown user %s", BGPD_USER); + + log_init(debug); ++ log_verbose(conf.opts & BGPD_OPT_VERBOSE); + + if (!debug) + daemon(1, 0); +@@ -225,13 +209,9 @@ main(int argc, char *argv[]) session_socket_blockmode(pipe_s2r_c[0], BM_NONBLOCK); session_socket_blockmode(pipe_s2r_c[1], BM_NONBLOCK); @@ -167,7 +179,7 @@ diff -u -p -r1.1.1.7 bgpd.c setproctitle("parent"); -@@ -254,33 +231,12 @@ main(int argc, char *argv[]) +@@ -254,33 +234,12 @@ main(int argc, char *argv[]) imsg_init(ibuf_se, pipe_m2s[0]); imsg_init(ibuf_rde, pipe_m2r[0]); mrt_init(ibuf_rde, ibuf_se); @@ -203,17 +215,27 @@ diff -u -p -r1.1.1.7 bgpd.c while (quit == 0) { bzero(pfd, sizeof(pfd)); pfd[PFD_PIPE_SESSION].fd = ibuf_se->fd; -@@ -336,8 +292,7 @@ main(int argc, char *argv[]) +@@ -335,15 +294,16 @@ main(int argc, char *argv[]) + u_int error; reconfig = 0; - log_info("rereading config"); +- log_info("rereading config"); - switch (reconfigure(conffile, &conf, &mrt_l, &peer_l, - rules_l)) { + switch (reconfigure(conffile, &conf, &mrt_l, &peer_l)) { case -1: /* fatal error */ quit = 1; break; -@@ -389,13 +344,13 @@ main(int argc, char *argv[]) + case 0: /* all OK */ + error = 0; + break; ++ case 2: ++ error = CTL_RES_PENDING; ++ break; + default: /* parse error */ + error = CTL_RES_PARSE_ERROR; + break; +@@ -389,13 +349,13 @@ main(int argc, char *argv[]) LIST_REMOVE(m, entry); free(m); } @@ -233,7 +255,7 @@ diff -u -p -r1.1.1.7 bgpd.c control_cleanup(conf.csock); control_cleanup(conf.rcsock); carp_demote_shutdown(); -@@ -413,6 +368,8 @@ main(int argc, char *argv[]) +@@ -413,6 +373,8 @@ main(int argc, char *argv[]) free(ibuf_se); msgbuf_clear(&ibuf_rde->w); free(ibuf_rde); @@ -242,7 +264,7 @@ diff -u -p -r1.1.1.7 bgpd.c log_info("Terminating"); return (0); -@@ -452,27 +409,25 @@ send_filterset(struct imsgbuf *i, struct +@@ -452,27 +414,32 @@ send_filterset(struct imsgbuf *i, struct int reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l, @@ -260,6 +282,13 @@ diff -u -p -r1.1.1.7 bgpd.c + struct rdomain *rd; - if (parse_config(conffile, conf, mrt_l, peer_l, &net_l, rules_l)) { ++ if (reconfpending) { ++ log_info("previous reload still running"); ++ return (2); ++ } ++ reconfpending = 2; /* one per child */ ++ ++ log_info("rereading config"); + if (parse_config(conffile, conf, mrt_l, peer_l, &net_l, &rules_l, + &rdom_l)) { log_warnx("config file %s has errors, not reloading", @@ -276,7 +305,7 @@ diff -u -p -r1.1.1.7 bgpd.c prepare_listeners(conf); /* start reconfiguration */ -@@ -483,12 +438,6 @@ reconfigure(char *conffile, struct bgpd_ +@@ -483,12 +450,6 @@ reconfigure(char *conffile, struct bgpd_ conf, sizeof(struct bgpd_config)) == -1) return (-1); @@ -289,7 +318,7 @@ diff -u -p -r1.1.1.7 bgpd.c TAILQ_FOREACH(la, conf->listen_addrs, entry) { if (imsg_compose(ibuf_se, IMSG_RECONF_LISTENER, 0, 0, la->fd, la, sizeof(struct listen_addr)) == -1) -@@ -496,51 +445,104 @@ reconfigure(char *conffile, struct bgpd_ +@@ -496,51 +457,104 @@ reconfigure(char *conffile, struct bgpd_ la->fd = -1; } @@ -411,7 +440,7 @@ diff -u -p -r1.1.1.7 bgpd.c /* mrt changes can be sent out of bound */ mrt_reconfigure(mrt_l); return (0); -@@ -550,8 +552,8 @@ int +@@ -550,8 +564,8 @@ int dispatch_imsg(struct imsgbuf *ibuf, int idx) { struct imsg imsg; @@ -422,7 +451,7 @@ diff -u -p -r1.1.1.7 bgpd.c if ((n = imsg_read(ibuf)) == -1) return (-1); -@@ -573,46 +575,39 @@ dispatch_imsg(struct imsgbuf *ibuf, int +@@ -573,46 +587,39 @@ dispatch_imsg(struct imsgbuf *ibuf, int case IMSG_KROUTE_CHANGE: if (idx != PFD_PIPE_ROUTE) log_warnx("route request not from RDE"); @@ -487,7 +516,17 @@ diff -u -p -r1.1.1.7 bgpd.c break; case IMSG_PFTABLE_ADD: if (idx != PFD_PIPE_ROUTE) -@@ -654,18 +649,19 @@ dispatch_imsg(struct imsgbuf *ibuf, int +@@ -646,26 +653,28 @@ dispatch_imsg(struct imsgbuf *ibuf, int + case IMSG_CTL_RELOAD: + if (idx != PFD_PIPE_SESSION) + log_warnx("reload request not from SE"); +- else ++ else { + reconfig = 1; + reconfpid = imsg.hdr.pid; ++ } + break; + case IMSG_CTL_FIB_COUPLE: if (idx != PFD_PIPE_SESSION) log_warnx("couple request not from SE"); else @@ -509,7 +548,7 @@ diff -u -p -r1.1.1.7 bgpd.c if (idx != PFD_PIPE_SESSION) log_warnx("kroute request not from SE"); else -@@ -692,6 +688,11 @@ dispatch_imsg(struct imsgbuf *ibuf, int +@@ -692,6 +701,16 @@ dispatch_imsg(struct imsgbuf *ibuf, int carp_demote_set(msg->demote_group, msg->level); } break; @@ -518,10 +557,15 @@ diff -u -p -r1.1.1.7 bgpd.c + memcpy(&verbose, imsg.data, sizeof(verbose)); + log_verbose(verbose); + break; ++ case IMSG_RECONF_DONE: ++ if (reconfpending == 0) ++ log_warnx("unexpected RECONF_DONE received"); ++ reconfpending--; ++ break; default: break; } -@@ -707,7 +708,7 @@ send_nexthop_update(struct kroute_nextho +@@ -707,7 +726,7 @@ send_nexthop_update(struct kroute_nextho { char *gw = NULL; @@ -530,7 +574,7 @@ diff -u -p -r1.1.1.7 bgpd.c if (asprintf(&gw, ": via %s", log_addr(&msg->gateway)) == -1) { log_warn("send_nexthop_update"); -@@ -717,7 +718,7 @@ send_nexthop_update(struct kroute_nextho +@@ -717,7 +736,7 @@ send_nexthop_update(struct kroute_nextho log_info("nexthop %s now %s%s%s", log_addr(&msg->nexthop), msg->valid ? "valid" : "invalid", msg->connected ? ": directly connected" : "", @@ -539,7 +583,7 @@ diff -u -p -r1.1.1.7 bgpd.c free(gw); -@@ -733,56 +734,20 @@ send_imsg_session(int type, pid_t pid, v +@@ -733,56 +752,20 @@ send_imsg_session(int type, pid_t pid, v } int @@ -600,7 +644,7 @@ diff -u -p -r1.1.1.7 bgpd.c } int -@@ -810,3 +775,45 @@ bgpd_filternexthop(struct kroute *kr, st +@@ -810,3 +793,45 @@ bgpd_filternexthop(struct kroute *kr, st return (1); } diff --git a/net/openbgpd/files/patch-bgpd_bgpd.conf.5 b/net/openbgpd/files/patch-bgpd_bgpd.conf.5 index 3b8afd260fd6..306de76703d7 100644 --- a/net/openbgpd/files/patch-bgpd_bgpd.conf.5 +++ b/net/openbgpd/files/patch-bgpd_bgpd.conf.5 @@ -2,13 +2,13 @@ Index: bgpd/bgpd.conf.5 =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.conf.5,v retrieving revision 1.1.1.7 -retrieving revision 1.8 -diff -u -p -r1.1.1.7 -r1.8 +retrieving revision 1.9 +diff -u -p -r1.1.1.7 -r1.9 --- bgpd/bgpd.conf.5 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/bgpd.conf.5 2 Jul 2011 16:06:38 -0000 1.8 ++++ bgpd/bgpd.conf.5 13 Oct 2012 18:36:00 -0000 1.9 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bgpd.conf.5,v 1.94 2009/06/07 00:31:22 claudio Exp $ -+.\" $OpenBSD: bgpd.conf.5,v 1.104 2010/03/05 15:25:00 claudio Exp $ ++.\" $OpenBSD: bgpd.conf.5,v 1.120 2012/07/07 08:22:57 claudio Exp $ .\" .\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> .\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -17,11 +17,11 @@ diff -u -p -r1.1.1.7 -r1.8 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: June 7 2009 $ -+.Dd $Mdocdate: October 23 2010 $ ++.Dd $Mdocdate: July 7 2012 $ .Dt BGPD.CONF 5 .Os .Sh NAME -@@ -26,7 +26,7 @@ +@@ -26,11 +26,11 @@ The .Xr bgpd 8 daemon implements the Border Gateway Protocol version 4 as described @@ -30,6 +30,11 @@ diff -u -p -r1.1.1.7 -r1.8 .Sh SECTIONS The .Nm +-config file is divided into four main sections. ++config file is divided into five main sections. + .Bl -tag -width xxxx + .It Sy Macros + User-defined variables may be defined and used later, simplifying the @@ -38,6 +38,8 @@ configuration file. .It Sy Global Configuration Global settings for @@ -39,7 +44,35 @@ diff -u -p -r1.1.1.7 -r1.8 .It Sy Neighbors and Groups .Xr bgpd 8 establishes sessions with -@@ -93,7 +95,7 @@ Set the local +@@ -54,9 +56,16 @@ the sections should be grouped and appea + .Nm + in the order shown above. + .Pp ++The current line can be extended over multiple lines using a backslash ++.Pq Sq \e . + Comments can be put anywhere in the file using a hash mark + .Pq Sq # , + and extend to the end of the current line. ++Care should be taken when commenting out multi-line text: ++the comment is effective until the end of the entire block. ++.Pp ++Argument names not beginning with a letter, digit, or underscore ++must be quoted. + .Pp + Additional configuration files can be included with the + .Ic include +@@ -66,8 +75,8 @@ include "/etc/bgpd/bgpd-10.0.0.1.filter" + .Ed + .Sh MACROS + Macros can be defined that will later be expanded in context. +-Macro names must start with a letter, and may contain letters, digits +-and underscores. ++Macro names must start with a letter, digit, or underscore, ++and may contain any of those characters. + Macro names may not be reserved words (for example, + .Ic AS , + .Ic neighbor , +@@ -93,7 +102,7 @@ Set the local .Em autonomous system number to .Ar as-number . @@ -48,12 +81,12 @@ diff -u -p -r1.1.1.7 -r1.8 2-byte AS number which is used for neighbors which do not support 4-byte AS numbers. The default for the secondary AS is 23456. -@@ -143,13 +145,13 @@ The default is 120 seconds. +@@ -143,29 +152,33 @@ The default is 120 seconds. .It Xo .Ic dump .Op Ic rib Ar name -.Pq Ic table Ns \&| Ns Ic table-mp -+.Pq Ic table Ns | Ns Ic table-mp ++.Pq Ic table Ns | Ns Ic table-mp Ns | Ns Ic table-v2 .Ar file Op Ar timeout .Xc .It Xo @@ -65,7 +98,31 @@ diff -u -p -r1.1.1.7 -r1.8 .Ar file Op Ar timeout .Xc Dump the RIB, a.k.a. the -@@ -195,7 +197,7 @@ dump updates out "/tmp/updates-out-%H%M" + .Em routing information base , + and all BGP messages in Multi-threaded Routing Toolkit (MRT) format. +-Dumping the RIB is normally an expensive operation, +-but it should not influence the session handling. + It is possible to dump alternate RIB with the use of + .Ar name . + .Pp + For example, the following will dump the entire table to the + .Xr strftime 3 Ns -expanded + filename. +-The ++Only the ++.Ic table-v2 ++format is able to dump a multi-protocol RIB correctly. ++Both ++.Ic table ++and + .Ic table-mp +-format is multi-protocol capable but often not supported by 3rd-party tools. ++formats are more or less limited when handling multi-protocol entries and ++are only left around to support 3rd party tools not handling the new format. + The timeout is optional: + .Bd -literal -offset indent + dump table "/tmp/rib-dump-%H%M" 300 +@@ -195,7 +208,7 @@ dump updates out "/tmp/updates-out-%H%M" .Pp .It Xo .Ic fib-update @@ -74,7 +131,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Xc If set to .Ic no , -@@ -242,12 +244,12 @@ Log received and sent updates. +@@ -242,12 +255,12 @@ Log received and sent updates. .Xc .It Xo .Ic network @@ -89,7 +146,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Ic connected Op Ic set ...\& .Xc Announce the specified network as belonging to our AS. -@@ -278,7 +280,7 @@ section. +@@ -278,7 +291,7 @@ section. .Ic nexthop .Ic qualify .Ic via @@ -98,7 +155,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Xc If set to .Ic bgp , -@@ -295,7 +297,7 @@ daemons like +@@ -295,38 +308,47 @@ daemons like .Ic rde .Ic med .Ic compare @@ -107,7 +164,19 @@ diff -u -p -r1.1.1.7 -r1.8 .Xc If set to .Ic always , -@@ -313,20 +315,31 @@ is only compared between peers belonging + the +-.Em MED ++.Em MULTI_EXIT_DISC + attributes will always be compared. + The default is + .Ic strict , +-where the +-.Em MED +-is only compared between peers belonging to the same AS. ++where the metric is only compared between peers belonging to the same AS. + .Pp + .It Xo + .Ic rde .Ic rib Ar name .Op Ic no Ic evaluate .Xc @@ -142,7 +211,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Xc If set to .Ic evaluate , -@@ -339,7 +352,7 @@ The default is +@@ -339,7 +361,7 @@ The default is .Pp .It Xo .Ic route-collector @@ -151,7 +220,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Xc If set to .Ic yes , -@@ -361,13 +374,24 @@ to the local machine. +@@ -361,13 +383,24 @@ to the local machine. Work with the given kernel routing table instead of the default table, .Ar 0 . @@ -180,7 +249,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Xc If set to .Ic yes , -@@ -376,6 +400,111 @@ to EBGP neighbors are not prepended with +@@ -376,6 +409,111 @@ to EBGP neighbors are not prepended with The default is .Ic no . .El @@ -270,13 +339,13 @@ diff -u -p -r1.1.1.7 -r1.8 +.Pp +.It Ic rd Ar as-number Ns Li : Ns Ar local +.It Ic rd Ar IP Ns Li : Ns Ar local -+The Route Distinguishers uniquely identifies a set of VPN prefixes. -+Only prefixes matching the ++The sole purpose of the Route Distinguisher +.Ic rd -+will be imported into the routing domain. -+The purpose of the ++is to ensure that possible common prefixes are destinct between VPNs. ++The +.Ic rd -+is solely to allow one to create distinct routes to a common address prefix. ++is neither used to identify the origin of the prefix nor to control into ++which VPNs the prefix is distributed to. +The +.Ar as-number +or @@ -292,7 +361,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Sh NEIGHBORS AND GROUPS .Xr bgpd 8 establishes TCP connections to other BGP speakers called -@@ -470,21 +599,35 @@ The default for IBGP peers is +@@ -470,21 +608,35 @@ The default for IBGP peers is .Pp .It Xo .Ic announce @@ -334,7 +403,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Xc If set to .Ic no , -@@ -493,6 +636,29 @@ This can be helpful to connect to old or +@@ -493,6 +645,29 @@ This can be helpful to connect to old or The default is .Ic yes . .Pp @@ -364,7 +433,7 @@ diff -u -p -r1.1.1.7 -r1.8 .It Ic demote Ar group Increase the .Xr carp 4 -@@ -504,7 +670,7 @@ The demotion counter will be increased a +@@ -504,7 +679,7 @@ The demotion counter will be increased a .Xr bgpd 8 starts and decreased 60 seconds after the session went to state @@ -373,7 +442,7 @@ diff -u -p -r1.1.1.7 -r1.8 For neighbors added at runtime, the demotion counter is only increased after the session has been .Em ESTABLISHED -@@ -548,8 +714,8 @@ Do not start the session when bgpd comes +@@ -548,8 +723,8 @@ Do not start the session when bgpd comes .Pp .It Xo .Ic dump @@ -384,7 +453,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Ar file Op Ar timeout .Xc Do a peer specific MRT dump. -@@ -564,7 +730,7 @@ section in +@@ -564,7 +739,7 @@ section in .Pp .It Xo .Ic enforce neighbor-as @@ -393,7 +462,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Xc If set to .Ic yes , -@@ -589,10 +755,16 @@ Inherited from the global configuration +@@ -589,10 +764,16 @@ Inherited from the global configuration Set the minimal acceptable holdtime. Inherited from the global configuration if not given. .Pp @@ -412,7 +481,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Ic spi Ar spi-number authspec Op Ar encspec .Xc Enable IPsec with static keying. -@@ -627,7 +799,7 @@ Keys must be given in hexadecimal format +@@ -627,7 +808,7 @@ Keys must be given in hexadecimal format .Pp .It Xo .Ic ipsec @@ -421,7 +490,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Ic ike .Xc Enable IPsec with dynamic keying. -@@ -639,11 +811,11 @@ is responsible for managing the session +@@ -639,11 +820,11 @@ is responsible for managing the session With .Xr isakmpd 8 , it is sufficient to copy the peer's public key, found in @@ -435,7 +504,7 @@ diff -u -p -r1.1.1.7 -r1.8 The local public key must be copied to the peer in the same way. As .Xr bgpd 8 -@@ -698,7 +870,7 @@ Do not attempt to actively open a TCP co +@@ -698,11 +879,11 @@ Do not attempt to actively open a TCP co .It Ic remote-as Ar as-number Set the AS number of the remote system. .Pp @@ -444,7 +513,12 @@ diff -u -p -r1.1.1.7 -r1.8 Bind the neighbor to the specified RIB. .Pp .It Ic route-reflector Op Ar address -@@ -732,8 +904,8 @@ These sets are rewritten into filter rul +-Act as an RFC 2796 ++Act as an RFC 4456 + .Em route-reflector + for this neighbor. + An optional cluster ID can be specified; otherwise the BGP ID will be used. +@@ -732,8 +913,8 @@ These sets are rewritten into filter rul .Pp .It Xo .Ic softreconfig @@ -455,7 +529,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Xc Turn soft reconfiguration on or off for the specified direction. If soft reconfiguration is turned on, filter changes will be applied on -@@ -760,7 +932,7 @@ tcp md5sig key deadbeef +@@ -760,7 +941,7 @@ tcp md5sig key deadbeef .Pp .It Xo .Ic transparent-as @@ -464,7 +538,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Xc If set to .Ic yes , -@@ -772,7 +944,7 @@ setting. +@@ -772,7 +953,7 @@ setting. .Pp .It Xo .Ic ttl-security @@ -473,7 +547,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Xc Enable or disable ttl-security. When enabled, -@@ -849,6 +1021,10 @@ is matched against a part of the +@@ -849,6 +1030,10 @@ is matched against a part of the .Em AS path specified by the .Ar as-type . @@ -484,7 +558,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Ar as-type is one of the following operators: .Pp -@@ -917,7 +1093,32 @@ may be set to +@@ -917,7 +1102,32 @@ may be set to which is expanded to the current neighbor remote AS number. .Pp .It Xo @@ -518,7 +592,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Ar peer .Xc This rule applies only to -@@ -945,7 +1146,7 @@ if enclosed in curly brackets: +@@ -945,7 +1155,7 @@ if enclosed in curly brackets: deny from { 128.251.16.1, 251.128.16.2, group hojo } .Ed .Pp @@ -527,7 +601,7 @@ diff -u -p -r1.1.1.7 -r1.8 This rule applies only to routes matching the stated address family. The address family needs to be set only in rules that use .Ic prefixlen -@@ -953,6 +1154,24 @@ without specifying a +@@ -953,6 +1163,24 @@ without specifying a .Ic prefix beforehand. .Pp @@ -552,7 +626,7 @@ diff -u -p -r1.1.1.7 -r1.8 .It Xo .Ic prefix .Ar address Ns Li / Ns Ar len -@@ -1028,6 +1247,12 @@ matches a rule which has the +@@ -1028,6 +1256,12 @@ matches a rule which has the option set, this rule is considered the last matching rule, and evaluation of subsequent rules is skipped. .Pp @@ -565,7 +639,7 @@ diff -u -p -r1.1.1.7 -r1.8 .It Ic set Ar attribute ... All matching rules can set the .Em AS path attributes -@@ -1079,6 +1304,48 @@ Alternately, well-known communities may +@@ -1079,6 +1313,48 @@ Alternately, well-known communities may or .Ic NO_PEER . .Pp @@ -614,7 +688,7 @@ diff -u -p -r1.1.1.7 -r1.8 .It Ic localpref Ar number Set the .Em LOCAL_PREF -@@ -1108,6 +1375,20 @@ otherwise it will be set to +@@ -1108,6 +1384,20 @@ otherwise it will be set to .Ar number . .Pp .It Xo @@ -635,7 +709,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Ic nexthop .Sm off .Po Ar address \*(Ba -@@ -1157,9 +1438,8 @@ times to the +@@ -1157,9 +1447,8 @@ times to the .Em AS path . .Pp .It Ic rtlabel Ar label @@ -647,7 +721,7 @@ diff -u -p -r1.1.1.7 -r1.8 .Pp .It Ic weight Ar number The -@@ -1181,8 +1461,8 @@ For prefixes with equally long paths, th +@@ -1181,8 +1470,8 @@ For prefixes with equally long paths, th is selected. .El .Sh FILES diff --git a/net/openbgpd/files/patch-bgpd_bgpd.h b/net/openbgpd/files/patch-bgpd_bgpd.h index c374b981553c..a624b0796bd8 100644 --- a/net/openbgpd/files/patch-bgpd_bgpd.h +++ b/net/openbgpd/files/patch-bgpd_bgpd.h @@ -2,13 +2,13 @@ Index: bgpd/bgpd.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.h,v retrieving revision 1.1.1.8 -retrieving revision 1.12 -diff -u -p -r1.1.1.8 -r1.12 +retrieving revision 1.13 +diff -u -p -r1.1.1.8 -r1.13 --- bgpd/bgpd.h 14 Feb 2010 20:19:57 -0000 1.1.1.8 -+++ bgpd/bgpd.h 2 Jul 2011 16:06:38 -0000 1.12 ++++ bgpd/bgpd.h 13 Oct 2012 18:36:00 -0000 1.13 @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.241 2009/06/12 16:42:53 claudio Exp $ */ -+/* $OpenBSD: bgpd.h,v 1.255 2010/04/06 13:25:08 claudio Exp $ */ ++/* $OpenBSD: bgpd.h,v 1.272 2012/09/18 09:45:51 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -61,7 +61,7 @@ diff -u -p -r1.1.1.8 -r1.12 #define BGPD_FLAG_NEXTHOP_BGP 0x0080 #define BGPD_FLAG_NEXTHOP_DEFAULT 0x1000 #define BGPD_FLAG_DECISION_MASK 0x0f00 -@@ -83,6 +82,8 @@ +@@ -83,9 +82,12 @@ #define F_REJECT 0x0080 #define F_BLACKHOLE 0x0100 #define F_LONGER 0x0200 @@ -70,7 +70,11 @@ diff -u -p -r1.1.1.8 -r1.12 #define F_CTL_DETAIL 0x1000 /* only used by bgpctl */ #define F_CTL_ADJ_IN 0x2000 #define F_CTL_ADJ_OUT 0x4000 -@@ -109,18 +110,74 @@ enum reconf_action { ++#define F_CTL_ACTIVE 0x8000 + + /* + * Limit the number of control messages generated by the RDE and queued in +@@ -109,18 +111,75 @@ enum reconf_action { RECONF_DELETE }; @@ -100,6 +104,7 @@ diff -u -p -r1.1.1.8 -r1.12 +#define AID_INET6 2 +#define AID_VPN_IPv4 3 +#define AID_MAX 4 ++#define AID_MIN 1 /* skip AID_UNSPEC since that is a dummy */ + +#define AID_VALS { \ + /* afi, af, safii, name */ \ @@ -149,7 +154,7 @@ diff -u -p -r1.1.1.8 -r1.12 #define addr8 ba.addr8 #define addr16 ba.addr16 #define addr32 ba.addr32 -@@ -141,17 +198,12 @@ TAILQ_HEAD(listen_addrs, listen_addr); +@@ -141,17 +200,12 @@ TAILQ_HEAD(listen_addrs, listen_addr); TAILQ_HEAD(filter_set_head, filter_set); struct bgpd_config { @@ -167,7 +172,7 @@ diff -u -p -r1.1.1.8 -r1.12 u_int32_t bgpid; u_int32_t clusterid; u_int32_t as; -@@ -205,11 +257,10 @@ struct peer_auth { +@@ -205,12 +259,24 @@ struct peer_auth { }; struct capabilities { @@ -176,14 +181,38 @@ diff -u -p -r1.1.1.8 -r1.12 - u_int8_t refresh; /* route refresh, RFC 2918 */ - u_int8_t restart; /* graceful restart, RFC 4724 */ - u_int8_t as4byte; /* draft-ietf-idr-as4bytes-13 */ -+ int8_t mp[AID_MAX]; /* multiprotocol extensions, RFC 4760 */ -+ int8_t refresh; /* route refresh, RFC 2918 */ -+ int8_t restart; /* graceful restart, RFC 4724 */ -+ int8_t as4byte; /* draft-ietf-idr-as4bytes-13 */ - }; +-}; ++ struct { ++ int16_t timeout; /* graceful restart timeout */ ++ int8_t flags[AID_MAX]; /* graceful restart per AID flags */ ++ int8_t restart; /* graceful restart, RFC 4724 */ ++ } grestart; ++ int8_t mp[AID_MAX]; /* multiprotocol extensions, RFC 4760 */ ++ int8_t refresh; /* route refresh, RFC 2918 */ ++ int8_t as4byte; /* 4-byte ASnum, RFC 4893 */ ++}; ++ ++#define CAPA_GR_PRESENT 0x01 ++#define CAPA_GR_RESTART 0x02 ++#define CAPA_GR_FORWARD 0x04 ++#define CAPA_GR_RESTARTING 0x08 ++ ++#define CAPA_GR_TIMEMASK 0x0fff ++#define CAPA_GR_R_FLAG 0x8000 ++#define CAPA_GR_F_FLAG 0x80 struct peer_config { -@@ -248,21 +299,31 @@ struct peer_config { + struct bgpd_addr remote_addr; +@@ -237,7 +303,7 @@ struct peer_config { + u_int8_t template; + u_int8_t remote_masklen; + u_int8_t cloned; +- u_int8_t ebgp; /* 1 = ebgp, 0 = ibgp */ ++ u_int8_t ebgp; /* 0 = ibgp else ebgp */ + u_int8_t distance; /* 1 = direct, >1 = multihop */ + u_int8_t passive; + u_int8_t down; +@@ -248,21 +314,33 @@ struct peer_config { u_int8_t ttlsec; /* TTL security hack */ u_int8_t flags; u_int8_t pad[3]; @@ -195,16 +224,21 @@ diff -u -p -r1.1.1.8 -r1.12 +enum network_type { + NETWORK_DEFAULT, + NETWORK_STATIC, -+ NETWORK_CONNECTED ++ NETWORK_CONNECTED, ++ NETWORK_MRTCLONE +}; + struct network_config { - struct bgpd_addr prefix; - struct filter_set_head attrset; -+ u_int rtableid; -+ enum network_type type; - u_int8_t prefixlen; -+ u_int8_t old; /* used for reloading */ +- struct bgpd_addr prefix; +- struct filter_set_head attrset; +- u_int8_t prefixlen; ++ struct bgpd_addr prefix; ++ struct filter_set_head attrset; ++ struct rde_aspath *asp; ++ u_int rtableid; ++ enum network_type type; ++ u_int8_t prefixlen; ++ u_int8_t old; /* used for reloading */ }; TAILQ_HEAD(network_head, network); @@ -217,7 +251,7 @@ diff -u -p -r1.1.1.8 -r1.12 }; enum imsg_type { -@@ -276,7 +337,6 @@ enum imsg_type { +@@ -276,7 +354,6 @@ enum imsg_type { IMSG_CTL_NEIGHBOR_CLEAR, IMSG_CTL_NEIGHBOR_RREFRESH, IMSG_CTL_KROUTE, @@ -225,7 +259,7 @@ diff -u -p -r1.1.1.8 -r1.12 IMSG_CTL_KROUTE_ADDR, IMSG_CTL_RESULT, IMSG_CTL_SHOW_NEIGHBOR, -@@ -288,10 +348,11 @@ enum imsg_type { +@@ -288,11 +365,14 @@ enum imsg_type { IMSG_CTL_SHOW_RIB_ATTR, IMSG_CTL_SHOW_RIB_COMMUNITY, IMSG_CTL_SHOW_NETWORK, @@ -236,9 +270,12 @@ diff -u -p -r1.1.1.8 -r1.12 + IMSG_CTL_LOG_VERBOSE, + IMSG_CTL_SHOW_FIB_TABLES, IMSG_NETWORK_ADD, ++ IMSG_NETWORK_ASPATH, ++ IMSG_NETWORK_ATTR, IMSG_NETWORK_REMOVE, IMSG_NETWORK_FLUSH, -@@ -302,6 +363,11 @@ enum imsg_type { + IMSG_NETWORK_DONE, +@@ -302,19 +382,25 @@ enum imsg_type { IMSG_RECONF_PEER, IMSG_RECONF_FILTER, IMSG_RECONF_LISTENER, @@ -250,7 +287,14 @@ diff -u -p -r1.1.1.8 -r1.12 IMSG_RECONF_DONE, IMSG_UPDATE, IMSG_UPDATE_ERR, -@@ -313,8 +379,6 @@ enum imsg_type { + IMSG_SESSION_ADD, + IMSG_SESSION_UP, + IMSG_SESSION_DOWN, ++ IMSG_SESSION_STALE, ++ IMSG_SESSION_FLUSH, ++ IMSG_SESSION_RESTARTED, + IMSG_MRT_OPEN, + IMSG_MRT_REOPEN, IMSG_MRT_CLOSE, IMSG_KROUTE_CHANGE, IMSG_KROUTE_DELETE, @@ -259,7 +303,15 @@ diff -u -p -r1.1.1.8 -r1.12 IMSG_NEXTHOP_ADD, IMSG_NEXTHOP_REMOVE, IMSG_NEXTHOP_UPDATE, -@@ -379,9 +443,43 @@ enum suberr_cease { +@@ -337,6 +423,7 @@ enum ctl_results { + CTL_RES_DENIED, + CTL_RES_NOCAP, + CTL_RES_PARSE_ERROR, ++ CTL_RES_PENDING, + CTL_RES_NOMEM + }; + +@@ -379,9 +466,43 @@ enum suberr_cease { ERR_CEASE_RSRC_EXHAUST }; @@ -303,7 +355,7 @@ diff -u -p -r1.1.1.8 -r1.12 u_int16_t flags; u_int16_t labelid; u_short ifindex; -@@ -400,14 +498,12 @@ struct kroute6 { +@@ -400,14 +521,12 @@ struct kroute6 { }; struct kroute_nexthop { @@ -320,7 +372,7 @@ diff -u -p -r1.1.1.8 -r1.12 }; struct kif { -@@ -423,8 +519,7 @@ struct kif { +@@ -423,8 +542,7 @@ struct kif { struct session_up { struct bgpd_addr local_addr; struct bgpd_addr remote_addr; @@ -330,7 +382,7 @@ diff -u -p -r1.1.1.8 -r1.12 u_int32_t remote_bgpid; u_int16_t short_as; }; -@@ -437,8 +532,13 @@ struct pftable_msg { +@@ -437,8 +555,13 @@ struct pftable_msg { struct ctl_show_nexthop { struct bgpd_addr addr; @@ -345,7 +397,7 @@ diff -u -p -r1.1.1.8 -r1.12 }; struct ctl_neighbor { -@@ -447,20 +547,10 @@ struct ctl_neighbor { +@@ -447,20 +570,11 @@ struct ctl_neighbor { int show_timers; }; @@ -367,10 +419,36 @@ diff -u -p -r1.1.1.8 -r1.12 +#define F_PREF_ACTIVE 0x02 +#define F_PREF_INTERNAL 0x04 +#define F_PREF_ANNOUNCE 0x08 ++#define F_PREF_STALE 0x10 struct ctl_show_rib { struct bgpd_addr true_nexthop; -@@ -498,16 +588,52 @@ enum as_spec { +@@ -472,9 +586,7 @@ struct ctl_show_rib { + u_int32_t remote_id; + u_int32_t local_pref; + u_int32_t med; +- u_int32_t prefix_cnt; +- u_int32_t active_cnt; +- u_int32_t rib_cnt; ++ u_int32_t weight; + u_int16_t aspath_len; + u_int16_t flags; + u_int8_t prefixlen; +@@ -482,13 +594,6 @@ struct ctl_show_rib { + /* plus a aspath_len bytes long aspath */ + }; + +-struct ctl_show_rib_prefix { +- struct bgpd_addr prefix; +- time_t lastchange; +- u_int16_t flags; +- u_int8_t prefixlen; +-}; +- + enum as_spec { + AS_NONE, + AS_ALL, +@@ -498,16 +603,52 @@ enum as_spec { AS_EMPTY }; @@ -385,13 +463,13 @@ diff -u -p -r1.1.1.8 -r1.12 u_int32_t as; + u_int16_t flags; + enum as_spec type; - }; - ++}; ++ +struct filter_aslen { + u_int aslen; + enum aslen_spec type; -+}; -+ + }; + +#define AS_FLAG_NEIGHBORAS 0x01 + struct filter_community { @@ -426,7 +504,7 @@ diff -u -p -r1.1.1.8 -r1.12 struct ctl_show_rib_request { char rib[PEER_DESCR_LEN]; struct ctl_neighbor neighbor; -@@ -518,8 +644,8 @@ struct ctl_show_rib_request { +@@ -518,8 +659,8 @@ struct ctl_show_rib_request { pid_t pid; u_int16_t flags; enum imsg_type type; @@ -436,7 +514,7 @@ diff -u -p -r1.1.1.8 -r1.12 }; enum filter_actions { -@@ -585,6 +711,28 @@ struct filter_peers { +@@ -585,6 +726,28 @@ struct filter_peers { #define EXT_COMMUNITY_OSPF_RTR_TYPE 6 /* RFC 4577 */ #define EXT_COMMUNITY_OSPF_RTR_ID 7 /* RFC 4577 */ #define EXT_COMMUNITY_BGP_COLLECT 8 /* RFC 4384 */ @@ -465,7 +543,7 @@ diff -u -p -r1.1.1.8 -r1.12 struct filter_prefix { -@@ -594,16 +742,18 @@ struct filter_prefix { +@@ -594,16 +757,18 @@ struct filter_prefix { struct filter_prefixlen { enum comp_ops op; @@ -489,7 +567,7 @@ diff -u -p -r1.1.1.8 -r1.12 }; TAILQ_HEAD(filter_head, filter_rule); -@@ -635,10 +785,13 @@ enum action_types { +@@ -635,10 +800,13 @@ enum action_types { ACTION_SET_NEXTHOP_SELF, ACTION_SET_COMMUNITY, ACTION_DEL_COMMUNITY, @@ -504,7 +582,7 @@ diff -u -p -r1.1.1.8 -r1.12 }; struct filter_set { -@@ -650,23 +803,53 @@ struct filter_set { +@@ -650,23 +818,53 @@ struct filter_set { int32_t relative; struct bgpd_addr nexthop; struct filter_community community; @@ -530,7 +608,7 @@ diff -u -p -r1.1.1.8 -r1.12 + u_int rtableid; + u_int label; + int flags; -+}; + }; +SIMPLEQ_HEAD(rdomain_head, rdomain); + +struct rde_rib { @@ -539,7 +617,7 @@ diff -u -p -r1.1.1.8 -r1.12 + u_int rtableid; + u_int16_t id; + u_int16_t flags; - }; ++}; +SIMPLEQ_HEAD(rib_names, rde_rib); +extern struct rib_names ribnames; + @@ -563,7 +641,7 @@ diff -u -p -r1.1.1.8 -r1.12 int64_t nexthop_cnt; int64_t aspath_cnt; int64_t aspath_size; -@@ -677,38 +860,29 @@ struct rde_memstats { +@@ -677,82 +875,117 @@ struct rde_memstats { int64_t attr_dcnt; }; @@ -572,7 +650,39 @@ diff -u -p -r1.1.1.8 -r1.12 - char name[PEER_DESCR_LEN]; - u_int16_t id; - u_int16_t flags; --}; ++/* macros for IPv6 link-local address */ ++#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER) ++#define IN6_LINKLOCAL_IFINDEX(addr) \ ++ ((addr).s6_addr[2] << 8 | (addr).s6_addr[3]) ++ ++#define SET_IN6_LINKLOCAL_IFINDEX(addr, index) \ ++ do { \ ++ (addr).s6_addr[2] = ((index) >> 8) & 0xff; \ ++ (addr).s6_addr[3] = (index) & 0xff; \ ++ } while (0) ++#endif ++ ++#define MRT_FILE_LEN 512 ++#define MRT2MC(x) ((struct mrt_config *)(x)) ++#define MRT_MAX_TIMEOUT 7200 ++ ++enum mrt_type { ++ MRT_NONE, ++ MRT_TABLE_DUMP, ++ MRT_TABLE_DUMP_MP, ++ MRT_TABLE_DUMP_V2, ++ MRT_ALL_IN, ++ MRT_ALL_OUT, ++ MRT_UPDATE_IN, ++ MRT_UPDATE_OUT ++}; ++ ++enum mrt_state { ++ MRT_STATE_RUNNING, ++ MRT_STATE_OPEN, ++ MRT_STATE_REOPEN, ++ MRT_STATE_REMOVE + }; -SIMPLEQ_HEAD(rib_names, rde_rib); -extern struct rib_names ribnames; - @@ -580,26 +690,32 @@ diff -u -p -r1.1.1.8 -r1.12 -#define AFI_IPv4 1 -#define AFI_IPv6 2 -#define AFI_ALL 0xffff -- + -/* Subsequent Address Family Identifier as per RFC 4760 */ -#define SAFI_NONE 0x00 -#define SAFI_UNICAST 0x01 -#define SAFI_MULTICAST 0x02 -#define SAFI_ALL 0xff -- ++struct mrt { ++ char rib[PEER_DESCR_LEN]; ++ struct msgbuf wbuf; ++ LIST_ENTRY(mrt) entry; ++ u_int32_t peer_id; ++ u_int32_t group_id; ++ enum mrt_type type; ++ enum mrt_state state; ++ u_int16_t seqnum; ++}; + -/* 4-byte magic AS number */ -#define AS_TRANS 23456 -+/* macros for IPv6 link-local address */ -+#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER) -+#define IN6_LINKLOCAL_IFINDEX(addr) \ -+ ((addr).s6_addr[2] << 8 | (addr).s6_addr[3]) -+ -+#define SET_IN6_LINKLOCAL_IFINDEX(addr, index) \ -+ do { \ -+ (addr).s6_addr[2] = ((index) >> 8) & 0xff; \ -+ (addr).s6_addr[3] = (index) & 0xff; \ -+ } while (0) -+#endif ++struct mrt_config { ++ struct mrt conf; ++ char name[MRT_FILE_LEN]; /* base file name */ ++ char file[MRT_FILE_LEN]; /* actual file name */ ++ time_t ReopenTimer; ++ time_t ReopenTimerInterval; ++}; /* prototypes */ /* bgpd.c */ @@ -610,13 +726,25 @@ diff -u -p -r1.1.1.8 -r1.12 + struct filter_set_head *); int bgpd_filternexthop(struct kroute *, struct kroute6 *); - /* log.c */ - void log_init(int); -+void log_verbose(int); - void vlog(int, const char *, va_list); - void log_peer_warn(const struct peer_config *, const char *, ...); - void log_peer_warnx(const struct peer_config *, const char *, ...); -@@ -726,19 +900,22 @@ int cmdline_symset(char *); +-/* log.c */ +-void log_init(int); +-void vlog(int, const char *, va_list); +-void log_peer_warn(const struct peer_config *, const char *, ...); +-void log_peer_warnx(const struct peer_config *, const char *, ...); +-void log_warn(const char *, ...); +-void log_warnx(const char *, ...); +-void log_info(const char *, ...); +-void log_debug(const char *, ...); +-void fatal(const char *) __dead; +-void fatalx(const char *) __dead; +- +-/* parse.y */ +-int cmdline_symset(char *); ++/* control.c */ ++void control_cleanup(const char *); ++int control_imsg_relay(struct imsg *); + + /* config.c */ int host(const char *, struct bgpd_addr *, u_int8_t *); /* kroute.c */ @@ -648,7 +776,57 @@ diff -u -p -r1.1.1.8 -r1.12 int kr_reload(void); struct in6_addr *prefixlen2mask6(u_int8_t prefixlen); -@@ -772,6 +949,8 @@ void pftable_ref(u_int16_t); +-/* control.c */ +-void control_cleanup(const char *); +-int control_imsg_relay(struct imsg *); ++/* log.c */ ++void log_init(int); ++void log_verbose(int); ++void vlog(int, const char *, va_list); ++void log_peer_warn(const struct peer_config *, const char *, ...); ++void log_peer_warnx(const struct peer_config *, const char *, ...); ++void log_warn(const char *, ...); ++void log_warnx(const char *, ...); ++void log_info(const char *, ...); ++void log_debug(const char *, ...); ++void fatal(const char *) __dead; ++void fatalx(const char *) __dead; + +-/* pftable.c */ +-int pftable_exists(const char *); +-int pftable_add(const char *); +-int pftable_clear_all(void); +-int pftable_addr_add(struct pftable_msg *); +-int pftable_addr_remove(struct pftable_msg *); +-int pftable_commit(void); ++/* mrt.c */ ++void mrt_clear_seq(void); ++void mrt_write(struct mrt *); ++void mrt_clean(struct mrt *); ++void mrt_init(struct imsgbuf *, struct imsgbuf *); ++int mrt_timeout(struct mrt_head *); ++void mrt_reconfigure(struct mrt_head *); ++void mrt_handler(struct mrt_head *); ++struct mrt *mrt_get(struct mrt_head *, struct mrt *); ++int mrt_mergeconfig(struct mrt_head *, struct mrt_head *); + + /* name2id.c */ + u_int16_t rib_name2id(const char *); +@@ -768,10 +1001,22 @@ const char *pftable_id2name(u_int16_t); + void pftable_unref(u_int16_t); + void pftable_ref(u_int16_t); + ++/* parse.y */ ++int cmdline_symset(char *); ++ ++/* pftable.c */ ++int pftable_exists(const char *); ++int pftable_add(const char *); ++int pftable_clear_all(void); ++int pftable_addr_add(struct pftable_msg *); ++int pftable_addr_remove(struct pftable_msg *); ++int pftable_commit(void); + /* rde_filter.c */ void filterset_free(struct filter_set_head *); int filterset_cmp(struct filter_set *, struct filter_set *); @@ -657,7 +835,7 @@ diff -u -p -r1.1.1.8 -r1.12 const char *filterset_name(enum action_types); /* util.c */ -@@ -779,11 +958,20 @@ const char *log_addr(const struct bgpd_a +@@ -779,11 +1024,24 @@ const char *log_addr(const struct bgpd_a const char *log_in6addr(const struct in6_addr *); const char *log_sockaddr(struct sockaddr *); const char *log_as(u_int32_t); @@ -666,6 +844,10 @@ diff -u -p -r1.1.1.8 -r1.12 int aspath_snprint(char *, size_t, void *, u_int16_t); int aspath_asprint(char **, void *, u_int16_t); size_t aspath_strlen(void *, u_int16_t); ++int aspath_match(void *, u_int16_t, enum as_spec, u_int32_t); ++u_int32_t aspath_extract(const void *, int); ++int prefix_compare(const struct bgpd_addr *, ++ const struct bgpd_addr *, int); in_addr_t prefixlen2mask(u_int8_t); void inet6applymask(struct in6_addr *, const struct in6_addr *, int); diff --git a/net/openbgpd/files/patch-bgpd_carp.c b/net/openbgpd/files/patch-bgpd_carp.c index 7ed50075cd5c..4a93258dc940 100644 --- a/net/openbgpd/files/patch-bgpd_carp.c +++ b/net/openbgpd/files/patch-bgpd_carp.c @@ -2,10 +2,9 @@ Index: bgpd/carp.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/carp.c,v retrieving revision 1.1.1.6 -retrieving revision 1.4 -diff -u -p -r1.1.1.6 -r1.4 +diff -u -p -r1.1.1.6 carp.c --- bgpd/carp.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/carp.c 22 Oct 2009 15:10:02 -0000 1.4 ++++ bgpd/carp.c 13 Oct 2012 18:23:46 -0000 @@ -93,9 +93,8 @@ carp_demote_shutdown(void) while ((c = TAILQ_FIRST(&carpgroups)) != NULL) { diff --git a/net/openbgpd/files/patch-bgpd_config.c b/net/openbgpd/files/patch-bgpd_config.c index 3df03c1b3795..fbd02e102483 100644 --- a/net/openbgpd/files/patch-bgpd_config.c +++ b/net/openbgpd/files/patch-bgpd_config.c @@ -2,13 +2,13 @@ Index: bgpd/config.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/config.c,v retrieving revision 1.1.1.6 -retrieving revision 1.2 -diff -u -p -r1.1.1.6 -r1.2 +retrieving revision 1.3 +diff -u -p -r1.1.1.6 -r1.3 --- bgpd/config.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/config.c 2 Jul 2011 16:06:38 -0000 1.2 ++++ bgpd/config.c 13 Oct 2012 18:36:00 -0000 1.3 @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.51 2009/01/26 23:10:02 claudio Exp $ */ -+/* $OpenBSD: config.c,v 1.56 2010/10/24 17:20:08 deraadt Exp $ */ ++/* $OpenBSD: config.c,v 1.55 2010/09/02 14:03:21 sobrado Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> diff --git a/net/openbgpd/files/patch-bgpd_control.c b/net/openbgpd/files/patch-bgpd_control.c index 09c2ac85a831..5d6bade713cc 100644 --- a/net/openbgpd/files/patch-bgpd_control.c +++ b/net/openbgpd/files/patch-bgpd_control.c @@ -2,13 +2,13 @@ Index: bgpd/control.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/control.c,v retrieving revision 1.1.1.7 -retrieving revision 1.1.1.9 -diff -u -p -r1.1.1.7 -r1.1.1.9 +retrieving revision 1.1.1.10 +diff -u -p -r1.1.1.7 -r1.1.1.10 --- bgpd/control.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/control.c 12 Jun 2011 10:44:24 -0000 1.1.1.9 ++++ bgpd/control.c 13 Oct 2012 18:22:41 -0000 1.1.1.10 @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.61 2009/05/05 20:09:19 sthen Exp $ */ -+/* $OpenBSD: control.c,v 1.70 2010/10/29 12:51:53 henning Exp $ */ ++/* $OpenBSD: control.c,v 1.71 2012/04/12 17:26:09 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -21,11 +21,16 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 close(fd); return (-1); } -@@ -123,14 +123,14 @@ control_accept(int listenfd, int restric +@@ -122,15 +122,18 @@ control_accept(int listenfd, int restric + len = sizeof(sun); if ((connfd = accept(listenfd, (struct sockaddr *)&sun, &len)) == -1) { - if (errno != EWOULDBLOCK && errno != EINTR) +- if (errno != EWOULDBLOCK && errno != EINTR) - log_warn("session_control_accept"); ++ if (errno == ENFILE || errno == EMFILE) { ++ pauseaccept = getmonotime(); ++ return (0); ++ } else if (errno != EWOULDBLOCK && errno != EINTR) + log_warn("control_accept: accept"); return (0); } @@ -39,7 +44,16 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 close(connfd); return (0); } -@@ -191,7 +191,8 @@ control_dispatch_msg(struct pollfd *pfd, +@@ -182,7 +185,7 @@ control_close(int fd) + + close(c->ibuf.fd); + free(c); +- ++ pauseaccept = 0; + return (1); + } + +@@ -191,7 +194,8 @@ control_dispatch_msg(struct pollfd *pfd, { struct imsg imsg; struct ctl_conn *c; @@ -49,7 +63,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 struct peer *p; struct ctl_neighbor *neighbor; struct ctl_show_rib_request *ribreq; -@@ -305,7 +306,8 @@ control_dispatch_msg(struct pollfd *pfd, +@@ -305,7 +309,8 @@ control_dispatch_msg(struct pollfd *pfd, break; case IMSG_CTL_FIB_COUPLE: case IMSG_CTL_FIB_DECOUPLE: @@ -59,7 +73,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 break; case IMSG_CTL_NEIGHBOR_UP: case IMSG_CTL_NEIGHBOR_DOWN: -@@ -328,13 +330,19 @@ control_dispatch_msg(struct pollfd *pfd, +@@ -328,13 +333,19 @@ control_dispatch_msg(struct pollfd *pfd, control_result(c, CTL_RES_OK); break; case IMSG_CTL_NEIGHBOR_DOWN: @@ -83,7 +97,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 control_result(c, CTL_RES_OK); break; case IMSG_CTL_NEIGHBOR_RREFRESH: -@@ -352,13 +360,19 @@ control_dispatch_msg(struct pollfd *pfd, +@@ -352,13 +363,19 @@ control_dispatch_msg(struct pollfd *pfd, "wrong length"); break; case IMSG_CTL_RELOAD: @@ -106,7 +120,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 break; case IMSG_CTL_SHOW_RIB: case IMSG_CTL_SHOW_RIB_AS: -@@ -370,7 +384,7 @@ control_dispatch_msg(struct pollfd *pfd, +@@ -370,7 +387,7 @@ control_dispatch_msg(struct pollfd *pfd, neighbor->descr[PEER_DESCR_LEN - 1] = 0; ribreq->peerid = 0; p = NULL; @@ -115,7 +129,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 p = getpeerbyaddr(&neighbor->addr); if (p == NULL) { control_result(c, -@@ -397,8 +411,7 @@ control_dispatch_msg(struct pollfd *pfd, +@@ -397,8 +414,7 @@ control_dispatch_msg(struct pollfd *pfd, break; } if ((imsg.hdr.type == IMSG_CTL_SHOW_RIB_PREFIX) @@ -125,7 +139,16 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 /* malformed request, must specify af */ control_result(c, CTL_RES_PARSE_ERROR); break; -@@ -425,6 +438,20 @@ control_dispatch_msg(struct pollfd *pfd, +@@ -418,6 +434,8 @@ control_dispatch_msg(struct pollfd *pfd, + imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); + break; + case IMSG_NETWORK_ADD: ++ case IMSG_NETWORK_ASPATH: ++ case IMSG_NETWORK_ATTR: + case IMSG_NETWORK_REMOVE: + case IMSG_NETWORK_FLUSH: + case IMSG_NETWORK_DONE: +@@ -425,6 +443,20 @@ control_dispatch_msg(struct pollfd *pfd, imsg_compose_rde(imsg.hdr.type, 0, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); break; diff --git a/net/openbgpd/files/patch-bgpd_kroute.c b/net/openbgpd/files/patch-bgpd_kroute.c index 6f93029d60cd..963ad6653ce4 100644 --- a/net/openbgpd/files/patch-bgpd_kroute.c +++ b/net/openbgpd/files/patch-bgpd_kroute.c @@ -2,13 +2,13 @@ Index: bgpd/kroute.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/kroute.c,v retrieving revision 1.1.1.7 -retrieving revision 1.12 -diff -u -p -r1.1.1.7 -r1.12 +retrieving revision 1.13 +diff -u -p -r1.1.1.7 -r1.13 --- bgpd/kroute.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/kroute.c 3 Jul 2011 04:46:36 -0000 1.12 ++++ bgpd/kroute.c 13 Oct 2012 18:36:00 -0000 1.13 @@ -1,4 +1,4 @@ -/* $OpenBSD: kroute.c,v 1.169 2009/06/25 15:54:22 claudio Exp $ */ -+/* $OpenBSD: kroute.c,v 1.176 2010/04/06 13:25:08 claudio Exp $ */ ++/* $OpenBSD: kroute.c,v 1.189 2012/05/27 18:52:07 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -106,7 +106,7 @@ diff -u -p -r1.1.1.7 -r1.12 struct kif_node *kif_find(int); int kif_insert(struct kif_node *); -@@ -124,13 +148,15 @@ int kif_kr6_remove(struct kroute6_nod +@@ -124,13 +148,16 @@ int kif_kr6_remove(struct kroute6_nod int kif_validate(struct kif *); int kroute_validate(struct kroute *); int kroute6_validate(struct kroute6 *); @@ -118,6 +118,7 @@ diff -u -p -r1.1.1.7 -r1.12 +void knexthop_validate(struct ktable *, + struct knexthop_node *); +void knexthop_track(struct ktable *, void *); ++void knexthop_send_update(struct knexthop_node *); +struct kroute_node *kroute_match(struct ktable *, in_addr_t, int); +struct kroute6_node *kroute6_match(struct ktable *, struct in6_addr *, int); +void kroute_detach_nexthop(struct ktable *, @@ -128,7 +129,7 @@ diff -u -p -r1.1.1.7 -r1.12 u_int8_t prefixlen_classful(in_addr_t); u_int8_t mask2prefixlen(in_addr_t); u_int8_t mask2prefixlen6(struct sockaddr_in6 *); -@@ -138,23 +164,20 @@ void get_rtaddrs(int, struct sockaddr * +@@ -138,23 +165,20 @@ void get_rtaddrs(int, struct sockaddr * void if_change(u_short, int, struct if_data *); void if_announce(void *); @@ -156,7 +157,7 @@ diff -u -p -r1.1.1.7 -r1.12 RB_PROTOTYPE(knexthop_tree, knexthop_node, entry, knexthop_compare) RB_GENERATE(knexthop_tree, knexthop_node, entry, knexthop_compare) -@@ -162,19 +185,21 @@ RB_HEAD(kif_tree, kif_node) kit; +@@ -162,19 +186,21 @@ RB_HEAD(kif_tree, kif_node) kit; RB_PROTOTYPE(kif_tree, kif_node, entry, kif_compare) RB_GENERATE(kif_tree, kif_node, entry, kif_compare) @@ -182,7 +183,7 @@ diff -u -p -r1.1.1.7 -r1.12 if ((kr_state.fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) { log_warn("kr_init: socket"); return (-1); -@@ -198,194 +223,533 @@ kr_init(int fs, u_int rtableid) +@@ -198,194 +224,533 @@ kr_init(int fs, u_int rtableid) rcvbuf /= 2) ; /* nothing */ @@ -399,9 +400,10 @@ diff -u -p -r1.1.1.7 -r1.12 + else if (kt->state == RECONF_REINIT) + kt->fib_sync = kt->fib_conf; + } -+} -+ -+int + } + + int +-kr_change(struct kroute_label *kl) +ktable_exists(u_int rtableid, u_int *rdomid) +{ +#if !defined(__FreeBSD__) /* FreeBSD does not have NET_RT_TABLE. */ @@ -431,10 +433,9 @@ diff -u -p -r1.1.1.7 -r1.12 + *rdomid = 0; +#endif + return (1); - } - - int --kr_change(struct kroute_label *kl) ++} ++ ++int +kr_change(u_int rtableid, struct kroute_full *kl) +{ + struct ktable *kt; @@ -564,7 +565,8 @@ diff -u -p -r1.1.1.7 -r1.12 + /* for blackhole and reject routes nexthop needs to be ::1 */ + if (kl->flags & (F_BLACKHOLE|F_REJECT)) + bcopy(&lo6, &kl->nexthop.v6, sizeof(kl->nexthop.v6)); -+ + +- rtlabel_unref(kl->kr.labelid); + if (action == RTM_ADD) { + if ((kr6 = calloc(1, sizeof(struct kroute6_node))) == NULL) { + log_warn("kr_change"); @@ -577,8 +579,7 @@ diff -u -p -r1.1.1.7 -r1.12 + kr6->r.flags = kl->flags | F_BGPD_INSERTED; + kr6->r.priority = RTP_BGP; + kr6->r.labelid = labelid; - -- rtlabel_unref(kl->kr.labelid); ++ + if (kroute6_insert(kt, kr6) == -1) + free(kr6); + } else { @@ -700,15 +701,16 @@ diff -u -p -r1.1.1.7 -r1.12 else - kr6->r.flags &= ~F_REJECT; + kr->r.flags &= ~F_REJECT; -+ } -+ + } + + if (send_rtmsg(kr_state.fd, action, kt, &kr->r) == -1) + return (-1); + -+ return (0); -+} -+ -+int + return (0); + } + + int +-kr6_delete(struct kroute6_label *kl) +kr_delete(u_int rtableid, struct kroute_full *kl) +{ + struct ktable *kt; @@ -724,7 +726,7 @@ diff -u -p -r1.1.1.7 -r1.12 + return (kr6_delete(kt, kl)); + case AID_VPN_IPv4: + return (krVPN4_delete(kt, kl)); - } ++ } + log_warnx("kr_change: not handled AID"); + return (-1); +} @@ -748,12 +750,11 @@ diff -u -p -r1.1.1.7 -r1.12 + + if (kroute_remove(kt, kr) == -1) + return (-1); - - return (0); - } - - int --kr6_delete(struct kroute6_label *kl) ++ ++ return (0); ++} ++ ++int +kr6_delete(struct ktable *kt, struct kroute_full *kl) { struct kroute6_node *kr6; @@ -804,7 +805,7 @@ diff -u -p -r1.1.1.7 -r1.12 return (-1); return (0); -@@ -394,53 +758,63 @@ kr6_delete(struct kroute6_label *kl) +@@ -394,53 +759,63 @@ kr6_delete(struct kroute6_label *kl) void kr_shutdown(void) { @@ -888,7 +889,7 @@ diff -u -p -r1.1.1.7 -r1.12 } int -@@ -450,11 +824,16 @@ kr_dispatch_msg(void) +@@ -450,41 +825,18 @@ kr_dispatch_msg(void) } int @@ -905,46 +906,40 @@ diff -u -p -r1.1.1.7 -r1.12 + } + if ((h = knexthop_find(kt, addr)) != NULL) { /* should not happen... this is actually an error path */ - struct kroute_nexthop nh; - struct kroute_node *k; -@@ -463,25 +842,30 @@ kr_nexthop_add(struct bgpd_addr *addr) - bzero(&nh, sizeof(nh)); - memcpy(&nh.nexthop, addr, sizeof(nh.nexthop)); - nh.valid = 1; +- struct kroute_nexthop nh; +- struct kroute_node *k; +- struct kroute6_node *k6; +- +- bzero(&nh, sizeof(nh)); +- memcpy(&nh.nexthop, addr, sizeof(nh.nexthop)); +- nh.valid = 1; - if (h->kroute != NULL && addr->af == AF_INET) { -+ if (h->kroute != NULL && addr->aid == AID_INET) { - k = h->kroute; - nh.connected = k->r.flags & F_CONNECTED; - if (k->r.nexthop.s_addr != 0) { +- k = h->kroute; +- nh.connected = k->r.flags & F_CONNECTED; +- if (k->r.nexthop.s_addr != 0) { - nh.gateway.af = AF_INET; -+ nh.gateway.aid = AID_INET; - nh.gateway.v4.s_addr = - k->r.nexthop.s_addr; - } +- nh.gateway.v4.s_addr = +- k->r.nexthop.s_addr; +- } - memcpy(&nh.kr.kr4, &k->r, sizeof(nh.kr.kr4)); - } else if (h->kroute != NULL && addr->af == AF_INET6) { -+ nh.net.aid = AID_INET; -+ nh.net.v4.s_addr = k->r.prefix.s_addr; -+ nh.netlen = k->r.prefixlen; -+ } else if (h->kroute != NULL && addr->aid == AID_INET6) { - k6 = h->kroute; - nh.connected = k6->r.flags & F_CONNECTED; - if (memcmp(&k6->r.nexthop, &in6addr_any, - sizeof(struct in6_addr)) != 0) { +- k6 = h->kroute; +- nh.connected = k6->r.flags & F_CONNECTED; +- if (memcmp(&k6->r.nexthop, &in6addr_any, +- sizeof(struct in6_addr)) != 0) { - nh.gateway.af = AF_INET6; -+ nh.gateway.aid = AID_INET6; - memcpy(&nh.gateway.v6, &k6->r.nexthop, - sizeof(struct in6_addr)); - } +- memcpy(&nh.gateway.v6, &k6->r.nexthop, +- sizeof(struct in6_addr)); +- } - memcpy(&nh.kr.kr6, &k6->r, sizeof(nh.kr.kr6)); -+ nh.net.aid = AID_INET6; -+ memcpy(&nh.net.v6, &k6->r.nexthop, -+ sizeof(struct in6_addr)); -+ nh.netlen = k6->r.prefixlen; - } - - send_nexthop_update(&nh); -@@ -492,7 +876,7 @@ kr_nexthop_add(struct bgpd_addr *addr) +- } +- +- send_nexthop_update(&nh); ++ knexthop_send_update(h); + } else { + if ((h = calloc(1, sizeof(struct knexthop_node))) == NULL) { + log_warn("kr_nexthop_add"); +@@ -492,7 +844,7 @@ kr_nexthop_add(struct bgpd_addr *addr) } memcpy(&h->nexthop, addr, sizeof(h->nexthop)); @@ -953,7 +948,7 @@ diff -u -p -r1.1.1.7 -r1.12 return (-1); } -@@ -500,19 +884,25 @@ kr_nexthop_add(struct bgpd_addr *addr) +@@ -500,19 +852,26 @@ kr_nexthop_add(struct bgpd_addr *addr) } void @@ -965,7 +960,8 @@ diff -u -p -r1.1.1.7 -r1.12 - if ((kn = knexthop_find(addr)) == NULL) + if ((kt = ktable_get(rtableid)) == NULL) { -+ log_warnx("kr_nexthop_add: non-existent rtableid %d", rtableid); ++ log_warnx("kr_nexthop_delete: non-existent rtableid %d", ++ rtableid); + return; + } + if ((kn = knexthop_find(kt, addr)) == NULL) @@ -982,7 +978,7 @@ diff -u -p -r1.1.1.7 -r1.12 struct kroute_node *kr, *kn; struct kroute6_node *kr6, *kn6; struct bgpd_addr *addr; -@@ -521,6 +911,7 @@ kr_show_route(struct imsg *imsg) +@@ -521,6 +880,7 @@ kr_show_route(struct imsg *imsg) struct ctl_show_nexthop snh; struct knexthop_node *h; struct kif_node *kif; @@ -990,7 +986,7 @@ diff -u -p -r1.1.1.7 -r1.12 u_short ifindex = 0; switch (imsg->hdr.type) { -@@ -528,70 +919,96 @@ kr_show_route(struct imsg *imsg) +@@ -528,70 +888,96 @@ kr_show_route(struct imsg *imsg) if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(flags) + sizeof(af)) { log_warnx("kr_show_route: wrong imsg len"); @@ -1121,7 +1117,7 @@ diff -u -p -r1.1.1.7 -r1.12 ifindex = kr6->r.ifindex; break; } -@@ -608,6 +1025,24 @@ kr_show_route(struct imsg *imsg) +@@ -608,6 +994,24 @@ kr_show_route(struct imsg *imsg) send_imsg_session(IMSG_CTL_SHOW_INTERFACE, imsg->hdr.pid, &kif->k, sizeof(kif->k)); break; @@ -1146,7 +1142,7 @@ diff -u -p -r1.1.1.7 -r1.12 default: /* nada */ break; } -@@ -628,21 +1063,146 @@ kr_ifinfo(char *ifname) +@@ -628,21 +1032,152 @@ kr_ifinfo(char *ifname) } } @@ -1185,11 +1181,14 @@ diff -u -p -r1.1.1.7 -r1.12 + if (kr->flags & F_CONNECTED) + return (xn); + break; ++ case NETWORK_MRTCLONE: ++ /* can not happen */ ++ break; + } + } + return (NULL); +} -+ + +struct network * +kr_net_match6(struct ktable *kt, struct kroute6 *kr6) +{ @@ -1214,11 +1213,15 @@ diff -u -p -r1.1.1.7 -r1.12 + if (kr6->flags & F_CONNECTED) + return (xn); + break; ++ case NETWORK_MRTCLONE: ++ /* can not happen */ ++ break; + } + } + return (NULL); +} -+ + +-LIST_HEAD(, redist_node) redistlist; +struct network * +kr_net_find(struct ktable *kt, struct network *n) +{ @@ -1235,10 +1238,12 @@ diff -u -p -r1.1.1.7 -r1.12 + } + return (NULL); +} -+ -+int + + int +-kr_redistribute(int type, struct kroute *kr) +kr_net_reload(u_int rtableid, struct network_head *nh) -+{ + { +- struct redist_node *rn; + struct network *n, *xn; + struct ktable *kt; + @@ -1263,7 +1268,7 @@ diff -u -p -r1.1.1.7 -r1.12 + } else + TAILQ_INSERT_TAIL(&kt->krn, n, entry); + } - ++ + for (n = TAILQ_FIRST(&kt->krn); n != NULL; n = xn) { + xn = TAILQ_NEXT(n, entry); + if (n->net.old) { @@ -1275,16 +1280,13 @@ diff -u -p -r1.1.1.7 -r1.12 + kr_net_delete(n); + } + } - --LIST_HEAD(, redist_node) redistlist; ++ + return (0); +} - - int --kr_redistribute(int type, struct kroute *kr) ++ ++int +kr_redistribute(int type, struct ktable *kt, struct kroute *kr) - { -- struct redist_node *rn; ++{ + struct network *match; + struct network_config net; u_int32_t a; @@ -1301,7 +1303,7 @@ diff -u -p -r1.1.1.7 -r1.12 if (!(kr->flags & F_KERNEL)) return (0); -@@ -670,41 +1230,40 @@ kr_redistribute(int type, struct kroute +@@ -670,41 +1205,40 @@ kr_redistribute(int type, struct kroute if (kr->prefix.s_addr == INADDR_ANY && kr->prefixlen == 0) return (0); @@ -1374,7 +1376,7 @@ diff -u -p -r1.1.1.7 -r1.12 if (!(kr6->flags & F_KERNEL)) return (0); -@@ -736,60 +1295,107 @@ kr_redistribute6(int type, struct kroute +@@ -736,60 +1270,107 @@ kr_redistribute6(int type, struct kroute * never allow ::/0 the default route can only be redistributed * with announce default. */ @@ -1452,12 +1454,12 @@ diff -u -p -r1.1.1.7 -r1.12 + for (rid = 0; rid < krt_size; rid++) { + if ((kt = ktable_get(rid)) == NULL) + continue; ++ ++ RB_FOREACH(nh, knexthop_tree, KT2KNT(kt)) ++ knexthop_validate(kt, nh); - RB_FOREACH(nh, knexthop_tree, &knt) - knexthop_validate(nh); -+ RB_FOREACH(nh, knexthop_tree, KT2KNT(kt)) -+ knexthop_validate(kt, nh); -+ + TAILQ_FOREACH(n, &kt->krn, entry) + if (n->net.type == NETWORK_DEFAULT) { + if (send_network(IMSG_NETWORK_ADD, &n->net, @@ -1521,7 +1523,7 @@ diff -u -p -r1.1.1.7 -r1.12 /* * RB-tree compare functions */ -@@ -846,26 +1452,28 @@ kroute6_compare(struct kroute6_node *a, +@@ -846,26 +1427,28 @@ kroute6_compare(struct kroute6_node *a, int knexthop_compare(struct knexthop_node *a, struct knexthop_node *b) { @@ -1566,7 +1568,7 @@ diff -u -p -r1.1.1.7 -r1.12 } return (0); -@@ -883,7 +1491,8 @@ kif_compare(struct kif_node *a, struct k +@@ -883,7 +1466,8 @@ kif_compare(struct kif_node *a, struct k */ struct kroute_node * @@ -1576,7 +1578,7 @@ diff -u -p -r1.1.1.7 -r1.12 { struct kroute_node s; struct kroute_node *kn, *tmp; -@@ -892,15 +1501,15 @@ kroute_find(in_addr_t prefix, u_int8_t p +@@ -892,15 +1476,15 @@ kroute_find(in_addr_t prefix, u_int8_t p s.r.prefixlen = prefixlen; s.r.priority = prio; @@ -1595,7 +1597,7 @@ diff -u -p -r1.1.1.7 -r1.12 } } return (kn); -@@ -927,13 +1536,13 @@ kroute_matchgw(struct kroute_node *kr, s +@@ -927,13 +1511,13 @@ kroute_matchgw(struct kroute_node *kr, s } int @@ -1611,7 +1613,11 @@ diff -u -p -r1.1.1.7 -r1.12 /* multipath route, add at end of list */ while (krm->next != NULL) krm = krm->next; -@@ -944,10 +1553,10 @@ kroute_insert(struct kroute_node *kr) +@@ -941,13 +1525,14 @@ kroute_insert(struct kroute_node *kr) + kr->next = NULL; /* to be sure */ + } + ++ /* XXX this is wrong for nexthop validated via BGP */ if (kr->r.flags & F_KERNEL) { mask = prefixlen2mask(kr->r.prefixlen); ina = ntohl(kr->r.prefix.s_addr); @@ -1625,7 +1631,7 @@ diff -u -p -r1.1.1.7 -r1.12 if (kr->r.flags & F_CONNECTED) if (kif_kr_insert(kr) == -1) -@@ -955,19 +1564,19 @@ kroute_insert(struct kroute_node *kr) +@@ -955,19 +1540,19 @@ kroute_insert(struct kroute_node *kr) if (krm == NULL) /* redistribute multipath routes only once */ @@ -1648,7 +1654,7 @@ diff -u -p -r1.1.1.7 -r1.12 log_warnx("kroute_remove failed to find %s/%u", inet_ntoa(kr->r.prefix), kr->r.prefixlen); return (-1); -@@ -975,13 +1584,14 @@ kroute_remove(struct kroute_node *kr) +@@ -975,13 +1560,14 @@ kroute_remove(struct kroute_node *kr) if (krm == kr) { /* head element */ @@ -1665,11 +1671,13 @@ diff -u -p -r1.1.1.7 -r1.12 log_warnx("kroute_remove failed to add %s/%u", inet_ntoa(kr->r.prefix), kr->r.prefixlen); return (-1); -@@ -1002,13 +1612,13 @@ kroute_remove(struct kroute_node *kr) +@@ -1001,14 +1587,14 @@ kroute_remove(struct kroute_node *kr) + } /* check whether a nexthop depends on this kroute */ - if ((kr->r.flags & F_KERNEL) && (kr->r.flags & F_NEXTHOP)) +- if ((kr->r.flags & F_KERNEL) && (kr->r.flags & F_NEXTHOP)) - RB_FOREACH(s, knexthop_tree, &knt) ++ if (kr->r.flags & F_NEXTHOP) + RB_FOREACH(s, knexthop_tree, KT2KNT(kt)) if (s->kroute == kr) - knexthop_validate(s); @@ -1682,7 +1690,7 @@ diff -u -p -r1.1.1.7 -r1.12 if (kr->r.flags & F_CONNECTED) if (kif_kr_remove(kr) == -1) { -@@ -1021,16 +1631,17 @@ kroute_remove(struct kroute_node *kr) +@@ -1021,16 +1607,17 @@ kroute_remove(struct kroute_node *kr) } void @@ -1704,7 +1712,7 @@ diff -u -p -r1.1.1.7 -r1.12 { struct kroute6_node s; struct kroute6_node *kn6, *tmp; -@@ -1039,15 +1650,15 @@ kroute6_find(const struct in6_addr *pref +@@ -1039,15 +1626,15 @@ kroute6_find(const struct in6_addr *pref s.r.prefixlen = prefixlen; s.r.priority = prio; @@ -1724,7 +1732,7 @@ diff -u -p -r1.1.1.7 -r1.12 } } return (kn6); -@@ -1065,7 +1676,7 @@ kroute6_matchgw(struct kroute6_node *kr, +@@ -1065,7 +1652,7 @@ kroute6_matchgw(struct kroute6_node *kr, memcpy(&nexthop, &sa_in6->sin6_addr, sizeof(nexthop)); while (kr) { @@ -1733,7 +1741,7 @@ diff -u -p -r1.1.1.7 -r1.12 return (kr); kr = kr->next; } -@@ -1074,13 +1685,13 @@ kroute6_matchgw(struct kroute6_node *kr, +@@ -1074,13 +1661,13 @@ kroute6_matchgw(struct kroute6_node *kr, } int @@ -1749,8 +1757,11 @@ diff -u -p -r1.1.1.7 -r1.12 /* multipath route, add at end of list */ while (krm->next != NULL) krm = krm->next; -@@ -1090,12 +1701,12 @@ kroute6_insert(struct kroute6_node *kr) +@@ -1088,14 +1675,15 @@ kroute6_insert(struct kroute6_node *kr) + kr->next = NULL; /* to be sure */ + } ++ /* XXX this is wrong for nexthop validated via BGP */ if (kr->r.flags & F_KERNEL) { inet6applymask(&ina, &kr->r.prefix, kr->r.prefixlen); - RB_FOREACH(h, knexthop_tree, &knt) @@ -1765,7 +1776,7 @@ diff -u -p -r1.1.1.7 -r1.12 } if (kr->r.flags & F_CONNECTED) -@@ -1104,19 +1715,19 @@ kroute6_insert(struct kroute6_node *kr) +@@ -1104,19 +1692,19 @@ kroute6_insert(struct kroute6_node *kr) if (krm == NULL) /* redistribute multipath routes only once */ @@ -1788,7 +1799,7 @@ diff -u -p -r1.1.1.7 -r1.12 log_warnx("kroute6_remove failed for %s/%u", log_in6addr(&kr->r.prefix), kr->r.prefixlen); return (-1); -@@ -1124,13 +1735,14 @@ kroute6_remove(struct kroute6_node *kr) +@@ -1124,13 +1712,14 @@ kroute6_remove(struct kroute6_node *kr) if (krm == kr) { /* head element */ @@ -1805,11 +1816,13 @@ diff -u -p -r1.1.1.7 -r1.12 log_warnx("kroute6_remove failed to add %s/%u", log_in6addr(&kr->r.prefix), kr->r.prefixlen); -@@ -1152,13 +1764,13 @@ kroute6_remove(struct kroute6_node *kr) +@@ -1151,14 +1740,14 @@ kroute6_remove(struct kroute6_node *kr) + } /* check whether a nexthop depends on this kroute */ - if ((kr->r.flags & F_KERNEL) && (kr->r.flags & F_NEXTHOP)) +- if ((kr->r.flags & F_KERNEL) && (kr->r.flags & F_NEXTHOP)) - RB_FOREACH(s, knexthop_tree, &knt) ++ if (kr->r.flags & F_NEXTHOP) + RB_FOREACH(s, knexthop_tree, KT2KNT(kt)) if (s->kroute == kr) - knexthop_validate(s); @@ -1822,7 +1835,7 @@ diff -u -p -r1.1.1.7 -r1.12 if (kr->r.flags & F_CONNECTED) if (kif_kr6_remove(kr) == -1) { -@@ -1171,45 +1783,46 @@ kroute6_remove(struct kroute6_node *kr) +@@ -1171,45 +1760,46 @@ kroute6_remove(struct kroute6_node *kr) } void @@ -1880,7 +1893,7 @@ diff -u -p -r1.1.1.7 -r1.12 log_warnx("knexthop_remove failed for %s", log_addr(&kn->nexthop)); return (-1); -@@ -1220,12 +1833,12 @@ knexthop_remove(struct knexthop_node *kn +@@ -1220,12 +1810,12 @@ knexthop_remove(struct knexthop_node *kn } void @@ -1896,7 +1909,7 @@ diff -u -p -r1.1.1.7 -r1.12 } struct kif_node * -@@ -1257,6 +1870,7 @@ kif_insert(struct kif_node *kif) +@@ -1257,6 +1847,7 @@ kif_insert(struct kif_node *kif) int kif_remove(struct kif_node *kif) { @@ -1904,7 +1917,7 @@ diff -u -p -r1.1.1.7 -r1.12 struct kif_kr *kkr; struct kif_kr6 *kkr6; -@@ -1265,20 +1879,23 @@ kif_remove(struct kif_node *kif) +@@ -1265,20 +1856,23 @@ kif_remove(struct kif_node *kif) return (-1); } @@ -1931,81 +1944,95 @@ diff -u -p -r1.1.1.7 -r1.12 free(kif); return (0); } -@@ -1473,25 +2090,25 @@ kroute6_validate(struct kroute6 *kr) +@@ -1473,113 +2067,109 @@ kroute6_validate(struct kroute6 *kr) } void -knexthop_validate(struct knexthop_node *kn) +knexthop_validate(struct ktable *kt, struct knexthop_node *kn) { ++ void *oldk; struct kroute_node *kr; struct kroute6_node *kr6; - struct kroute_nexthop n; - int was_valid = 0; +- struct kroute_nexthop n; +- int was_valid = 0; - if (kn->nexthop.af == AF_INET && (kr = kn->kroute) != NULL) -+ if (kn->nexthop.aid == AID_INET && (kr = kn->kroute) != NULL) - was_valid = kroute_validate(&kr->r); +- was_valid = kroute_validate(&kr->r); - if (kn->nexthop.af == AF_INET6 && (kr6 = kn->kroute) != NULL) -+ if (kn->nexthop.aid == AID_INET6 && (kr6 = kn->kroute) != NULL) - was_valid = kroute6_validate(&kr6->r); - - bzero(&n, sizeof(n)); - memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop)); -- kroute_detach_nexthop(kn); +- was_valid = kroute6_validate(&kr6->r); ++ oldk = kn->kroute; + kroute_detach_nexthop(kt, kn); +- bzero(&n, sizeof(n)); +- memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop)); +- kroute_detach_nexthop(kn); +- - switch (kn->nexthop.af) { - case AF_INET: - if ((kr = kroute_match(kn->nexthop.v4.s_addr, 0)) == NULL) { -+ switch (kn->nexthop.aid) { -+ case AID_INET: -+ if ((kr = kroute_match(kt, kn->nexthop.v4.s_addr, 0)) == NULL) { - if (was_valid) - send_nexthop_update(&n); - } else { /* match */ -@@ -1500,8 +2117,10 @@ knexthop_validate(struct knexthop_node * - n.connected = kr->r.flags & F_CONNECTED; - if ((n.gateway.v4.s_addr = - kr->r.nexthop.s_addr) != 0) +- if (was_valid) +- send_nexthop_update(&n); +- } else { /* match */ +- if (kroute_validate(&kr->r)) { /* valid */ +- n.valid = 1; +- n.connected = kr->r.flags & F_CONNECTED; +- if ((n.gateway.v4.s_addr = +- kr->r.nexthop.s_addr) != 0) - n.gateway.af = AF_INET; - memcpy(&n.kr.kr4, &kr->r, sizeof(n.kr.kr4)); -+ n.gateway.aid = AID_INET; -+ n.net.aid = AID_INET; -+ n.net.v4.s_addr = kr->r.prefix.s_addr; -+ n.netlen = kr->r.prefixlen; - send_nexthop_update(&n); - } else /* down */ - if (was_valid) -@@ -1511,8 +2130,8 @@ knexthop_validate(struct knexthop_node * +- send_nexthop_update(&n); +- } else /* down */ +- if (was_valid) +- send_nexthop_update(&n); ++ switch (kn->nexthop.aid) { ++ case AID_INET: ++ kr = kroute_match(kt, kn->nexthop.v4.s_addr, 0); + ++ if (kr) { + kn->kroute = kr; kr->r.flags |= F_NEXTHOP; } ++ ++ /* ++ * Send update if nexthop route changed under us if ++ * the route remains the same then the NH state has not ++ * changed. State changes are tracked by knexthop_track(). ++ */ ++ if (kr != oldk) ++ knexthop_send_update(kn); break; - case AF_INET6: - if ((kr6 = kroute6_match(&kn->nexthop.v6, 0)) == NULL) { -+ case AID_INET6: -+ if ((kr6 = kroute6_match(kt, &kn->nexthop.v6, 0)) == NULL) { - if (was_valid) - send_nexthop_update(&n); - } else { /* match */ -@@ -1521,11 +2140,14 @@ knexthop_validate(struct knexthop_node * - n.connected = kr6->r.flags & F_CONNECTED; - if (memcmp(&kr6->r.nexthop, &in6addr_any, - sizeof(struct in6_addr)) != 0) { +- if (was_valid) +- send_nexthop_update(&n); +- } else { /* match */ +- if (kroute6_validate(&kr6->r)) { /* valid */ +- n.valid = 1; +- n.connected = kr6->r.flags & F_CONNECTED; +- if (memcmp(&kr6->r.nexthop, &in6addr_any, +- sizeof(struct in6_addr)) != 0) { - n.gateway.af = AF_INET6; -+ n.gateway.aid = AID_INET6; - memcpy(&n.gateway.v6, &kr6->r.nexthop, - sizeof(struct in6_addr)); - } +- memcpy(&n.gateway.v6, &kr6->r.nexthop, +- sizeof(struct in6_addr)); +- } - memcpy(&n.kr.kr6, &kr6->r, sizeof(n.kr.kr6)); -+ n.net.aid = AID_INET6; -+ memcpy(&n.net.v6, &kr6->r.nexthop, -+ sizeof(struct in6_addr)); -+ n.netlen = kr6->r.prefixlen; - send_nexthop_update(&n); - } else /* down */ - if (was_valid) -@@ -1539,39 +2161,44 @@ knexthop_validate(struct knexthop_node * +- send_nexthop_update(&n); +- } else /* down */ +- if (was_valid) +- send_nexthop_update(&n); ++ case AID_INET6: ++ kr6 = kroute6_match(kt, &kn->nexthop.v6, 0); + ++ if (kr6) { + kn->kroute = kr6; + kr6->r.flags |= F_NEXTHOP; + } ++ ++ if (kr6 != oldk) ++ knexthop_send_update(kn); + break; + } } void @@ -2013,56 +2040,90 @@ diff -u -p -r1.1.1.7 -r1.12 +knexthop_track(struct ktable *kt, void *krp) { struct knexthop_node *kn; ++ ++ RB_FOREACH(kn, knexthop_tree, KT2KNT(kt)) ++ if (kn->kroute == krp) ++ knexthop_send_update(kn); ++} ++ ++void ++knexthop_send_update(struct knexthop_node *kn) ++{ ++ struct kroute_nexthop n; struct kroute_node *kr; struct kroute6_node *kr6; - struct kroute_nexthop n; +- struct kroute_nexthop n; - RB_FOREACH(kn, knexthop_tree, &knt) - if (kn->kroute == krn) { -+ RB_FOREACH(kn, knexthop_tree, KT2KNT(kt)) -+ if (kn->kroute == krp) { - bzero(&n, sizeof(n)); - memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop)); +- bzero(&n, sizeof(n)); +- memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop)); ++ bzero(&n, sizeof(n)); ++ memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop)); - switch (kn->nexthop.af) { - case AF_INET: - kr = krn; -+ switch (kn->nexthop.aid) { -+ case AID_INET: -+ kr = krp; - n.valid = 1; - n.connected = kr->r.flags & F_CONNECTED; - if ((n.gateway.v4.s_addr = - kr->r.nexthop.s_addr) != 0) +- n.valid = 1; +- n.connected = kr->r.flags & F_CONNECTED; +- if ((n.gateway.v4.s_addr = +- kr->r.nexthop.s_addr) != 0) - n.gateway.af = AF_INET; - memcpy(&n.kr.kr4, &kr->r, sizeof(n.kr.kr4)); -+ n.gateway.aid = AID_INET; -+ n.net.aid = AID_INET; -+ n.net.v4.s_addr = kr->r.prefix.s_addr; -+ n.netlen = kr->r.prefixlen; - break; +- break; - case AF_INET6: - kr6 = krn; -+ case AID_INET6: -+ kr6 = krp; - n.valid = 1; - n.connected = kr6->r.flags & F_CONNECTED; - if (memcmp(&kr6->r.nexthop, &in6addr_any, - sizeof(struct in6_addr)) != 0) { +- n.valid = 1; +- n.connected = kr6->r.flags & F_CONNECTED; +- if (memcmp(&kr6->r.nexthop, &in6addr_any, +- sizeof(struct in6_addr)) != 0) { - n.gateway.af = AF_INET6; -+ n.gateway.aid = AID_INET6; - memcpy(&n.gateway.v6, &kr6->r.nexthop, - sizeof(struct in6_addr)); - } +- memcpy(&n.gateway.v6, &kr6->r.nexthop, +- sizeof(struct in6_addr)); +- } - memcpy(&n.kr.kr6, &kr6->r, sizeof(n.kr.kr6)); -+ n.net.aid = AID_INET6; -+ memcpy(&n.net.v6, &kr6->r.nexthop, -+ sizeof(struct in6_addr)); -+ n.netlen = kr6->r.prefixlen; - break; - } - send_nexthop_update(&n); -@@ -1579,7 +2206,7 @@ knexthop_track(void *krn) +- break; +- } +- send_nexthop_update(&n); ++ if (kn->kroute == NULL) { ++ n.valid = 0; /* NH is not valid */ ++ send_nexthop_update(&n); ++ return; ++ } ++ ++ switch (kn->nexthop.aid) { ++ case AID_INET: ++ kr = kn->kroute; ++ n.valid = kroute_validate(&kr->r); ++ n.connected = kr->r.flags & F_CONNECTED; ++ if ((n.gateway.v4.s_addr = ++ kr->r.nexthop.s_addr) != 0) ++ n.gateway.aid = AID_INET; ++ if (n.connected) { ++ n.net.aid = AID_INET; ++ n.net.v4.s_addr = kr->r.prefix.s_addr; ++ n.netlen = kr->r.prefixlen; ++ } ++ break; ++ case AID_INET6: ++ kr6 = kn->kroute; ++ n.valid = kroute6_validate(&kr6->r); ++ n.connected = kr6->r.flags & F_CONNECTED; ++ if (memcmp(&kr6->r.nexthop, &in6addr_any, ++ sizeof(struct in6_addr)) != 0) { ++ n.gateway.aid = AID_INET6; ++ memcpy(&n.gateway.v6, &kr6->r.nexthop, ++ sizeof(struct in6_addr)); ++ } ++ if (n.connected) { ++ n.net.aid = AID_INET6; ++ memcpy(&n.net.v6, &kr6->r.nexthop, ++ sizeof(struct in6_addr)); ++ n.netlen = kr6->r.prefixlen; + } ++ break; ++ } ++ send_nexthop_update(&n); } struct kroute_node * @@ -2071,7 +2132,7 @@ diff -u -p -r1.1.1.7 -r1.12 { int i; struct kroute_node *kr; -@@ -1589,13 +2216,13 @@ kroute_match(in_addr_t key, int matchall +@@ -1589,13 +2179,13 @@ kroute_match(in_addr_t key, int matchall /* we will never match the default route */ for (i = 32; i > 0; i--) @@ -2087,7 +2148,7 @@ diff -u -p -r1.1.1.7 -r1.12 if (matchall || bgpd_filternexthop(&kr->r, NULL) == 0) return (kr); -@@ -1603,7 +2230,7 @@ kroute_match(in_addr_t key, int matchall +@@ -1603,7 +2193,7 @@ kroute_match(in_addr_t key, int matchall } struct kroute6_node * @@ -2096,7 +2157,7 @@ diff -u -p -r1.1.1.7 -r1.12 { int i; struct kroute6_node *kr6; -@@ -1612,13 +2239,13 @@ kroute6_match(struct in6_addr *key, int +@@ -1612,13 +2202,13 @@ kroute6_match(struct in6_addr *key, int /* we will never match the default route */ for (i = 128; i > 0; i--) { inet6applymask(&ina, key, i); @@ -2112,7 +2173,7 @@ diff -u -p -r1.1.1.7 -r1.12 if (matchall || bgpd_filternexthop(NULL, &kr6->r) == 0) return (kr6); -@@ -1626,7 +2253,7 @@ kroute6_match(struct in6_addr *key, int +@@ -1626,31 +2216,30 @@ kroute6_match(struct in6_addr *key, int } void @@ -2121,15 +2182,25 @@ diff -u -p -r1.1.1.7 -r1.12 { struct knexthop_node *s; struct kroute_node *k; -@@ -1640,17 +2267,17 @@ kroute_detach_nexthop(struct knexthop_no - if (kn->kroute == NULL) - return; + struct kroute6_node *k6; ++ if (kn->kroute == NULL) ++ return; ++ + /* + * check whether there's another nexthop depending on this kroute + * if not remove the flag + */ +- +- if (kn->kroute == NULL) +- return; +- - for (s = RB_MIN(knexthop_tree, &knt); s != NULL && - s->kroute != kn->kroute; s = RB_NEXT(knexthop_tree, &knt, s)) -+ for (s = RB_MIN(knexthop_tree, KT2KNT(kt)); s != NULL && -+ s->kroute != kn->kroute; s = RB_NEXT(knexthop_tree, KT2KNT(kt), s)) - ; /* nothing */ +- ; /* nothing */ ++ RB_FOREACH(s, knexthop_tree, KT2KNT(kt)) ++ if (s->kroute == kn->kroute && s != kn) ++ break; if (s == NULL) { - switch (kn->nexthop.af) { @@ -2144,7 +2215,7 @@ diff -u -p -r1.1.1.7 -r1.12 k6 = kn->kroute; k6->r.flags &= ~F_NEXTHOP; break; -@@ -1665,7 +2292,7 @@ kroute_detach_nexthop(struct knexthop_no +@@ -1665,7 +2254,7 @@ kroute_detach_nexthop(struct knexthop_no */ int @@ -2153,7 +2224,7 @@ diff -u -p -r1.1.1.7 -r1.12 { struct kroute_node *kr; struct kroute6_node *kr6; -@@ -1675,11 +2302,11 @@ protect_lo(void) +@@ -1675,11 +2264,11 @@ protect_lo(void) log_warn("protect_lo"); return (-1); } @@ -2167,7 +2238,7 @@ diff -u -p -r1.1.1.7 -r1.12 free(kr); /* kernel route already there, no problem */ /* special protection for loopback */ -@@ -1689,9 +2316,9 @@ protect_lo(void) +@@ -1689,9 +2278,9 @@ protect_lo(void) } memcpy(&kr6->r.prefix, &in6addr_loopback, sizeof(kr6->r.prefix)); kr6->r.prefixlen = 128; @@ -2179,7 +2250,7 @@ diff -u -p -r1.1.1.7 -r1.12 free(kr6); /* kernel route already there, no problem */ return (0); -@@ -1726,17 +2353,17 @@ mask2prefixlen(in_addr_t ina) +@@ -1726,17 +2315,17 @@ mask2prefixlen(in_addr_t ina) u_int8_t mask2prefixlen6(struct sockaddr_in6 *sa_in6) { @@ -2202,7 +2273,7 @@ diff -u -p -r1.1.1.7 -r1.12 case 0xff: l += 8; break; -@@ -1764,7 +2391,7 @@ mask2prefixlen6(struct sockaddr_in6 *sa_ +@@ -1764,7 +2353,7 @@ mask2prefixlen6(struct sockaddr_in6 *sa_ case 0x00: return (l); default: @@ -2211,7 +2282,7 @@ diff -u -p -r1.1.1.7 -r1.12 } } -@@ -1788,7 +2415,7 @@ prefixlen2mask6(u_int8_t prefixlen) +@@ -1788,7 +2377,7 @@ prefixlen2mask6(u_int8_t prefixlen) } #define ROUNDUP(a) \ @@ -2220,7 +2291,7 @@ diff -u -p -r1.1.1.7 -r1.12 void get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) -@@ -1808,6 +2435,7 @@ get_rtaddrs(int addrs, struct sockaddr * +@@ -1808,11 +2397,10 @@ get_rtaddrs(int addrs, struct sockaddr * void if_change(u_short ifindex, int flags, struct if_data *ifd) { @@ -2228,7 +2299,12 @@ diff -u -p -r1.1.1.7 -r1.12 struct kif_node *kif; struct kif_kr *kkr; struct kif_kr6 *kkr6; -@@ -1833,13 +2461,18 @@ if_change(u_short ifindex, int flags, st +- struct kroute_nexthop nh; +- struct knexthop_node *n; + u_int8_t reachable; + + if ((kif = kif_find(ifindex)) == NULL) { +@@ -1833,28 +2421,18 @@ if_change(u_short ifindex, int flags, st kif->k.nh_reachable = reachable; @@ -2241,60 +2317,61 @@ diff -u -p -r1.1.1.7 -r1.12 kkr->kr->r.flags |= F_DOWN; - RB_FOREACH(n, knexthop_tree, &knt) -+ if (kt == NULL) -+ continue; -+ -+ RB_FOREACH(n, knexthop_tree, KT2KNT(kt)) - if (n->kroute == kkr->kr) { - bzero(&nh, sizeof(nh)); - memcpy(&nh.nexthop, &n->nexthop, -@@ -1849,10 +2482,11 @@ if_change(u_short ifindex, int flags, st - nh.connected = 1; - if ((nh.gateway.v4.s_addr = - kkr->kr->r.nexthop.s_addr) != 0) +- if (n->kroute == kkr->kr) { +- bzero(&nh, sizeof(nh)); +- memcpy(&nh.nexthop, &n->nexthop, +- sizeof(nh.nexthop)); +- if (kroute_validate(&kkr->kr->r)) { +- nh.valid = 1; +- nh.connected = 1; +- if ((nh.gateway.v4.s_addr = +- kkr->kr->r.nexthop.s_addr) != 0) - nh.gateway.af = AF_INET; -+ nh.gateway.aid = AID_INET; - } +- } - memcpy(&nh.kr.kr4, &kkr->kr->r, - sizeof(nh.kr.kr4)); -+ nh.net.aid = AID_INET; -+ nh.net.v4.s_addr = kkr->kr->r.prefix.s_addr; -+ nh.netlen = kkr->kr->r.prefixlen; - send_nexthop_update(&nh); - } +- send_nexthop_update(&nh); +- } ++ if (kt == NULL) ++ continue; ++ ++ knexthop_track(kt, kkr->kr); } -@@ -1862,7 +2496,9 @@ if_change(u_short ifindex, int flags, st + LIST_FOREACH(kkr6, &kif->kroute6_l, entry) { + if (reachable) +@@ -1862,27 +2440,10 @@ if_change(u_short ifindex, int flags, st else kkr6->kr->r.flags |= F_DOWN; - RB_FOREACH(n, knexthop_tree, &knt) -+ if (kt == NULL) -+ continue; -+ RB_FOREACH(n, knexthop_tree, KT2KNT(kt)) - if (n->kroute == kkr6->kr) { - bzero(&nh, sizeof(nh)); - memcpy(&nh.nexthop, &n->nexthop, -@@ -1873,14 +2509,16 @@ if_change(u_short ifindex, int flags, st - if (memcmp(&kkr6->kr->r.nexthop, - &in6addr_any, sizeof(struct - in6_addr))) { +- if (n->kroute == kkr6->kr) { +- bzero(&nh, sizeof(nh)); +- memcpy(&nh.nexthop, &n->nexthop, +- sizeof(nh.nexthop)); +- if (kroute6_validate(&kkr6->kr->r)) { +- nh.valid = 1; +- nh.connected = 1; +- if (memcmp(&kkr6->kr->r.nexthop, +- &in6addr_any, sizeof(struct +- in6_addr))) { - nh.gateway.af = AF_INET6; -+ nh.gateway.aid = AID_INET6; - memcpy(&nh.gateway.v6, - &kkr6->kr->r.nexthop, - sizeof(struct in6_addr)); - } - } +- memcpy(&nh.gateway.v6, +- &kkr6->kr->r.nexthop, +- sizeof(struct in6_addr)); +- } +- } - memcpy(&nh.kr.kr6, &kkr6->kr->r, - sizeof(nh.kr.kr6)); -+ nh.net.aid = AID_INET6; -+ memcpy(&nh.net.v6, &kkr6->kr->r.nexthop, -+ sizeof(struct in6_addr)); -+ nh.netlen = kkr6->kr->r.prefixlen; - send_nexthop_update(&nh); - } +- send_nexthop_update(&nh); +- } ++ if (kt == NULL) ++ continue; ++ ++ knexthop_track(kt, kkr6->kr); } -@@ -1917,25 +2555,38 @@ if_announce(void *msg) + } + +@@ -1917,25 +2478,38 @@ if_announce(void *msg) */ int @@ -2337,7 +2414,7 @@ diff -u -p -r1.1.1.7 -r1.12 if (kroute->flags & F_BLACKHOLE) hdr.rtm_flags |= RTF_BLACKHOLE; if (kroute->flags & F_REJECT) -@@ -1984,6 +2635,37 @@ send_rtmsg(int fd, int action, struct kr +@@ -1984,6 +2558,37 @@ send_rtmsg(int fd, int action, struct kr iov[iovcnt].iov_base = &mask; iov[iovcnt++].iov_len = sizeof(mask); @@ -2375,7 +2452,7 @@ diff -u -p -r1.1.1.7 -r1.12 if (kroute->labelid) { bzero(&label, sizeof(label)); label.sr_len = sizeof(label); -@@ -1996,11 +2678,11 @@ send_rtmsg(int fd, int action, struct kr +@@ -1996,11 +2601,11 @@ send_rtmsg(int fd, int action, struct kr iov[iovcnt].iov_base = &label; iov[iovcnt++].iov_len = sizeof(label); } @@ -2389,7 +2466,7 @@ diff -u -p -r1.1.1.7 -r1.12 if (hdr.rtm_type == RTM_CHANGE) { hdr.rtm_type = RTM_ADD; goto retry; -@@ -2009,27 +2691,18 @@ retry: +@@ -2009,27 +2614,18 @@ retry: inet_ntoa(kroute->prefix), kroute->prefixlen); return (0); @@ -2421,7 +2498,7 @@ diff -u -p -r1.1.1.7 -r1.12 { struct iovec iov[5]; struct rt_msghdr hdr; -@@ -2037,17 +2710,23 @@ send_rt6msg(int fd, int action, struct k +@@ -2037,17 +2633,23 @@ send_rt6msg(int fd, int action, struct k struct sockaddr_in6 addr; char pad[sizeof(long)]; } prefix, nexthop, mask; @@ -2446,7 +2523,7 @@ diff -u -p -r1.1.1.7 -r1.12 if (kroute->flags & F_BLACKHOLE) hdr.rtm_flags |= RTF_BLACKHOLE; if (kroute->flags & F_REJECT) -@@ -2100,6 +2779,7 @@ send_rt6msg(int fd, int action, struct k +@@ -2100,6 +2702,7 @@ send_rt6msg(int fd, int action, struct k iov[iovcnt].iov_base = &mask; iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6)); @@ -2454,7 +2531,7 @@ diff -u -p -r1.1.1.7 -r1.12 if (kroute->labelid) { bzero(&label, sizeof(label)); label.sr_len = sizeof(label); -@@ -2112,11 +2792,11 @@ send_rt6msg(int fd, int action, struct k +@@ -2112,11 +2715,11 @@ send_rt6msg(int fd, int action, struct k iov[iovcnt].iov_base = &label; iov[iovcnt++].iov_len = sizeof(label); } @@ -2468,7 +2545,7 @@ diff -u -p -r1.1.1.7 -r1.12 if (hdr.rtm_type == RTM_CHANGE) { hdr.rtm_type = RTM_ADD; goto retry; -@@ -2125,31 +2805,26 @@ retry: +@@ -2125,31 +2728,26 @@ retry: log_in6addr(&kroute->prefix), kroute->prefixlen); return (0); @@ -2509,7 +2586,7 @@ diff -u -p -r1.1.1.7 -r1.12 struct rt_msghdr *rtm; struct sockaddr *sa, *gw, *rti_info[RTAX_MAX]; struct sockaddr_in *sa_in; -@@ -2163,22 +2838,35 @@ fetchtable(u_int rtableid, int connected +@@ -2163,22 +2761,35 @@ fetchtable(u_int rtableid, int connected mib[3] = 0; mib[4] = NET_RT_DUMP; mib[5] = 0; @@ -2555,7 +2632,7 @@ diff -u -p -r1.1.1.7 -r1.12 } lim = buf + len; -@@ -2186,7 +2874,11 @@ fetchtable(u_int rtableid, int connected +@@ -2186,7 +2797,11 @@ fetchtable(u_int rtableid, int connected rtm = (struct rt_msghdr *)next; if (rtm->rtm_version != RTM_VERSION) continue; @@ -2567,7 +2644,7 @@ diff -u -p -r1.1.1.7 -r1.12 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); if ((sa = rti_info[RTAX_DST]) == NULL) -@@ -2205,7 +2897,11 @@ fetchtable(u_int rtableid, int connected +@@ -2205,7 +2820,11 @@ fetchtable(u_int rtableid, int connected } kr->r.flags = F_KERNEL; @@ -2579,7 +2656,7 @@ diff -u -p -r1.1.1.7 -r1.12 kr->r.ifindex = rtm->rtm_index; kr->r.prefix.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; -@@ -2223,8 +2919,12 @@ fetchtable(u_int rtableid, int connected +@@ -2223,8 +2842,12 @@ fetchtable(u_int rtableid, int connected break; kr->r.prefixlen = mask2prefixlen(sa_in->sin_addr.s_addr); @@ -2593,7 +2670,7 @@ diff -u -p -r1.1.1.7 -r1.12 else kr->r.prefixlen = prefixlen_classful(kr->r.prefix.s_addr); -@@ -2238,7 +2938,11 @@ fetchtable(u_int rtableid, int connected +@@ -2238,7 +2861,11 @@ fetchtable(u_int rtableid, int connected } kr6->r.flags = F_KERNEL; @@ -2605,7 +2682,7 @@ diff -u -p -r1.1.1.7 -r1.12 kr6->r.ifindex = rtm->rtm_index; memcpy(&kr6->r.prefix, &((struct sockaddr_in6 *)sa)->sin6_addr, -@@ -2257,8 +2961,12 @@ fetchtable(u_int rtableid, int connected +@@ -2257,8 +2884,12 @@ fetchtable(u_int rtableid, int connected if (sa_in6->sin6_len == 0) break; kr6->r.prefixlen = mask2prefixlen6(sa_in6); @@ -2619,7 +2696,7 @@ diff -u -p -r1.1.1.7 -r1.12 else fatalx("INET6 route without netmask"); break; -@@ -2290,23 +2998,28 @@ fetchtable(u_int rtableid, int connected +@@ -2290,23 +2921,28 @@ fetchtable(u_int rtableid, int connected } if (sa->sa_family == AF_INET) { @@ -2660,7 +2737,7 @@ diff -u -p -r1.1.1.7 -r1.12 } } free(buf); -@@ -2327,7 +3040,7 @@ fetchifs(int ifindex) +@@ -2327,7 +2963,7 @@ fetchifs(int ifindex) mib[0] = CTL_NET; mib[1] = AF_ROUTE; mib[2] = 0; @@ -2669,7 +2746,7 @@ diff -u -p -r1.1.1.7 -r1.12 mib[4] = NET_RT_IFLIST; mib[5] = ifindex; -@@ -2396,7 +3109,7 @@ dispatch_rtmsg(void) +@@ -2396,7 +3032,7 @@ dispatch_rtmsg(void) struct rt_msghdr *rtm; struct if_msghdr ifm; struct sockaddr *sa, *rti_info[RTAX_MAX]; @@ -2678,7 +2755,7 @@ diff -u -p -r1.1.1.7 -r1.12 if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) { log_warn("dispatch_rtmsg: read error"); -@@ -2418,7 +3131,11 @@ dispatch_rtmsg(void) +@@ -2418,7 +3054,11 @@ dispatch_rtmsg(void) case RTM_ADD: case RTM_CHANGE: case RTM_DELETE: @@ -2690,7 +2767,7 @@ diff -u -p -r1.1.1.7 -r1.12 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); if (rtm->rtm_pid == kr_state.pid) /* cause by us */ -@@ -2430,16 +3147,14 @@ dispatch_rtmsg(void) +@@ -2430,16 +3070,14 @@ dispatch_rtmsg(void) if (rtm->rtm_flags & RTF_LLINFO) /* arp cache */ continue; @@ -2714,7 +2791,7 @@ diff -u -p -r1.1.1.7 -r1.12 return (-1); break; case RTM_IFINFO: -@@ -2460,7 +3175,7 @@ dispatch_rtmsg(void) +@@ -2460,7 +3098,7 @@ dispatch_rtmsg(void) int dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr *rti_info[RTAX_MAX], @@ -2723,7 +2800,16 @@ diff -u -p -r1.1.1.7 -r1.12 { struct sockaddr *sa; struct sockaddr_in *sa_in; -@@ -2494,31 +3209,44 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt +@@ -2468,7 +3106,7 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt + struct kroute_node *kr; + struct kroute6_node *kr6; + struct bgpd_addr prefix; +- int flags, oflags, mpath = 0; ++ int flags, oflags, mpath = 0, changed = 0; + u_int16_t ifindex; + u_int8_t prefixlen; + u_int8_t prio; +@@ -2494,31 +3132,44 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt mpath = 1; #endif @@ -2772,7 +2858,7 @@ diff -u -p -r1.1.1.7 -r1.12 else fatalx("in6 net addr without netmask"); break; -@@ -2537,10 +3265,10 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt +@@ -2537,10 +3188,10 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt } if (rtm->rtm_type == RTM_DELETE) { @@ -2786,7 +2872,7 @@ diff -u -p -r1.1.1.7 -r1.12 prefixlen, prio)) == NULL) return (0); if (!(kr->r.flags & F_KERNEL)) -@@ -2554,12 +3282,12 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt +@@ -2554,12 +3205,12 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt return (0); } @@ -2802,7 +2888,7 @@ diff -u -p -r1.1.1.7 -r1.12 prio)) == NULL) return (0); if (!(kr6->r.flags & F_KERNEL)) -@@ -2574,26 +3302,23 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt +@@ -2574,26 +3225,23 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt return (0); } @@ -2833,7 +2919,31 @@ diff -u -p -r1.1.1.7 -r1.12 prio)) != NULL) { if (kr->r.flags & F_KERNEL) { /* get the correct route */ -@@ -2619,16 +3344,16 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt +@@ -2605,30 +3253,38 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt + } else if (mpath && rtm->rtm_type == RTM_ADD) + goto add4; + +- if (sa_in != NULL) ++ if (sa_in != NULL) { ++ if (kr->r.nexthop.s_addr != ++ sa_in->sin_addr.s_addr) ++ changed = 1; + kr->r.nexthop.s_addr = + sa_in->sin_addr.s_addr; +- else ++ } else { ++ if (kr->r.nexthop.s_addr != 0) ++ changed = 1; + kr->r.nexthop.s_addr = 0; ++ } + + if (kr->r.flags & F_NEXTHOP) + flags |= F_NEXTHOP; + oflags = kr->r.flags; ++ if (flags != oflags) ++ changed = 1; + kr->r.flags = flags; + if ((oflags & F_CONNECTED) && !(flags & F_CONNECTED)) { kif_kr_remove(kr); kr_redistribute(IMSG_NETWORK_REMOVE, @@ -2847,13 +2957,14 @@ diff -u -p -r1.1.1.7 -r1.12 - &kr->r); + kt, &kr->r); } - if (kr->r.flags & F_NEXTHOP) +- if (kr->r.flags & F_NEXTHOP) - knexthop_track(kr); ++ if (kr->r.flags & F_NEXTHOP && changed) + knexthop_track(kt, kr); } } else if (rtm->rtm_type == RTM_CHANGE) { log_warnx("change req for %s/%u: not in table", -@@ -2651,12 +3376,13 @@ add4: +@@ -2651,12 +3307,13 @@ add4: kr->r.ifindex = ifindex; kr->r.priority = prio; @@ -2870,7 +2981,37 @@ diff -u -p -r1.1.1.7 -r1.12 if (kr6->r.flags & F_KERNEL) { /* get the correct route */ if (mpath && rtm->rtm_type == RTM_CHANGE && -@@ -2685,16 +3411,16 @@ add4: +@@ -2668,33 +3325,44 @@ add4: + } else if (mpath && rtm->rtm_type == RTM_ADD) + goto add6; + +- if (sa_in6 != NULL) ++ if (sa_in6 != NULL) { ++ if (memcmp(&kr6->r.nexthop, ++ &sa_in6->sin6_addr, ++ sizeof(struct in6_addr))) ++ changed = 1; + memcpy(&kr6->r.nexthop, + &sa_in6->sin6_addr, + sizeof(struct in6_addr)); +- else ++ } else { ++ if (memcmp(&kr6->r.nexthop, ++ &in6addr_any, ++ sizeof(struct in6_addr))) ++ changed = 1; + memcpy(&kr6->r.nexthop, + &in6addr_any, + sizeof(struct in6_addr)); ++ } + + if (kr6->r.flags & F_NEXTHOP) + flags |= F_NEXTHOP; + oflags = kr6->r.flags; ++ if (flags != oflags) ++ changed = 1; + kr6->r.flags = flags; + if ((oflags & F_CONNECTED) && !(flags & F_CONNECTED)) { kif_kr6_remove(kr6); kr_redistribute6(IMSG_NETWORK_REMOVE, @@ -2884,13 +3025,14 @@ diff -u -p -r1.1.1.7 -r1.12 - &kr6->r); + kt, &kr6->r); } - if (kr6->r.flags & F_NEXTHOP) +- if (kr6->r.flags & F_NEXTHOP) - knexthop_track(kr6); ++ if (kr6->r.flags & F_NEXTHOP && changed) + knexthop_track(kt, kr6); } } else if (rtm->rtm_type == RTM_CHANGE) { log_warnx("change req for %s/%u: not in table", -@@ -2720,7 +3446,7 @@ add6: +@@ -2720,7 +3388,7 @@ add6: kr6->r.ifindex = ifindex; kr6->r.priority = prio; diff --git a/net/openbgpd/files/patch-bgpd_log.c b/net/openbgpd/files/patch-bgpd_log.c index ca58a9bcfa0c..6860c0f7f940 100644 --- a/net/openbgpd/files/patch-bgpd_log.c +++ b/net/openbgpd/files/patch-bgpd_log.c @@ -2,13 +2,13 @@ Index: bgpd/log.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/log.c,v retrieving revision 1.1.1.5 -retrieving revision 1.1.1.7 -diff -u -p -r1.1.1.5 -r1.1.1.7 +retrieving revision 1.1.1.8 +diff -u -p -r1.1.1.5 -r1.1.1.8 --- bgpd/log.c 14 Feb 2010 20:19:57 -0000 1.1.1.5 -+++ bgpd/log.c 12 Jun 2011 10:44:25 -0000 1.1.1.7 ++++ bgpd/log.c 13 Oct 2012 18:22:43 -0000 1.1.1.8 @@ -1,4 +1,4 @@ -/* $OpenBSD: log.c,v 1.50 2007/04/23 13:04:24 claudio Exp $ */ -+/* $OpenBSD: log.c,v 1.54 2010/11/18 12:51:24 claudio Exp $ */ ++/* $OpenBSD: log.c,v 1.55 2011/08/20 19:02:28 sthen Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -32,15 +32,7 @@ diff -u -p -r1.1.1.5 -r1.1.1.7 if (asprintf(&p, "%s/%u", ip, peer->remote_masklen) == -1) fatal(NULL); } else { -@@ -69,6 +71,7 @@ log_init(int n_debug) - extern char *__progname; - - debug = n_debug; -+ verbose = n_debug; - - if (!debug) - openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); -@@ -77,6 +80,12 @@ log_init(int n_debug) +@@ -77,6 +79,12 @@ log_init(int n_debug) } void @@ -53,7 +45,7 @@ diff -u -p -r1.1.1.5 -r1.1.1.7 logit(int pri, const char *fmt, ...) { va_list ap; -@@ -193,7 +202,7 @@ log_debug(const char *emsg, ...) +@@ -193,7 +201,7 @@ log_debug(const char *emsg, ...) { va_list ap; @@ -62,7 +54,7 @@ diff -u -p -r1.1.1.5 -r1.1.1.7 va_start(ap, emsg); vlog(LOG_DEBUG, emsg, ap); va_end(ap); -@@ -250,7 +259,7 @@ log_statechange(struct peer *peer, enum +@@ -250,7 +258,7 @@ log_statechange(struct peer *peer, enum void log_notification(const struct peer *peer, u_int8_t errcode, u_int8_t subcode, @@ -71,9 +63,19 @@ diff -u -p -r1.1.1.5 -r1.1.1.7 { char *p; const char *suberrname = NULL; -@@ -287,23 +296,22 @@ log_notification(const struct peer *peer +@@ -283,27 +291,31 @@ log_notification(const struct peer *peer + suberrname = suberr_cease_names[subcode]; + break; + case ERR_HOLDTIMEREXPIRED: +- case ERR_FSM: uk = 1; break; ++ case ERR_FSM: ++ if (subcode >= sizeof(suberr_fsm_names)/sizeof(char *)) ++ uk = 1; ++ else ++ suberrname = suberr_fsm_names[subcode]; ++ break; default: - logit(LOG_CRIT, "%s: received notification, unknown errcode " - "%u, subcode %u", p, errcode, subcode); @@ -103,7 +105,7 @@ diff -u -p -r1.1.1.5 -r1.1.1.7 } free(p); } -@@ -318,6 +326,9 @@ log_conn_attempt(const struct peer *peer +@@ -318,6 +330,9 @@ log_conn_attempt(const struct peer *peer b = log_sockaddr(sa); logit(LOG_INFO, "connection from non-peer %s refused", b); } else { diff --git a/net/openbgpd/files/patch-bgpd_log.h b/net/openbgpd/files/patch-bgpd_log.h new file mode 100644 index 000000000000..3d0d94de2a2e --- /dev/null +++ b/net/openbgpd/files/patch-bgpd_log.h @@ -0,0 +1,39 @@ +Index: bgpd/log.h +=================================================================== +RCS file: /home/cvs/private/hrs/openbgpd/bgpd/log.h,v +retrieving revision 1.1.1.2 +retrieving revision 1.1.1.3 +diff -u -p -r1.1.1.2 -r1.1.1.3 +--- bgpd/log.h 9 Jul 2009 16:49:54 -0000 1.1.1.2 ++++ bgpd/log.h 13 Oct 2012 18:22:43 -0000 1.1.1.3 +@@ -1,4 +1,4 @@ +-/* $OpenBSD: log.h,v 1.11 2008/09/11 14:49:58 henning Exp $ */ ++/* $OpenBSD: log.h,v 1.13 2012/06/10 11:16:08 claudio Exp $ */ + + /* + * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> +@@ -71,6 +71,13 @@ static const char * const suberr_open_na + "unsupported capability" + }; + ++static const char * const suberr_fsm_names[] = { ++ "unspecified error", ++ "received unexpected message in OpenSent", ++ "received unexpected message in OpenConfirm", ++ "received unexpected message in Established" ++}; ++ + static const char * const suberr_update_names[] = { + "none", + "attribute list error", +@@ -109,7 +116,9 @@ static const char * const ctl_res_strerr + "no such neighbor", + "permission denied", + "neighbor does not have this capability", +- "config file has errors, reload failed" ++ "config file has errors, reload failed", ++ "previous reload still running", ++ "out of memory" + }; + + static const char * const timernames[] = { diff --git a/net/openbgpd/files/patch-bgpd_mrt.c b/net/openbgpd/files/patch-bgpd_mrt.c index 4b5248a73d4e..2ff724a4714f 100644 --- a/net/openbgpd/files/patch-bgpd_mrt.c +++ b/net/openbgpd/files/patch-bgpd_mrt.c @@ -2,26 +2,36 @@ Index: bgpd/mrt.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/mrt.c,v retrieving revision 1.1.1.7 -retrieving revision 1.1.1.9 -diff -u -p -r1.1.1.7 -r1.1.1.9 +retrieving revision 1.1.1.10 +diff -u -p -r1.1.1.7 -r1.1.1.10 --- bgpd/mrt.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/mrt.c 12 Jun 2011 10:44:25 -0000 1.1.1.9 ++++ bgpd/mrt.c 13 Oct 2012 18:22:43 -0000 1.1.1.10 @@ -1,4 +1,4 @@ -/* $OpenBSD: mrt.c,v 1.63 2009/06/29 12:22:16 claudio Exp $ */ -+/* $OpenBSD: mrt.c,v 1.70 2010/09/02 14:03:21 sobrado Exp $ */ ++/* $OpenBSD: mrt.c,v 1.71 2011/09/17 16:29:44 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> -@@ -32,20 +32,20 @@ +@@ -21,6 +21,7 @@ + + #include <errno.h> + #include <fcntl.h> ++#include <limits.h> + #include <stdlib.h> + #include <string.h> + #include <time.h> +@@ -32,20 +33,22 @@ #include "mrt.h" -int mrt_attr_dump(struct buf *, struct rde_aspath *, struct bgpd_addr *); -+int mrt_attr_dump(struct ibuf *, struct rde_aspath *, struct bgpd_addr *); ++int mrt_attr_dump(struct ibuf *, struct rde_aspath *, struct bgpd_addr *, int); int mrt_dump_entry_mp(struct mrt *, struct prefix *, u_int16_t, struct rde_peer*); int mrt_dump_entry(struct mrt *, struct prefix *, u_int16_t, struct rde_peer*); -int mrt_dump_hdr_se(struct buf **, struct peer *, u_int16_t, u_int16_t, ++int mrt_dump_entry_v2(struct mrt *, struct rib_entry *, u_int32_t); ++int mrt_dump_peer(struct ibuf *, struct rde_peer *); +int mrt_dump_hdr_se(struct ibuf **, struct peer *, u_int16_t, u_int16_t, u_int32_t, int); -int mrt_dump_hdr_rde(struct buf **, u_int16_t type, u_int16_t, u_int32_t); @@ -34,44 +44,44 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 - if (buf_add((x), &t, sizeof(t)) == -1) { \ - log_warnx("mrt_dump1: buf_add error"); \ + if (ibuf_add((x), &t, sizeof(t)) == -1) { \ -+ log_warnx("mrt_dump1: ibuf_add error"); \ ++ log_warn("mrt_dump1: ibuf_add error"); \ goto fail; \ } \ } while (0) -@@ -54,8 +54,8 @@ int mrt_open(struct mrt *, time_t); +@@ -54,8 +57,8 @@ int mrt_open(struct mrt *, time_t); do { \ u_int16_t t; \ t = htons((s)); \ - if (buf_add((x), &t, sizeof(t)) == -1) { \ - log_warnx("mrt_dump2: buf_add error"); \ + if (ibuf_add((x), &t, sizeof(t)) == -1) { \ -+ log_warnx("mrt_dump2: ibuf_add error"); \ ++ log_warn("mrt_dump2: ibuf_add error"); \ goto fail; \ } \ } while (0) -@@ -64,8 +64,8 @@ int mrt_open(struct mrt *, time_t); +@@ -64,8 +67,8 @@ int mrt_open(struct mrt *, time_t); do { \ u_int32_t t; \ t = htonl((l)); \ - if (buf_add((x), &t, sizeof(t)) == -1) { \ - log_warnx("mrt_dump3: buf_add error"); \ + if (ibuf_add((x), &t, sizeof(t)) == -1) { \ -+ log_warnx("mrt_dump3: ibuf_add error"); \ ++ log_warn("mrt_dump3: ibuf_add error"); \ goto fail; \ } \ } while (0) -@@ -73,8 +73,8 @@ int mrt_open(struct mrt *, time_t); +@@ -73,8 +76,8 @@ int mrt_open(struct mrt *, time_t); #define DUMP_NLONG(x, l) \ do { \ u_int32_t t = (l); \ - if (buf_add((x), &t, sizeof(t)) == -1) { \ - log_warnx("mrt_dump4: buf_add error"); \ + if (ibuf_add((x), &t, sizeof(t)) == -1) { \ -+ log_warnx("mrt_dump4: ibuf_add error"); \ ++ log_warn("mrt_dump4: ibuf_add error"); \ goto fail; \ } \ } while (0) -@@ -83,55 +83,63 @@ void +@@ -83,55 +86,64 @@ void mrt_dump_bgp_msg(struct mrt *mrt, void *pkg, u_int16_t pkglen, struct peer *peer) { @@ -93,9 +103,10 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 return; - if (buf_add(buf, pkg, pkglen) == -1) { -+ if (ibuf_add(buf, pkg, pkglen) == -1) { - log_warnx("mrt_dump_bgp_msg: buf_add error"); +- log_warnx("mrt_dump_bgp_msg: buf_add error"); - buf_free(buf); ++ if (ibuf_add(buf, pkg, pkglen) == -1) { ++ log_warn("mrt_dump_bgp_msg: buf_add error"); + ibuf_free(buf); return; } @@ -134,7 +145,8 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 int -mrt_attr_dump(struct buf *buf, struct rde_aspath *a, struct bgpd_addr *nexthop) -+mrt_attr_dump(struct ibuf *buf, struct rde_aspath *a, struct bgpd_addr *nexthop) ++mrt_attr_dump(struct ibuf *buf, struct rde_aspath *a, struct bgpd_addr *nexthop, ++ int v2) { struct attr *oa; u_char *pdata; @@ -143,15 +155,18 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 - u_int16_t plen; - u_int8_t l; + u_int16_t plen, afi; -+ u_int8_t l, mpattr[21]; ++ u_int8_t l, safi; /* origin */ if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ORIGIN, -@@ -141,11 +149,14 @@ mrt_attr_dump(struct buf *buf, struct rd +@@ -140,12 +152,16 @@ mrt_attr_dump(struct buf *buf, struct rd + /* aspath */ pdata = aspath_prepend(a->aspath, rde_local_as(), 0, &plen); - pdata = aspath_deflate(pdata, &plen, &neednewpath); +- pdata = aspath_deflate(pdata, &plen, &neednewpath); - if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ASPATH, pdata, plen) == -1) ++ if (!v2) ++ pdata = aspath_deflate(pdata, &plen, &neednewpath); + if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ASPATH, pdata, + plen) == -1) { + free(pdata); @@ -164,21 +179,54 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 /* nexthop, already network byte order */ if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_NEXTHOP, &nexthop->v4.s_addr, 4) == -1) -@@ -173,12 +184,27 @@ mrt_attr_dump(struct buf *buf, struct rd +@@ -159,7 +175,7 @@ mrt_attr_dump(struct buf *buf, struct rd + return (-1); + } + +- /* local preference, only valid for ibgp */ ++ /* local preference */ + tmp = htonl(a->lpref); + if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_LOCALPREF, &tmp, 4) == -1) + return (-1); +@@ -173,12 +189,51 @@ mrt_attr_dump(struct buf *buf, struct rd return (-1); } + if (nexthop && nexthop->aid != AID_INET) { -+ if (aid2afi(nexthop->aid, &afi, &mpattr[2])) ++ struct ibuf *nhbuf; ++ ++ if ((nhbuf = ibuf_dynamic(0, UCHAR_MAX)) == NULL) + return (-1); -+ afi = htons(afi); -+ memcpy(mpattr, &afi, sizeof(afi)); -+ mpattr[3] = sizeof(struct in6_addr); -+ memcpy(&mpattr[4], &nexthop->v6, sizeof(struct in6_addr)); -+ mpattr[20] = 0; /* Reserved must be 0 */ ++ if (!v2) { ++ if (aid2afi(nexthop->aid, &afi, &safi)) ++ return (-1); ++ DUMP_SHORT(nhbuf, afi); ++ DUMP_BYTE(nhbuf, safi); ++ } ++ switch (nexthop->aid) { ++ case AID_INET6: ++ DUMP_BYTE(nhbuf, sizeof(struct in6_addr)); ++ if (ibuf_add(nhbuf, &nexthop->v6, ++ sizeof(struct in6_addr)) == -1) { ++ } ++ break; ++ case AID_VPN_IPv4: ++ DUMP_BYTE(nhbuf, sizeof(u_int64_t) + ++ sizeof(struct in_addr)); ++ DUMP_NLONG(nhbuf, 0); /* set RD to 0 */ ++ DUMP_NLONG(nhbuf, 0); ++ DUMP_NLONG(nhbuf, nexthop->v4.s_addr); ++ break; ++ } ++ if (!v2) ++ DUMP_BYTE(nhbuf, 0); + if (attr_writebuf(buf, ATTR_OPTIONAL, ATTR_MP_REACH_NLRI, -+ mpattr, sizeof(mpattr)) == -1) ++ nhbuf->buf, ibuf_size(nhbuf)) == -1) { ++fail: ++ ibuf_free(nhbuf); + return (-1); ++ } ++ ibuf_free(nhbuf); + } + if (neednewpath) { @@ -193,16 +241,16 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 free(pdata); } -@@ -189,14 +215,14 @@ int +@@ -189,25 +244,23 @@ int mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum, struct rde_peer *peer) { - struct buf *buf, *hbuf = NULL, *h2buf = NULL; +- void *bptr; + struct ibuf *buf, *hbuf = NULL, *h2buf = NULL; - void *bptr; struct bgpd_addr addr, nexthop, *nh; u_int16_t len; - u_int8_t p_len; +- u_int8_t p_len; - sa_family_t af; + u_int8_t aid; @@ -211,7 +259,9 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 log_warn("mrt_dump_entry_mp: buf_dynamic"); return (-1); } -@@ -205,9 +231,9 @@ mrt_dump_entry_mp(struct mrt *mrt, struc + +- if (mrt_attr_dump(buf, p->aspath, NULL) == -1) { ++ if (mrt_attr_dump(buf, p->aspath, NULL, 0) == -1) { log_warnx("mrt_dump_entry_mp: mrt_attr_dump error"); goto fail; } @@ -223,7 +273,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 MRT_BGP4MP_IPv4_ENTRY_SIZE, MRT_BGP4MP_IPv6_HEADER_SIZE + MRT_BGP4MP_IPv6_ENTRY_SIZE + MRT_BGP4MP_MAX_PREFIXLEN)) == NULL) { log_warn("mrt_dump_entry_mp: buf_dynamic"); -@@ -219,25 +245,26 @@ mrt_dump_entry_mp(struct mrt *mrt, struc +@@ -219,25 +272,26 @@ mrt_dump_entry_mp(struct mrt *mrt, struc DUMP_SHORT(h2buf, /* ifindex */ 0); /* XXX is this for peer self? */ @@ -247,7 +297,8 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 - buf_add(h2buf, &peer->remote_addr.v6, + ibuf_add(h2buf, &peer->remote_addr.v6, sizeof(struct in6_addr)) == -1) { - log_warnx("mrt_dump_entry_mp: buf_add error"); +- log_warnx("mrt_dump_entry_mp: buf_add error"); ++ log_warn("mrt_dump_entry_mp: buf_add error"); goto fail; } break; @@ -257,7 +308,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 goto fail; } -@@ -247,24 +274,24 @@ mrt_dump_entry_mp(struct mrt *mrt, struc +@@ -247,25 +301,25 @@ mrt_dump_entry_mp(struct mrt *mrt, struc if (p->aspath->nexthop == NULL) { bzero(&nexthop, sizeof(struct bgpd_addr)); @@ -283,21 +334,27 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 DUMP_BYTE(h2buf, SAFI_UNICAST); /* safi */ DUMP_BYTE(h2buf, 16); /* nhlen */ - if (buf_add(h2buf, &nh->v6, sizeof(struct in6_addr)) == -1) { +- log_warnx("mrt_dump_entry_mp: buf_add error"); + if (ibuf_add(h2buf, &nh->v6, sizeof(struct in6_addr)) == -1) { - log_warnx("mrt_dump_entry_mp: buf_add error"); ++ log_warn("mrt_dump_entry_mp: buf_add error"); goto fail; } -@@ -275,7 +302,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struc + break; +@@ -274,35 +328,30 @@ mrt_dump_entry_mp(struct mrt *mrt, struc + goto fail; } - p_len = PREFIX_SIZE(p->prefix->prefixlen); +- p_len = PREFIX_SIZE(p->prefix->prefixlen); - if ((bptr = buf_reserve(h2buf, p_len)) == NULL) { -+ if ((bptr = ibuf_reserve(h2buf, p_len)) == NULL) { - log_warnx("mrt_dump_entry_mp: buf_reserve error"); +- log_warnx("mrt_dump_entry_mp: buf_reserve error"); +- goto fail; +- } +- if (prefix_write(bptr, p_len, &addr, p->prefix->prefixlen) == -1) { +- log_warnx("mrt_dump_entry_mp: prefix_write error"); ++ if (prefix_writebuf(h2buf, &addr, p->prefix->prefixlen) == -1) { ++ log_warn("mrt_dump_entry_mp: prefix_writebuf error"); goto fail; } -@@ -285,24 +312,24 @@ mrt_dump_entry_mp(struct mrt *mrt, struc - } DUMP_SHORT(h2buf, len); - len += buf_size(h2buf); @@ -329,7 +386,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 return (-1); } -@@ -310,34 +337,37 @@ int +@@ -310,34 +359,37 @@ int mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum, struct rde_peer *peer) { @@ -348,8 +405,9 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 return (0); - if ((buf = buf_dynamic(0, MAX_PKTSIZE)) == NULL) { +- log_warnx("mrt_dump_entry: buf_dynamic"); + if ((buf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) { - log_warnx("mrt_dump_entry: buf_dynamic"); ++ log_warn("mrt_dump_entry: buf_dynamic"); return (-1); } @@ -360,7 +418,8 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 nh = &addr; } else nh = &p->aspath->nexthop->exit_nexthop; - if (mrt_attr_dump(buf, p->aspath, nh) == -1) { +- if (mrt_attr_dump(buf, p->aspath, nh) == -1) { ++ if (mrt_attr_dump(buf, p->aspath, nh, 0) == -1) { log_warnx("mrt_dump_entry: mrt_attr_dump error"); - buf_free(buf); + ibuf_free(buf); @@ -377,7 +436,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 return (-1); } -@@ -345,23 +375,44 @@ mrt_dump_entry(struct mrt *mrt, struct p +@@ -345,23 +397,241 @@ mrt_dump_entry(struct mrt *mrt, struct p DUMP_SHORT(hbuf, snum); pt_getaddr(p->prefix, &addr); @@ -388,7 +447,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 + break; + case AID_INET6: + if (ibuf_add(hbuf, &addr.v6, sizeof(struct in6_addr)) == -1) { -+ log_warnx("mrt_dump_entry: buf_add error"); ++ log_warn("mrt_dump_entry: buf_add error"); + goto fail; + } + break; @@ -405,7 +464,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 + case AID_INET6: + if (ibuf_add(hbuf, &peer->remote_addr.v6, + sizeof(struct in6_addr)) == -1) { -+ log_warnx("mrt_dump_entry: buf_add error"); ++ log_warn("mrt_dump_entry: buf_add error"); + goto fail; + } + break; @@ -425,10 +484,219 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 - buf_free(buf); + ibuf_free(hbuf); + ibuf_free(buf); ++ return (-1); ++} ++ ++int ++mrt_dump_entry_v2(struct mrt *mrt, struct rib_entry *re, u_int32_t snum) ++{ ++ struct ibuf *buf, *hbuf = NULL; ++ struct prefix *p; ++ struct bgpd_addr addr; ++ size_t len, off; ++ u_int16_t subtype, nump; ++ ++ switch (re->prefix->aid) { ++ case AID_INET: ++ subtype = MRT_DUMP_V2_RIB_IPV4_UNICAST; ++ break; ++ case AID_INET6: ++ subtype = MRT_DUMP_V2_RIB_IPV6_UNICAST; ++ break; ++ default: ++ subtype = MRT_DUMP_V2_RIB_GENERIC; ++ break; ++ } ++ ++ if ((buf = ibuf_dynamic(0, UINT_MAX)) == NULL) { ++ log_warn("mrt_dump_entry: buf_dynamic"); ++ return (-1); ++ } ++ ++ DUMP_LONG(buf, snum); ++ pt_getaddr(re->prefix, &addr); ++ if (subtype == MRT_DUMP_V2_RIB_GENERIC) { ++ u_int16_t afi; ++ u_int8_t safi; ++ ++ aid2afi(re->prefix->aid, &afi, &safi); ++ DUMP_SHORT(buf, afi); ++ DUMP_BYTE(buf, safi); ++ } ++ if (prefix_writebuf(buf, &addr, re->prefix->prefixlen) == -1) { ++ log_warn("mrt_dump_entry_mp: prefix_writebuf error"); ++ goto fail; ++ } ++ ++ off = ibuf_size(buf); ++ if (ibuf_reserve(buf, sizeof(nump)) == NULL) { ++ log_warn("mrt_dump_v2_hdr: buf_reserve error"); ++ goto fail; ++ } ++ nump = 0; ++ LIST_FOREACH(p, &re->prefix_h, rib_l) { ++ struct bgpd_addr *nh; ++ struct ibuf *tbuf; ++ ++ if (p->aspath->nexthop == NULL) { ++ bzero(&addr, sizeof(struct bgpd_addr)); ++ addr.aid = p->prefix->aid; ++ nh = &addr; ++ } else ++ nh = &p->aspath->nexthop->exit_nexthop; ++ ++ DUMP_SHORT(buf, p->aspath->peer->mrt_idx); ++ DUMP_LONG(buf, p->lastchange); /* originated */ ++ ++ if ((tbuf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) { ++ log_warn("mrt_dump_entry_v2: buf_dynamic"); ++ return (-1); ++ } ++ if (mrt_attr_dump(tbuf, p->aspath, nh, 1) == -1) { ++ log_warnx("mrt_dump_entry_v2: mrt_attr_dump error"); ++ ibuf_free(buf); ++ return (-1); ++ } ++ len = ibuf_size(tbuf); ++ DUMP_SHORT(buf, (u_int16_t)len); ++ if (ibuf_add(buf, tbuf->buf, ibuf_size(tbuf)) == -1) { ++ log_warn("mrt_dump_entry_v2: ibuf_add error"); ++ ibuf_free(tbuf); ++ return (-1); ++ } ++ ibuf_free(tbuf); ++ nump++; ++ } ++ nump = htons(nump); ++ memcpy(ibuf_seek(buf, off, sizeof(nump)), &nump, sizeof(nump)); ++ ++ len = ibuf_size(buf); ++ if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP_V2, subtype, len) == -1) { ++ ibuf_free(buf); ++ return (-1); ++ } ++ ++ ibuf_close(&mrt->wbuf, hbuf); ++ ibuf_close(&mrt->wbuf, buf); ++ ++ return (0); ++fail: ++ if (hbuf) ++ ibuf_free(hbuf); ++ ibuf_free(buf); ++ return (-1); ++} ++ ++int ++mrt_dump_v2_hdr(struct mrt *mrt, struct bgpd_config *conf, ++ struct rde_peer_head *ph) ++{ ++ struct rde_peer *peer; ++ struct ibuf *buf, *hbuf = NULL; ++ size_t len, off; ++ u_int16_t nlen, nump; ++ ++ if ((buf = ibuf_dynamic(0, UINT_MAX)) == NULL) { ++ log_warn("mrt_dump_v2_hdr: buf_dynamic"); ++ return (-1); ++ } ++ ++ DUMP_NLONG(buf, conf->bgpid); ++ nlen = strlen(mrt->rib); ++ if (nlen > 0) ++ nlen += 1; ++ DUMP_SHORT(buf, nlen); ++ if (ibuf_add(buf, mrt->rib, nlen) == -1) { ++ log_warn("mrt_dump_v2_hdr: buf_add error"); ++ goto fail; ++ } ++ ++ off = ibuf_size(buf); ++ if (ibuf_reserve(buf, sizeof(nump)) == NULL) { ++ log_warn("mrt_dump_v2_hdr: buf_reserve error"); ++ goto fail; ++ } ++ nump = 0; ++ LIST_FOREACH(peer, ph, peer_l) { ++ peer->mrt_idx = nump; ++ if (mrt_dump_peer(buf, peer) == -1) ++ goto fail; ++ nump++; ++ } ++ nump = htons(nump); ++ memcpy(ibuf_seek(buf, off, sizeof(nump)), &nump, sizeof(nump)); ++ ++ len = ibuf_size(buf); ++ if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP_V2, ++ MRT_DUMP_V2_PEER_INDEX_TABLE, len) == -1) ++ goto fail; ++ ++ ibuf_close(&mrt->wbuf, hbuf); ++ ibuf_close(&mrt->wbuf, buf); ++ ++ return (0); ++fail: ++ if (hbuf) ++ ibuf_free(hbuf); ++ ibuf_free(buf); ++ return (-1); ++} ++ ++int ++mrt_dump_peer(struct ibuf *buf, struct rde_peer *peer) ++{ ++ u_int8_t type = 0; ++ ++ if (peer->capa.as4byte) ++ type |= MRT_DUMP_V2_PEER_BIT_A; ++ if (peer->remote_addr.aid == AID_INET6) ++ type |= MRT_DUMP_V2_PEER_BIT_I; ++ ++ DUMP_BYTE(buf, type); ++ DUMP_LONG(buf, peer->remote_bgpid); ++ ++ switch (peer->remote_addr.aid) { ++ case AID_INET: ++ DUMP_NLONG(buf, peer->remote_addr.v4.s_addr); ++ break; ++ case AID_INET6: ++ if (ibuf_add(buf, &peer->remote_addr.v6, ++ sizeof(struct in6_addr)) == -1) { ++ log_warn("mrt_dump_peer: buf_add error"); ++ goto fail; ++ } ++ break; ++ case AID_UNSPEC: /* XXX special handling for peer_self? */ ++ DUMP_NLONG(buf, 0); ++ break; ++ default: ++ log_warnx("king bula found new AF in mrt_dump_entry_mp"); ++ goto fail; ++ } ++ ++ if (peer->capa.as4byte) ++ DUMP_LONG(buf, peer->conf.remote_as); ++ else ++ DUMP_SHORT(buf, peer->short_as); ++ ++ return (0); ++fail: return (-1); } -@@ -387,7 +438,7 @@ mrt_dump_upcall(struct rib_entry *re, vo +@@ -371,6 +641,11 @@ mrt_dump_upcall(struct rib_entry *re, vo + struct mrt *mrtbuf = ptr; + struct prefix *p; + ++ if (mrtbuf->type == MRT_TABLE_DUMP_V2) { ++ mrt_dump_entry_v2(mrtbuf, re, mrtbuf->seqnum++); ++ return; ++ } ++ + /* + * dump all prefixes even the inactive ones. That is the way zebra + * dumps the table so we do the same. If only the active route should +@@ -387,7 +662,7 @@ mrt_dump_upcall(struct rib_entry *re, vo } void @@ -437,7 +705,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 { struct mrt *mrtbuf = ptr; -@@ -395,12 +446,12 @@ mrt_dump_done(void *ptr) +@@ -395,14 +670,14 @@ mrt_dump_done(void *ptr) } int @@ -450,9 +718,12 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 - if ((*bp = buf_dynamic(MRT_HEADER_SIZE, MRT_HEADER_SIZE + + if ((*bp = ibuf_dynamic(MRT_HEADER_SIZE, MRT_HEADER_SIZE + MRT_BGP4MP_AS4_IPv6_HEADER_SIZE + len)) == NULL) { - log_warnx("mrt_dump_hdr_se: buf_open error"); +- log_warnx("mrt_dump_hdr_se: buf_open error"); ++ log_warn("mrt_dump_hdr_se: buf_open error"); return (-1); -@@ -468,20 +519,20 @@ mrt_dump_hdr_se(struct buf ** bp, struct + } + +@@ -468,23 +743,23 @@ mrt_dump_hdr_se(struct buf ** bp, struct case AF_INET6: DUMP_SHORT(*bp, AFI_IPv6); if (!swap) @@ -460,14 +731,16 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 + if (ibuf_add(*bp, &((struct sockaddr_in6 *) &peer->sa_local)->sin6_addr, sizeof(struct in6_addr)) == -1) { - log_warnx("mrt_dump_hdr_se: buf_add error"); +- log_warnx("mrt_dump_hdr_se: buf_add error"); ++ log_warn("mrt_dump_hdr_se: buf_add error"); goto fail; } - if (buf_add(*bp, + if (ibuf_add(*bp, &((struct sockaddr_in6 *)&peer->sa_remote)->sin6_addr, sizeof(struct in6_addr)) == -1) { - log_warnx("mrt_dump_hdr_se: buf_add error"); +- log_warnx("mrt_dump_hdr_se: buf_add error"); ++ log_warn("mrt_dump_hdr_se: buf_add error"); goto fail; } if (swap) @@ -475,8 +748,12 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 + if (ibuf_add(*bp, &((struct sockaddr_in6 *) &peer->sa_local)->sin6_addr, sizeof(struct in6_addr)) == -1) { - log_warnx("mrt_dump_hdr_se: buf_add error"); -@@ -493,17 +544,17 @@ mrt_dump_hdr_se(struct buf ** bp, struct +- log_warnx("mrt_dump_hdr_se: buf_add error"); ++ log_warn("mrt_dump_hdr_se: buf_add error"); + goto fail; + } + break; +@@ -493,20 +768,20 @@ mrt_dump_hdr_se(struct buf ** bp, struct return (0); fail: @@ -496,8 +773,12 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 + if ((*bp = ibuf_dynamic(MRT_HEADER_SIZE, MRT_HEADER_SIZE + MRT_BGP4MP_AS4_IPv6_HEADER_SIZE + MRT_BGP4MP_IPv6_ENTRY_SIZE)) == NULL) { - log_warnx("mrt_dump_hdr_rde: buf_dynamic error"); -@@ -517,7 +568,15 @@ mrt_dump_hdr_rde(struct buf **bp, u_int1 +- log_warnx("mrt_dump_hdr_rde: buf_dynamic error"); ++ log_warn("mrt_dump_hdr_rde: buf_dynamic error"); + return (-1); + } + +@@ -517,19 +792,28 @@ mrt_dump_hdr_rde(struct buf **bp, u_int1 switch (type) { case MSG_TABLE_DUMP: @@ -513,8 +794,9 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 + DUMP_LONG(*bp, len); break; case MSG_PROTOCOL_BGP4MP: ++ case MSG_TABLE_DUMP_V2: DUMP_LONG(*bp, len); -@@ -525,11 +584,11 @@ mrt_dump_hdr_rde(struct buf **bp, u_int1 + break; default: log_warnx("mrt_dump_hdr_rde: unsupported type"); goto fail; @@ -528,7 +810,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 return (-1); } -@@ -538,21 +597,22 @@ mrt_write(struct mrt *mrt) +@@ -538,21 +822,22 @@ mrt_write(struct mrt *mrt) { int r; @@ -554,3 +836,24 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 } mrt->wbuf.queued = 0; } +@@ -590,7 +875,8 @@ mrt_open(struct mrt *mrt, time_t now) + else + type = IMSG_MRT_REOPEN; + +- if (mrt->type == MRT_TABLE_DUMP || mrt->type == MRT_TABLE_DUMP_MP) ++ if (mrt->type == MRT_TABLE_DUMP || mrt->type == MRT_TABLE_DUMP_MP || ++ mrt->type == MRT_TABLE_DUMP_V2) + i = 0; + + if (imsg_compose(mrt_imsgbuf[i], type, 0, 0, fd, +@@ -659,7 +945,9 @@ mrt_handler(struct mrt_head *mrt) + LIST_FOREACH(m, mrt, entry) { + if (m->state == MRT_STATE_RUNNING && + (MRT2MC(m)->ReopenTimerInterval != 0 || +- m->type == MRT_TABLE_DUMP)) { ++ m->type == MRT_TABLE_DUMP || ++ m->type == MRT_TABLE_DUMP_MP || ++ m->type == MRT_TABLE_DUMP_V2)) { + if (mrt_open(m, now) == -1) + continue; + MRT2MC(m)->ReopenTimer = diff --git a/net/openbgpd/files/patch-bgpd_mrt.h b/net/openbgpd/files/patch-bgpd_mrt.h index 7bf1857d39eb..0c9d835f5b78 100644 --- a/net/openbgpd/files/patch-bgpd_mrt.h +++ b/net/openbgpd/files/patch-bgpd_mrt.h @@ -2,13 +2,13 @@ Index: bgpd/mrt.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/mrt.h,v retrieving revision 1.1.1.6 -retrieving revision 1.1.1.8 -diff -u -p -r1.1.1.6 -r1.1.1.8 +retrieving revision 1.1.1.9 +diff -u -p -r1.1.1.6 -r1.1.1.9 --- bgpd/mrt.h 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/mrt.h 12 Jun 2011 10:44:25 -0000 1.1.1.8 ++++ bgpd/mrt.h 13 Oct 2012 18:22:43 -0000 1.1.1.9 @@ -1,4 +1,4 @@ -/* $OpenBSD: mrt.h,v 1.23 2009/06/29 12:22:16 claudio Exp $ */ -+/* $OpenBSD: mrt.h,v 1.27 2010/06/04 10:13:00 claudio Exp $ */ ++/* $OpenBSD: mrt.h,v 1.30 2011/09/18 09:31:25 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -26,7 +26,34 @@ diff -u -p -r1.1.1.6 -r1.1.1.8 * http://www.quagga.net/docs/docs-multi/Packet-Binary-Dump-Format.html */ -@@ -75,8 +73,10 @@ enum MRT_BGP4MP_TYPES { +@@ -37,11 +35,18 @@ + * | length | length of packet excluding this header + * +--------+--------+--------+--------+ + * +- * ET types include an additional 32bit microsecond field comming after the +- * length field. ++ * ET types include an additional 32bit microsecond field coming after the ++ * length field. Which is accounted in the length field. + */ + #define MRT_HEADER_SIZE 12 + ++struct mrt_hdr { ++ u_int32_t timestamp; ++ u_int16_t type; ++ u_int16_t subtype; ++ u_int32_t length; ++} __packed; ++ + enum MRT_MSG_TYPES { + MSG_NULL, /* 0 empty msg (deprecated) */ + MSG_START, /* 1 sender is starting up */ +@@ -70,13 +75,15 @@ enum MRT_MSG_TYPES { + * that are normaly saved as MSG_TABLE_DUMP. + * In most cases this is the format to choose to dump updates et al. + */ +-enum MRT_BGP4MP_TYPES { ++enum MRT_BGP4MP_SUBTYPES { + BGP4MP_STATE_CHANGE, /* state change */ BGP4MP_MESSAGE, /* bgp message */ BGP4MP_ENTRY, /* table dumps (deprecated) */ BGP4MP_SNAPSHOT, /* file name for dump (deprecated) */ @@ -38,29 +65,223 @@ diff -u -p -r1.1.1.6 -r1.1.1.8 }; /* size of the BGP4MP headers without payload */ -@@ -184,6 +184,7 @@ enum MRT_BGP4MP_TYPES { +@@ -104,6 +111,7 @@ enum MRT_BGP4MP_TYPES { + * + * The source_ip and dest_ip are dependant of the afi type. For IPv6 source_ip + * and dest_ip are both 16 bytes long. ++ * For the AS4 types the source_as and dest_as numbers are both 4 bytes long. + * + * Payload of a BGP4MP_STATE_CHANGE packet: + * +@@ -155,6 +163,98 @@ enum MRT_BGP4MP_TYPES { + */ + + /* ++ * New MRT dump format MSG_TABLE_DUMP_V2, the dump is implemented with ++ * sub-tables for peers and NLRI entries just use the index into the peer ++ * table. ++ */ ++enum MRT_DUMP_V2_SUBTYPES { ++ MRT_DUMP_V2_PEER_INDEX_TABLE=1, ++ MRT_DUMP_V2_RIB_IPV4_UNICAST=2, ++ MRT_DUMP_V2_RIB_IPV4_MULTICAST=3, ++ MRT_DUMP_V2_RIB_IPV6_UNICAST=4, ++ MRT_DUMP_V2_RIB_IPV6_MULTICAST=5, ++ MRT_DUMP_V2_RIB_GENERIC=6 ++}; ++ ++/* ++ * Format of the MRT_DUMP_V2_PEER_INDEX_TABLE: ++ * If there is no view_name, view_name_len must be set to 0 ++ * ++ * +--------+--------+--------+--------+ ++ * | collector_bgp_id | ++ * +--------+--------+--------+--------+ ++ * | view_name_len | view_name ++ * +--------+--------+--------+--------+ ++ * view_name (variable) ... | ++ * +--------+--------+--------+--------+ ++ * | peer_count | peer_entries ++ * +--------+--------+--------+--------+ ++ * peer_entries (variable) ... ++ * +--------+--------+--------+--------+ ++ * ++ * The format of a peer_entry is the following: ++ * ++ * +--------+ ++ * | type | ++ * +--------+--------+--------+--------+ ++ * | peer_bgp_id | ++ * +--------+--------+--------+--------+ ++ * | peer_ip_addr (variable) | ++ * +--------+--------+--------+--------+ ++ * | peer_as (variable) | ++ * +--------+--------+--------+--------+ ++ * ++ * The message is packed a bit strangely. The type byte defines what size ++ * the peer addr and peer AS have. ++ * The position of a peer in the PEER_INDEX_TABLE is used as the index for ++ * the other messages. ++ */ ++#define MRT_DUMP_V2_PEER_BIT_I 0x1 /* set for IPv6 addrs */ ++#define MRT_DUMP_V2_PEER_BIT_A 0x2 /* set for 32 bits AS number */ ++ ++/* ++ * AFI/SAFI specific RIB Subtypes are special to save a few bytes. ++ * ++ * +--------+--------+--------+--------+ ++ * | seq_num | ++ * +--------+--------+--------+--------+ ++ * | plen | prefix (variable) ++ * +--------+--------+--------+--------+ ++ * | #entry | rib entries (variable) ++ * +--------+--------+--------+--------+ ++ * ++ * The RIB_GENERIC subtype is needed for the less common AFI/SAFI pairs ++ * ++ * +--------+--------+--------+--------+ ++ * | seq_num | ++ * +--------+--------+--------+--------+ ++ * | AFI | SAFI | NLRI ++ * +--------+--------+--------+--------+ ++ * NLRI (variable) ... ++ * +--------+--------+--------+--------+ ++ * | #entry | rib entries (variable) ++ * +--------+--------+--------+--------+ ++ */ ++ ++/* ++ * The RIB entries have the following form. ++ * ++ * +--------+--------+ ++ * | peer index | ++ * +--------+--------+--------+--------+ ++ * | originated_time | ++ * +--------+--------+--------+--------+ ++ * | attr_len | bgp_attrs ++ * +--------+--------+--------+--------+ ++ * bgp_attrs (variable) ... ++ * +--------+--------+--------+--------+ ++ * ++ * Some BGP path attributes need special encoding: ++ * - the AS_PATH attribute MUST be encoded as 4-Byte AS ++ * - the MP_REACH_NLRI only consists of the nexthop len and nexthop address ++ */ ++ ++/* + * Format for routing table dumps in "old" mrt format. + * Type MSG_TABLE_DUMP and subtype is AFI_IPv4 (1) for IPv4 and AFI_IPv6 (2) + * for IPv6. In the IPv6 case prefix and peer_ip are both 16 bytes long. +@@ -182,8 +282,14 @@ enum MRT_BGP4MP_TYPES { + * The status field is unused and should be set to 1. + */ ++enum MRT_DUMP_SUBTYPES { ++ MRT_DUMP_AFI_IP=1, ++ MRT_DUMP_AFI_IPv6=2 ++}; ++ /* size of the dump header until attr_len */ #define MRT_DUMP_HEADER_SIZE 22 +#define MRT_DUMP_HEADER_SIZE_V6 46 /* * OLD MRT message headers. These structs are here for completion but -@@ -235,7 +236,7 @@ enum MRT_BGP_TYPES { +@@ -192,7 +298,7 @@ enum MRT_BGP4MP_TYPES { + * Only for bgp messages (type 5, 9 and 10) + * Nota bene for bgp dumps MSG_PROTOCOL_BGP4MP should be used. + */ +-enum MRT_BGP_TYPES { ++enum MRT_BGP_SUBTYPES { + MSG_BGP_NULL, + MSG_BGP_UPDATE, /* raw update packet (contains both withdraws + and announcements) */ +@@ -221,10 +327,8 @@ enum MRT_BGP_TYPES { + * + * For IPv6 the type is MSG_PROTOCOL_BGP4PLUS and the subtype remains + * MSG_BGP_UPDATE. The source_ip and dest_ip are again extended to 16 bytes. +- */ +- +-/* +- * For subtype MSG_BGP_STATECHANGE (for all BGP types or just for the ++ * ++ * For subtype MSG_BGP_STATE_CHANGE (for all BGP types or just for the + * MSG_PROTOCOL_BGP4PLUS case? Unclear.) + * + * +--------+--------+--------+--------+ +@@ -235,7 +339,7 @@ enum MRT_BGP_TYPES { * | new_state | * +--------+--------+ * - * State are defined in RFC 1771. -+ * State are defined in RFC 1771/4271. ++ * States are defined in RFC 1771/4271. */ /* -@@ -303,7 +304,7 @@ void mrt_dump_state(struct mrt *, u_in - struct peer *); - void mrt_clear_seq(void); - void mrt_dump_upcall(struct rib_entry *, void *); +@@ -251,66 +355,4 @@ enum MRT_BGP_TYPES { + * terminated ... | 0 | + * +--------+--------+--------+ + */ +- +-#define MRT_FILE_LEN 512 +-enum mrt_type { +- MRT_NONE, +- MRT_TABLE_DUMP, +- MRT_TABLE_DUMP_MP, +- MRT_ALL_IN, +- MRT_ALL_OUT, +- MRT_UPDATE_IN, +- MRT_UPDATE_OUT +-}; +- +-enum mrt_state { +- MRT_STATE_RUNNING, +- MRT_STATE_OPEN, +- MRT_STATE_REOPEN, +- MRT_STATE_REMOVE +-}; +- +-struct mrt { +- char rib[PEER_DESCR_LEN]; +- struct msgbuf wbuf; +- LIST_ENTRY(mrt) entry; +- u_int32_t peer_id; +- u_int32_t group_id; +- enum mrt_type type; +- enum mrt_state state; +- u_int16_t seqnum; +-}; +- +-struct mrt_config { +- struct mrt conf; +- char name[MRT_FILE_LEN]; /* base file name */ +- char file[MRT_FILE_LEN]; /* actual file name */ +- time_t ReopenTimer; +- time_t ReopenTimerInterval; +-}; +- +-#define MRT2MC(x) ((struct mrt_config *)(x)) +-#define MRT_MAX_TIMEOUT 7200 +- +-struct peer; +-struct prefix; +-struct rib_entry; +- +-/* prototypes */ +-void mrt_dump_bgp_msg(struct mrt *, void *, u_int16_t, +- struct peer *); +-void mrt_dump_state(struct mrt *, u_int16_t, u_int16_t, +- struct peer *); +-void mrt_clear_seq(void); +-void mrt_dump_upcall(struct rib_entry *, void *); -void mrt_dump_done(void *); -+void mrt_done(void *); - void mrt_write(struct mrt *); - void mrt_clean(struct mrt *); - void mrt_init(struct imsgbuf *, struct imsgbuf *); +-void mrt_write(struct mrt *); +-void mrt_clean(struct mrt *); +-void mrt_init(struct imsgbuf *, struct imsgbuf *); +-int mrt_timeout(struct mrt_head *); +-void mrt_reconfigure(struct mrt_head *); +-void mrt_handler(struct mrt_head *); +-struct mrt *mrt_get(struct mrt_head *, struct mrt *); +-int mrt_mergeconfig(struct mrt_head *, struct mrt_head *); +- + #endif diff --git a/net/openbgpd/files/patch-bgpd_name2id.c b/net/openbgpd/files/patch-bgpd_name2id.c new file mode 100644 index 000000000000..bf6cfbd067a8 --- /dev/null +++ b/net/openbgpd/files/patch-bgpd_name2id.c @@ -0,0 +1,14 @@ +Index: bgpd/name2id.c +=================================================================== +RCS file: /home/cvs/private/hrs/openbgpd/bgpd/name2id.c,v +retrieving revision 1.1.1.2 +retrieving revision 1.1.1.3 +diff -u -p -r1.1.1.2 -r1.1.1.3 +--- bgpd/name2id.c 9 Jul 2009 16:49:54 -0000 1.1.1.2 ++++ bgpd/name2id.c 13 Oct 2012 18:22:43 -0000 1.1.1.3 +@@ -1,4 +1,4 @@ +-/* $OpenBSD: name2id.c,v 1.9 2009/06/04 04:46:42 claudio Exp $ */ ++/* $OpenBSD: name2id.c,v 1.8 2009/05/17 12:25:15 claudio Exp $ */ + + /* + * Copyright (c) 2004, 2005 Henning Brauer <henning@openbsd.org> diff --git a/net/openbgpd/files/patch-bgpd_parse.y b/net/openbgpd/files/patch-bgpd_parse.y index 64e9081f287d..76bc093b8ed3 100644 --- a/net/openbgpd/files/patch-bgpd_parse.y +++ b/net/openbgpd/files/patch-bgpd_parse.y @@ -2,12 +2,13 @@ Index: bgpd/parse.y =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/parse.y,v retrieving revision 1.1.1.8 -diff -u -p -r1.1.1.8 parse.y +retrieving revision 1.11 +diff -u -p -r1.1.1.8 -r1.11 --- bgpd/parse.y 14 Feb 2010 20:19:57 -0000 1.1.1.8 -+++ bgpd/parse.y 3 Jul 2011 04:43:32 -0000 ++++ bgpd/parse.y 13 Oct 2012 18:50:07 -0000 1.11 @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.231 2009/06/06 01:10:29 claudio Exp $ */ -+/* $OpenBSD: parse.y,v 1.250 2010/03/31 18:53:23 claudio Exp $ */ ++/* $OpenBSD: parse.y,v 1.263 2012/09/12 05:56:22 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -23,7 +24,17 @@ diff -u -p -r1.1.1.8 parse.y #include <ctype.h> #include <err.h> #include <unistd.h> -@@ -74,10 +77,12 @@ char *symget(const char *); +@@ -33,6 +36,9 @@ + #include <limits.h> + #include <stdarg.h> + #include <stdio.h> ++#if defined(__FreeBSD__) ++#include <stdlib.h> ++#endif + #include <string.h> + #include <syslog.h> + +@@ -74,10 +80,12 @@ char *symget(const char *); static struct bgpd_config *conf; static struct mrt_head *mrtconf; @@ -37,7 +48,7 @@ diff -u -p -r1.1.1.8 parse.y static struct filter_head *filter_l; static struct filter_head *peerfilter_l; static struct filter_head *groupfilter_l; -@@ -105,7 +110,7 @@ struct filter_match_l { +@@ -105,7 +113,7 @@ struct filter_match_l { struct filter_match m; struct filter_prefix_l *prefix_l; struct filter_as_l *as_l; @@ -46,7 +57,7 @@ diff -u -p -r1.1.1.8 parse.y } fmopts; struct peer *alloc_peer(void); -@@ -113,8 +118,8 @@ struct peer *new_peer(void); +@@ -113,8 +121,8 @@ struct peer *new_peer(void); struct peer *new_group(void); int add_mrtconfig(enum mrt_type, char *, time_t, struct peer *, char *); @@ -57,7 +68,7 @@ diff -u -p -r1.1.1.8 parse.y int get_id(struct peer *); int expand_rule(struct filter_rule *, struct filter_peers_l *, struct filter_match_l *, struct filter_set_head *); -@@ -123,12 +128,14 @@ int neighbor_consistent(struct peer *) +@@ -123,12 +131,14 @@ int neighbor_consistent(struct peer *) int merge_filterset(struct filter_set_head *, struct filter_set *); void copy_filterset(struct filter_set_head *, struct filter_set_head *); @@ -75,7 +86,7 @@ diff -u -p -r1.1.1.8 parse.y typedef struct { union { -@@ -159,29 +166,33 @@ typedef struct { +@@ -159,29 +169,33 @@ typedef struct { %} %token AS ROUTERID HOLDTIME YMIN LISTEN ON FIBUPDATE RTABLE @@ -117,7 +128,7 @@ diff -u -p -r1.1.1.8 parse.y %type <v.string> string filter_rib %type <v.addr> address %type <v.prefix> prefix addrspec -@@ -204,6 +215,7 @@ grammar : /* empty */ +@@ -204,6 +218,7 @@ grammar : /* empty */ | grammar include '\n' | grammar conf_main '\n' | grammar varset '\n' @@ -125,7 +136,7 @@ diff -u -p -r1.1.1.8 parse.y | grammar neighbor '\n' | grammar group '\n' | grammar filterrule '\n' -@@ -211,8 +223,12 @@ grammar : /* empty */ +@@ -211,8 +226,12 @@ grammar : /* empty */ ; asnumber : NUMBER { @@ -140,7 +151,7 @@ diff -u -p -r1.1.1.8 parse.y YYERROR; } } -@@ -274,6 +290,8 @@ yesno : STRING { +@@ -274,6 +293,8 @@ yesno : STRING { else if (!strcmp($1, "no")) $$ = 0; else { @@ -149,7 +160,7 @@ diff -u -p -r1.1.1.8 parse.y free($1); YYERROR; } -@@ -318,7 +336,7 @@ conf_main : AS as4number { +@@ -318,7 +339,7 @@ conf_main : AS as4number { conf->short_as = $3; } | ROUTERID address { @@ -158,7 +169,7 @@ diff -u -p -r1.1.1.8 parse.y yyerror("router-id must be an IPv4 address"); YYERROR; } -@@ -342,42 +360,25 @@ conf_main : AS as4number { +@@ -342,42 +363,25 @@ conf_main : AS as4number { } | LISTEN ON address { struct listen_addr *la; @@ -209,7 +220,7 @@ diff -u -p -r1.1.1.8 parse.y } | ROUTECOLL yesno { if ($2 == 1) -@@ -386,7 +387,7 @@ conf_main : AS as4number { +@@ -386,7 +390,7 @@ conf_main : AS as4number { conf->flags &= ~BGPD_FLAG_NO_EVALUATE; } | RDE RIB STRING { @@ -218,7 +229,7 @@ diff -u -p -r1.1.1.8 parse.y free($3); YYERROR; } -@@ -395,9 +396,27 @@ conf_main : AS as4number { +@@ -395,9 +399,27 @@ conf_main : AS as4number { | RDE RIB STRING yesno EVALUATE { if ($4) { free($3); @@ -247,7 +258,7 @@ diff -u -p -r1.1.1.8 parse.y free($3); YYERROR; } -@@ -418,59 +437,7 @@ conf_main : AS as4number { +@@ -418,59 +440,7 @@ conf_main : AS as4number { } free($2); } @@ -308,7 +319,25 @@ diff -u -p -r1.1.1.8 parse.y | DUMP STRING STRING optnumber { int action; -@@ -575,11 +542,20 @@ conf_main : AS as4number { +@@ -484,6 +454,8 @@ conf_main : AS as4number { + action = MRT_TABLE_DUMP; + else if (!strcmp($2, "table-mp")) + action = MRT_TABLE_DUMP_MP; ++ else if (!strcmp($2, "table-v2")) ++ action = MRT_TABLE_DUMP_V2; + else { + yyerror("unknown mrt dump type"); + free($2); +@@ -511,6 +483,8 @@ conf_main : AS as4number { + action = MRT_TABLE_DUMP; + else if (!strcmp($4, "table-mp")) + action = MRT_TABLE_DUMP_MP; ++ else if (!strcmp($4, "table-v2")) ++ action = MRT_TABLE_DUMP_V2; + else { + yyerror("unknown mrt dump type"); + free($3); +@@ -575,11 +549,20 @@ conf_main : AS as4number { free($4); } | RTABLE NUMBER { @@ -332,7 +361,7 @@ diff -u -p -r1.1.1.8 parse.y } | CONNECTRETRY NUMBER { if ($2 > USHRT_MAX || $2 < 1) { -@@ -588,6 +564,15 @@ conf_main : AS as4number { +@@ -588,6 +571,15 @@ conf_main : AS as4number { } conf->connectretry = $2; } @@ -348,7 +377,7 @@ diff -u -p -r1.1.1.8 parse.y ; mrtdump : DUMP STRING inout STRING optnumber { -@@ -620,10 +605,47 @@ mrtdump : DUMP STRING inout STRING optn +@@ -620,10 +612,47 @@ mrtdump : DUMP STRING inout STRING optn } ; @@ -396,7 +425,7 @@ diff -u -p -r1.1.1.8 parse.y address : STRING { u_int8_t len; -@@ -635,11 +657,11 @@ address : STRING { +@@ -635,11 +664,11 @@ address : STRING { } free($1); @@ -411,7 +440,7 @@ diff -u -p -r1.1.1.8 parse.y YYERROR; } } -@@ -653,7 +675,7 @@ prefix : STRING '/' NUMBER { +@@ -653,7 +682,7 @@ prefix : STRING '/' NUMBER { free($1); YYERROR; } @@ -420,7 +449,7 @@ diff -u -p -r1.1.1.8 parse.y fatal(NULL); free($1); -@@ -672,7 +694,7 @@ prefix : STRING '/' NUMBER { +@@ -672,7 +701,7 @@ prefix : STRING '/' NUMBER { yyerror("bad prefix %lld/%lld", $1, $3); YYERROR; } @@ -429,7 +458,7 @@ diff -u -p -r1.1.1.8 parse.y fatal(NULL); if (!host(s, &$$.prefix, &$$.len)) { -@@ -686,7 +708,7 @@ prefix : STRING '/' NUMBER { +@@ -686,7 +715,7 @@ prefix : STRING '/' NUMBER { addrspec : address { memcpy(&$$.prefix, &$1, sizeof(struct bgpd_addr)); @@ -438,7 +467,7 @@ diff -u -p -r1.1.1.8 parse.y $$.len = 32; else $$.len = 128; -@@ -705,14 +727,150 @@ optnumber : /* empty */ { $$ = 0; } +@@ -705,14 +734,150 @@ optnumber : /* empty */ { $$ = 0; } | NUMBER ; @@ -591,7 +620,7 @@ diff -u -p -r1.1.1.8 parse.y if (get_id(curpeer)) { yyerror("get_id failed"); YYERROR; -@@ -802,6 +960,17 @@ peeropts : REMOTEAS as4number { +@@ -802,6 +967,17 @@ peeropts : REMOTEAS as4number { } free($2); } @@ -609,7 +638,7 @@ diff -u -p -r1.1.1.8 parse.y | LOCALADDR address { memcpy(&curpeer->conf.local_addr, &$2, sizeof(curpeer->conf.local_addr)); -@@ -852,13 +1021,17 @@ peeropts : REMOTEAS as4number { +@@ -852,13 +1028,17 @@ peeropts : REMOTEAS as4number { curpeer->conf.min_holdtime = $3; } | ANNOUNCE family STRING { @@ -632,7 +661,7 @@ diff -u -p -r1.1.1.8 parse.y yyerror("unknown/unsupported SAFI \"%s\"", $3); free($3); -@@ -866,25 +1039,31 @@ peeropts : REMOTEAS as4number { +@@ -866,25 +1046,31 @@ peeropts : REMOTEAS as4number { } free($3); @@ -658,7 +687,7 @@ diff -u -p -r1.1.1.8 parse.y + curpeer->conf.capabilities.refresh = $3; + } + | ANNOUNCE RESTART yesno { -+ curpeer->conf.capabilities.restart = $3; ++ curpeer->conf.capabilities.grestart.restart = $3; + } + | ANNOUNCE AS4BYTE yesno { + curpeer->conf.capabilities.as4byte = $3; @@ -674,7 +703,7 @@ diff -u -p -r1.1.1.8 parse.y curpeer->conf.announce_type = ANNOUNCE_NONE; else if (!strcmp($2, "all")) curpeer->conf.announce_type = ANNOUNCE_ALL; -@@ -1083,7 +1262,7 @@ peeropts : REMOTEAS as4number { +@@ -1083,7 +1269,7 @@ peeropts : REMOTEAS as4number { curpeer->conf.reflector_client = 1; } | REFLECTOR address { @@ -683,7 +712,7 @@ diff -u -p -r1.1.1.8 parse.y yyerror("route reflector cluster-id must be " "an IPv4 address"); YYERROR; -@@ -1157,6 +1336,10 @@ family : IPV4 { $$ = AFI_IPv4; } +@@ -1157,6 +1343,10 @@ family : IPV4 { $$ = AFI_IPv4; } | IPV6 { $$ = AFI_IPv6; } ; @@ -694,7 +723,7 @@ diff -u -p -r1.1.1.8 parse.y espah : ESP { $$ = 1; } | AH { $$ = 0; } ; -@@ -1336,12 +1519,12 @@ filter_prefix_l : filter_prefix { $$ +@@ -1336,12 +1526,12 @@ filter_prefix_l : filter_prefix { $$ ; filter_prefix : prefix { @@ -709,7 +738,7 @@ diff -u -p -r1.1.1.8 parse.y if (($$ = calloc(1, sizeof(struct filter_prefix_l))) == NULL) fatal(NULL); -@@ -1410,6 +1593,12 @@ filter_as : as4number { +@@ -1410,6 +1600,12 @@ filter_as : as4number { fatal(NULL); $$->a.as = $1; } @@ -722,7 +751,7 @@ diff -u -p -r1.1.1.8 parse.y ; filter_match_h : /* empty */ { -@@ -1437,18 +1626,18 @@ filter_elm : filter_prefix_h { +@@ -1437,18 +1633,18 @@ filter_elm : filter_prefix_h { fmopts.prefix_l = $1; } | PREFIXLEN prefixlenop { @@ -744,7 +773,7 @@ diff -u -p -r1.1.1.8 parse.y } | filter_as_h { if (fmopts.as_l != NULL) { -@@ -1457,32 +1646,73 @@ filter_elm : filter_prefix_h { +@@ -1457,32 +1653,73 @@ filter_elm : filter_prefix_h { } fmopts.as_l = $1; } @@ -781,11 +810,11 @@ diff -u -p -r1.1.1.8 parse.y - if (parsecommunity($2, &fmopts.m.community.as, - &fmopts.m.community.type) == -1) { + if (parsecommunity(&fmopts.m.community, $2) == -1) { - free($2); - YYERROR; - } - free($2); - } ++ free($2); ++ YYERROR; ++ } ++ free($2); ++ } + | EXTCOMMUNITY STRING STRING { + if (fmopts.m.ext_community.flags & + EXT_COMMUNITY_FLAG_VALID) { @@ -797,13 +826,13 @@ diff -u -p -r1.1.1.8 parse.y + + if (parseextcommunity(&fmopts.m.ext_community, + $2, $3) == -1) { -+ free($2); + free($2); + free($3); -+ YYERROR; -+ } -+ free($2); + YYERROR; + } + free($2); + free($3); -+ } + } | IPV4 { - if (fmopts.af) { + if (fmopts.aid) { @@ -824,7 +853,25 @@ diff -u -p -r1.1.1.8 parse.y } ; -@@ -1782,8 +2012,7 @@ filter_set_opt : LOCALPREF NUMBER { +@@ -1588,7 +1825,7 @@ filter_set_opt : LOCALPREF NUMBER { + } + if (($$ = calloc(1, sizeof(struct filter_set))) == NULL) + fatal(NULL); +- if ($2 > 0) { ++ if ($2 >= 0) { + $$->type = ACTION_SET_MED; + $$->action.metric = $2; + } else { +@@ -1623,7 +1860,7 @@ filter_set_opt : LOCALPREF NUMBER { + } + if (($$ = calloc(1, sizeof(struct filter_set))) == NULL) + fatal(NULL); +- if ($2 > 0) { ++ if ($2 >= 0) { + $$->type = ACTION_SET_MED; + $$->action.metric = $2; + } else { +@@ -1782,8 +2019,7 @@ filter_set_opt : LOCALPREF NUMBER { else $$->type = ACTION_SET_COMMUNITY; @@ -834,7 +881,7 @@ diff -u -p -r1.1.1.8 parse.y free($3); free($$); YYERROR; -@@ -1796,40 +2025,62 @@ filter_set_opt : LOCALPREF NUMBER { +@@ -1796,40 +2032,62 @@ filter_set_opt : LOCALPREF NUMBER { free($$); YYERROR; } @@ -917,7 +964,7 @@ diff -u -p -r1.1.1.8 parse.y ; %% -@@ -1873,6 +2124,7 @@ lookup(char *s) +@@ -1873,6 +2131,7 @@ lookup(char *s) { "allow", ALLOW}, { "announce", ANNOUNCE}, { "any", ANY}, @@ -925,7 +972,7 @@ diff -u -p -r1.1.1.8 parse.y { "blackhole", BLACKHOLE}, { "capabilities", CAPABILITIES}, { "community", COMMUNITY}, -@@ -1889,16 +2141,22 @@ lookup(char *s) +@@ -1889,16 +2148,22 @@ lookup(char *s) { "enforce", ENFORCE}, { "esp", ESP}, { "evaluate", EVALUATE}, @@ -948,7 +995,7 @@ diff -u -p -r1.1.1.8 parse.y { "ipsec", IPSEC}, { "key", KEY}, { "listen", LISTEN}, -@@ -1906,6 +2164,8 @@ lookup(char *s) +@@ -1906,6 +2171,8 @@ lookup(char *s) { "localpref", LOCALPREF}, { "log", LOG}, { "match", MATCH}, @@ -957,7 +1004,7 @@ diff -u -p -r1.1.1.8 parse.y { "max-prefix", MAXPREFIX}, { "md5sig", MD5SIG}, { "med", MED}, -@@ -1918,6 +2178,7 @@ lookup(char *s) +@@ -1918,6 +2185,7 @@ lookup(char *s) { "nexthop", NEXTHOP}, { "no-modify", NOMODIFY}, { "on", ON}, @@ -965,7 +1012,7 @@ diff -u -p -r1.1.1.8 parse.y { "out", OUT}, { "passive", PASSIVE}, { "password", PASSWORD}, -@@ -1929,10 +2190,14 @@ lookup(char *s) +@@ -1929,10 +2197,14 @@ lookup(char *s) { "prepend-self", PREPEND_SELF}, { "qualify", QUALIFY}, { "quick", QUICK}, @@ -980,7 +1027,7 @@ diff -u -p -r1.1.1.8 parse.y { "rib", RIB}, { "route-collector", ROUTECOLL}, { "route-reflector", REFLECTOR}, -@@ -1941,6 +2206,7 @@ lookup(char *s) +@@ -1941,6 +2213,7 @@ lookup(char *s) { "rtlabel", RTLABEL}, { "self", SELF}, { "set", SET}, @@ -988,7 +1035,7 @@ diff -u -p -r1.1.1.8 parse.y { "softreconfig", SOFTRECONFIG}, { "source-as", SOURCEAS}, { "spi", SPI}, -@@ -2117,9 +2383,10 @@ top: +@@ -2117,9 +2390,10 @@ top: return (0); if (next == quotec || c == ' ' || c == '\t') c = next; @@ -1001,7 +1048,7 @@ diff -u -p -r1.1.1.8 parse.y lungetc(next); } else if (c == quotec) { *p = '\0'; -@@ -2135,6 +2402,26 @@ top: +@@ -2135,6 +2409,26 @@ top: if (yylval.v.string == NULL) fatal("yylex: strdup"); return (STRING); @@ -1028,7 +1075,7 @@ diff -u -p -r1.1.1.8 parse.y } #define allowed_to_end_number(x) \ -@@ -2274,18 +2561,21 @@ popfile(void) +@@ -2274,18 +2568,21 @@ popfile(void) int parse_config(char *filename, struct bgpd_config *xconf, struct mrt_head *xmconf, struct peer **xpeers, struct network_head *nc, @@ -1051,7 +1098,7 @@ diff -u -p -r1.1.1.8 parse.y if ((file = pushfile(filename, 1)) == NULL) { free(conf); -@@ -2316,13 +2606,15 @@ parse_config(char *filename, struct bgpd +@@ -2316,13 +2613,15 @@ parse_config(char *filename, struct bgpd id = 1; /* network list is always empty in the parent */ @@ -1070,7 +1117,7 @@ diff -u -p -r1.1.1.8 parse.y yyparse(); errors = file->errors; -@@ -2344,6 +2636,9 @@ parse_config(char *filename, struct bgpd +@@ -2344,6 +2643,9 @@ parse_config(char *filename, struct bgpd if (errors) { /* XXX more leaks in this case */ @@ -1080,7 +1127,7 @@ diff -u -p -r1.1.1.8 parse.y while ((la = TAILQ_FIRST(listen_addrs)) != NULL) { TAILQ_REMOVE(listen_addrs, la, entry); free(la); -@@ -2357,23 +2652,44 @@ parse_config(char *filename, struct bgpd +@@ -2357,23 +2659,44 @@ parse_config(char *filename, struct bgpd while ((n = TAILQ_FIRST(netconf)) != NULL) { TAILQ_REMOVE(netconf, n, entry); @@ -1125,7 +1172,7 @@ diff -u -p -r1.1.1.8 parse.y } else { errors += merge_config(xconf, conf, peer_l, listen_addrs); errors += mrt_mergeconfig(xmconf, mrtconf); -@@ -2505,27 +2821,27 @@ getcommunity(char *s) +@@ -2505,27 +2828,27 @@ getcommunity(char *s) } int @@ -1163,7 +1210,7 @@ diff -u -p -r1.1.1.8 parse.y return (0); } -@@ -2537,23 +2853,176 @@ parsecommunity(char *s, int *as, int *ty +@@ -2537,23 +2860,176 @@ parsecommunity(char *s, int *as, int *ty if ((i = getcommunity(s)) == COMMUNITY_ERROR) return (-1); @@ -1343,7 +1390,7 @@ diff -u -p -r1.1.1.8 parse.y if ((p = calloc(1, sizeof(struct peer))) == NULL) fatal("new_peer"); -@@ -2564,11 +3033,11 @@ alloc_peer(void) +@@ -2564,11 +3040,11 @@ alloc_peer(void) p->conf.distance = 1; p->conf.announce_type = ANNOUNCE_UNDEF; p->conf.announce_capa = 1; @@ -1352,13 +1399,14 @@ diff -u -p -r1.1.1.8 parse.y + for (i = 0; i < AID_MAX; i++) + p->conf.capabilities.mp[i] = -1; p->conf.capabilities.refresh = 1; - p->conf.capabilities.restart = 0; +- p->conf.capabilities.restart = 0; - p->conf.capabilities.as4byte = 0; ++ p->conf.capabilities.grestart.restart = 1; + p->conf.capabilities.as4byte = 1; p->conf.local_as = conf->as; p->conf.local_short_as = conf->short_as; p->conf.softreconfig_in = 1; -@@ -2592,6 +3061,9 @@ new_peer(void) +@@ -2592,6 +3068,9 @@ new_peer(void) if (strlcpy(p->conf.descr, curgroup->conf.descr, sizeof(p->conf.descr)) >= sizeof(p->conf.descr)) fatalx("new_peer descr strlcpy"); @@ -1368,7 +1416,7 @@ diff -u -p -r1.1.1.8 parse.y p->conf.groupid = curgroup->conf.id; p->conf.local_as = curgroup->conf.local_as; p->conf.local_short_as = curgroup->conf.local_short_as; -@@ -2674,39 +3146,52 @@ add_mrtconfig(enum mrt_type type, char * +@@ -2674,39 +3153,52 @@ add_mrtconfig(enum mrt_type type, char * } int @@ -1433,7 +1481,7 @@ diff -u -p -r1.1.1.8 parse.y } int -@@ -2715,7 +3200,7 @@ get_id(struct peer *newpeer) +@@ -2715,7 +3207,7 @@ get_id(struct peer *newpeer) struct peer *p; for (p = peer_l_old; p != NULL; p = p->next) @@ -1442,7 +1490,7 @@ diff -u -p -r1.1.1.8 parse.y if (!memcmp(&p->conf.remote_addr, &newpeer->conf.remote_addr, sizeof(p->conf.remote_addr))) { -@@ -2856,9 +3341,11 @@ str2key(char *s, char *dest, size_t max_ +@@ -2856,9 +3348,11 @@ str2key(char *s, char *dest, size_t max_ int neighbor_consistent(struct peer *p) { @@ -1456,7 +1504,7 @@ diff -u -p -r1.1.1.8 parse.y yyerror("local-address and neighbor address " "must be of the same address family"); return (-1); -@@ -2869,7 +3356,7 @@ neighbor_consistent(struct peer *p) +@@ -2869,7 +3363,7 @@ neighbor_consistent(struct peer *p) p->conf.auth.method == AUTH_IPSEC_IKE_AH || p->conf.auth.method == AUTH_IPSEC_MANUAL_ESP || p->conf.auth.method == AUTH_IPSEC_MANUAL_AH) && @@ -1465,7 +1513,7 @@ diff -u -p -r1.1.1.8 parse.y yyerror("neighbors with any form of IPsec configured " "need local-address to be specified"); return (-1); -@@ -2889,10 +3376,6 @@ neighbor_consistent(struct peer *p) +@@ -2889,18 +3383,14 @@ neighbor_consistent(struct peer *p) return (-1); } @@ -1476,7 +1524,19 @@ diff -u -p -r1.1.1.8 parse.y /* set default values if they where undefined */ p->conf.ebgp = (p->conf.remote_as != conf->as); if (p->conf.announce_type == ANNOUNCE_UNDEF) -@@ -2909,6 +3392,11 @@ neighbor_consistent(struct peer *p) +- p->conf.announce_type = p->conf.ebgp == 0 ? +- ANNOUNCE_ALL : ANNOUNCE_SELF; ++ p->conf.announce_type = p->conf.ebgp ? ++ ANNOUNCE_SELF : ANNOUNCE_ALL; + if (p->conf.enforce_as == ENFORCE_AS_UNDEF) +- p->conf.enforce_as = p->conf.ebgp == 0 ? +- ENFORCE_AS_OFF : ENFORCE_AS_ON; ++ p->conf.enforce_as = p->conf.ebgp ? ++ ENFORCE_AS_ON : ENFORCE_AS_OFF; + + /* EBGP neighbors are not allowed in route reflector clusters */ + if (p->conf.reflector_client && p->conf.ebgp) { +@@ -2909,6 +3399,11 @@ neighbor_consistent(struct peer *p) return (-1); } @@ -1488,7 +1548,7 @@ diff -u -p -r1.1.1.8 parse.y return (0); } -@@ -2927,6 +3415,11 @@ merge_filterset(struct filter_set_head * +@@ -2927,6 +3422,11 @@ merge_filterset(struct filter_set_head * yyerror("community is already set"); else if (s->type == ACTION_DEL_COMMUNITY) yyerror("community will already be deleted"); @@ -1500,7 +1560,7 @@ diff -u -p -r1.1.1.8 parse.y else yyerror("redefining set parameter %s", filterset_name(s->type)); -@@ -2953,9 +3446,18 @@ merge_filterset(struct filter_set_head * +@@ -2953,9 +3453,18 @@ merge_filterset(struct filter_set_head * return (0); } break; @@ -1521,7 +1581,7 @@ diff -u -p -r1.1.1.8 parse.y TAILQ_INSERT_BEFORE(t, s, entry); return (0); } -@@ -2985,22 +3487,6 @@ copy_filterset(struct filter_set_head *s +@@ -2985,22 +3494,6 @@ copy_filterset(struct filter_set_head *s } } diff --git a/net/openbgpd/files/patch-bgpd_pfkey.c b/net/openbgpd/files/patch-bgpd_pfkey.c index f8e6845f1661..7ad7548a3e5a 100644 --- a/net/openbgpd/files/patch-bgpd_pfkey.c +++ b/net/openbgpd/files/patch-bgpd_pfkey.c @@ -2,13 +2,13 @@ Index: bgpd/pfkey.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/pfkey.c,v retrieving revision 1.1.1.6 -retrieving revision 1.1.1.8 -diff -u -p -r1.1.1.6 -r1.1.1.8 +retrieving revision 1.1.1.9 +diff -u -p -r1.1.1.6 -r1.1.1.9 --- bgpd/pfkey.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/pfkey.c 12 Jun 2011 10:44:25 -0000 1.1.1.8 ++++ bgpd/pfkey.c 13 Oct 2012 18:22:44 -0000 1.1.1.9 @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkey.c,v 1.37 2009/04/21 15:25:52 henning Exp $ */ -+/* $OpenBSD: pfkey.c,v 1.41 2010/12/09 13:50:41 claudio Exp $ */ ++/* $OpenBSD: pfkey.c,v 1.40 2009/12/14 17:38:18 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> diff --git a/net/openbgpd/files/patch-bgpd_pftable.c b/net/openbgpd/files/patch-bgpd_pftable.c index a9f2092dd156..ee6a1ea2750c 100644 --- a/net/openbgpd/files/patch-bgpd_pftable.c +++ b/net/openbgpd/files/patch-bgpd_pftable.c @@ -2,16 +2,10 @@ Index: bgpd/pftable.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/pftable.c,v retrieving revision 1.1.1.5 -retrieving revision 1.1.1.6 -diff -u -p -r1.1.1.5 -r1.1.1.6 +retrieving revision 1.1.1.7 +diff -u -p -r1.1.1.5 -r1.1.1.7 --- bgpd/pftable.c 14 Feb 2010 20:19:57 -0000 1.1.1.5 -+++ bgpd/pftable.c 14 Feb 2010 20:27:06 -0000 1.1.1.6 -@@ -1,4 +1,4 @@ --/* $OpenBSD: pftable.c,v 1.5 2005/07/01 09:19:24 claudio Exp $ */ -+/* $OpenBSD: pftable.c,v 1.6 2009/12/01 14:28:05 claudio Exp $ */ - - /* - * Copyright (c) 2004 Damien Miller <djm@openbsd.org> ++++ bgpd/pftable.c 13 Oct 2012 18:22:44 -0000 1.1.1.7 @@ -214,7 +214,7 @@ pftable_add_work(const char *table, stru bzero(pfa, sizeof(*pfa)); diff --git a/net/openbgpd/files/patch-bgpd_printconf.c b/net/openbgpd/files/patch-bgpd_printconf.c index 82fb337ccb7b..ecc7dfdc4aaf 100644 --- a/net/openbgpd/files/patch-bgpd_printconf.c +++ b/net/openbgpd/files/patch-bgpd_printconf.c @@ -2,13 +2,13 @@ Index: bgpd/printconf.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/printconf.c,v retrieving revision 1.1.1.7 -retrieving revision 1.8 -diff -u -p -r1.1.1.7 -r1.8 +retrieving revision 1.9 +diff -u -p -r1.1.1.7 -r1.9 --- bgpd/printconf.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/printconf.c 2 Jul 2011 16:06:38 -0000 1.8 ++++ bgpd/printconf.c 13 Oct 2012 18:36:00 -0000 1.9 @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.70 2009/06/06 01:10:29 claudio Exp $ */ -+/* $OpenBSD: printconf.c,v 1.79 2010/03/05 15:25:00 claudio Exp $ */ ++/* $OpenBSD: printconf.c,v 1.87 2012/09/12 05:56:22 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -263,8 +263,8 @@ diff -u -p -r1.1.1.7 -r1.8 printf("%s\tannounce capabilities no\n", c); + if (p->capabilities.refresh == 0) + printf("%s\tannounce refresh no\n", c); -+ if (p->capabilities.restart == 1) -+ printf("%s\tannounce restart yes\n", c); ++ if (p->capabilities.grestart.restart == 0) ++ printf("%s\tannounce restart no\n", c); + if (p->capabilities.as4byte == 0) + printf("%s\tannounce as4byte no\n", c); if (p->announce_type == ANNOUNCE_SELF) @@ -356,16 +356,34 @@ diff -u -p -r1.1.1.7 -r1.8 print_set(&r->set); -@@ -547,7 +645,7 @@ print_mrt(u_int32_t pid, u_int32_t gid, +@@ -513,6 +611,8 @@ mrt_type(enum mrt_type t) + return "table"; + case MRT_TABLE_DUMP_MP: + return "table-mp"; ++ case MRT_TABLE_DUMP_V2: ++ return "table-v2"; + case MRT_ALL_IN: + return "all in"; + case MRT_ALL_OUT: +@@ -541,13 +641,12 @@ print_mrt(u_int32_t pid, u_int32_t gid, + printf("%s%sdump ", prep, prep2); + if (m->rib[0]) + printf("rib %s ", m->rib); ++ printf("%s \"%s\"", mrt_type(m->type), ++ MRT2MC(m)->name); + if (MRT2MC(m)->ReopenTimerInterval == 0) +- printf("%s %s\n", mrt_type(m->type), +- MRT2MC(m)->name); ++ printf("\n"); else - printf("%s %s %d\n", mrt_type(m->type), - MRT2MC(m)->name, +- printf("%s %s %d\n", mrt_type(m->type), +- MRT2MC(m)->name, - MRT2MC(m)->ReopenTimerInterval); -+ (int)MRT2MC(m)->ReopenTimerInterval); ++ printf(" %d\n", MRT2MC(m)->ReopenTimerInterval); } } -@@ -612,26 +710,34 @@ peer_compare(const void *aa, const void +@@ -612,26 +711,34 @@ peer_compare(const void *aa, const void void print_config(struct bgpd_config *conf, struct rib_names *rib_l, struct network_head *net_l, struct peer *peer_l, diff --git a/net/openbgpd/files/patch-bgpd_rde.c b/net/openbgpd/files/patch-bgpd_rde.c index a62bcf26fdc7..62634c6aa5c1 100644 --- a/net/openbgpd/files/patch-bgpd_rde.c +++ b/net/openbgpd/files/patch-bgpd_rde.c @@ -2,16 +2,17 @@ Index: bgpd/rde.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde.c,v retrieving revision 1.1.1.8 -diff -u -p -r1.1.1.8 rde.c +retrieving revision 1.11 +diff -u -p -r1.1.1.8 -r1.11 --- bgpd/rde.c 14 Feb 2010 20:19:57 -0000 1.1.1.8 -+++ bgpd/rde.c 3 Jul 2011 04:43:59 -0000 ++++ bgpd/rde.c 13 Oct 2012 18:36:00 -0000 1.11 @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.264 2009/06/29 12:22:16 claudio Exp $ */ -+/* $OpenBSD: rde.c,v 1.290 2010/03/30 15:43:30 claudio Exp $ */ ++/* $OpenBSD: rde.c,v 1.320 2012/09/18 09:45:51 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -18,6 +18,8 @@ +@@ -18,10 +18,11 @@ #include <sys/types.h> #include <sys/socket.h> @@ -20,9 +21,15 @@ diff -u -p -r1.1.1.8 rde.c #include <errno.h> #include <ifaddrs.h> -@@ -51,12 +53,16 @@ void rde_update_withdraw(struct rde_pe +-#include <limits.h> + #include <pwd.h> + #include <poll.h> + #include <signal.h> +@@ -50,13 +51,18 @@ void rde_update_withdraw(struct rde_pe + u_int8_t); int rde_attr_parse(u_char *, u_int16_t, struct rde_peer *, struct rde_aspath *, struct mpattr *); ++int rde_attr_add(struct rde_aspath *, u_char *, u_int16_t); u_int8_t rde_attr_missing(struct rde_aspath *, int, u_int16_t); -int rde_get_mp_nexthop(u_char *, u_int16_t, u_int16_t, - struct rde_aspath *); @@ -56,12 +63,15 @@ diff -u -p -r1.1.1.8 rde.c void peer_init(u_int32_t); void peer_shutdown(void); -@@ -91,10 +101,9 @@ struct rde_peer *peer_add(u_int32_t, str +@@ -91,10 +101,12 @@ struct rde_peer *peer_add(u_int32_t, str struct rde_peer *peer_get(u_int32_t); void peer_up(u_int32_t, struct session_up *); void peer_down(u_int32_t); -void peer_dump(u_int32_t, u_int16_t, u_int8_t); -void peer_send_eor(struct rde_peer *, u_int16_t, u_int16_t); ++void peer_flush(struct rde_peer *, u_int8_t); ++void peer_stale(u_int32_t, u_int8_t); ++void peer_recv_eor(struct rde_peer *, u_int8_t); +void peer_dump(u_int32_t, u_int8_t); +void peer_send_eor(struct rde_peer *, u_int8_t); @@ -69,7 +79,7 @@ diff -u -p -r1.1.1.8 rde.c void network_add(struct network_config *, int); void network_delete(struct network_config *, int); void network_dump_upcall(struct rib_entry *, void *); -@@ -108,6 +117,7 @@ time_t reloadtime; +@@ -108,6 +120,7 @@ time_t reloadtime; struct rde_peer_head peerlist; struct rde_peer *peerself; struct filter_head *rules_l, *newrules; @@ -77,7 +87,7 @@ diff -u -p -r1.1.1.8 rde.c struct imsgbuf *ibuf_se; struct imsgbuf *ibuf_se_ctl; struct imsgbuf *ibuf_main; -@@ -120,11 +130,12 @@ struct rde_dump_ctx { +@@ -120,11 +133,12 @@ struct rde_dump_ctx { }; struct rde_mrt_ctx { @@ -93,7 +103,7 @@ diff -u -p -r1.1.1.8 rde.c u_int rde_mrt_cnt; void -@@ -144,24 +155,18 @@ u_int32_t attrhashsize = 512; +@@ -144,24 +158,17 @@ u_int32_t attrhashsize = 512; u_int32_t nexthophashsize = 64; pid_t @@ -104,7 +114,6 @@ diff -u -p -r1.1.1.8 rde.c +rde_main(int pipe_m2r[2], int pipe_s2r[2], int pipe_m2s[2], int pipe_s2rctl[2], + int debug) { -+ struct rlimit rl; pid_t pid; struct passwd *pw; - struct peer *p; @@ -123,7 +132,7 @@ diff -u -p -r1.1.1.8 rde.c switch (pid = fork()) { case -1: -@@ -172,8 +177,6 @@ rde_main(struct bgpd_config *config, str +@@ -172,8 +179,6 @@ rde_main(struct bgpd_config *config, str return (pid); } @@ -132,20 +141,7 @@ diff -u -p -r1.1.1.8 rde.c if ((pw = getpwnam(BGPD_USER)) == NULL) fatal("getpwnam"); -@@ -185,6 +188,12 @@ rde_main(struct bgpd_config *config, str - setproctitle("route decision engine"); - bgpd_process = PROC_RDE; - -+ if (getrlimit(RLIMIT_DATA, &rl) == -1) -+ fatal("getrlimit"); -+ rl.rlim_cur = rl.rlim_max; -+ if (setrlimit(RLIMIT_DATA, &rl) == -1) -+ fatal("setrlimit"); -+ - if (setgroups(1, &pw->pw_gid) || - setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || - setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) -@@ -194,6 +203,8 @@ rde_main(struct bgpd_config *config, str +@@ -194,6 +199,8 @@ rde_main(struct bgpd_config *config, str signal(SIGINT, rde_sighdlr); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); @@ -154,7 +150,7 @@ diff -u -p -r1.1.1.8 rde.c close(pipe_s2r[0]); close(pipe_s2rctl[0]); -@@ -210,50 +221,25 @@ rde_main(struct bgpd_config *config, str +@@ -210,50 +217,25 @@ rde_main(struct bgpd_config *config, str imsg_init(ibuf_se_ctl, pipe_s2rctl[1]); imsg_init(ibuf_main, pipe_m2r[1]); @@ -215,7 +211,7 @@ diff -u -p -r1.1.1.8 rde.c while (rde_quit == 0) { if (pfd_elms < PFD_PIPE_COUNT + rde_mrt_cnt) { if ((newp = realloc(pfd, sizeof(struct pollfd) * -@@ -287,11 +273,18 @@ rde_main(struct bgpd_config *config, str +@@ -287,11 +269,18 @@ rde_main(struct bgpd_config *config, str timeout = 0; i = PFD_PIPE_COUNT; @@ -237,7 +233,7 @@ diff -u -p -r1.1.1.8 rde.c } } -@@ -325,24 +318,17 @@ rde_main(struct bgpd_config *config, str +@@ -325,24 +314,17 @@ rde_main(struct bgpd_config *config, str if (pfd[PFD_PIPE_SESSION_CTL].revents & POLLIN) rde_dispatch_imsg_session(ibuf_se_ctl); @@ -269,7 +265,7 @@ diff -u -p -r1.1.1.8 rde.c if (ibuf_se_ctl->w.queued <= 0) rib_dump_runner(); } -@@ -351,11 +337,12 @@ rde_main(struct bgpd_config *config, str +@@ -351,11 +333,12 @@ rde_main(struct bgpd_config *config, str if (debug) rde_shutdown(); @@ -287,26 +283,73 @@ diff -u -p -r1.1.1.8 rde.c } msgbuf_clear(&ibuf_se->w); -@@ -378,13 +365,14 @@ rde_dispatch_imsg_session(struct imsgbuf +@@ -378,13 +361,18 @@ rde_dispatch_imsg_session(struct imsgbuf struct imsg imsg; struct peer p; struct peer_config pconf; - struct rrefresh r; - struct rde_peer *peer; +- struct rde_peer *peer; struct session_up sup; ++ struct ctl_show_rib csr; struct ctl_show_rib_request req; ++ struct rde_peer *peer; ++ struct rde_aspath *asp; struct filter_set *s; struct nexthop *nh; - int n; ++ u_int8_t *asdata; + ssize_t n; + int verbose; ++ u_int16_t len; + u_int8_t aid; if ((n = imsg_read(ibuf)) == -1) fatal("rde_dispatch_imsg_session: imsg_read error"); -@@ -423,12 +411,14 @@ rde_dispatch_imsg_session(struct imsgbuf +@@ -422,13 +410,56 @@ rde_dispatch_imsg_session(struct imsgbuf + case IMSG_SESSION_DOWN: peer_down(imsg.hdr.peerid); break; ++ case IMSG_SESSION_STALE: ++ if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(aid)) { ++ log_warnx("rde_dispatch: wrong imsg len"); ++ break; ++ } ++ memcpy(&aid, imsg.data, sizeof(aid)); ++ if (aid >= AID_MAX) ++ fatalx("IMSG_SESSION_STALE: bad AID"); ++ peer_stale(imsg.hdr.peerid, aid); ++ break; ++ case IMSG_SESSION_FLUSH: ++ if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(aid)) { ++ log_warnx("rde_dispatch: wrong imsg len"); ++ break; ++ } ++ memcpy(&aid, imsg.data, sizeof(aid)); ++ if (aid >= AID_MAX) ++ fatalx("IMSG_SESSION_FLUSH: bad AID"); ++ if ((peer = peer_get(imsg.hdr.peerid)) == NULL) { ++ log_warnx("rde_dispatch: unknown peer id %d", ++ imsg.hdr.peerid); ++ break; ++ } ++ peer_flush(peer, aid); ++ break; ++ case IMSG_SESSION_RESTARTED: ++ if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(aid)) { ++ log_warnx("rde_dispatch: wrong imsg len"); ++ break; ++ } ++ memcpy(&aid, imsg.data, sizeof(aid)); ++ if (aid >= AID_MAX) ++ fatalx("IMSG_SESSION_RESTARTED: bad AID"); ++ if ((peer = peer_get(imsg.hdr.peerid)) == NULL) { ++ log_warnx("rde_dispatch: unknown peer id %d", ++ imsg.hdr.peerid); ++ break; ++ } ++ if (peer->staletime[aid]) ++ peer_flush(peer, aid); ++ break; case IMSG_REFRESH: - if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(r)) { + if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(aid)) { @@ -322,7 +365,55 @@ diff -u -p -r1.1.1.8 rde.c break; case IMSG_NETWORK_ADD: if (imsg.hdr.len - IMSG_HEADER_SIZE != -@@ -446,13 +436,13 @@ rde_dispatch_imsg_session(struct imsgbuf +@@ -440,23 +471,68 @@ rde_dispatch_imsg_session(struct imsgbuf + TAILQ_INIT(&netconf_s.attrset); + session_set = &netconf_s.attrset; + break; ++ case IMSG_NETWORK_ASPATH: ++ if (imsg.hdr.len - IMSG_HEADER_SIZE < ++ sizeof(struct ctl_show_rib)) { ++ log_warnx("rde_dispatch: wrong imsg len"); ++ bzero(&netconf_s, sizeof(netconf_s)); ++ break; ++ } ++ asdata = imsg.data; ++ asdata += sizeof(struct ctl_show_rib); ++ memcpy(&csr, imsg.data, sizeof(csr)); ++ if (csr.aspath_len + sizeof(csr) > imsg.hdr.len - ++ IMSG_HEADER_SIZE) { ++ log_warnx("rde_dispatch: wrong aspath len"); ++ bzero(&netconf_s, sizeof(netconf_s)); ++ break; ++ } ++ asp = path_get(); ++ asp->lpref = csr.local_pref; ++ asp->med = csr.med; ++ asp->weight = csr.weight; ++ asp->flags = csr.flags; ++ asp->origin = csr.origin; ++ asp->flags |= F_PREFIX_ANNOUNCED | F_ANN_DYNAMIC; ++ asp->aspath = aspath_get(asdata, csr.aspath_len); ++ netconf_s.asp = asp; ++ break; ++ case IMSG_NETWORK_ATTR: ++ if (imsg.hdr.len <= IMSG_HEADER_SIZE) { ++ log_warnx("rde_dispatch: wrong imsg len"); ++ break; ++ } ++ /* parse path attributes */ ++ len = imsg.hdr.len - IMSG_HEADER_SIZE; ++ asp = netconf_s.asp; ++ if (rde_attr_add(asp, imsg.data, len) == -1) { ++ log_warnx("rde_dispatch: bad network " ++ "attribute"); ++ path_put(asp); ++ bzero(&netconf_s, sizeof(netconf_s)); ++ break; ++ } ++ break; + case IMSG_NETWORK_DONE: + if (imsg.hdr.len != IMSG_HEADER_SIZE) { + log_warnx("rde_dispatch: wrong imsg len"); break; } session_set = NULL; @@ -339,7 +430,29 @@ diff -u -p -r1.1.1.8 rde.c if (netconf_s.prefixlen > 128) goto badnet; network_add(&netconf_s, 0); -@@ -544,6 +534,11 @@ badnet: + break; ++ case 0: ++ /* something failed beforehands */ ++ break; + default: + badnet: + log_warnx("rde_dispatch: bad network"); +@@ -528,10 +604,14 @@ badnet: + peer->prefix_rcvd_update; + p.stats.prefix_rcvd_withdraw = + peer->prefix_rcvd_withdraw; ++ p.stats.prefix_rcvd_eor = ++ peer->prefix_rcvd_eor; + p.stats.prefix_sent_update = + peer->prefix_sent_update; + p.stats.prefix_sent_withdraw = + peer->prefix_sent_withdraw; ++ p.stats.prefix_sent_eor = ++ peer->prefix_sent_eor; + } + imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NEIGHBOR, 0, + imsg.hdr.pid, -1, &p, sizeof(struct peer)); +@@ -544,6 +624,11 @@ badnet: imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_RIB_MEM, 0, imsg.hdr.pid, -1, &rdemem, sizeof(rdemem)); break; @@ -351,7 +464,7 @@ diff -u -p -r1.1.1.8 rde.c default: break; } -@@ -554,14 +549,17 @@ badnet: +@@ -554,14 +639,17 @@ badnet: void rde_dispatch_imsg_parent(struct imsgbuf *ibuf) { @@ -370,7 +483,7 @@ diff -u -p -r1.1.1.8 rde.c u_int16_t rid; if ((n = imsg_read(ibuf)) == -1) -@@ -576,20 +574,12 @@ rde_dispatch_imsg_parent(struct imsgbuf +@@ -576,20 +664,12 @@ rde_dispatch_imsg_parent(struct imsgbuf break; switch (imsg.hdr.type) { @@ -396,7 +509,7 @@ diff -u -p -r1.1.1.8 rde.c memcpy(&netconf_p, imsg.data, sizeof(netconf_p)); TAILQ_INIT(&netconf_p.attrset); parent_set = &netconf_p.attrset; -@@ -608,6 +598,26 @@ rde_dispatch_imsg_parent(struct imsgbuf +@@ -608,6 +688,26 @@ rde_dispatch_imsg_parent(struct imsgbuf TAILQ_INIT(&netconf_p.attrset); network_delete(&netconf_p, 1); break; @@ -423,7 +536,7 @@ diff -u -p -r1.1.1.8 rde.c case IMSG_RECONF_RIB: if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(struct rde_rib)) -@@ -615,9 +625,26 @@ rde_dispatch_imsg_parent(struct imsgbuf +@@ -615,9 +715,26 @@ rde_dispatch_imsg_parent(struct imsgbuf memcpy(&rn, imsg.data, sizeof(rn)); rid = rib_find(rn.name); if (rid == RIB_FAILED) @@ -453,7 +566,7 @@ diff -u -p -r1.1.1.8 rde.c break; case IMSG_RECONF_FILTER: if (imsg.hdr.len - IMSG_HEADER_SIZE != -@@ -631,12 +658,42 @@ rde_dispatch_imsg_parent(struct imsgbuf +@@ -631,12 +748,42 @@ rde_dispatch_imsg_parent(struct imsgbuf parent_set = &r->set; TAILQ_INSERT_TAIL(newrules, r, entry); break; @@ -497,7 +610,7 @@ diff -u -p -r1.1.1.8 rde.c "mode ignored"); if (conf->flags & BGPD_FLAG_NO_EVALUATE) nconf->flags |= BGPD_FLAG_NO_EVALUATE; -@@ -644,10 +701,27 @@ rde_dispatch_imsg_parent(struct imsgbuf +@@ -644,10 +791,27 @@ rde_dispatch_imsg_parent(struct imsgbuf nconf->flags &= ~BGPD_FLAG_NO_EVALUATE; } memcpy(conf, nconf, sizeof(struct bgpd_config)); @@ -526,7 +639,7 @@ diff -u -p -r1.1.1.8 rde.c /* check if filter changed */ LIST_FOREACH(peer, &peerlist, peer_l) { -@@ -655,30 +729,59 @@ rde_dispatch_imsg_parent(struct imsgbuf +@@ -655,30 +819,59 @@ rde_dispatch_imsg_parent(struct imsgbuf continue; peer->reconf_out = 0; peer->reconf_in = 0; @@ -558,9 +671,7 @@ diff -u -p -r1.1.1.8 rde.c + peer->reconf_out = 1; + reconf_out = 1; + } - } -- /* XXX this needs rework anyway */ -- /* sync local-RIB first */ ++ } + /* bring ribs in sync before softreconfig dance */ + for (rid = 0; rid < rib_size; rid++) { + if (ribs[rid].state == RECONF_DELETE) @@ -569,7 +680,9 @@ diff -u -p -r1.1.1.8 rde.c + rib_dump(&ribs[0], + rde_softreconfig_load, &ribs[rid], + AID_UNSPEC); -+ } + } +- /* XXX this needs rework anyway */ +- /* sync local-RIB first */ + /* sync local-RIBs first */ if (reconf_in) rib_dump(&ribs[0], rde_softreconfig_in, NULL, @@ -597,7 +710,7 @@ diff -u -p -r1.1.1.8 rde.c } while ((r = TAILQ_FIRST(rules_l)) != NULL) { -@@ -688,16 +791,16 @@ rde_dispatch_imsg_parent(struct imsgbuf +@@ -688,16 +881,18 @@ rde_dispatch_imsg_parent(struct imsgbuf } free(rules_l); rules_l = newrules; @@ -607,6 +720,8 @@ diff -u -p -r1.1.1.8 rde.c - } + log_info("RDE reconfigured"); ++ imsg_compose(ibuf_main, IMSG_RECONF_DONE, 0, 0, ++ -1, NULL, 0); break; case IMSG_NEXTHOP_UPDATE: nexthop_update(imsg.data); @@ -618,7 +733,17 @@ diff -u -p -r1.1.1.8 rde.c if (parent_set == NULL) { log_warnx("rde_dispatch_imsg_parent: " "IMSG_FILTER_SET unexpected"); -@@ -744,6 +847,8 @@ rde_dispatch_imsg_parent(struct imsgbuf +@@ -725,7 +920,8 @@ rde_dispatch_imsg_parent(struct imsgbuf + log_warnx("expected to receive fd for mrt dump " + "but didn't receive any"); + else if (xmrt.type == MRT_TABLE_DUMP || +- xmrt.type == MRT_TABLE_DUMP_MP) { ++ xmrt.type == MRT_TABLE_DUMP_MP || ++ xmrt.type == MRT_TABLE_DUMP_V2) { + rde_dump_mrt_new(&xmrt, imsg.hdr.pid, fd); + } else + close(fd); +@@ -744,6 +940,8 @@ rde_dispatch_imsg_parent(struct imsgbuf int rde_update_dispatch(struct imsg *imsg) { @@ -627,7 +752,7 @@ diff -u -p -r1.1.1.8 rde.c struct rde_peer *peer; struct rde_aspath *asp = NULL; u_char *p, *mpp = NULL; -@@ -752,9 +857,8 @@ rde_update_dispatch(struct imsg *imsg) +@@ -752,9 +950,8 @@ rde_update_dispatch(struct imsg *imsg) u_int16_t withdrawn_len; u_int16_t attrpath_len; u_int16_t nlri_len; @@ -639,7 +764,7 @@ diff -u -p -r1.1.1.8 rde.c peer = peer_get(imsg->hdr.peerid); if (peer == NULL) /* unknown peer, cannot happen */ -@@ -810,26 +914,21 @@ rde_update_dispatch(struct imsg *imsg) +@@ -810,26 +1007,21 @@ rde_update_dispatch(struct imsg *imsg) goto done; } @@ -676,7 +801,7 @@ diff -u -p -r1.1.1.8 rde.c rde_reflector(peer, asp); } -@@ -860,9 +959,9 @@ rde_update_dispatch(struct imsg *imsg) +@@ -860,9 +1052,9 @@ rde_update_dispatch(struct imsg *imsg) p += pos; len -= pos; @@ -689,7 +814,18 @@ diff -u -p -r1.1.1.8 rde.c rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, NULL, 0); goto done; -@@ -892,15 +991,25 @@ rde_update_dispatch(struct imsg *imsg) +@@ -879,6 +1071,10 @@ rde_update_dispatch(struct imsg *imsg) + ERR_UPD_ATTRLIST, NULL, 0); + return (-1); + } ++ if (withdrawn_len == 0) { ++ /* EoR marker */ ++ peer_recv_eor(peer, AID_INET); ++ } + return (0); + } + +@@ -892,15 +1088,30 @@ rde_update_dispatch(struct imsg *imsg) afi = ntohs(afi); safi = *mpp++; mplen--; @@ -719,12 +855,17 @@ diff -u -p -r1.1.1.8 rde.c + goto done; + } + ++ if ((asp->flags & ~F_ATTR_MP_UNREACH) == 0 && mplen == 0) { ++ /* EoR marker */ ++ peer_recv_eor(peer, aid); ++ } ++ + switch (aid) { + case AID_INET6: while (mplen > 0) { if ((pos = rde_update_get_prefix6(mpp, mplen, &prefix, &prefixlen)) == -1) { -@@ -926,6 +1035,32 @@ rde_update_dispatch(struct imsg *imsg) +@@ -926,6 +1137,32 @@ rde_update_dispatch(struct imsg *imsg) rde_update_withdraw(peer, &prefix, prefixlen); } break; @@ -757,7 +898,7 @@ diff -u -p -r1.1.1.8 rde.c default: /* silently ignore unsupported multiprotocol AF */ break; -@@ -963,9 +1098,9 @@ rde_update_dispatch(struct imsg *imsg) +@@ -963,9 +1200,9 @@ rde_update_dispatch(struct imsg *imsg) p += pos; nlri_len -= pos; @@ -770,7 +911,7 @@ diff -u -p -r1.1.1.8 rde.c rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, NULL, 0); goto done; -@@ -995,6 +1130,22 @@ rde_update_dispatch(struct imsg *imsg) +@@ -995,6 +1232,22 @@ rde_update_dispatch(struct imsg *imsg) safi = *mpp++; mplen--; @@ -793,7 +934,7 @@ diff -u -p -r1.1.1.8 rde.c /* * this works because asp is not linked. * But first unlock the previously locked nexthop. -@@ -1004,8 +1155,8 @@ rde_update_dispatch(struct imsg *imsg) +@@ -1004,8 +1257,8 @@ rde_update_dispatch(struct imsg *imsg) (void)nexthop_delete(asp->nexthop); asp->nexthop = NULL; } @@ -804,7 +945,7 @@ diff -u -p -r1.1.1.8 rde.c rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, mpa.reach, mpa.reach_len); goto done; -@@ -1013,16 +1164,8 @@ rde_update_dispatch(struct imsg *imsg) +@@ -1013,16 +1266,8 @@ rde_update_dispatch(struct imsg *imsg) mpp += pos; mplen -= pos; @@ -823,7 +964,7 @@ diff -u -p -r1.1.1.8 rde.c while (mplen > 0) { if ((pos = rde_update_get_prefix6(mpp, mplen, &prefix, &prefixlen)) == -1) { -@@ -1058,6 +1201,42 @@ rde_update_dispatch(struct imsg *imsg) +@@ -1058,6 +1303,42 @@ rde_update_dispatch(struct imsg *imsg) } break; @@ -866,7 +1007,7 @@ diff -u -p -r1.1.1.8 rde.c default: /* silently ignore unsupported multiprotocol AF */ break; -@@ -1085,7 +1264,8 @@ rde_update_update(struct rde_peer *peer, +@@ -1085,7 +1366,8 @@ rde_update_update(struct rde_peer *peer, struct bgpd_addr *prefix, u_int8_t prefixlen) { struct rde_aspath *fasp; @@ -876,7 +1017,7 @@ diff -u -p -r1.1.1.8 rde.c u_int16_t i; peer->prefix_rcvd_update++; -@@ -1095,18 +1275,24 @@ rde_update_update(struct rde_peer *peer, +@@ -1095,18 +1377,24 @@ rde_update_update(struct rde_peer *peer, for (i = 1; i < rib_size; i++) { /* input filter */ @@ -908,7 +1049,7 @@ diff -u -p -r1.1.1.8 rde.c /* free modified aspath */ if (fasp != asp) path_put(fasp); -@@ -1114,6 +1300,8 @@ done: +@@ -1114,6 +1402,8 @@ done: if (r) peer->prefix_cnt++; @@ -917,7 +1058,16 @@ diff -u -p -r1.1.1.8 rde.c } void -@@ -1161,6 +1349,7 @@ rde_attr_parse(u_char *p, u_int16_t len, +@@ -1152,7 +1442,7 @@ rde_update_withdraw(struct rde_peer *pee + } while (0) + + #define CHECK_FLAGS(s, t, m) \ +- (((s) & ~(ATTR_EXTLEN | (m))) == (t)) ++ (((s) & ~(ATTR_DEFMASK | (m))) == (t)) + + int + rde_attr_parse(u_char *p, u_int16_t len, struct rde_peer *peer, +@@ -1161,6 +1451,7 @@ rde_attr_parse(u_char *p, u_int16_t len, struct bgpd_addr nexthop; u_char *op = p, *npath; u_int32_t tmp32; @@ -925,7 +1075,7 @@ diff -u -p -r1.1.1.8 rde.c u_int16_t attr_len, nlen; u_int16_t plen = 0; u_int8_t flags; -@@ -1195,6 +1384,7 @@ bad_len: +@@ -1195,6 +1486,7 @@ bad_len: switch (type) { case ATTR_UNDEF: /* ignore and drop path attributes with a type code of 0 */ @@ -933,7 +1083,7 @@ diff -u -p -r1.1.1.8 rde.c break; case ATTR_ORIGIN: if (attr_len != 1) -@@ -1220,7 +1410,17 @@ bad_flags: +@@ -1220,7 +1512,17 @@ bad_flags: case ATTR_ASPATH: if (!CHECK_FLAGS(flags, ATTR_WELL_KNOWN, 0)) goto bad_flags; @@ -952,7 +1102,7 @@ diff -u -p -r1.1.1.8 rde.c rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH, NULL, 0); return (-1); -@@ -1248,7 +1448,7 @@ bad_flags: +@@ -1248,7 +1550,7 @@ bad_flags: a->flags |= F_ATTR_NEXTHOP; bzero(&nexthop, sizeof(nexthop)); @@ -961,7 +1111,7 @@ diff -u -p -r1.1.1.8 rde.c UPD_READ(&nexthop.v4.s_addr, p, plen, 4); /* * Check if the nexthop is a valid IP address. We consider -@@ -1305,9 +1505,21 @@ bad_flags: +@@ -1305,9 +1607,21 @@ bad_flags: goto optattr; case ATTR_AGGREGATOR: if ((!rde_as4byte(peer) && attr_len != 6) || @@ -986,7 +1136,7 @@ diff -u -p -r1.1.1.8 rde.c goto bad_flags; if (!rde_as4byte(peer)) { /* need to inflate aggregator AS to 4-byte */ -@@ -1323,8 +1535,35 @@ bad_flags: +@@ -1323,8 +1637,35 @@ bad_flags: /* 4-byte ready server take the default route */ goto optattr; case ATTR_COMMUNITIES: @@ -1024,7 +1174,7 @@ diff -u -p -r1.1.1.8 rde.c if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, ATTR_PARTIAL)) goto bad_flags; -@@ -1336,7 +1575,7 @@ bad_flags: +@@ -1336,7 +1677,7 @@ bad_flags: goto bad_flags; goto optattr; case ATTR_CLUSTER_LIST: @@ -1033,7 +1183,7 @@ diff -u -p -r1.1.1.8 rde.c goto bad_len; if (!CHECK_FLAGS(flags, ATTR_OPTIONAL, 0)) goto bad_flags; -@@ -1370,8 +1609,15 @@ bad_flags: +@@ -1370,8 +1711,15 @@ bad_flags: plen += attr_len; break; case ATTR_AS4_AGGREGATOR: @@ -1051,7 +1201,7 @@ diff -u -p -r1.1.1.8 rde.c if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, ATTR_PARTIAL)) goto bad_flags; -@@ -1381,17 +1627,28 @@ bad_flags: +@@ -1381,19 +1729,30 @@ bad_flags: if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, ATTR_PARTIAL)) goto bad_flags; @@ -1074,6 +1224,8 @@ diff -u -p -r1.1.1.8 rde.c */ - a->flags |= F_ATTR_LOOP; - goto optattr; +- } +- a->flags |= F_ATTR_AS4BYTE_NEW; + if (flags & ATTR_PARTIAL || err == AS_ERR_SOFT) { + a->flags |= F_ATTR_PARSE_ERR; + log_peer_warnx(&peer->conf, "bad AS4_PATH, " @@ -1084,10 +1236,55 @@ diff -u -p -r1.1.1.8 rde.c + NULL, 0); + return (-1); + } - } - a->flags |= F_ATTR_AS4BYTE_NEW; ++ } ++ a->flags |= F_ATTR_AS4BYTE_NEW; goto optattr; -@@ -1440,8 +1697,8 @@ rde_attr_missing(struct rde_aspath *a, i + default: + if ((flags & ATTR_OPTIONAL) == 0) { +@@ -1415,6 +1774,42 @@ bad_list: + + return (plen); + } ++ ++int ++rde_attr_add(struct rde_aspath *a, u_char *p, u_int16_t len) ++{ ++ u_int16_t attr_len; ++ u_int16_t plen = 0; ++ u_int8_t flags; ++ u_int8_t type; ++ u_int8_t tmp8; ++ ++ if (a == NULL) /* no aspath, nothing to do */ ++ return (0); ++ if (len < 3) ++ return (-1); ++ ++ UPD_READ(&flags, p, plen, 1); ++ UPD_READ(&type, p, plen, 1); ++ ++ if (flags & ATTR_EXTLEN) { ++ if (len - plen < 2) ++ return (-1); ++ UPD_READ(&attr_len, p, plen, 2); ++ attr_len = ntohs(attr_len); ++ } else { ++ UPD_READ(&tmp8, p, plen, 1); ++ attr_len = tmp8; ++ } ++ ++ if (len - plen < attr_len) ++ return (-1); ++ ++ if (attr_optadd(a, flags, type, p, attr_len) == -1) ++ return (-1); ++ return (0); ++} ++ + #undef UPD_READ + #undef CHECK_FLAGS + +@@ -1440,8 +1835,8 @@ rde_attr_missing(struct rde_aspath *a, i } int @@ -1098,7 +1295,7 @@ diff -u -p -r1.1.1.8 rde.c { struct bgpd_addr nexthop; u_int8_t totlen, nhlen; -@@ -1457,8 +1714,9 @@ rde_get_mp_nexthop(u_char *data, u_int16 +@@ -1457,8 +1852,9 @@ rde_get_mp_nexthop(u_char *data, u_int16 return (-1); bzero(&nexthop, sizeof(nexthop)); @@ -1110,7 +1307,7 @@ diff -u -p -r1.1.1.8 rde.c /* * RFC2545 describes that there may be a link-local * address carried in nexthop. Yikes! -@@ -1471,72 +1729,143 @@ rde_get_mp_nexthop(u_char *data, u_int16 +@@ -1471,72 +1867,143 @@ rde_get_mp_nexthop(u_char *data, u_int16 log_warnx("bad multiprotocol nexthop, bad size"); return (-1); } @@ -1137,7 +1334,7 @@ diff -u -p -r1.1.1.8 rde.c - * cause a use after free error. + * Neither RFC4364 nor RFC3107 specify the format of the + * nexthop in an explicit way. The quality of RFC went down -+ * the toilet the larger the the number got. ++ * the toilet the larger the number got. + * RFC4364 is very confusing about VPN-IPv4 address and the + * VPN-IPv4 prefix that carries also a MPLS label. + * So the nexthop is a 12-byte address with a 64bit RD and @@ -1293,7 +1490,7 @@ diff -u -p -r1.1.1.8 rde.c if (len < 1) return (-1); -@@ -1546,25 +1875,50 @@ rde_update_get_prefix6(u_char *p, u_int1 +@@ -1546,25 +2013,50 @@ rde_update_get_prefix6(u_char *p, u_int1 plen = 1; bzero(prefix, sizeof(struct bgpd_addr)); @@ -1355,7 +1552,7 @@ diff -u -p -r1.1.1.8 rde.c if ((wbuf = imsg_create(ibuf_se, IMSG_UPDATE_ERR, peer->conf.id, 0, size + sizeof(error) + sizeof(suberr))) == NULL) -@@ -1616,16 +1970,30 @@ rde_as4byte_fixup(struct rde_peer *peer, +@@ -1616,16 +2108,30 @@ rde_as4byte_fixup(struct rde_peer *peer, struct attr *nasp, *naggr, *oaggr; u_int32_t as; @@ -1388,7 +1585,7 @@ diff -u -p -r1.1.1.8 rde.c return; } /* OLD session using 2-byte ASNs */ -@@ -1669,6 +2037,10 @@ rde_reflector(struct rde_peer *peer, str +@@ -1669,6 +2175,10 @@ rde_reflector(struct rde_peer *peer, str u_int16_t len; u_int32_t id; @@ -1399,7 +1596,21 @@ diff -u -p -r1.1.1.8 rde.c /* check for originator id if eq router_id drop */ if ((a = attr_optget(asp, ATTR_ORIGINATOR_ID)) != NULL) { if (memcmp(&conf->bgpid, a->data, sizeof(conf->bgpid)) == 0) { -@@ -1724,7 +2096,7 @@ void +@@ -1677,10 +2187,10 @@ rde_reflector(struct rde_peer *peer, str + return; + } + } else if (conf->flags & BGPD_FLAG_REFLECTOR) { +- if (peer->conf.ebgp == 0) +- id = htonl(peer->remote_bgpid); +- else ++ if (peer->conf.ebgp) + id = conf->bgpid; ++ else ++ id = htonl(peer->remote_bgpid); + if (attr_optadd(asp, ATTR_OPTIONAL, ATTR_ORIGINATOR_ID, + &id, sizeof(u_int32_t)) == -1) + fatalx("attr_optadd failed but impossible"); +@@ -1724,17 +2234,17 @@ void rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags) { struct ctl_show_rib rib; @@ -1407,8 +1618,20 @@ diff -u -p -r1.1.1.8 rde.c + struct ibuf *wbuf; struct attr *a; void *bp; ++ time_t staletime; u_int8_t l; -@@ -1748,23 +2120,23 @@ rde_dump_rib_as(struct prefix *p, struct + + bzero(&rib, sizeof(rib)); + rib.lastchange = p->lastchange; + rib.local_pref = asp->lpref; + rib.med = asp->med; +- rib.prefix_cnt = asp->prefix_cnt; +- rib.active_cnt = asp->active_cnt; ++ rib.weight = asp->weight; + strlcpy(rib.descr, asp->peer->conf.descr, sizeof(rib.descr)); + memcpy(&rib.remote_addr, &asp->peer->remote_addr, + sizeof(rib.remote_addr)); +@@ -1748,23 +2258,26 @@ rde_dump_rib_as(struct prefix *p, struct /* announced network may have a NULL nexthop */ bzero(&rib.true_nexthop, sizeof(rib.true_nexthop)); bzero(&rib.exit_nexthop, sizeof(rib.exit_nexthop)); @@ -1423,9 +1646,10 @@ diff -u -p -r1.1.1.8 rde.c rib.flags = 0; if (p->rib->active == p) - rib.flags |= F_RIB_ACTIVE; -+ rib.flags |= F_PREF_ACTIVE; - if (asp->peer->conf.ebgp == 0) +- if (asp->peer->conf.ebgp == 0) - rib.flags |= F_RIB_INTERNAL; ++ rib.flags |= F_PREF_ACTIVE; ++ if (!asp->peer->conf.ebgp) + rib.flags |= F_PREF_INTERNAL; if (asp->flags & F_PREFIX_ANNOUNCED) - rib.flags |= F_RIB_ANNOUNCE; @@ -1436,10 +1660,13 @@ diff -u -p -r1.1.1.8 rde.c if (asp->flags & F_ATTR_LOOP) - rib.flags &= ~F_RIB_ELIGIBLE; + rib.flags &= ~F_PREF_ELIGIBLE; ++ staletime = asp->peer->staletime[p->prefix->aid]; ++ if (staletime && p->lastchange <= staletime) ++ rib.flags |= F_PREF_STALE; rib.aspath_len = aspath_length(asp->aspath); if ((wbuf = imsg_create(ibuf_se_ctl, IMSG_CTL_SHOW_RIB, 0, pid, -@@ -1784,13 +2156,13 @@ rde_dump_rib_as(struct prefix *p, struct +@@ -1784,13 +2297,13 @@ rde_dump_rib_as(struct prefix *p, struct IMSG_CTL_SHOW_RIB_ATTR, 0, pid, attr_optlen(a))) == NULL) return; @@ -1456,7 +1683,7 @@ diff -u -p -r1.1.1.8 rde.c return; } imsg_close(ibuf_se_ctl, wbuf); -@@ -1828,15 +2200,15 @@ rde_dump_filter(struct prefix *p, struct +@@ -1828,17 +2341,20 @@ rde_dump_filter(struct prefix *p, struct { struct rde_peer *peer; @@ -1466,16 +1693,22 @@ diff -u -p -r1.1.1.8 rde.c if (req->peerid && req->peerid != p->aspath->peer->conf.id) return; - if (req->type == IMSG_CTL_SHOW_RIB_AS && +- !aspath_match(p->aspath->aspath, req->as.type, req->as.as)) + if (req->type == IMSG_CTL_SHOW_RIB_AS && - !aspath_match(p->aspath->aspath, req->as.type, req->as.as)) ++ !aspath_match(p->aspath->aspath->data, ++ p->aspath->aspath->len, req->as.type, req->as.as)) return; if (req->type == IMSG_CTL_SHOW_RIB_COMMUNITY && - !rde_filter_community(p->aspath, req->community.as, + !community_match(p->aspath, req->community.as, req->community.type)) return; ++ if ((req->flags & F_CTL_ACTIVE) && p->rib->active != p) ++ return; rde_dump_rib_as(p, p->aspath, req->pid, req->flags); -@@ -1872,7 +2244,7 @@ rde_dump_prefix_upcall(struct rib_entry + } else if (req->flags & F_CTL_ADJ_OUT) { + if (p->rib->active != p) +@@ -1872,7 +2388,7 @@ rde_dump_prefix_upcall(struct rib_entry pt = re->prefix; pt_getaddr(pt, &addr); @@ -1484,7 +1717,7 @@ diff -u -p -r1.1.1.8 rde.c return; if (ctx->req.prefixlen > pt->prefixlen) return; -@@ -1889,6 +2261,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req +@@ -1889,6 +2405,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req struct rib_entry *re; u_int error; u_int16_t id; @@ -1492,7 +1725,7 @@ diff -u -p -r1.1.1.8 rde.c if ((ctx = calloc(1, sizeof(*ctx))) == NULL) { log_warn("rde_dump_ctx_new"); -@@ -1902,6 +2275,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req +@@ -1902,6 +2419,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req error = CTL_RES_NOSUCHPEER; imsg_compose(ibuf_se_ctl, IMSG_CTL_RESULT, 0, pid, -1, &error, sizeof(error)); @@ -1500,7 +1733,7 @@ diff -u -p -r1.1.1.8 rde.c return; } -@@ -1924,7 +2298,18 @@ rde_dump_ctx_new(struct ctl_show_rib_req +@@ -1924,7 +2442,18 @@ rde_dump_ctx_new(struct ctl_show_rib_req ctx->ribctx.ctx_upcall = rde_dump_prefix_upcall; break; } @@ -1520,7 +1753,7 @@ diff -u -p -r1.1.1.8 rde.c re = rib_lookup(&ribs[id], &req->prefix); else re = rib_get(&ribs[id], &req->prefix, req->prefixlen); -@@ -1937,7 +2322,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req +@@ -1937,7 +2466,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req } ctx->ribctx.ctx_done = rde_dump_done; ctx->ribctx.ctx_arg = ctx; @@ -1529,7 +1762,14 @@ diff -u -p -r1.1.1.8 rde.c rib_dump_r(&ctx->ribctx); } -@@ -1974,10 +2359,10 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t +@@ -1971,13 +2500,17 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t + free(ctx); + return; + } ++ ++ if (ctx->mrt.type == MRT_TABLE_DUMP_V2) ++ mrt_dump_v2_hdr(&ctx->mrt, conf, &peerlist); ++ ctx->ribctx.ctx_count = RDE_RUNNER_ROUNDS; ctx->ribctx.ctx_rib = &ribs[id]; ctx->ribctx.ctx_upcall = mrt_dump_upcall; @@ -1543,7 +1783,7 @@ diff -u -p -r1.1.1.8 rde.c rde_mrt_cnt++; rib_dump_r(&ctx->ribctx); } -@@ -1985,13 +2370,25 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t +@@ -1985,13 +2518,25 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t /* * kroute specific functions */ @@ -1572,7 +1812,7 @@ diff -u -p -r1.1.1.8 rde.c enum imsg_type type; /* -@@ -2011,43 +2408,45 @@ rde_send_kroute(struct prefix *new, stru +@@ -2011,43 +2556,43 @@ rde_send_kroute(struct prefix *new, stru } pt_getaddr(p->prefix, &addr); @@ -1613,8 +1853,6 @@ diff -u -p -r1.1.1.8 rde.c + break; + + SIMPLEQ_FOREACH(rd, rdomains_l, entry) { -+ if (addr.vpn4.rd != rd->rd) -+ continue; + if (!rde_rdomain_import(p->aspath, rd)) + continue; + /* must send exit_nexthop so that correct MPLS tunnel @@ -1654,7 +1892,7 @@ diff -u -p -r1.1.1.8 rde.c fatal("imsg_compose error"); break; } -@@ -2098,7 +2497,6 @@ rde_send_pftable_commit(void) +@@ -2098,7 +2643,6 @@ rde_send_pftable_commit(void) void rde_send_nexthop(struct bgpd_addr *next, int valid) { @@ -1662,7 +1900,7 @@ diff -u -p -r1.1.1.8 rde.c int type; if (valid) -@@ -2106,8 +2504,6 @@ rde_send_nexthop(struct bgpd_addr *next, +@@ -2106,8 +2650,6 @@ rde_send_nexthop(struct bgpd_addr *next, else type = IMSG_NEXTHOP_REMOVE; @@ -1671,7 +1909,7 @@ diff -u -p -r1.1.1.8 rde.c if (imsg_compose(ibuf_main, type, 0, 0, -1, next, sizeof(struct bgpd_addr)) == -1) fatal("imsg_compose error"); -@@ -2201,6 +2597,10 @@ rde_softreconfig_in(struct rib_entry *re +@@ -2201,6 +2743,10 @@ rde_softreconfig_in(struct rib_entry *re continue; for (i = 1; i < rib_size; i++) { @@ -1682,7 +1920,7 @@ diff -u -p -r1.1.1.8 rde.c /* check if prefix changed */ oa = rde_filter(i, &oasp, rules_l, peer, asp, &addr, pt->prefixlen, peer, DIR_IN); -@@ -2228,7 +2628,7 @@ rde_softreconfig_in(struct rib_entry *re +@@ -2228,7 +2774,7 @@ rde_softreconfig_in(struct rib_entry *re if (path_compare(nasp, oasp) == 0) goto done; /* send update */ @@ -1691,7 +1929,7 @@ diff -u -p -r1.1.1.8 rde.c pt->prefixlen); } -@@ -2241,6 +2641,104 @@ done: +@@ -2241,6 +2787,104 @@ done: } } @@ -1796,7 +2034,7 @@ diff -u -p -r1.1.1.8 rde.c /* * update specific functions */ -@@ -2252,7 +2750,7 @@ rde_up_dump_upcall(struct rib_entry *re, +@@ -2252,7 +2896,7 @@ rde_up_dump_upcall(struct rib_entry *re, struct rde_peer *peer = ptr; if (re->ribid != peer->ribid) @@ -1805,7 +2043,7 @@ diff -u -p -r1.1.1.8 rde.c if (re->active == NULL) return; up_generate_updates(rules_l, peer, re->active, NULL); -@@ -2265,7 +2763,7 @@ rde_generate_updates(u_int16_t ribid, st +@@ -2265,7 +2909,7 @@ rde_generate_updates(u_int16_t ribid, st /* * If old is != NULL we know it was active and should be removed. @@ -1814,7 +2052,7 @@ diff -u -p -r1.1.1.8 rde.c * generate an update. */ if (old == NULL && new == NULL) -@@ -2286,7 +2784,7 @@ void +@@ -2286,7 +2930,7 @@ void rde_update_queue_runner(void) { struct rde_peer *peer; @@ -1823,7 +2061,7 @@ diff -u -p -r1.1.1.8 rde.c u_int16_t len, wd_len, wpos; len = sizeof(queue_buf) - MSGSIZE_HEADER; -@@ -2300,7 +2798,7 @@ rde_update_queue_runner(void) +@@ -2300,7 +2944,7 @@ rde_update_queue_runner(void) /* first withdraws */ wpos = 2; /* reserve space for the length field */ r = up_dump_prefix(queue_buf + wpos, len - wpos - 2, @@ -1832,7 +2070,7 @@ diff -u -p -r1.1.1.8 rde.c wd_len = r; /* write withdraws length filed */ wd_len = htons(wd_len); -@@ -2310,31 +2808,49 @@ rde_update_queue_runner(void) +@@ -2310,31 +2954,49 @@ rde_update_queue_runner(void) /* now bgp path attributes */ r = up_dump_attrnlri(queue_buf + wpos, len - wpos, peer); @@ -1892,7 +2130,7 @@ diff -u -p -r1.1.1.8 rde.c u_int16_t len; /* first withdraws ... */ -@@ -2346,7 +2862,7 @@ rde_update6_queue_runner(void) +@@ -2346,7 +3008,7 @@ rde_update6_queue_runner(void) if (peer->state != PEER_UP) continue; len = sizeof(queue_buf) - MSGSIZE_HEADER; @@ -1901,7 +2139,7 @@ diff -u -p -r1.1.1.8 rde.c if (b == NULL) continue; -@@ -2369,10 +2885,18 @@ rde_update6_queue_runner(void) +@@ -2369,10 +3031,18 @@ rde_update6_queue_runner(void) if (peer->state != PEER_UP) continue; len = sizeof(queue_buf) - MSGSIZE_HEADER; @@ -1911,10 +2149,10 @@ diff -u -p -r1.1.1.8 rde.c + r = up_dump_mp_reach(queue_buf, &len, peer, aid); + switch (r) { + case -2: -+ continue; + continue; + case -1: + peer_send_eor(peer, aid); - continue; ++ continue; + default: + b = queue_buf + r; + break; @@ -1923,7 +2161,7 @@ diff -u -p -r1.1.1.8 rde.c /* finally send message to SE */ if (imsg_compose(ibuf_se, IMSG_UPDATE, peer->conf.id, 0, -1, b, len) == -1) -@@ -2411,7 +2935,7 @@ rde_decisionflags(void) +@@ -2411,7 +3081,7 @@ rde_decisionflags(void) int rde_as4byte(struct rde_peer *peer) { @@ -1932,7 +2170,7 @@ diff -u -p -r1.1.1.8 rde.c } /* -@@ -2429,7 +2953,6 @@ void +@@ -2429,7 +3099,6 @@ void peer_init(u_int32_t hashsize) { struct peer_config pc; @@ -1940,7 +2178,7 @@ diff -u -p -r1.1.1.8 rde.c u_int32_t hs, i; for (hs = 1; hs < hashsize; hs <<= 1) -@@ -2445,17 +2968,13 @@ peer_init(u_int32_t hashsize) +@@ -2445,17 +3114,13 @@ peer_init(u_int32_t hashsize) peertable.peer_hashmask = hs - 1; bzero(&pc, sizeof(pc)); @@ -1959,7 +2197,7 @@ diff -u -p -r1.1.1.8 rde.c } void -@@ -2534,14 +3053,10 @@ peer_localaddrs(struct rde_peer *peer, s +@@ -2534,14 +3199,10 @@ peer_localaddrs(struct rde_peer *peer, s if (ifa->ifa_addr->sa_family == match->ifa_addr->sa_family) ifa = match; @@ -1975,7 +2213,7 @@ diff -u -p -r1.1.1.8 rde.c for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family == AF_INET6 && strcmp(ifa->ifa_name, match->ifa_name) == 0) { -@@ -2559,13 +3074,7 @@ peer_localaddrs(struct rde_peer *peer, s +@@ -2559,13 +3220,7 @@ peer_localaddrs(struct rde_peer *peer, s &((struct sockaddr_in6 *)ifa-> ifa_addr)->sin6_addr)) continue; @@ -1990,7 +2228,7 @@ diff -u -p -r1.1.1.8 rde.c break; } } -@@ -2577,6 +3086,7 @@ void +@@ -2577,23 +3232,22 @@ void peer_up(u_int32_t id, struct session_up *sup) { struct rde_peer *peer; @@ -1998,7 +2236,16 @@ diff -u -p -r1.1.1.8 rde.c peer = peer_get(id); if (peer == NULL) { -@@ -2590,10 +3100,7 @@ peer_up(u_int32_t id, struct session_up +- log_warnx("peer_up: peer id %d already exists", id); ++ log_warnx("peer_up: unknown peer id %d", id); + return; + } + +- if (peer->state != PEER_DOWN && peer->state != PEER_NONE) ++ if (peer->state != PEER_DOWN && peer->state != PEER_NONE && ++ peer->state != PEER_UP) + fatalx("peer_up: bad state"); + peer->remote_bgpid = ntohl(sup->remote_bgpid); peer->short_as = sup->short_as; memcpy(&peer->remote_addr, &sup->remote_addr, sizeof(peer->remote_addr)); @@ -2010,7 +2257,7 @@ diff -u -p -r1.1.1.8 rde.c peer_localaddrs(peer, &sup->local_addr); -@@ -2607,7 +3114,10 @@ peer_up(u_int32_t id, struct session_up +@@ -2607,7 +3261,10 @@ peer_up(u_int32_t id, struct session_up */ return; @@ -2022,19 +2269,43 @@ diff -u -p -r1.1.1.8 rde.c } void -@@ -2642,42 +3152,32 @@ peer_down(u_int32_t id) +@@ -2641,43 +3298,90 @@ peer_down(u_int32_t id) + free(peer); } ++/* ++ * Flush all routes older then staletime. If staletime is 0 all routes will ++ * be flushed. ++ */ ++void ++peer_flush(struct rde_peer *peer, u_int8_t aid) ++{ ++ struct rde_aspath *asp, *nasp; ++ ++ /* walk through per peer RIB list and remove all stale prefixes. */ ++ for (asp = LIST_FIRST(&peer->path_h); asp != NULL; asp = nasp) { ++ nasp = LIST_NEXT(asp, peer_l); ++ path_remove_stale(asp, aid); ++ } ++ ++ /* Deletions are performed in path_remove() */ ++ rde_send_pftable_commit(); ++ ++ /* flushed no need to keep staletime */ ++ peer->staletime[aid] = 0; ++} ++ void -peer_dump(u_int32_t id, u_int16_t afi, u_int8_t safi) -+peer_dump(u_int32_t id, u_int8_t aid) ++peer_stale(u_int32_t id, u_int8_t aid) { struct rde_peer *peer; ++ time_t now; peer = peer_get(id); if (peer == NULL) { - log_warnx("peer_down: unknown peer id %d", id); -+ log_warnx("peer_dump: unknown peer id %d", id); ++ log_warnx("peer_stale: unknown peer id %d", id); return; } @@ -2054,32 +2325,65 @@ diff -u -p -r1.1.1.8 rde.c - rib_dump(&ribs[peer->ribid], rde_up_dump_upcall, - peer, AF_INET6); - } -- ++ if (peer->staletime[aid]) ++ peer_flush(peer, aid); ++ peer->staletime[aid] = now = time(NULL); + - if (peer->capa_received.restart && peer->capa_announced.restart) - peer_send_eor(peer, afi, safi); -+ if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE) -+ up_generate_default(rules_l, peer, aid); -+ else -+ rib_dump(&ribs[peer->ribid], rde_up_dump_upcall, peer, aid); -+ if (peer->capa.restart) -+ up_generate_marker(peer, aid); ++ /* make sure new prefixes start on a higher timestamp */ ++ do { ++ sleep(1); ++ } while (now >= time(NULL)); } -/* End-of-RIB marker, draft-ietf-idr-restart-13.txt */ -+/* End-of-RIB marker, RFC 4724 */ void -peer_send_eor(struct rde_peer *peer, u_int16_t afi, u_int16_t safi) -+peer_send_eor(struct rde_peer *peer, u_int8_t aid) ++peer_dump(u_int32_t id, u_int8_t aid) { - if (afi == AFI_IPv4 && safi == SAFI_UNICAST) { ++ struct rde_peer *peer; ++ ++ peer = peer_get(id); ++ if (peer == NULL) { ++ log_warnx("peer_dump: unknown peer id %d", id); ++ return; ++ } ++ ++ if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE) ++ up_generate_default(rules_l, peer, aid); ++ else ++ rib_dump(&ribs[peer->ribid], rde_up_dump_upcall, peer, aid); ++ if (peer->capa.grestart.restart) ++ up_generate_marker(peer, aid); ++} ++ ++/* End-of-RIB marker, RFC 4724 */ ++void ++peer_recv_eor(struct rde_peer *peer, u_int8_t aid) ++{ ++ peer->prefix_rcvd_eor++; ++ ++ /* First notify SE to remove possible race with the timeout. */ ++ if (imsg_compose(ibuf_se, IMSG_SESSION_RESTARTED, peer->conf.id, ++ 0, -1, &aid, sizeof(aid)) == -1) ++ fatal("imsg_compose error"); ++} ++ ++void ++peer_send_eor(struct rde_peer *peer, u_int8_t aid) ++{ + u_int16_t afi; + u_int8_t safi; + ++ peer->prefix_sent_eor++; ++ + if (aid == AID_INET) { u_char null[4]; bzero(&null, 4); -@@ -2688,6 +3188,9 @@ peer_send_eor(struct rde_peer *peer, u_i +@@ -2688,6 +3392,9 @@ peer_send_eor(struct rde_peer *peer, u_i u_int16_t i; u_char buf[10]; @@ -2089,7 +2393,7 @@ diff -u -p -r1.1.1.8 rde.c i = 0; /* v4 withdrawn len */ bcopy(&i, &buf[0], sizeof(i)); i = htons(6); /* path attr len */ -@@ -2709,25 +3212,43 @@ peer_send_eor(struct rde_peer *peer, u_i +@@ -2709,39 +3416,61 @@ peer_send_eor(struct rde_peer *peer, u_i * network announcement stuff */ void @@ -2115,6 +2419,12 @@ diff -u -p -r1.1.1.8 rde.c + in_addr_t prefix4; u_int16_t i; +- asp = path_get(); +- asp->aspath = aspath_get(NULL, 0); +- asp->origin = ORIGIN_IGP; +- asp->flags = F_ATTR_ORIGIN | F_ATTR_ASPATH | +- F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED; +- /* the nexthop is unset unless a default set overrides it */ + if (nc->rtableid) { + SIMPLEQ_FOREACH(rd, rdomains_l, entry) { + if (rd->rtableid != nc->rtableid) @@ -2144,13 +2454,19 @@ diff -u -p -r1.1.1.8 rde.c + } + } + - asp = path_get(); - asp->aspath = aspath_get(NULL, 0); - asp->origin = ORIGIN_IGP; -@@ -2737,7 +3258,9 @@ network_add(struct network_config *nc, i ++ if (nc->type == NETWORK_MRTCLONE) { ++ asp = nc->asp; ++ } else { ++ asp = path_get(); ++ asp->aspath = aspath_get(NULL, 0); ++ asp->origin = ORIGIN_IGP; ++ asp->flags = F_ATTR_ORIGIN | F_ATTR_ASPATH | ++ F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED; ++ /* the nexthop is unset unless a default set overrides it */ ++ } if (!flagstatic) asp->flags |= F_ANN_DYNAMIC; - +- - rde_apply_set(asp, &nc->attrset, nc->prefix.af, peerself, peerself); + rde_apply_set(asp, &nc->attrset, nc->prefix.aid, peerself, peerself); + if (vpnset) @@ -2158,7 +2474,11 @@ diff -u -p -r1.1.1.8 rde.c for (i = 1; i < rib_size; i++) path_update(&ribs[i], peerself, asp, &nc->prefix, nc->prefixlen); -@@ -2749,12 +3272,41 @@ network_add(struct network_config *nc, i +- + path_put(asp); + filterset_free(&nc->attrset); + } +@@ -2749,12 +3478,41 @@ network_add(struct network_config *nc, i void network_delete(struct network_config *nc, int flagstatic) { @@ -2202,7 +2522,7 @@ diff -u -p -r1.1.1.8 rde.c for (i = rib_size - 1; i > 0; i--) prefix_remove(&ribs[i], peerself, &nc->prefix, nc->prefixlen, flags); -@@ -2764,38 +3316,31 @@ void +@@ -2764,38 +3522,31 @@ void network_dump_upcall(struct rib_entry *re, void *ptr) { struct prefix *p; @@ -2260,7 +2580,7 @@ diff -u -p -r1.1.1.8 rde.c } } -@@ -2841,10 +3386,10 @@ sa_cmp(struct bgpd_addr *a, struct socka +@@ -2841,10 +3592,10 @@ sa_cmp(struct bgpd_addr *a, struct socka struct sockaddr_in *in_b; struct sockaddr_in6 *in6_b; diff --git a/net/openbgpd/files/patch-bgpd_rde.h b/net/openbgpd/files/patch-bgpd_rde.h index 22b372178ee9..717422949486 100644 --- a/net/openbgpd/files/patch-bgpd_rde.h +++ b/net/openbgpd/files/patch-bgpd_rde.h @@ -2,17 +2,17 @@ Index: bgpd/rde.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde.h,v retrieving revision 1.1.1.8 -retrieving revision 1.1.1.11 -diff -u -p -r1.1.1.8 -r1.1.1.11 +retrieving revision 1.1.1.12 +diff -u -p -r1.1.1.8 -r1.1.1.12 --- bgpd/rde.h 14 Feb 2010 20:19:57 -0000 1.1.1.8 -+++ bgpd/rde.h 12 Jun 2011 10:44:25 -0000 1.1.1.11 ++++ bgpd/rde.h 13 Oct 2012 18:22:46 -0000 1.1.1.12 @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.120 2009/06/06 01:10:29 claudio Exp $ */ -+/* $OpenBSD: rde.h,v 1.138 2010/11/18 12:18:31 claudio Exp $ */ ++/* $OpenBSD: rde.h,v 1.143 2012/08/12 14:24:56 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and -@@ -56,12 +56,9 @@ struct rde_peer { +@@ -56,16 +56,16 @@ struct rde_peer { struct bgpd_addr local_v6_addr; struct uptree_prefix up_prefix; struct uptree_attr up_attrs; @@ -25,11 +25,21 @@ diff -u -p -r1.1.1.8 -r1.1.1.11 + struct uplist_attr updates[AID_MAX]; + struct uplist_prefix withdraws[AID_MAX]; + struct capabilities capa; ++ time_t staletime[AID_MAX]; u_int64_t prefix_rcvd_update; u_int64_t prefix_rcvd_withdraw; ++ u_int64_t prefix_rcvd_eor; u_int64_t prefix_sent_update; -@@ -77,10 +74,13 @@ struct rde_peer { + u_int64_t prefix_sent_withdraw; ++ u_int64_t prefix_sent_eor; + u_int32_t prefix_cnt; /* # of prefixes */ + u_int32_t remote_bgpid; /* host byte order! */ + u_int32_t up_pcnt; +@@ -75,12 +75,16 @@ struct rde_peer { + enum peer_state state; + u_int16_t ribid; u_int16_t short_as; ++ u_int16_t mrt_idx; u_int8_t reconf_in; /* in filter changed */ u_int8_t reconf_out; /* out filter changed */ + u_int8_t reconf_rib; /* rib changed */ @@ -42,15 +52,26 @@ diff -u -p -r1.1.1.8 -r1.1.1.11 #define ASPATH_HEADER_SIZE (sizeof(struct aspath) - sizeof(u_char)) LIST_HEAD(aspath_list, aspath); -@@ -163,6 +163,7 @@ LIST_HEAD(prefix_head, prefix); +@@ -117,6 +121,9 @@ enum attrtypes { + #define ATTR_PARTIAL 0x20 + #define ATTR_TRANSITIVE 0x40 + #define ATTR_OPTIONAL 0x80 ++#define ATTR_RESERVED 0x0f ++/* by default mask the reserved bits and the ext len bit */ ++#define ATTR_DEFMASK (ATTR_RESERVED | ATTR_EXTLEN) + + /* default attribute flags for well known attributes */ + #define ATTR_WELL_KNOWN ATTR_TRANSITIVE +@@ -163,6 +170,8 @@ LIST_HEAD(prefix_head, prefix); #define F_NEXTHOP_REJECT 0x02000 #define F_NEXTHOP_BLACKHOLE 0x04000 #define F_NEXTHOP_NOMODIFY 0x08000 ++#define F_NEXTHOP_MASK 0x0f000 +#define F_ATTR_PARSE_ERR 0x10000 #define F_ATTR_LINKED 0x20000 -@@ -220,14 +221,14 @@ struct nexthop { +@@ -220,14 +229,14 @@ struct nexthop { /* generic entry without address specific part */ struct pt_entry { RB_ENTRY(pt_entry) pt_e; @@ -67,7 +88,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.11 u_int8_t prefixlen; u_int16_t refcnt; struct in_addr prefix4; -@@ -235,12 +236,25 @@ struct pt_entry4 { +@@ -235,12 +244,25 @@ struct pt_entry4 { struct pt_entry6 { RB_ENTRY(pt_entry) pt_e; @@ -94,7 +115,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.11 struct rib_context { LIST_ENTRY(rib_context) entry; struct rib_entry *ctx_re; -@@ -250,7 +264,7 @@ struct rib_context { +@@ -250,7 +272,7 @@ struct rib_context { void (*ctx_wait)(void *); void *ctx_arg; unsigned int ctx_count; @@ -103,7 +124,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.11 }; struct rib_entry { -@@ -262,23 +276,15 @@ struct rib_entry { +@@ -262,23 +284,15 @@ struct rib_entry { u_int16_t flags; }; @@ -129,16 +150,23 @@ diff -u -p -r1.1.1.8 -r1.1.1.11 #define RIB_FAILED 0xffff struct prefix { -@@ -293,7 +299,7 @@ extern struct rde_memstats rdemem; +@@ -292,8 +306,14 @@ struct prefix { + extern struct rde_memstats rdemem; /* prototypes */ ++/* mrt.c */ ++int mrt_dump_v2_hdr(struct mrt *, struct bgpd_config *, ++ struct rde_peer_head *); ++void mrt_dump_upcall(struct rib_entry *, void *); ++void mrt_done(void *); ++ /* rde.c */ -void rde_send_kroute(struct prefix *, struct prefix *); +void rde_send_kroute(struct prefix *, struct prefix *, u_int16_t); void rde_send_nexthop(struct bgpd_addr *, int); void rde_send_pftable(u_int16_t, struct bgpd_addr *, u_int8_t, int); -@@ -309,7 +315,7 @@ int rde_as4byte(struct rde_peer *); +@@ -309,7 +329,7 @@ int rde_as4byte(struct rde_peer *); /* rde_attr.c */ int attr_write(void *, u_int16_t, u_int8_t, u_int8_t, void *, u_int16_t); @@ -147,7 +175,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.11 u_int16_t); void attr_init(u_int32_t); void attr_shutdown(void); -@@ -327,6 +333,7 @@ int aspath_verify(void *, u_int16_t, i +@@ -327,6 +347,7 @@ int aspath_verify(void *, u_int16_t, i #define AS_ERR_LEN -1 #define AS_ERR_TYPE -2 #define AS_ERR_BAD -3 @@ -155,10 +183,11 @@ diff -u -p -r1.1.1.8 -r1.1.1.11 void aspath_init(u_int32_t); void aspath_shutdown(void); struct aspath *aspath_get(void *, u_int16_t); -@@ -342,21 +349,30 @@ int aspath_loopfree(struct aspath *, u +@@ -341,22 +362,66 @@ u_int32_t aspath_neighbor(struct aspath + int aspath_loopfree(struct aspath *, u_int32_t); int aspath_compare(struct aspath *, struct aspath *); u_char *aspath_prepend(struct aspath *, u_int32_t, int, u_int16_t *); - int aspath_match(struct aspath *, enum as_spec, u_int32_t); +-int aspath_match(struct aspath *, enum as_spec, u_int32_t); -int community_match(void *, u_int16_t, int, int); +int aspath_lenmatch(struct aspath *, enum aslen_spec, u_int); +int community_match(struct rde_aspath *, int, int); @@ -172,6 +201,42 @@ diff -u -p -r1.1.1.8 -r1.1.1.11 + struct filter_extcommunity *, u_int16_t); +int community_ext_conv(struct filter_extcommunity *, u_int16_t, + u_int64_t *); ++ ++/* rde_decide.c */ ++void prefix_evaluate(struct prefix *, struct rib_entry *); ++ ++/* rde_filter.c */ ++enum filter_actions rde_filter(u_int16_t, struct rde_aspath **, ++ struct filter_head *, struct rde_peer *, ++ struct rde_aspath *, struct bgpd_addr *, u_int8_t, ++ struct rde_peer *, enum directions); ++void rde_apply_set(struct rde_aspath *, struct filter_set_head *, ++ u_int8_t, struct rde_peer *, struct rde_peer *); ++int rde_filter_equal(struct filter_head *, struct filter_head *, ++ struct rde_peer *, enum directions); ++ ++/* rde_prefix.c */ ++#define pt_empty(pt) ((pt)->refcnt == 0) ++#define pt_ref(pt) do { \ ++ ++(pt)->refcnt; \ ++ if ((pt)->refcnt == 0) \ ++ fatalx("pt_ref: overflow"); \ ++} while(0) ++#define pt_unref(pt) do { \ ++ if ((pt)->refcnt == 0) \ ++ fatalx("pt_unref: underflow"); \ ++ --(pt)->refcnt; \ ++} while(0) ++ ++void pt_init(void); ++void pt_shutdown(void); ++void pt_getaddr(struct pt_entry *, struct bgpd_addr *); ++struct pt_entry *pt_fill(struct bgpd_addr *, int); ++struct pt_entry *pt_get(struct bgpd_addr *, int); ++struct pt_entry *pt_add(struct bgpd_addr *, int); ++void pt_remove(struct pt_entry *); ++struct pt_entry *pt_lookup(struct bgpd_addr *); ++int pt_prefix_cmp(const struct pt_entry *, const struct pt_entry *); /* rde_rib.c */ extern u_int16_t rib_size; @@ -189,7 +254,32 @@ diff -u -p -r1.1.1.8 -r1.1.1.11 void rib_dump_r(struct rib_context *); void rib_dump_runner(void); int rib_dump_pending(void); -@@ -395,7 +411,7 @@ void prefix_network_clean(struct rde_p +@@ -368,6 +433,7 @@ int path_update(struct rib *, struct r + int path_compare(struct rde_aspath *, struct rde_aspath *); + struct rde_aspath *path_lookup(struct rde_aspath *, struct rde_peer *); + void path_remove(struct rde_aspath *); ++void path_remove_stale(struct rde_aspath *, u_int8_t); + void path_destroy(struct rde_aspath *); + int path_empty(struct rde_aspath *); + struct rde_aspath *path_copy(struct rde_aspath *); +@@ -375,8 +441,6 @@ struct rde_aspath *path_get(void); + void path_put(struct rde_aspath *); + + #define PREFIX_SIZE(x) (((x) + 7) / 8 + 1) +-int prefix_compare(const struct bgpd_addr *, +- const struct bgpd_addr *, int); + struct prefix *prefix_get(struct rib *, struct rde_peer *, + struct bgpd_addr *, int, u_int32_t); + int prefix_add(struct rib *, struct rde_aspath *, +@@ -385,6 +449,7 @@ void prefix_move(struct rde_aspath *, + int prefix_remove(struct rib *, struct rde_peer *, + struct bgpd_addr *, int, u_int32_t); + int prefix_write(u_char *, int, struct bgpd_addr *, u_int8_t); ++int prefix_writebuf(struct ibuf *, struct bgpd_addr *, u_int8_t); + struct prefix *prefix_bypeer(struct rib_entry *, struct rde_peer *, + u_int32_t); + void prefix_updateall(struct rde_aspath *, enum nexthop_state, +@@ -395,7 +460,7 @@ void prefix_network_clean(struct rde_p void nexthop_init(u_int32_t); void nexthop_shutdown(void); void nexthop_modify(struct rde_aspath *, struct bgpd_addr *, @@ -198,7 +288,17 @@ diff -u -p -r1.1.1.8 -r1.1.1.11 void nexthop_link(struct rde_aspath *); void nexthop_unlink(struct rde_aspath *); int nexthop_delete(struct nexthop *); -@@ -415,12 +431,15 @@ int up_generate(struct rde_peer *, str +@@ -403,9 +468,6 @@ void nexthop_update(struct kroute_next + struct nexthop *nexthop_get(struct bgpd_addr *); + int nexthop_compare(struct nexthop *, struct nexthop *); + +-/* rde_decide.c */ +-void prefix_evaluate(struct prefix *, struct rib_entry *); +- + /* rde_update.c */ + void up_init(struct rde_peer *); + void up_down(struct rde_peer *); +@@ -415,49 +477,14 @@ int up_generate(struct rde_peer *, str void up_generate_updates(struct filter_head *, struct rde_peer *, struct prefix *, struct prefix *); void up_generate_default(struct filter_head *, struct rde_peer *, @@ -210,20 +310,47 @@ diff -u -p -r1.1.1.8 -r1.1.1.11 int up_dump_attrnlri(u_char *, int, struct rde_peer *); -u_char *up_dump_mp_unreach(u_char *, u_int16_t *, struct rde_peer *); -u_char *up_dump_mp_reach(u_char *, u_int16_t *, struct rde_peer *); +- +-/* rde_prefix.c */ +-#define pt_empty(pt) ((pt)->refcnt == 0) +-#define pt_ref(pt) do { \ +- ++(pt)->refcnt; \ +- if ((pt)->refcnt == 0) \ +- fatalx("pt_ref: overflow"); \ +-} while(0) +-#define pt_unref(pt) do { \ +- if ((pt)->refcnt == 0) \ +- fatalx("pt_unref: underflow"); \ +- --(pt)->refcnt; \ +-} while(0) +- +-void pt_init(void); +-void pt_shutdown(void); +-void pt_getaddr(struct pt_entry *, struct bgpd_addr *); +-struct pt_entry *pt_fill(struct bgpd_addr *, int); +-struct pt_entry *pt_get(struct bgpd_addr *, int); +-struct pt_entry *pt_add(struct bgpd_addr *, int); +-void pt_remove(struct pt_entry *); +-struct pt_entry *pt_lookup(struct bgpd_addr *); +-int pt_prefix_cmp(const struct pt_entry *, const struct pt_entry *); +- +- +-/* rde_filter.c */ +-enum filter_actions rde_filter(u_int16_t, struct rde_aspath **, +- struct filter_head *, struct rde_peer *, +- struct rde_aspath *, struct bgpd_addr *, u_int8_t, +- struct rde_peer *, enum directions); +-void rde_apply_set(struct rde_aspath *, struct filter_set_head *, +- sa_family_t, struct rde_peer *, struct rde_peer *); +-int rde_filter_community(struct rde_aspath *, int, int); +-int rde_filter_equal(struct filter_head *, struct filter_head *, +- struct rde_peer *, enum directions); +- +-/* util.c */ +-u_int32_t aspath_extract(const void *, int); +u_char *up_dump_mp_unreach(u_char *, u_int16_t *, struct rde_peer *, + u_int8_t); +int up_dump_mp_reach(u_char *, u_int16_t *, struct rde_peer *, + u_int8_t); - /* rde_prefix.c */ - #define pt_empty(pt) ((pt)->refcnt == 0) -@@ -452,8 +471,7 @@ enum filter_actions rde_filter(u_int16_t - struct rde_aspath *, struct bgpd_addr *, u_int8_t, - struct rde_peer *, enum directions); - void rde_apply_set(struct rde_aspath *, struct filter_set_head *, -- sa_family_t, struct rde_peer *, struct rde_peer *); --int rde_filter_community(struct rde_aspath *, int, int); -+ u_int8_t, struct rde_peer *, struct rde_peer *); - int rde_filter_equal(struct filter_head *, struct filter_head *, - struct rde_peer *, enum directions); - + #endif /* __RDE_H__ */ diff --git a/net/openbgpd/files/patch-bgpd_rde_attr.c b/net/openbgpd/files/patch-bgpd_rde_attr.c index eccdc1e36c27..2c0192abe5da 100644 --- a/net/openbgpd/files/patch-bgpd_rde_attr.c +++ b/net/openbgpd/files/patch-bgpd_rde_attr.c @@ -2,13 +2,13 @@ Index: bgpd/rde_attr.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_attr.c,v retrieving revision 1.1.1.6 -retrieving revision 1.6 -diff -u -p -r1.1.1.6 -r1.6 +retrieving revision 1.7 +diff -u -p -r1.1.1.6 -r1.7 --- bgpd/rde_attr.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/rde_attr.c 2 Jul 2011 16:06:38 -0000 1.6 ++++ bgpd/rde_attr.c 13 Oct 2012 18:36:00 -0000 1.7 @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_attr.c,v 1.79 2009/03/19 06:52:59 claudio Exp $ */ -+/* $OpenBSD: rde_attr.c,v 1.83 2010/03/29 09:24:07 claudio Exp $ */ ++/* $OpenBSD: rde_attr.c,v 1.90 2012/04/12 17:27:20 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -35,7 +35,21 @@ diff -u -p -r1.1.1.6 -r1.6 #include "bgpd.h" #include "rde.h" -@@ -63,7 +71,7 @@ attr_write(void *p, u_int16_t p_len, u_i +@@ -36,12 +44,12 @@ attr_write(void *p, u_int16_t p_len, u_i + u_char *b = p; + u_int16_t tmp, tot_len = 2; /* attribute header (without len) */ + ++ flags &= ~ATTR_DEFMASK; + if (data_len > 255) { + tot_len += 2 + data_len; + flags |= ATTR_EXTLEN; + } else { + tot_len += 1 + data_len; +- flags &= ~ATTR_EXTLEN; + } + + if (tot_len > p_len) +@@ -63,26 +71,26 @@ attr_write(void *p, u_int16_t p_len, u_i } int @@ -44,7 +58,17 @@ diff -u -p -r1.1.1.6 -r1.6 u_int16_t data_len) { u_char hdr[4]; -@@ -80,9 +88,9 @@ attr_writebuf(struct buf *buf, u_int8_t + ++ flags &= ~ATTR_DEFMASK; + if (data_len > 255) { + flags |= ATTR_EXTLEN; + hdr[2] = (data_len >> 8) & 0xff; + hdr[3] = data_len & 0xff; + } else { +- flags &= ~ATTR_EXTLEN; + hdr[2] = data_len & 0xff; + } + hdr[0] = flags; hdr[1] = type; @@ -69,7 +93,23 @@ diff -u -p -r1.1.1.6 -r1.6 } /* add attribute to the table but first bump refcnt */ -@@ -405,6 +416,7 @@ aspath_verify(void *data, u_int16_t len, +@@ -318,6 +329,7 @@ attr_alloc(u_int8_t flags, u_int8_t type + fatal("attr_optadd"); + rdemem.attr_cnt++; + ++ flags &= ~ATTR_DEFMASK; /* normalize mask */ + a->flags = flags; + a->hash = hash32_buf(&flags, sizeof(flags), HASHINIT); + a->type = type; +@@ -347,6 +359,7 @@ attr_lookup(u_int8_t flags, u_int8_t typ + struct attr *a; + u_int32_t hash; + ++ flags &= ~ATTR_DEFMASK; /* normalize mask */ + hash = hash32_buf(&flags, sizeof(flags), HASHINIT); + hash = hash32_buf(&type, sizeof(type), hash); + hash = hash32_buf(&len, sizeof(len), hash); +@@ -405,6 +418,7 @@ aspath_verify(void *data, u_int16_t len, u_int8_t *seg = data; u_int16_t seg_size, as_size = 2; u_int8_t seg_len, seg_type; @@ -77,7 +117,7 @@ diff -u -p -r1.1.1.6 -r1.6 if (len & 1) /* odd length aspath are invalid */ -@@ -419,7 +431,15 @@ aspath_verify(void *data, u_int16_t len, +@@ -419,7 +433,15 @@ aspath_verify(void *data, u_int16_t len, seg_type = seg[0]; seg_len = seg[1]; @@ -94,7 +134,7 @@ diff -u -p -r1.1.1.6 -r1.6 return (AS_ERR_TYPE); seg_size = 2 + as_size * seg_len; -@@ -431,7 +451,7 @@ aspath_verify(void *data, u_int16_t len, +@@ -431,7 +453,7 @@ aspath_verify(void *data, u_int16_t len, /* empty aspath segments are not allowed */ return (AS_ERR_BAD); } @@ -103,38 +143,90 @@ diff -u -p -r1.1.1.6 -r1.6 } void -@@ -972,14 +992,62 @@ aspath_match(struct aspath *a, enum as_s +@@ -762,15 +784,9 @@ aspath_countcopy(struct aspath *aspath, + u_int32_t + aspath_neighbor(struct aspath *aspath) + { +- /* +- * Empty aspath is OK -- internal as route. +- * But what is the neighbor? For now let's return 0. +- * That should not break anything. +- */ +- ++ /* Empty aspath is OK -- internal AS route. */ + if (aspath->len == 0) +- return (0); +- ++ return (rde_local_as()); + return (aspath_extract(aspath->data, 0)); + } + +@@ -910,76 +926,63 @@ aspath_prepend(struct aspath *asp, u_int + return (p); } +-/* we need to be able to search more than one as */ int --community_match(void *data, u_int16_t len, int as, int type) +-aspath_match(struct aspath *a, enum as_spec type, u_int32_t as) +aspath_lenmatch(struct aspath *a, enum aslen_spec type, u_int aslen) { -- u_int8_t *p = data; -- u_int16_t eas, etype; -+ u_int8_t *seg; + u_int8_t *seg; +- int final; + u_int32_t as, lastas = 0; + u_int count = 0; -+ u_int16_t len, seg_size; -+ u_int8_t i, seg_type, seg_len; -+ + u_int16_t len, seg_size; + u_int8_t i, seg_type, seg_len; + +- if (type == AS_EMPTY) { +- if (a->len == 0) + if (type == ASLEN_MAX) { + if (aslen < aspath_count(a->data, a->len)) -+ return (1); -+ else -+ return (0); -+ } + return (1); + else + return (0); + } -- len >>= 2; /* divide by four */ +- final = 0; + /* type == ASLEN_SEQ */ -+ seg = a->data; -+ for (len = a->len; len > 0; len -= seg_size, seg += seg_size) { -+ seg_type = seg[0]; -+ seg_len = seg[1]; -+ seg_size = 2 + sizeof(u_int32_t) * seg_len; + seg = a->data; + for (len = a->len; len > 0; len -= seg_size, seg += seg_size) { + seg_type = seg[0]; + seg_len = seg[1]; + seg_size = 2 + sizeof(u_int32_t) * seg_len; -- for (; len > 0; len--) { -+ for (i = 0; i < seg_len; i++) { +- final = (len == seg_size); +- +- /* just check the first (leftmost) AS */ +- if (type == AS_PEER) { +- if (as == aspath_extract(seg, 0)) +- return (1); +- else +- return (0); +- } +- /* just check the final (rightmost) AS */ +- if (type == AS_SOURCE) { +- /* not yet in the final segment */ +- if (!final) +- continue; +- +- if (as == aspath_extract(seg, seg_len - 1)) +- return (1); +- else +- return (0); +- } +- +- /* AS_TRANSIT or AS_ALL */ + for (i = 0; i < seg_len; i++) { +- if (as == aspath_extract(seg, i)) { +- /* +- * the source (rightmost) AS is excluded from +- * AS_TRANSIT matches. +- */ +- if (final && i == seg_len - 1 && +- type == AS_TRANSIT) +- return (0); +- return (1); +- } + /* what should we do with AS_SET? */ + as = aspath_extract(seg, i); + if (as == lastas) { @@ -143,35 +235,40 @@ diff -u -p -r1.1.1.6 -r1.6 + } else + count = 1; + lastas = as; -+ } -+ } -+ return (0); -+} -+ + } + } + return (0); + } + +/* + * Functions handling communities and extended communities. + */ + +int community_ext_matchone(struct filter_extcommunity *, u_int16_t, u_int64_t); + -+int + int +-community_match(void *data, u_int16_t len, int as, int type) +community_match(struct rde_aspath *asp, int as, int type) -+{ + { +- u_int8_t *p = data; +- u_int16_t eas, etype; + struct attr *a; + u_int8_t *p; + u_int16_t eas, etype, len; -+ + +- len >>= 2; /* divide by four */ + a = attr_optget(asp, ATTR_COMMUNITIES); + if (a == NULL) + /* no communities, no match */ + return (0); -+ + +- for (; len > 0; len--) { + p = a->data; + for (len = a->len / 4; len > 0; len--) { eas = *p++; eas <<= 8; eas |= *p++; -@@ -1000,7 +1068,6 @@ community_set(struct rde_aspath *asp, in +@@ -1000,7 +1003,6 @@ community_set(struct rde_aspath *asp, in u_int8_t *p = NULL; unsigned int i, ncommunities = 0; u_int8_t f = ATTR_OPTIONAL|ATTR_TRANSITIVE; @@ -179,7 +276,7 @@ diff -u -p -r1.1.1.6 -r1.6 attr = attr_optget(asp, ATTR_COMMUNITIES); if (attr != NULL) { -@@ -1017,7 +1084,7 @@ community_set(struct rde_aspath *asp, in +@@ -1017,7 +1019,7 @@ community_set(struct rde_aspath *asp, in p += 4; } @@ -188,7 +285,7 @@ diff -u -p -r1.1.1.6 -r1.6 /* overflow */ return (0); -@@ -1032,11 +1099,10 @@ community_set(struct rde_aspath *asp, in +@@ -1032,11 +1034,10 @@ community_set(struct rde_aspath *asp, in if (attr != NULL) { memcpy(p + 4, attr->data, attr->len); f = attr->flags; @@ -201,7 +298,7 @@ diff -u -p -r1.1.1.6 -r1.6 free(p); return (1); -@@ -1049,7 +1115,7 @@ community_delete(struct rde_aspath *asp, +@@ -1049,7 +1050,7 @@ community_delete(struct rde_aspath *asp, u_int8_t *p, *n; u_int16_t l, len = 0; u_int16_t eas, etype; @@ -210,7 +307,7 @@ diff -u -p -r1.1.1.6 -r1.6 attr = attr_optget(asp, ATTR_COMMUNITIES); if (attr == NULL) -@@ -1100,10 +1166,250 @@ community_delete(struct rde_aspath *asp, +@@ -1100,10 +1101,250 @@ community_delete(struct rde_aspath *asp, } f = attr->flags; @@ -219,9 +316,9 @@ diff -u -p -r1.1.1.6 -r1.6 attr_free(asp, attr); - attr_optadd(asp, f, t, n, len); + attr_optadd(asp, f, ATTR_COMMUNITIES, n, len); -+ free(n); -+} -+ + free(n); + } + +int +community_ext_match(struct rde_aspath *asp, struct filter_extcommunity *c, + u_int16_t neighas) @@ -343,9 +440,9 @@ diff -u -p -r1.1.1.6 -r1.6 + + attr_free(asp, attr); + attr_optadd(asp, f, ATTR_EXT_COMMUNITIES, n, len); - free(n); - } - ++ free(n); ++} ++ +int +community_ext_conv(struct filter_extcommunity *c, u_int16_t neighas, + u_int64_t *community) diff --git a/net/openbgpd/files/patch-bgpd_rde_decide.c b/net/openbgpd/files/patch-bgpd_rde_decide.c index 3ed963b194dc..c9d27af5dbef 100644 --- a/net/openbgpd/files/patch-bgpd_rde_decide.c +++ b/net/openbgpd/files/patch-bgpd_rde_decide.c @@ -2,16 +2,27 @@ Index: bgpd/rde_decide.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_decide.c,v retrieving revision 1.1.1.6 -diff -u -p -r1.1.1.6 rde_decide.c +retrieving revision 1.4 +diff -u -p -r1.1.1.6 -r1.4 --- bgpd/rde_decide.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/rde_decide.c 3 Jul 2011 04:44:36 -0000 ++++ bgpd/rde_decide.c 13 Oct 2012 18:36:00 -0000 1.4 @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_decide.c,v 1.58 2009/06/29 14:10:13 claudio Exp $ */ -+/* $OpenBSD: rde_decide.c,v 1.59 2009/08/06 08:53:11 claudio Exp $ */ ++/* $OpenBSD: rde_decide.c,v 1.61 2012/04/12 17:31:05 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> -@@ -118,6 +118,12 @@ prefix_cmp(struct prefix *p1, struct pre +@@ -109,6 +109,9 @@ int + prefix_cmp(struct prefix *p1, struct prefix *p2) + { + struct rde_aspath *asp1, *asp2; ++ struct attr *a; ++ u_int32_t p1id, p2id; ++ int p1cnt, p2cnt; + + if (p1 == NULL) + return (-1); +@@ -118,6 +121,12 @@ prefix_cmp(struct prefix *p1, struct pre asp1 = p1->aspath; asp2 = p2->aspath; @@ -24,7 +35,76 @@ diff -u -p -r1.1.1.6 rde_decide.c /* only loop free pathes are eligible */ if (asp1->flags & F_ATTR_LOOP) return (-1); -@@ -204,7 +210,7 @@ prefix_cmp(struct prefix *p1, struct pre +@@ -130,7 +139,7 @@ prefix_cmp(struct prefix *p1, struct pre + if (asp1->nexthop != NULL && asp1->nexthop->state != NEXTHOP_REACH) + return (-1); + +- /* 2. preference of prefix, bigger is better */ ++ /* 2. local preference of prefix, bigger is better */ + if ((asp1->lpref - asp2->lpref) != 0) + return (asp1->lpref - asp2->lpref); + +@@ -154,10 +163,10 @@ prefix_cmp(struct prefix *p1, struct pre + * It is absolutely important that the ebgp value in peer_config.ebgp + * is bigger than all other ones (IBGP, confederations) + */ +- if ((asp1->peer->conf.ebgp - asp2->peer->conf.ebgp) != 0) { +- if (asp1->peer->conf.ebgp == 1) /* p1 is EBGP other is lower */ ++ if (asp1->peer->conf.ebgp != asp2->peer->conf.ebgp) { ++ if (asp1->peer->conf.ebgp) /* p1 is EBGP other is lower */ + return 1; +- else if (asp2->peer->conf.ebgp == 1) /* p2 is EBGP */ ++ else if (asp2->peer->conf.ebgp) /* p2 is EBGP */ + return -1; + } + +@@ -181,13 +190,30 @@ prefix_cmp(struct prefix *p1, struct pre + if ((p2->lastchange - p1->lastchange) != 0) + return (p2->lastchange - p1->lastchange); + +- /* 10. lowest BGP Id wins */ +- if ((p2->aspath->peer->remote_bgpid - +- p1->aspath->peer->remote_bgpid) != 0) +- return (p2->aspath->peer->remote_bgpid - +- p1->aspath->peer->remote_bgpid); ++ /* 10. lowest BGP Id wins, use ORIGINATOR_ID if present */ ++ if ((a = attr_optget(asp1, ATTR_ORIGINATOR_ID)) != NULL) { ++ memcpy(&p1id, a->data, sizeof(p1id)); ++ p1id = ntohl(p1id); ++ } else ++ p1id = asp1->peer->remote_bgpid; ++ if ((a = attr_optget(asp2, ATTR_ORIGINATOR_ID)) != NULL) { ++ memcpy(&p2id, a->data, sizeof(p2id)); ++ p2id = ntohl(p2id); ++ } else ++ p2id = asp2->peer->remote_bgpid; ++ if ((p2id - p1id) != 0) ++ return (p2id - p1id); ++ ++ /* 11. compare CLUSTER_LIST length, shorter is better */ ++ p1cnt = p2cnt = 0; ++ if ((a = attr_optget(asp1, ATTR_CLUSTER_LIST)) != NULL) ++ p1cnt = a->len / sizeof(u_int32_t); ++ if ((a = attr_optget(asp2, ATTR_CLUSTER_LIST)) != NULL) ++ p2cnt = a->len / sizeof(u_int32_t); ++ if ((p2cnt - p1cnt) != 0) ++ return (p2cnt - p1cnt); + +- /* 11. lowest peer address wins (IPv4 is better than IPv6) */ ++ /* 12. lowest peer address wins (IPv4 is better than IPv6) */ + if (memcmp(&p1->aspath->peer->remote_addr, + &p2->aspath->peer->remote_addr, + sizeof(p1->aspath->peer->remote_addr)) != 0) +@@ -195,7 +221,7 @@ prefix_cmp(struct prefix *p1, struct pre + &p2->aspath->peer->remote_addr, + sizeof(p1->aspath->peer->remote_addr))); + +- /* 12. for announced prefixes prefer dynamic routes */ ++ /* 13. for announced prefixes prefer dynamic routes */ + if ((asp1->flags & F_ANN_DYNAMIC) != (asp2->flags & F_ANN_DYNAMIC)) { + if (asp1->flags & F_ANN_DYNAMIC) + return (1); +@@ -204,7 +230,7 @@ prefix_cmp(struct prefix *p1, struct pre } fatalx("Uh, oh a politician in the decision process"); @@ -33,7 +113,7 @@ diff -u -p -r1.1.1.6 rde_decide.c } /* -@@ -245,7 +251,7 @@ prefix_evaluate(struct prefix *p, struct +@@ -245,7 +271,7 @@ prefix_evaluate(struct prefix *p, struct } xp = LIST_FIRST(&re->prefix_h); @@ -42,7 +122,7 @@ diff -u -p -r1.1.1.6 rde_decide.c (xp->aspath->nexthop != NULL && xp->aspath->nexthop->state != NEXTHOP_REACH)) /* xp is ineligible */ -@@ -263,7 +269,7 @@ prefix_evaluate(struct prefix *p, struct +@@ -263,7 +289,7 @@ prefix_evaluate(struct prefix *p, struct */ rde_generate_updates(re->ribid, xp, re->active); if ((re->flags & F_RIB_NOFIB) == 0) diff --git a/net/openbgpd/files/patch-bgpd_rde_filter.c b/net/openbgpd/files/patch-bgpd_rde_filter.c index b4fe8982b949..c08eff6a5a18 100644 --- a/net/openbgpd/files/patch-bgpd_rde_filter.c +++ b/net/openbgpd/files/patch-bgpd_rde_filter.c @@ -2,10 +2,10 @@ Index: bgpd/rde_filter.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_filter.c,v retrieving revision 1.1.1.7 -retrieving revision 1.7 -diff -u -p -r1.1.1.7 -r1.7 +retrieving revision 1.8 +diff -u -p -r1.1.1.7 -r1.8 --- bgpd/rde_filter.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/rde_filter.c 2 Jul 2011 16:06:38 -0000 1.7 ++++ bgpd/rde_filter.c 13 Oct 2012 18:36:00 -0000 1.8 @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_filter.c,v 1.56 2009/06/06 01:10:29 claudio Exp $ */ +/* $OpenBSD: rde_filter.c,v 1.62 2010/03/05 15:25:00 claudio Exp $ */ @@ -71,7 +71,7 @@ diff -u -p -r1.1.1.7 -r1.7 } } } -@@ -251,11 +269,21 @@ int +@@ -251,11 +269,22 @@ int rde_filter_match(struct filter_rule *f, struct rde_aspath *asp, struct bgpd_addr *prefix, u_int8_t plen, struct rde_peer *peer) { @@ -87,7 +87,8 @@ diff -u -p -r1.1.1.7 -r1.7 + pas = peer->conf.remote_as; + else + pas = f->match.as.as; -+ if (aspath_match(asp->aspath, f->match.as.type, pas) == 0) ++ if (aspath_match(asp->aspath->data, asp->aspath->len, ++ f->match.as.type, pas) == 0) + return (0); + } + @@ -97,7 +98,7 @@ diff -u -p -r1.1.1.7 -r1.7 return (0); if (asp != NULL && f->match.community.as != COMMUNITY_UNSET) { -@@ -263,10 +291,10 @@ rde_filter_match(struct filter_rule *f, +@@ -263,10 +292,10 @@ rde_filter_match(struct filter_rule *f, case COMMUNITY_ERROR: fatalx("rde_apply_set bad community string"); case COMMUNITY_NEIGHBOR_AS: @@ -110,7 +111,7 @@ diff -u -p -r1.1.1.7 -r1.7 break; } -@@ -281,12 +309,17 @@ rde_filter_match(struct filter_rule *f, +@@ -281,12 +310,17 @@ rde_filter_match(struct filter_rule *f, break; } @@ -131,7 +132,7 @@ diff -u -p -r1.1.1.7 -r1.7 /* don't use IPv4 rules for IPv6 and vice versa */ return (0); -@@ -322,7 +355,7 @@ rde_filter_match(struct filter_rule *f, +@@ -322,7 +356,7 @@ rde_filter_match(struct filter_rule *f, } else if (f->match.prefixlen.op != OP_NONE) { /* only prefixlen without a prefix */ @@ -140,7 +141,7 @@ diff -u -p -r1.1.1.7 -r1.7 /* don't use IPv4 rules for IPv6 and vice versa */ return (0); -@@ -356,19 +389,6 @@ rde_filter_match(struct filter_rule *f, +@@ -356,19 +390,6 @@ rde_filter_match(struct filter_rule *f, } int @@ -160,7 +161,7 @@ diff -u -p -r1.1.1.7 -r1.7 rde_filter_equal(struct filter_head *a, struct filter_head *b, struct rde_peer *peer, enum directions dir) { -@@ -476,6 +496,12 @@ filterset_cmp(struct filter_set *a, stru +@@ -476,6 +497,12 @@ filterset_cmp(struct filter_set *a, stru return (a->action.community.type - b->action.community.type); } @@ -173,7 +174,7 @@ diff -u -p -r1.1.1.7 -r1.7 if (a->type == ACTION_SET_NEXTHOP && b->type == ACTION_SET_NEXTHOP) { /* * This is the only interesting case, all others are considered -@@ -483,13 +509,29 @@ filterset_cmp(struct filter_set *a, stru +@@ -483,13 +510,29 @@ filterset_cmp(struct filter_set *a, stru * reject it at the same time. Allow one IPv4 and one IPv6 * per filter set or only one of the other nexthop modifiers. */ @@ -204,7 +205,7 @@ diff -u -p -r1.1.1.7 -r1.7 int filterset_equal(struct filter_set_head *ah, struct filter_set_head *bh) { -@@ -574,6 +616,19 @@ filterset_equal(struct filter_set_head * +@@ -574,6 +617,19 @@ filterset_equal(struct filter_set_head * if (strcmp(as, bs) == 0) continue; break; @@ -224,7 +225,7 @@ diff -u -p -r1.1.1.7 -r1.7 } /* compare failed */ return (0); -@@ -616,7 +671,14 @@ filterset_name(enum action_types type) +@@ -616,7 +672,14 @@ filterset_name(enum action_types type) case ACTION_RTLABEL: case ACTION_RTLABEL_ID: return ("rtlabel"); diff --git a/net/openbgpd/files/patch-bgpd_rde_prefix.c b/net/openbgpd/files/patch-bgpd_rde_prefix.c index a2612312ffcc..daea5cf62272 100644 --- a/net/openbgpd/files/patch-bgpd_rde_prefix.c +++ b/net/openbgpd/files/patch-bgpd_rde_prefix.c @@ -2,13 +2,13 @@ Index: bgpd/rde_prefix.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_prefix.c,v retrieving revision 1.1.1.6 -retrieving revision 1.5 -diff -u -p -r1.1.1.6 -r1.5 +retrieving revision 1.6 +diff -u -p -r1.1.1.6 -r1.6 --- bgpd/rde_prefix.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/rde_prefix.c 10 Apr 2010 12:16:23 -0000 1.5 ++++ bgpd/rde_prefix.c 13 Oct 2012 18:36:00 -0000 1.6 @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_prefix.c,v 1.29 2009/05/30 18:27:17 claudio Exp $ */ -+/* $OpenBSD: rde_prefix.c,v 1.32 2010/03/26 15:41:04 claudio Exp $ */ ++/* $OpenBSD: rde_prefix.c,v 1.31 2010/01/13 06:02:37 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> diff --git a/net/openbgpd/files/patch-bgpd_rde_rib.c b/net/openbgpd/files/patch-bgpd_rde_rib.c index 22d6f0ee0a48..2fe781c69c4b 100644 --- a/net/openbgpd/files/patch-bgpd_rde_rib.c +++ b/net/openbgpd/files/patch-bgpd_rde_rib.c @@ -2,12 +2,13 @@ Index: bgpd/rde_rib.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_rib.c,v retrieving revision 1.1.1.7 -diff -u -p -r1.1.1.7 rde_rib.c +retrieving revision 1.8 +diff -u -p -r1.1.1.7 -r1.8 --- bgpd/rde_rib.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/rde_rib.c 3 Jul 2011 04:45:31 -0000 ++++ bgpd/rde_rib.c 13 Oct 2012 18:36:00 -0000 1.8 @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_rib.c,v 1.116 2009/06/29 14:13:48 claudio Exp $ */ -+/* $OpenBSD: rde_rib.c,v 1.125 2010/04/07 09:44:11 claudio Exp $ */ ++/* $OpenBSD: rde_rib.c,v 1.133 2012/07/01 11:55:13 sthen Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -122,68 +123,102 @@ diff -u -p -r1.1.1.7 rde_rib.c re = RB_NEXT(rib_tree, unused, re); /* free the previously locked rib element if empty */ -@@ -632,11 +639,11 @@ prefix_compare(const struct bgpd_addr *a - int i; - u_int8_t m; +@@ -502,6 +509,36 @@ path_remove(struct rde_aspath *asp) + } + } ++/* remove all stale routes or if staletime is 0 remove all routes for ++ a specified AID. */ ++void ++path_remove_stale(struct rde_aspath *asp, u_int8_t aid) ++{ ++ struct prefix *p, *np; ++ time_t staletime; ++ ++ staletime = asp->peer->staletime[aid]; ++ for (p = LIST_FIRST(&asp->prefix_h); p != NULL; p = np) { ++ np = LIST_NEXT(p, path_l); ++ if (p->prefix->aid != aid) ++ continue; ++ ++ if (staletime && p->lastchange > staletime) ++ continue; ++ ++ if (asp->pftableid) { ++ struct bgpd_addr addr; ++ ++ pt_getaddr(p->prefix, &addr); ++ /* Commit is done in peer_flush() */ ++ rde_send_pftable(p->aspath->pftableid, &addr, ++ p->prefix->prefixlen, 1); ++ } ++ prefix_destroy(p); ++ } ++} ++ ++ + /* this function is only called by prefix_remove and path_remove */ + void + path_destroy(struct rde_aspath *asp) +@@ -624,48 +661,6 @@ static void prefix_link(struct prefix + struct rde_aspath *); + static void prefix_unlink(struct prefix *); + +-int +-prefix_compare(const struct bgpd_addr *a, const struct bgpd_addr *b, +- int prefixlen) +-{ +- in_addr_t mask, aa, ba; +- int i; +- u_int8_t m; +- - if (a->af != b->af) - return (a->af - b->af); -+ if (a->aid != b->aid) -+ return (a->aid - b->aid); - +- - switch (a->af) { - case AF_INET: -+ switch (a->aid) { -+ case AID_INET: - if (prefixlen > 32) - fatalx("prefix_cmp: bad IPv4 prefixlen"); - mask = htonl(prefixlen2mask(prefixlen)); -@@ -645,7 +652,7 @@ prefix_compare(const struct bgpd_addr *a - if (aa != ba) - return (aa - ba); - return (0); +- if (prefixlen > 32) +- fatalx("prefix_cmp: bad IPv4 prefixlen"); +- mask = htonl(prefixlen2mask(prefixlen)); +- aa = ntohl(a->v4.s_addr & mask); +- ba = ntohl(b->v4.s_addr & mask); +- if (aa != ba) +- return (aa - ba); +- return (0); - case AF_INET6: -+ case AID_INET6: - if (prefixlen > 128) - fatalx("prefix_cmp: bad IPv6 prefixlen"); - for (i = 0; i < prefixlen / 8; i++) -@@ -660,6 +667,24 @@ prefix_compare(const struct bgpd_addr *a - (b->v6.s6_addr[prefixlen / 8] & m)); - } - return (0); -+ case AID_VPN_IPv4: -+ if (prefixlen > 32) -+ fatalx("prefix_cmp: bad IPv4 VPN prefixlen"); -+ if (betoh64(a->vpn4.rd) > betoh64(b->vpn4.rd)) -+ return (1); -+ if (betoh64(a->vpn4.rd) < betoh64(b->vpn4.rd)) -+ return (-1); -+ mask = htonl(prefixlen2mask(prefixlen)); -+ aa = ntohl(a->vpn4.addr.s_addr & mask); -+ ba = ntohl(b->vpn4.addr.s_addr & mask); -+ if (aa != ba) -+ return (aa - ba); -+ if (a->vpn4.labellen > b->vpn4.labellen) -+ return (1); -+ if (a->vpn4.labellen < b->vpn4.labellen) -+ return (-1); -+ return (memcmp(a->vpn4.labelstack, b->vpn4.labelstack, -+ a->vpn4.labellen)); - default: - fatalx("prefix_cmp: unknown af"); - } -@@ -806,16 +831,33 @@ prefix_write(u_char *buf, int len, struc +- if (prefixlen > 128) +- fatalx("prefix_cmp: bad IPv6 prefixlen"); +- for (i = 0; i < prefixlen / 8; i++) +- if (a->v6.s6_addr[i] != b->v6.s6_addr[i]) +- return (a->v6.s6_addr[i] - b->v6.s6_addr[i]); +- i = prefixlen % 8; +- if (i) { +- m = 0xff00 >> i; +- if ((a->v6.s6_addr[prefixlen / 8] & m) != +- (b->v6.s6_addr[prefixlen / 8] & m)) +- return ((a->v6.s6_addr[prefixlen / 8] & m) - +- (b->v6.s6_addr[prefixlen / 8] & m)); +- } +- return (0); +- default: +- fatalx("prefix_cmp: unknown af"); +- } +- return (-1); +-} +- + /* + * search for specified prefix of a peer. Returns NULL if not found. + */ +@@ -806,16 +801,58 @@ prefix_write(u_char *buf, int len, struc { int totlen; - if (prefix->af != AF_INET && prefix->af != AF_INET6) -- return (-1); + switch (prefix->aid) { + case AID_INET: + case AID_INET6: + totlen = PREFIX_SIZE(plen); - -- totlen = PREFIX_SIZE(plen); ++ + if (totlen > len) + return (-1); + *buf++ = plen; @@ -193,8 +228,7 @@ diff -u -p -r1.1.1.7 rde_rib.c + totlen = PREFIX_SIZE(plen) + sizeof(prefix->vpn4.rd) + + prefix->vpn4.labellen; + plen += (sizeof(prefix->vpn4.rd) + prefix->vpn4.labellen) * 8; - -- if (totlen > len) ++ + if (totlen > len) + return (-1); + *buf++ = plen; @@ -206,14 +240,41 @@ diff -u -p -r1.1.1.7 rde_rib.c + return (totlen); + default: return (-1); ++ } ++} + +- totlen = PREFIX_SIZE(plen); ++int ++prefix_writebuf(struct ibuf *buf, struct bgpd_addr *prefix, u_int8_t plen) ++{ ++ int totlen; ++ void *bptr; + +- if (totlen > len) ++ switch (prefix->aid) { ++ case AID_INET: ++ case AID_INET6: ++ totlen = PREFIX_SIZE(plen); ++ break; ++ case AID_VPN_IPv4: ++ totlen = PREFIX_SIZE(plen) + sizeof(prefix->vpn4.rd) + ++ prefix->vpn4.labellen; ++ default: + return (-1); - *buf++ = plen; - memcpy(buf, &prefix->ba, totlen - 1); - return (totlen); + } ++ ++ if ((bptr = ibuf_reserve(buf, totlen)) == NULL) ++ return (-1); ++ if (prefix_write(bptr, totlen, prefix, plen) == -1) ++ return (-1); ++ return (0); } /* -@@ -861,7 +903,7 @@ prefix_updateall(struct rde_aspath *asp, +@@ -861,7 +898,7 @@ prefix_updateall(struct rde_aspath *asp, */ if ((p->rib->flags & F_RIB_NOFIB) == 0 && p == p->rib->active) @@ -222,7 +283,16 @@ diff -u -p -r1.1.1.7 rde_rib.c continue; } -@@ -885,16 +927,12 @@ prefix_updateall(struct rde_aspath *asp, +@@ -871,7 +908,7 @@ prefix_updateall(struct rde_aspath *asp, + * If the prefix is the active one remove it first, + * this has to be done because we can not detect when + * the active prefix changes its state. In this case +- * we know that this is a withdrawl and so the second ++ * we know that this is a withdrawal and so the second + * prefix_evaluate() will generate no update because + * the nexthop is unreachable or ineligible. + */ +@@ -885,16 +922,12 @@ prefix_updateall(struct rde_aspath *asp, void prefix_destroy(struct prefix *p) { @@ -239,7 +309,7 @@ diff -u -p -r1.1.1.7 rde_rib.c if (path_empty(asp)) path_destroy(asp); } -@@ -907,7 +945,6 @@ prefix_network_clean(struct rde_peer *pe +@@ -907,21 +940,16 @@ prefix_network_clean(struct rde_peer *pe { struct rde_aspath *asp, *xasp; struct prefix *p, *xp; @@ -247,7 +317,9 @@ diff -u -p -r1.1.1.7 rde_rib.c for (asp = LIST_FIRST(&peer->path_h); asp != NULL; asp = xasp) { xasp = LIST_NEXT(asp, peer_l); -@@ -916,12 +953,8 @@ prefix_network_clean(struct rde_peer *pe +- if ((asp->flags & F_ANN_DYNAMIC) == flags) ++ if ((asp->flags & F_ANN_DYNAMIC) != flags) + continue; for (p = LIST_FIRST(&asp->prefix_h); p != NULL; p = xp) { xp = LIST_NEXT(p, path_l); if (reloadtime > p->lastchange) { @@ -260,7 +332,7 @@ diff -u -p -r1.1.1.7 rde_rib.c } } if (path_empty(asp)) -@@ -954,11 +987,11 @@ prefix_link(struct prefix *pref, struct +@@ -954,11 +982,11 @@ prefix_link(struct prefix *pref, struct static void prefix_unlink(struct prefix *pref) { @@ -277,7 +349,7 @@ diff -u -p -r1.1.1.7 rde_rib.c LIST_REMOVE(pref, path_l); PREFIX_COUNT(pref->aspath, -1); -@@ -966,6 +999,8 @@ prefix_unlink(struct prefix *pref) +@@ -966,6 +994,8 @@ prefix_unlink(struct prefix *pref) pt_unref(pref->prefix); if (pt_empty(pref->prefix)) pt_remove(pref->prefix); @@ -286,7 +358,7 @@ diff -u -p -r1.1.1.7 rde_rib.c /* destroy all references to other objects */ pref->aspath = NULL; -@@ -973,8 +1008,8 @@ prefix_unlink(struct prefix *pref) +@@ -973,8 +1003,8 @@ prefix_unlink(struct prefix *pref) pref->rib = NULL; /* @@ -297,7 +369,7 @@ diff -u -p -r1.1.1.7 rde_rib.c */ } -@@ -1070,10 +1105,6 @@ nexthop_update(struct kroute_nexthop *ms +@@ -1070,10 +1100,6 @@ nexthop_update(struct kroute_nexthop *ms return; } @@ -308,7 +380,7 @@ diff -u -p -r1.1.1.7 rde_rib.c oldstate = nh->state; if (msg->valid) nh->state = NEXTHOP_REACH; -@@ -1088,21 +1119,13 @@ nexthop_update(struct kroute_nexthop *ms +@@ -1088,21 +1114,13 @@ nexthop_update(struct kroute_nexthop *ms memcpy(&nh->true_nexthop, &msg->gateway, sizeof(nh->true_nexthop)); @@ -337,7 +409,7 @@ diff -u -p -r1.1.1.7 rde_rib.c if (rde_noevaluate()) /* -@@ -1118,7 +1141,7 @@ nexthop_update(struct kroute_nexthop *ms +@@ -1118,35 +1136,38 @@ nexthop_update(struct kroute_nexthop *ms void nexthop_modify(struct rde_aspath *asp, struct bgpd_addr *nexthop, @@ -346,16 +418,58 @@ diff -u -p -r1.1.1.7 rde_rib.c { struct nexthop *nh; -@@ -1138,7 +1161,7 @@ nexthop_modify(struct rde_aspath *asp, s - asp->flags |= F_NEXTHOP_SELF; +- if (type == ACTION_SET_NEXTHOP_REJECT) { +- asp->flags |= F_NEXTHOP_REJECT; ++ if (type == ACTION_SET_NEXTHOP && aid != nexthop->aid) return; +- } +- if (type == ACTION_SET_NEXTHOP_BLACKHOLE) { ++ ++ asp->flags &= ~F_NEXTHOP_MASK; ++ switch (type) { ++ case ACTION_SET_NEXTHOP_REJECT: ++ asp->flags |= F_NEXTHOP_REJECT; ++ break; ++ case ACTION_SET_NEXTHOP_BLACKHOLE: + asp->flags |= F_NEXTHOP_BLACKHOLE; +- return; +- } +- if (type == ACTION_SET_NEXTHOP_NOMODIFY) { ++ break; ++ case ACTION_SET_NEXTHOP_NOMODIFY: + asp->flags |= F_NEXTHOP_NOMODIFY; +- return; +- } +- if (type == ACTION_SET_NEXTHOP_SELF) { ++ break; ++ case ACTION_SET_NEXTHOP_SELF: + asp->flags |= F_NEXTHOP_SELF; +- return; ++ break; ++ case ACTION_SET_NEXTHOP: ++ nh = nexthop_get(nexthop); ++ if (asp->flags & F_ATTR_LINKED) ++ nexthop_unlink(asp); ++ asp->nexthop = nh; ++ if (asp->flags & F_ATTR_LINKED) ++ nexthop_link(asp); ++ break; ++ default: ++ break; } - if (af != nexthop->af) -+ if (aid != nexthop->aid) - return; +- return; +- +- nh = nexthop_get(nexthop); +- if (asp->flags & F_ATTR_LINKED) +- nexthop_unlink(asp); +- asp->nexthop = nh; +- if (asp->flags & F_ATTR_LINKED) +- nexthop_link(asp); + } - nh = nexthop_get(nexthop); -@@ -1233,17 +1256,17 @@ nexthop_compare(struct nexthop *na, stru + void +@@ -1233,17 +1254,17 @@ nexthop_compare(struct nexthop *na, stru a = &na->exit_nexthop; b = &nb->exit_nexthop; @@ -378,7 +492,7 @@ diff -u -p -r1.1.1.7 rde_rib.c return (memcmp(&a->v6, &b->v6, sizeof(struct in6_addr))); default: fatalx("nexthop_cmp: unknown af"); -@@ -1269,14 +1292,14 @@ nexthop_hash(struct bgpd_addr *nexthop) +@@ -1269,14 +1290,14 @@ nexthop_hash(struct bgpd_addr *nexthop) { u_int32_t h = 0; diff --git a/net/openbgpd/files/patch-bgpd_rde_update.c b/net/openbgpd/files/patch-bgpd_rde_update.c index cbffb73387e5..ccd9601dcd3d 100644 --- a/net/openbgpd/files/patch-bgpd_rde_update.c +++ b/net/openbgpd/files/patch-bgpd_rde_update.c @@ -2,9 +2,10 @@ Index: bgpd/rde_update.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_update.c,v retrieving revision 1.1.1.7 -diff -u -p -r1.1.1.7 rde_update.c +retrieving revision 1.8 +diff -u -p -r1.1.1.7 -r1.8 --- bgpd/rde_update.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/rde_update.c 3 Jul 2011 04:45:50 -0000 ++++ bgpd/rde_update.c 13 Oct 2012 18:36:00 -0000 1.8 @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_update.c,v 1.68 2009/06/06 01:10:29 claudio Exp $ */ +/* $OpenBSD: rde_update.c,v 1.77 2010/01/13 06:02:37 claudio Exp $ */ @@ -143,7 +144,7 @@ diff -u -p -r1.1.1.7 rde_update.c /* 1. search for attr */ if (a != NULL && (na = RB_FIND(uptree_attr, &peer->up_attrs, a)) == -@@ -270,21 +291,14 @@ up_test_update(struct rde_peer *peer, st +@@ -270,23 +291,16 @@ up_test_update(struct rde_peer *peer, st /* Do not send routes back to sender */ return (0); @@ -167,8 +168,11 @@ diff -u -p -r1.1.1.7 rde_update.c + if (peer->capa.mp[addr.aid] == 0) + return (-1); - if (p->aspath->peer->conf.ebgp == 0 && peer->conf.ebgp == 0) { +- if (p->aspath->peer->conf.ebgp == 0 && peer->conf.ebgp == 0) { ++ if (!p->aspath->peer->conf.ebgp && !peer->conf.ebgp) { /* + * route reflector redistribution rules: + * 1. if announce is set -> announce @@ -325,13 +339,13 @@ up_test_update(struct rde_peer *peer, st } @@ -414,13 +418,41 @@ diff -u -p -r1.1.1.7 rde_update.c * unless the MED is originating from us or the peer is an IBGP one. + * Only exception are routers with "transparent-as yes" set. */ - if (a->flags & F_ATTR_MED && (peer->conf.ebgp == 0 || +- if (a->flags & F_ATTR_MED && (peer->conf.ebgp == 0 || - a->flags & F_ATTR_MED_ANNOUNCE)) { ++ if (a->flags & F_ATTR_MED && (!peer->conf.ebgp || + a->flags & F_ATTR_MED_ANNOUNCE || + peer->conf.flags & PEERFLAG_TRANS_AS)) { tmp32 = htonl(a->med); if ((r = attr_write(up_attr_buf + wlen, len, ATTR_OPTIONAL, ATTR_MED, &tmp32, 4)) == -1) +@@ -669,7 +791,7 @@ up_generate_attr(struct rde_peer *peer, + wlen += r; len -= r; + } + +- if (peer->conf.ebgp == 0) { ++ if (!peer->conf.ebgp) { + /* local preference, only valid for ibgp */ + tmp32 = htonl(a->lpref); + if ((r = attr_write(up_attr_buf + wlen, len, ATTR_WELL_KNOWN, +@@ -704,7 +826,7 @@ up_generate_attr(struct rde_peer *peer, + u_int16_t tas; + + if ((!(oa->flags & ATTR_TRANSITIVE)) && +- peer->conf.ebgp != 0) { ++ peer->conf.ebgp) { + r = 0; + break; + } +@@ -730,7 +852,7 @@ up_generate_attr(struct rde_peer *peer, + case ATTR_ORIGINATOR_ID: + case ATTR_CLUSTER_LIST: + if ((!(oa->flags & ATTR_TRANSITIVE)) && +- peer->conf.ebgp != 0) { ++ peer->conf.ebgp) { + r = 0; + break; + } @@ -791,7 +913,7 @@ up_generate_attr(struct rde_peer *peer, /* write mp attribute to different buffer */ diff --git a/net/openbgpd/files/patch-bgpd_session.c b/net/openbgpd/files/patch-bgpd_session.c index bfbef718ac84..97648857e8f7 100644 --- a/net/openbgpd/files/patch-bgpd_session.c +++ b/net/openbgpd/files/patch-bgpd_session.c @@ -2,26 +2,40 @@ Index: bgpd/session.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/session.c,v retrieving revision 1.1.1.8 -retrieving revision 1.9 -diff -u -p -r1.1.1.8 -r1.9 +retrieving revision 1.12 +diff -u -p -r1.1.1.8 -r1.12 --- bgpd/session.c 14 Feb 2010 20:19:57 -0000 1.1.1.8 -+++ bgpd/session.c 3 Jul 2011 11:18:26 -0000 1.9 ++++ bgpd/session.c 13 Oct 2012 19:10:00 -0000 1.12 @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.293 2009/06/07 05:56:24 eric Exp $ */ -+/* $OpenBSD: session.c,v 1.304 2010/01/05 08:49:57 claudio Exp $ */ ++/* $OpenBSD: session.c,v 1.324 2012/09/12 05:56:22 claudio Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> -@@ -21,6 +21,8 @@ +@@ -21,18 +21,21 @@ #include <sys/mman.h> #include <sys/socket.h> +#include <sys/time.h> +#include <sys/resource.h> #include <sys/un.h> ++#include <sys/queue.h> #include <net/if_types.h> #include <netinet/in.h> -@@ -50,7 +52,12 @@ + #include <netinet/in_systm.h> + #include <netinet/ip.h> + #include <netinet/tcp.h> ++#include <netinet/tcp_var.h> + #include <arpa/inet.h> + + #include <err.h> + #include <errno.h> + #include <fcntl.h> +-#include <limits.h> + #include <poll.h> + #include <pwd.h> + #include <signal.h> +@@ -50,7 +53,12 @@ #define PFD_PIPE_ROUTE_CTL 2 #define PFD_SOCK_CTL 3 #define PFD_SOCK_RCTL 4 @@ -35,7 +49,7 @@ diff -u -p -r1.1.1.8 -r1.9 void session_sighdlr(int); int setup_listeners(u_int *); -@@ -65,9 +72,8 @@ void session_accept(int); +@@ -65,9 +73,9 @@ void session_accept(int); int session_connect(struct peer *); void session_tcp_established(struct peer *); void session_capa_ann_none(struct peer *); @@ -44,19 +58,24 @@ diff -u -p -r1.1.1.8 -r1.9 -int session_capa_add_mp(struct buf *, u_int16_t, u_int8_t); +int session_capa_add(struct ibuf *, u_int8_t, u_int8_t); +int session_capa_add_mp(struct ibuf *, u_int8_t); ++int session_capa_add_gr(struct peer *, struct ibuf *, u_int8_t); struct bgp_msg *session_newmsg(enum msg_type, u_int16_t); int session_sendmsg(struct bgp_msg *, struct peer *); void session_open(struct peer *); -@@ -75,7 +81,7 @@ void session_keepalive(struct peer *); +@@ -75,30 +83,34 @@ void session_keepalive(struct peer *); void session_update(u_int32_t, void *, size_t); void session_notification(struct peer *, u_int8_t, u_int8_t, void *, ssize_t); -void session_rrefresh(struct peer *, u_int16_t, u_int8_t); +void session_rrefresh(struct peer *, u_int8_t); ++int session_graceful_restart(struct peer *); ++int session_graceful_is_restarting(struct peer *); ++int session_graceful_stop(struct peer *); int session_dispatch_msg(struct pollfd *, struct peer *); ++int session_process_msg(struct peer *); int parse_header(struct peer *, u_char *, u_int16_t *, u_int8_t *); int parse_open(struct peer *); -@@ -83,22 +89,22 @@ int parse_update(struct peer *); + int parse_update(struct peer *); int parse_refresh(struct peer *); int parse_notification(struct peer *); int parse_capabilities(struct peer *, u_char *, u_int16_t, u_int32_t *); @@ -88,7 +107,54 @@ diff -u -p -r1.1.1.8 -r1.9 int csock = -1, rcsock = -1; u_int peer_cnt; struct imsgbuf *ibuf_rde; -@@ -175,12 +181,11 @@ setup_listeners(u_int *la_cnt) +@@ -106,6 +118,7 @@ struct imsgbuf *ibuf_rde_ctl; + struct imsgbuf *ibuf_main; + + struct mrt_head mrthead; ++time_t pauseaccept; + + void + session_sighdlr(int sig) +@@ -125,6 +138,22 @@ setup_listeners(u_int *la_cnt) + int opt; + struct listen_addr *la; + u_int cnt = 0; ++#if defined(__FreeBSD__) ++ int s; ++ ++ /* Check if TCP_MD5SIG is supported. */ ++ s = socket(PF_LOCAL, SOCK_STREAM, 0); ++ if (s < 0) ++ fatal("socket open for TCP_MD5SIG check"); ++ opt = TF_SIGNATURE; ++ if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, &opt, sizeof(opt)) == -1) { ++ if (errno == ENOPROTOOPT || errno == EINVAL) ++ sysdep.no_md5sig = 1; ++ else ++ fatal("setsockopt TCP_MD5SIG"); ++ } ++ close(s); ++#endif /* defined(__FreeBSD__) */ + + TAILQ_FOREACH(la, conf->listen_addrs, entry) { + la->reconf = RECONF_NONE; +@@ -140,6 +169,7 @@ setup_listeners(u_int *la_cnt) + } + + opt = 1; ++#if !defined(__FreeBSD__) + if (setsockopt(la->fd, IPPROTO_TCP, TCP_MD5SIG, + &opt, sizeof(opt)) == -1) { + if (errno == ENOPROTOOPT) { /* system w/o md5sig */ +@@ -148,6 +178,7 @@ setup_listeners(u_int *la_cnt) + } else + fatal("setsockopt TCP_MD5SIG"); + } ++#endif /* !defined(__FreeBSD__) */ + + /* set ttl to 255 so that ttl-security works */ + if (la->sa.ss_family == AF_INET && setsockopt(la->fd, +@@ -175,12 +206,10 @@ setup_listeners(u_int *la_cnt) } pid_t @@ -100,12 +166,11 @@ diff -u -p -r1.1.1.8 -r1.9 + int pipe_s2rctl[2]) { - int nfds, timeout; -+ struct rlimit rl; + int nfds, timeout, pfkeysock; unsigned int i, j, idx_peers, idx_listeners, idx_mrts; pid_t pid; u_int pfd_elms = 0, peer_l_elms = 0, mrt_l_elms = 0; -@@ -189,19 +194,13 @@ session_main(struct bgpd_config *config, +@@ -189,19 +218,13 @@ session_main(struct bgpd_config *config, u_int32_t ctl_queued; struct passwd *pw; struct peer *p, **peer_l = NULL, *last, *next; @@ -126,7 +191,7 @@ diff -u -p -r1.1.1.8 -r1.9 switch (pid = fork()) { case -1: fatal("cannot fork"); -@@ -211,13 +210,6 @@ session_main(struct bgpd_config *config, +@@ -211,13 +234,6 @@ session_main(struct bgpd_config *config, return (pid); } @@ -140,18 +205,13 @@ diff -u -p -r1.1.1.8 -r1.9 if ((pw = getpwnam(BGPD_USER)) == NULL) fatal(NULL); -@@ -229,28 +221,31 @@ session_main(struct bgpd_config *config, +@@ -228,29 +244,25 @@ session_main(struct bgpd_config *config, + setproctitle("session engine"); bgpd_process = PROC_SE; - +- - if (pfkey_init(&sysdep) == -1) - fatalx("pfkey setup failed"); -+ if (getrlimit(RLIMIT_NOFILE, &rl) == -1) -+ fatal("getrlimit"); -+ rl.rlim_cur = rl.rlim_max; -+ if (setrlimit(RLIMIT_NOFILE, &rl) == -1) -+ fatal("setrlimit"); -+ + pfkeysock = pfkey_init(&sysdep); if (setgroups(1, &pw->pw_gid) || @@ -179,7 +239,7 @@ diff -u -p -r1.1.1.8 -r1.9 if ((ibuf_rde = malloc(sizeof(struct imsgbuf))) == NULL || (ibuf_rde_ctl = malloc(sizeof(struct imsgbuf))) == NULL || (ibuf_main = malloc(sizeof(struct imsgbuf))) == NULL) -@@ -258,37 +253,21 @@ session_main(struct bgpd_config *config, +@@ -258,37 +270,21 @@ session_main(struct bgpd_config *config, imsg_init(ibuf_rde, pipe_s2r[0]); imsg_init(ibuf_rde_ctl, pipe_s2rctl[0]); imsg_init(ibuf_main, pipe_m2s[1]); @@ -226,7 +286,7 @@ diff -u -p -r1.1.1.8 -r1.9 while (session_quit == 0) { /* check for peers to be initialized or deleted */ -@@ -308,8 +287,9 @@ session_main(struct bgpd_config *config, +@@ -308,8 +304,9 @@ session_main(struct bgpd_config *config, /* reinit due? */ if (p->conf.reconf_action == RECONF_REINIT) { @@ -238,7 +298,7 @@ diff -u -p -r1.1.1.8 -r1.9 } /* deletion due? */ -@@ -317,7 +297,7 @@ session_main(struct bgpd_config *config, +@@ -317,7 +314,7 @@ session_main(struct bgpd_config *config, if (p->demoted) session_demote(p, -1); p->conf.demote_group[0] = 0; @@ -247,7 +307,7 @@ diff -u -p -r1.1.1.8 -r1.9 log_peer_warnx(&p->conf, "removed"); if (last != NULL) last->next = next; -@@ -346,9 +326,17 @@ session_main(struct bgpd_config *config, +@@ -346,9 +343,17 @@ session_main(struct bgpd_config *config, } mrt_cnt = 0; @@ -266,7 +326,7 @@ diff -u -p -r1.1.1.8 -r1.9 if (mrt_cnt > mrt_l_elms) { if ((newp = realloc(mrt_l, sizeof(struct mrt *) * -@@ -394,14 +382,19 @@ session_main(struct bgpd_config *config, +@@ -394,18 +399,31 @@ session_main(struct bgpd_config *config, if (ctl_queued < SESSION_CTL_QUEUE_MAX) /* * Do not act as unlimited buffer. Don't read in more @@ -274,11 +334,20 @@ diff -u -p -r1.1.1.8 -r1.9 + * messages if the ctl sockets are getting full. */ pfd[PFD_PIPE_ROUTE_CTL].events = POLLIN; - pfd[PFD_SOCK_CTL].fd = csock; - pfd[PFD_SOCK_CTL].events = POLLIN; - pfd[PFD_SOCK_RCTL].fd = rcsock; - pfd[PFD_SOCK_RCTL].events = POLLIN; +- pfd[PFD_SOCK_CTL].fd = csock; +- pfd[PFD_SOCK_CTL].events = POLLIN; +- pfd[PFD_SOCK_RCTL].fd = rcsock; +- pfd[PFD_SOCK_RCTL].events = POLLIN; - ++ if (pauseaccept == 0) { ++ pfd[PFD_SOCK_CTL].fd = csock; ++ pfd[PFD_SOCK_CTL].events = POLLIN; ++ pfd[PFD_SOCK_RCTL].fd = rcsock; ++ pfd[PFD_SOCK_RCTL].events = POLLIN; ++ } else { ++ pfd[PFD_SOCK_CTL].fd = -1; ++ pfd[PFD_SOCK_RCTL].fd = -1; ++ } + pfd[PFD_SOCK_PFKEY].fd = pfkeysock; +#if !defined(__FreeBSD__) + pfd[PFD_SOCK_PFKEY].events = POLLIN; @@ -287,8 +356,60 @@ diff -u -p -r1.1.1.8 -r1.9 +#endif i = PFD_LISTENERS_START; TAILQ_FOREACH(la, conf->listen_addrs, entry) { - pfd[i].fd = la->fd; -@@ -534,6 +527,14 @@ session_main(struct bgpd_config *config, +- pfd[i].fd = la->fd; +- pfd[i].events = POLLIN; ++ if (pauseaccept == 0) { ++ pfd[i].fd = la->fd; ++ pfd[i].events = POLLIN; ++ } else ++ pfd[i].fd = -1; + i++; + } + idx_listeners = i; +@@ -450,6 +468,10 @@ session_main(struct bgpd_config *config, + p->state == STATE_ESTABLISHED) + session_demote(p, -1); + break; ++ case Timer_RestartTimeout: ++ timer_stop(p, Timer_RestartTimeout); ++ session_graceful_stop(p); ++ break; + default: + fatalx("King Bula lost in time"); + } +@@ -462,6 +484,9 @@ session_main(struct bgpd_config *config, + events = POLLIN; + if (p->wbuf.queued > 0 || p->state == STATE_CONNECT) + events |= POLLOUT; ++ /* is there still work to do? */ ++ if (p->rbuf && p->rbuf->wpos) ++ timeout = 0; + + /* poll events */ + if (p->fd != -1 && events != 0) { +@@ -492,12 +517,21 @@ session_main(struct bgpd_config *config, + i++; + } + ++ if (pauseaccept && timeout > 1) ++ timeout = 1; + if (timeout < 0) + timeout = 0; + if ((nfds = poll(pfd, i, timeout * 1000)) == -1) + if (errno != EINTR) + fatal("poll error"); + ++ /* ++ * If we previously saw fd exhaustion, we stop accept() ++ * for 1 second to throttle the accept() loop. ++ */ ++ if (pauseaccept && getmonotime() > pauseaccept + 1) ++ pauseaccept = 0; ++ + if (nfds > 0 && pfd[PFD_PIPE_MAIN].revents & POLLOUT) + if (msgbuf_write(&ibuf_main->w) < 0) + fatal("pipe write error"); +@@ -534,6 +568,14 @@ session_main(struct bgpd_config *config, ctl_cnt += control_accept(rcsock, 1); } @@ -303,7 +424,18 @@ diff -u -p -r1.1.1.8 -r1.9 for (j = PFD_LISTENERS_START; nfds > 0 && j < idx_listeners; j++) if (pfd[j].revents & POLLIN) { -@@ -557,7 +558,7 @@ session_main(struct bgpd_config *config, +@@ -545,6 +587,10 @@ session_main(struct bgpd_config *config, + nfds -= session_dispatch_msg(&pfd[j], + peer_l[j - idx_listeners]); + ++ for (p = peers; p != NULL; p = p->next) ++ if (p->rbuf && p->rbuf->wpos) ++ session_process_msg(p); ++ + for (; nfds > 0 && j < idx_mrts; j++) + if (pfd[j].revents & POLLOUT) { + nfds--; +@@ -557,7 +603,7 @@ session_main(struct bgpd_config *config, while ((p = peers) != NULL) { peers = p->next; @@ -312,7 +444,7 @@ diff -u -p -r1.1.1.8 -r1.9 pfkey_remove(p); free(p); } -@@ -643,10 +644,9 @@ bgp_fsm(struct peer *peer, enum session_ +@@ -643,10 +689,9 @@ bgp_fsm(struct peer *peer, enum session_ timer_stop(peer, Timer_IdleHold); /* allocate read buffer */ @@ -324,7 +456,7 @@ diff -u -p -r1.1.1.8 -r1.9 /* init write buffer */ msgbuf_init(&peer->wbuf); -@@ -746,7 +746,6 @@ bgp_fsm(struct peer *peer, enum session_ +@@ -746,7 +791,6 @@ bgp_fsm(struct peer *peer, enum session_ /* ignore */ break; case EVNT_STOP: @@ -332,7 +464,7 @@ diff -u -p -r1.1.1.8 -r1.9 change_state(peer, STATE_IDLE, event); break; case EVNT_CON_CLOSED: -@@ -780,7 +779,8 @@ bgp_fsm(struct peer *peer, enum session_ +@@ -780,7 +824,8 @@ bgp_fsm(struct peer *peer, enum session_ change_state(peer, STATE_IDLE, event); break; default: @@ -342,7 +474,7 @@ diff -u -p -r1.1.1.8 -r1.9 change_state(peer, STATE_IDLE, event); break; } -@@ -791,7 +791,6 @@ bgp_fsm(struct peer *peer, enum session_ +@@ -791,7 +836,6 @@ bgp_fsm(struct peer *peer, enum session_ /* ignore */ break; case EVNT_STOP: @@ -350,7 +482,7 @@ diff -u -p -r1.1.1.8 -r1.9 change_state(peer, STATE_IDLE, event); break; case EVNT_CON_CLOSED: -@@ -815,7 +814,8 @@ bgp_fsm(struct peer *peer, enum session_ +@@ -815,7 +859,8 @@ bgp_fsm(struct peer *peer, enum session_ change_state(peer, STATE_IDLE, event); break; default: @@ -360,7 +492,7 @@ diff -u -p -r1.1.1.8 -r1.9 change_state(peer, STATE_IDLE, event); break; } -@@ -826,7 +826,6 @@ bgp_fsm(struct peer *peer, enum session_ +@@ -826,7 +871,6 @@ bgp_fsm(struct peer *peer, enum session_ /* ignore */ break; case EVNT_STOP: @@ -368,7 +500,7 @@ diff -u -p -r1.1.1.8 -r1.9 change_state(peer, STATE_IDLE, event); break; case EVNT_CON_CLOSED: -@@ -856,7 +855,8 @@ bgp_fsm(struct peer *peer, enum session_ +@@ -856,7 +900,8 @@ bgp_fsm(struct peer *peer, enum session_ change_state(peer, STATE_IDLE, event); break; default: @@ -378,7 +510,20 @@ diff -u -p -r1.1.1.8 -r1.9 change_state(peer, STATE_IDLE, event); break; } -@@ -923,6 +923,7 @@ change_state(struct peer *peer, enum ses +@@ -885,9 +930,10 @@ start_timer_keepalive(struct peer *peer) + void + session_close_connection(struct peer *peer) + { +- if (peer->fd != -1) ++ if (peer->fd != -1) { + close(peer->fd); +- ++ pauseaccept = 0; ++ } + peer->fd = peer->wbuf.fd = -1; + } + +@@ -923,20 +969,31 @@ change_state(struct peer *peer, enum ses timer_stop(peer, Timer_ConnectRetry); timer_stop(peer, Timer_Keepalive); timer_stop(peer, Timer_Hold); @@ -386,7 +531,88 @@ diff -u -p -r1.1.1.8 -r1.9 timer_stop(peer, Timer_IdleHoldReset); session_close_connection(peer); msgbuf_clear(&peer->wbuf); -@@ -1069,7 +1070,7 @@ session_connect(struct peer *peer) + free(peer->rbuf); + peer->rbuf = NULL; + bzero(&peer->capa.peer, sizeof(peer->capa.peer)); +- if (peer->state == STATE_ESTABLISHED) +- session_down(peer); ++ + if (event != EVNT_STOP) { + timer_set(peer, Timer_IdleHold, peer->IdleHoldTime); + if (event != EVNT_NONE && + peer->IdleHoldTime < MAX_IDLE_HOLD/2) + peer->IdleHoldTime *= 2; + } ++ if (peer->state == STATE_ESTABLISHED) { ++ if (peer->capa.neg.grestart.restart == 2 && ++ (event == EVNT_CON_CLOSED || ++ event == EVNT_CON_FATAL)) { ++ /* don't punish graceful restart */ ++ timer_set(peer, Timer_IdleHold, 0); ++ peer->IdleHoldTime /= 2; ++ session_graceful_restart(peer); ++ } else ++ session_down(peer); ++ } + if (peer->state == STATE_NONE || + peer->state == STATE_ESTABLISHED) { + /* initialize capability negotiation structures */ +@@ -947,6 +1004,20 @@ change_state(struct peer *peer, enum ses + } + break; + case STATE_CONNECT: ++ if (peer->state == STATE_ESTABLISHED && ++ peer->capa.neg.grestart.restart == 2) { ++ /* do the graceful restart dance */ ++ session_graceful_restart(peer); ++ peer->holdtime = INTERVAL_HOLD_INITIAL; ++ timer_stop(peer, Timer_ConnectRetry); ++ timer_stop(peer, Timer_Keepalive); ++ timer_stop(peer, Timer_Hold); ++ timer_stop(peer, Timer_IdleHold); ++ timer_stop(peer, Timer_IdleHoldReset); ++ session_close_connection(peer); ++ msgbuf_clear(&peer->wbuf); ++ bzero(&peer->capa.peer, sizeof(peer->capa.peer)); ++ } + break; + case STATE_ACTIVE: + break; +@@ -990,7 +1061,10 @@ session_accept(int listenfd) + len = sizeof(cliaddr); + if ((connfd = accept(listenfd, + (struct sockaddr *)&cliaddr, &len)) == -1) { +- if (errno == EWOULDBLOCK || errno == EINTR) ++ if (errno == ENFILE || errno == EMFILE) { ++ pauseaccept = getmonotime(); ++ return; ++ } else if (errno == EWOULDBLOCK || errno == EINTR) + return; + else + log_warn("accept"); +@@ -1017,6 +1091,7 @@ session_accept(int listenfd) + } + } + ++open: + if (p->conf.auth.method != AUTH_NONE && sysdep.no_pfkey) { + log_peer_warnx(&p->conf, + "ipsec or md5sig configured but not available"); +@@ -1049,6 +1124,13 @@ session_accept(int listenfd) + } + session_socket_blockmode(connfd, BM_NONBLOCK); + bgp_fsm(p, EVNT_CON_OPEN); ++ return; ++ } else if (p != NULL && p->state == STATE_ESTABLISHED && ++ p->capa.neg.grestart.restart == 2) { ++ /* first do the graceful restart dance */ ++ change_state(p, STATE_CONNECT, EVNT_CON_CLOSED); ++ /* then do part of the open dance */ ++ goto open; + } else { + log_conn_attempt(p, (struct sockaddr *)&cliaddr); + close(connfd); +@@ -1069,7 +1151,7 @@ session_connect(struct peer *peer) if (peer->fd != -1) return (-1); @@ -395,7 +621,7 @@ diff -u -p -r1.1.1.8 -r1.9 IPPROTO_TCP)) == -1) { log_peer_warn(&peer->conf, "session_connect socket"); bgp_fsm(peer, EVNT_CON_OPENFAIL); -@@ -1100,8 +1101,7 @@ session_connect(struct peer *peer) +@@ -1100,8 +1182,7 @@ session_connect(struct peer *peer) peer->wbuf.fd = peer->fd; /* if update source is set we need to bind() */ @@ -405,7 +631,7 @@ diff -u -p -r1.1.1.8 -r1.9 if (bind(peer->fd, sa, sa->sa_len) == -1) { log_peer_warn(&peer->conf, "session_connect bind"); bgp_fsm(peer, EVNT_CON_OPENFAIL); -@@ -1139,42 +1139,50 @@ session_setup_socket(struct peer *p) +@@ -1139,42 +1220,50 @@ session_setup_socket(struct peer *p) int nodelay = 1; int bsize; @@ -486,7 +712,7 @@ diff -u -p -r1.1.1.8 -r1.9 } /* set TCP_NODELAY */ -@@ -1185,14 +1193,6 @@ session_setup_socket(struct peer *p) +@@ -1185,24 +1274,18 @@ session_setup_socket(struct peer *p) return (-1); } @@ -501,7 +727,23 @@ diff -u -p -r1.1.1.8 -r1.9 /* only increase bufsize (and thus window) if md5 or ipsec is in use */ if (p->conf.auth.method != AUTH_NONE) { /* try to increase bufsize. no biggie if it fails */ -@@ -1244,40 +1244,32 @@ session_tcp_established(struct peer *pee + bsize = 65535; +- while (setsockopt(p->fd, SOL_SOCKET, SO_RCVBUF, &bsize, +- sizeof(bsize)) == -1) ++ while (bsize > 8192 && ++ setsockopt(p->fd, SOL_SOCKET, SO_RCVBUF, &bsize, ++ sizeof(bsize)) == -1 && errno != EINVAL) + bsize /= 2; + bsize = 65535; +- while (setsockopt(p->fd, SOL_SOCKET, SO_SNDBUF, &bsize, +- sizeof(bsize)) == -1) ++ while (bsize > 8192 && ++ setsockopt(p->fd, SOL_SOCKET, SO_SNDBUF, &bsize, ++ sizeof(bsize)) == -1 && errno != EINVAL) + bsize /= 2; + } + +@@ -1244,40 +1327,56 @@ session_tcp_established(struct peer *pee void session_capa_ann_none(struct peer *peer) { @@ -516,11 +758,9 @@ diff -u -p -r1.1.1.8 -r1.9 int -session_capa_add(struct peer *p, struct buf *opb, u_int8_t capa_code, - u_int8_t capa_len, u_int8_t *optparamlen) -+session_capa_add(struct ibuf *opb, u_int8_t capa_code, u_int8_t capa_len) - { +-{ - u_int8_t op_type, op_len, tot_len, errs = 0; -+ int errs = 0; - +- - op_type = OPT_PARAM_CAPABILITIES; - op_len = sizeof(capa_code) + sizeof(capa_len) + capa_len; - tot_len = sizeof(op_type) + sizeof(op_len) + op_len; @@ -529,6 +769,10 @@ diff -u -p -r1.1.1.8 -r1.9 - errs += buf_add(opb, &capa_code, sizeof(capa_code)); - errs += buf_add(opb, &capa_len, sizeof(capa_len)); - *optparamlen += tot_len; ++session_capa_add(struct ibuf *opb, u_int8_t capa_code, u_int8_t capa_len) ++{ ++ int errs = 0; ++ + errs += ibuf_add(opb, &capa_code, sizeof(capa_code)); + errs += ibuf_add(opb, &capa_len, sizeof(capa_len)); return (errs); @@ -545,17 +789,41 @@ diff -u -p -r1.1.1.8 -r1.9 + if (aid2afi(aid, &afi, &safi) == -1) + fatalx("session_capa_add_mp: bad afi/safi pair"); ++ afi = htons(afi); ++ errs += ibuf_add(buf, &afi, sizeof(afi)); ++ errs += ibuf_add(buf, &pad, sizeof(pad)); ++ errs += ibuf_add(buf, &safi, sizeof(safi)); ++ ++ return (errs); ++} ++ ++int ++session_capa_add_gr(struct peer *p, struct ibuf *b, u_int8_t aid) ++{ ++ u_int errs = 0; ++ u_int16_t afi; ++ u_int8_t flags, safi; ++ ++ if (aid2afi(aid, &afi, &safi)) { ++ log_warn("session_capa_add_gr: bad AID"); ++ return (1); ++ } ++ if (p->capa.neg.grestart.flags[aid] & CAPA_GR_RESTARTING) ++ flags = CAPA_GR_F_FLAG; ++ else ++ flags = 0; ++ afi = htons(afi); - errs += buf_add(buf, &afi, sizeof(afi)); - errs += buf_add(buf, &pad, sizeof(pad)); - errs += buf_add(buf, &safi, sizeof(safi)); -+ errs += ibuf_add(buf, &afi, sizeof(afi)); -+ errs += ibuf_add(buf, &pad, sizeof(pad)); -+ errs += ibuf_add(buf, &safi, sizeof(safi)); ++ errs += ibuf_add(b, &afi, sizeof(afi)); ++ errs += ibuf_add(b, &safi, sizeof(safi)); ++ errs += ibuf_add(b, &flags, sizeof(flags)); return (errs); } -@@ -1287,23 +1279,22 @@ session_newmsg(enum msg_type msgtype, u_ +@@ -1287,23 +1386,22 @@ session_newmsg(enum msg_type msgtype, u_ { struct bgp_msg *msg; struct msg_header hdr; @@ -587,7 +855,7 @@ diff -u -p -r1.1.1.8 -r1.9 return (NULL); } -@@ -1329,7 +1320,7 @@ session_sendmsg(struct bgp_msg *msg, str +@@ -1329,7 +1427,7 @@ session_sendmsg(struct bgp_msg *msg, str mrt_dump_bgp_msg(mrt, msg->buf->buf, msg->len, p); } @@ -596,7 +864,7 @@ diff -u -p -r1.1.1.8 -r1.9 free(msg); return (0); } -@@ -1338,40 +1329,38 @@ void +@@ -1338,40 +1436,70 @@ void session_open(struct peer *p) { struct bgp_msg *buf; @@ -608,6 +876,7 @@ diff -u -p -r1.1.1.8 -r1.9 - u_int errs = 0; + u_int8_t i, op_type, optparamlen = 0; + int errs = 0; ++ int mpcapa = 0; - if ((opb = buf_dynamic(0, MAX_PKTSIZE - MSGSIZE_OPEN_MIN)) == NULL) { @@ -630,6 +899,7 @@ diff -u -p -r1.1.1.8 -r1.9 + if (p->capa.ann.mp[i]) { /* 4 bytes data */ + errs += session_capa_add(opb, CAPA_MP, 4); + errs += session_capa_add_mp(opb, i); ++ mpcapa++; + } /* route refresh, RFC 2918 */ @@ -637,21 +907,56 @@ diff -u -p -r1.1.1.8 -r1.9 - errs += session_capa_add(p, opb, CAPA_REFRESH, 0, &optparamlen); + errs += session_capa_add(opb, CAPA_REFRESH, 0); - /* End-of-RIB marker, RFC 4724 */ - if (p->capa.ann.restart) { /* 2 bytes data */ - u_char c[2]; - +- /* End-of-RIB marker, RFC 4724 */ +- if (p->capa.ann.restart) { /* 2 bytes data */ +- u_char c[2]; +- - bzero(&c, 2); - c[0] = 0x80; /* we're always restarting */ +- c[0] = 0x80; /* we're always restarting */ - errs += session_capa_add(p, opb, CAPA_RESTART, 2, &optparamlen); - errs += buf_add(opb, &c, 2); -+ c[1] = 0; -+ errs += session_capa_add(opb, CAPA_RESTART, 2); -+ errs += ibuf_add(opb, &c, 2); ++ /* graceful restart and End-of-RIB marker, RFC 4724 */ ++ if (p->capa.ann.grestart.restart) { ++ int rst = 0; ++ u_int16_t hdr; ++ u_int8_t grlen; ++ ++ if (mpcapa) { ++ grlen = 2 + 4 * mpcapa; ++ for (i = 0; i < AID_MAX; i++) { ++ if (p->capa.neg.grestart.flags[i] & ++ CAPA_GR_RESTARTING) ++ rst++; ++ } ++ } else { /* AID_INET */ ++ grlen = 2 + 4; ++ if (p->capa.neg.grestart.flags[AID_INET] & ++ CAPA_GR_RESTARTING) ++ rst++; ++ } ++ ++ hdr = conf->holdtime; /* default timeout */ ++ /* if client does graceful restart don't set R flag */ ++ if (!rst) ++ hdr |= CAPA_GR_R_FLAG; ++ hdr = htons(hdr); ++ ++ errs += session_capa_add(opb, CAPA_RESTART, grlen); ++ errs += ibuf_add(opb, &hdr, sizeof(hdr)); ++ ++ if (mpcapa) { ++ for (i = 0; i < AID_MAX; i++) { ++ if (p->capa.ann.mp[i]) { ++ errs += session_capa_add_gr(p, opb, i); ++ } ++ } ++ } else { /* AID_INET */ ++ errs += session_capa_add_gr(p, opb, AID_INET); ++ } } /* 4-bytes AS numbers, draft-ietf-idr-as4bytes-13 */ -@@ -1379,13 +1368,17 @@ session_open(struct peer *p) +@@ -1379,13 +1507,17 @@ session_open(struct peer *p) u_int32_t nas; nas = htonl(conf->as); @@ -672,7 +977,7 @@ diff -u -p -r1.1.1.8 -r1.9 bgp_fsm(p, EVNT_CON_FATAL); return; } -@@ -1399,19 +1392,24 @@ session_open(struct peer *p) +@@ -1399,19 +1531,24 @@ session_open(struct peer *p) msg.bgpid = conf->bgpid; /* is already in network byte order */ msg.optparamlen = optparamlen; @@ -708,7 +1013,7 @@ diff -u -p -r1.1.1.8 -r1.9 free(buf); bgp_fsm(p, EVNT_CON_FATAL); return; -@@ -1459,8 +1457,8 @@ session_update(u_int32_t peerid, void *d +@@ -1459,8 +1596,8 @@ session_update(u_int32_t peerid, void *d return; } @@ -719,7 +1024,7 @@ diff -u -p -r1.1.1.8 -r1.9 free(buf); bgp_fsm(p, EVNT_CON_FATAL); return; -@@ -1480,29 +1478,27 @@ session_notification(struct peer *p, u_i +@@ -1480,29 +1617,27 @@ session_notification(struct peer *p, u_i void *data, ssize_t datalen) { struct bgp_msg *buf; @@ -757,7 +1062,7 @@ diff -u -p -r1.1.1.8 -r1.9 free(buf); bgp_fsm(p, EVNT_CON_FATAL); return; -@@ -1521,23 +1517,29 @@ session_notification(struct peer *p, u_i +@@ -1521,23 +1656,29 @@ session_notification(struct peer *p, u_i int session_neighbor_rrefresh(struct peer *p) { @@ -793,7 +1098,7 @@ diff -u -p -r1.1.1.8 -r1.9 if ((buf = session_newmsg(RREFRESH, MSGSIZE_RREFRESH)) == NULL) { bgp_fsm(p, EVNT_CON_FATAL); -@@ -1545,12 +1547,12 @@ session_rrefresh(struct peer *p, u_int16 +@@ -1545,12 +1686,12 @@ session_rrefresh(struct peer *p, u_int16 } afi = htons(afi); @@ -811,7 +1116,229 @@ diff -u -p -r1.1.1.8 -r1.9 free(buf); bgp_fsm(p, EVNT_CON_FATAL); return; -@@ -1853,12 +1855,6 @@ parse_open(struct peer *peer) +@@ -1565,13 +1706,74 @@ session_rrefresh(struct peer *p, u_int16 + } + + int ++session_graceful_restart(struct peer *p) ++{ ++ u_int8_t i; ++ ++ timer_set(p, Timer_RestartTimeout, p->capa.neg.grestart.timeout); ++ ++ for (i = 0; i < AID_MAX; i++) { ++ if (p->capa.neg.grestart.flags[i] & CAPA_GR_PRESENT) { ++ if (imsg_compose(ibuf_rde, IMSG_SESSION_STALE, ++ p->conf.id, 0, -1, &i, sizeof(i)) == -1) ++ return (-1); ++ log_peer_warnx(&p->conf, ++ "graceful restart of %s, keeping routes", ++ aid2str(i)); ++ p->capa.neg.grestart.flags[i] |= CAPA_GR_RESTARTING; ++ } else if (p->capa.neg.mp[i]) { ++ if (imsg_compose(ibuf_rde, IMSG_SESSION_FLUSH, ++ p->conf.id, 0, -1, &i, sizeof(i)) == -1) ++ return (-1); ++ log_peer_warnx(&p->conf, ++ "graceful restart of %s, flushing routes", ++ aid2str(i)); ++ } ++ } ++ return (0); ++} ++ ++int ++session_graceful_is_restarting(struct peer *p) ++{ ++ u_int8_t i; ++ ++ for (i = 0; i < AID_MAX; i++) ++ if (p->capa.neg.grestart.flags[i] & CAPA_GR_RESTARTING) ++ return (1); ++ return (0); ++} ++ ++int ++session_graceful_stop(struct peer *p) ++{ ++ u_int8_t i; ++ ++ for (i = 0; i < AID_MAX; i++) { ++ /* ++ * Only flush if the peer is restarting and the peer indicated ++ * it hold the forwarding state. In all other cases the ++ * session was already flushed when the session came up. ++ */ ++ if (p->capa.neg.grestart.flags[i] & CAPA_GR_RESTARTING && ++ p->capa.neg.grestart.flags[i] & CAPA_GR_FORWARD) { ++ log_peer_warnx(&p->conf, "graceful restart of %s, " ++ "time-out, flushing", aid2str(i)); ++ if (imsg_compose(ibuf_rde, IMSG_SESSION_FLUSH, ++ p->conf.id, 0, -1, &i, sizeof(i)) == -1) ++ return (-1); ++ } ++ p->capa.neg.grestart.flags[i] &= ~CAPA_GR_RESTARTING; ++ } ++ return (0); ++} ++ ++int + session_dispatch_msg(struct pollfd *pfd, struct peer *p) + { +- ssize_t n, rpos, av, left; ++ ssize_t n; + socklen_t len; +- int error, processed = 0; +- u_int16_t msglen; +- u_int8_t msgtype; ++ int error; + + if (p->state == STATE_CONNECT) { + if (pfd->revents & POLLOUT) { +@@ -1641,71 +1843,83 @@ session_dispatch_msg(struct pollfd *pfd, + return (1); + } + +- rpos = 0; +- av = p->rbuf->wpos + n; ++ p->rbuf->wpos += n; + p->stats.last_read = time(NULL); ++ return (1); ++ } ++ return (0); ++} + +- /* +- * session might drop to IDLE -> buffers deallocated +- * we MUST check rbuf != NULL before use +- */ +- for (;;) { +- if (rpos + MSGSIZE_HEADER > av) +- break; +- if (p->rbuf == NULL) +- break; +- if (parse_header(p, p->rbuf->buf + rpos, &msglen, +- &msgtype) == -1) +- return (0); +- if (rpos + msglen > av) +- break; +- p->rbuf->rptr = p->rbuf->buf + rpos; ++int ++session_process_msg(struct peer *p) ++{ ++ ssize_t rpos, av, left; ++ int processed = 0; ++ u_int16_t msglen; ++ u_int8_t msgtype; + +- switch (msgtype) { +- case OPEN: +- bgp_fsm(p, EVNT_RCVD_OPEN); +- p->stats.msg_rcvd_open++; +- break; +- case UPDATE: +- bgp_fsm(p, EVNT_RCVD_UPDATE); +- p->stats.msg_rcvd_update++; +- break; +- case NOTIFICATION: +- bgp_fsm(p, EVNT_RCVD_NOTIFICATION); +- p->stats.msg_rcvd_notification++; +- break; +- case KEEPALIVE: +- bgp_fsm(p, EVNT_RCVD_KEEPALIVE); +- p->stats.msg_rcvd_keepalive++; +- break; +- case RREFRESH: +- parse_refresh(p); +- p->stats.msg_rcvd_rrefresh++; +- break; +- default: /* cannot happen */ +- session_notification(p, ERR_HEADER, +- ERR_HDR_TYPE, &msgtype, 1); +- log_warnx("received message with " +- "unknown type %u", msgtype); +- bgp_fsm(p, EVNT_CON_FATAL); +- } +- rpos += msglen; +- if (++processed > MSG_PROCESS_LIMIT) +- break; +- } +- if (p->rbuf == NULL) +- return (1); ++ rpos = 0; ++ av = p->rbuf->wpos; + +- if (rpos < av) { +- left = av - rpos; +- memcpy(&p->rbuf->buf, p->rbuf->buf + rpos, left); +- p->rbuf->wpos = left; +- } else +- p->rbuf->wpos = 0; ++ /* ++ * session might drop to IDLE -> buffers deallocated ++ * we MUST check rbuf != NULL before use ++ */ ++ for (;;) { ++ if (rpos + MSGSIZE_HEADER > av) ++ break; ++ if (p->rbuf == NULL) ++ break; ++ if (parse_header(p, p->rbuf->buf + rpos, &msglen, ++ &msgtype) == -1) ++ return (0); ++ if (rpos + msglen > av) ++ break; ++ p->rbuf->rptr = p->rbuf->buf + rpos; + +- return (1); ++ switch (msgtype) { ++ case OPEN: ++ bgp_fsm(p, EVNT_RCVD_OPEN); ++ p->stats.msg_rcvd_open++; ++ break; ++ case UPDATE: ++ bgp_fsm(p, EVNT_RCVD_UPDATE); ++ p->stats.msg_rcvd_update++; ++ break; ++ case NOTIFICATION: ++ bgp_fsm(p, EVNT_RCVD_NOTIFICATION); ++ p->stats.msg_rcvd_notification++; ++ break; ++ case KEEPALIVE: ++ bgp_fsm(p, EVNT_RCVD_KEEPALIVE); ++ p->stats.msg_rcvd_keepalive++; ++ break; ++ case RREFRESH: ++ parse_refresh(p); ++ p->stats.msg_rcvd_rrefresh++; ++ break; ++ default: /* cannot happen */ ++ session_notification(p, ERR_HEADER, ERR_HDR_TYPE, ++ &msgtype, 1); ++ log_warnx("received message with unknown type %u", ++ msgtype); ++ bgp_fsm(p, EVNT_CON_FATAL); ++ } ++ rpos += msglen; ++ if (++processed > MSG_PROCESS_LIMIT) ++ break; + } +- return (0); ++ if (p->rbuf == NULL) ++ return (1); ++ ++ if (rpos < av) { ++ left = av - rpos; ++ memcpy(&p->rbuf->buf, p->rbuf->buf + rpos, left); ++ p->rbuf->wpos = left; ++ } else ++ p->rbuf->wpos = 0; ++ ++ return (1); + } + + int +@@ -1853,12 +2067,6 @@ parse_open(struct peer *peer) p += sizeof(short_as); as = peer->short_as = ntohs(short_as); @@ -824,7 +1351,7 @@ diff -u -p -r1.1.1.8 -r1.9 memcpy(&oholdtime, p, sizeof(oholdtime)); p += sizeof(oholdtime); -@@ -1966,6 +1962,15 @@ parse_open(struct peer *peer) +@@ -1966,6 +2174,15 @@ parse_open(struct peer *peer) } } @@ -840,13 +1367,13 @@ diff -u -p -r1.1.1.8 -r1.9 if (peer->conf.remote_as != as) { log_peer_warnx(&peer->conf, "peer sent wrong AS %s", log_as(as)); -@@ -1974,6 +1979,14 @@ parse_open(struct peer *peer) +@@ -1974,6 +2191,14 @@ parse_open(struct peer *peer) return (-1); } + if (capa_neg_calc(peer) == -1) { + log_peer_warnx(&peer->conf, -+ "capabilitiy negotiation calculation failed"); ++ "capability negotiation calculation failed"); + session_notification(peer, ERR_OPEN, 0, NULL, 0); + change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); + return (-1); @@ -855,7 +1382,7 @@ diff -u -p -r1.1.1.8 -r1.9 return (0); } -@@ -2008,24 +2021,35 @@ int +@@ -2008,24 +2233,35 @@ int parse_refresh(struct peer *peer) { u_char *p; @@ -897,7 +1424,7 @@ diff -u -p -r1.1.1.8 -r1.9 return (-1); return (0); -@@ -2035,11 +2059,12 @@ int +@@ -2035,11 +2271,12 @@ int parse_notification(struct peer *peer) { u_char *p; @@ -911,7 +1438,7 @@ diff -u -p -r1.1.1.8 -r1.9 /* just log */ p = peer->rbuf->rptr; -@@ -2059,7 +2084,7 @@ parse_notification(struct peer *peer) +@@ -2059,7 +2296,7 @@ parse_notification(struct peer *peer) p += sizeof(subcode); datalen -= sizeof(subcode); @@ -920,7 +1447,7 @@ diff -u -p -r1.1.1.8 -r1.9 peer->errcnt++; if (errcode == ERR_OPEN && subcode == ERR_OPEN_CAPA) { -@@ -2094,8 +2119,8 @@ parse_notification(struct peer *peer) +@@ -2094,8 +2331,8 @@ parse_notification(struct peer *peer) datalen -= capa_len; switch (capa_code) { case CAPA_MP: @@ -931,7 +1458,16 @@ diff -u -p -r1.1.1.8 -r1.9 log_peer_warnx(&peer->conf, "disabling multiprotocol capability"); break; -@@ -2139,13 +2164,14 @@ parse_notification(struct peer *peer) +@@ -2105,7 +2342,7 @@ parse_notification(struct peer *peer) + "disabling route refresh capability"); + break; + case CAPA_RESTART: +- peer->capa.ann.restart = 0; ++ peer->capa.ann.grestart.restart = 0; + log_peer_warnx(&peer->conf, + "disabling restart capability"); + break; +@@ -2139,13 +2376,17 @@ parse_notification(struct peer *peer) int parse_capabilities(struct peer *peer, u_char *d, u_int16_t dlen, u_int32_t *as) { @@ -939,18 +1475,21 @@ diff -u -p -r1.1.1.8 -r1.9 + u_int32_t remote_as; u_int16_t len; + u_int16_t afi; ++ u_int16_t gr_header; + u_int8_t safi; + u_int8_t aid; ++ u_int8_t gr_flags; u_int8_t capa_code; u_int8_t capa_len; - u_char *capa_val; - u_int16_t mp_afi; - u_int8_t mp_safi; - u_int32_t remote_as; ++ u_int8_t i; len = dlen; while (len > 0) { -@@ -2182,29 +2208,16 @@ parse_capabilities(struct peer *peer, u_ +@@ -2182,36 +2423,65 @@ parse_capabilities(struct peer *peer, u_ "expect len 4, len is %u", capa_len); return (-1); } @@ -988,7 +1527,58 @@ diff -u -p -r1.1.1.8 -r1.9 break; case CAPA_REFRESH: peer->capa.peer.refresh = 1; -@@ -2232,6 +2245,37 @@ parse_capabilities(struct peer *peer, u_ + break; + case CAPA_RESTART: +- peer->capa.peer.restart = 1; +- /* we don't care about the further restart capas yet */ ++ if (capa_len == 2) { ++ /* peer only supports EoR marker */ ++ peer->capa.peer.grestart.restart = 1; ++ peer->capa.peer.grestart.timeout = 0; ++ break; ++ } else if (capa_len % 4 != 2) { ++ log_peer_warnx(&peer->conf, ++ "parse_capabilities: " ++ "expect len 2 + x*4, len is %u", capa_len); ++ return (-1); ++ } ++ ++ memcpy(&gr_header, capa_val, sizeof(gr_header)); ++ gr_header = ntohs(gr_header); ++ peer->capa.peer.grestart.timeout = ++ gr_header & CAPA_GR_TIMEMASK; ++ if (peer->capa.peer.grestart.timeout == 0) { ++ log_peer_warnx(&peer->conf, ++ "graceful restart timeout is zero"); ++ return (-1); ++ } ++ ++ for (i = 2; i <= capa_len - 4; i += 4) { ++ memcpy(&afi, capa_val + i, sizeof(afi)); ++ afi = ntohs(afi); ++ memcpy(&safi, capa_val + i + 2, sizeof(safi)); ++ if (afi2aid(afi, safi, &aid) == -1) { ++ log_peer_warnx(&peer->conf, ++ "parse_capabilities: restart: AFI " ++ "%u, safi %u unknown", afi, safi); ++ return (-1); ++ } ++ memcpy(&gr_flags, capa_val + i + 3, ++ sizeof(gr_flags)); ++ peer->capa.peer.grestart.flags[aid] |= ++ CAPA_GR_PRESENT; ++ if (gr_flags & CAPA_GR_F_FLAG) ++ peer->capa.peer.grestart.flags[aid] |= ++ CAPA_GR_FORWARD; ++ if (gr_header & CAPA_GR_R_FLAG) ++ peer->capa.peer.grestart.flags[aid] |= ++ CAPA_GR_RESTART; ++ peer->capa.peer.grestart.restart = 2; ++ } + break; + case CAPA_AS4BYTE: + if (capa_len != 4) { +@@ -2232,6 +2502,66 @@ parse_capabilities(struct peer *peer, u_ return (0); } @@ -1014,11 +1604,40 @@ diff -u -p -r1.1.1.8 -r1.9 + } else + p->capa.neg.mp[i] = 0; + } -+ /* if no MP capability present for default IPv4 unicast mode */ ++ /* if no MP capability present default to IPv4 unicast mode */ + if (!hasmp) + p->capa.neg.mp[AID_INET] = 1; + -+ p->capa.neg.restart = p->capa.peer.restart; ++ /* ++ * graceful restart: only the peer capabilities are of interest here. ++ * It is necessary to compare the new values with the previous ones ++ * and act acordingly. AFI/SAFI that are not part in the MP capability ++ * are treated as not being present. ++ */ ++ ++ for (i = 0; i < AID_MAX; i++) { ++ /* disable GR if the AFI/SAFI is not present */ ++ if (p->capa.peer.grestart.flags[i] & CAPA_GR_PRESENT && ++ p->capa.neg.mp[i] == 0) ++ p->capa.peer.grestart.flags[i] = 0; /* disable */ ++ /* look at current GR state and decide what to do */ ++ if (p->capa.neg.grestart.flags[i] & CAPA_GR_RESTARTING) { ++ if (!(p->capa.peer.grestart.flags[i] & ++ CAPA_GR_FORWARD)) { ++ if (imsg_compose(ibuf_rde, IMSG_SESSION_FLUSH, ++ p->conf.id, 0, -1, &i, sizeof(i)) == -1) ++ return (-1); ++ log_peer_warnx(&p->conf, "graceful restart of " ++ "%s, not restarted, flushing", aid2str(i)); ++ } ++ p->capa.neg.grestart.flags[i] = ++ p->capa.peer.grestart.flags[i] | CAPA_GR_RESTARTING; ++ } else ++ p->capa.neg.grestart.flags[i] = ++ p->capa.peer.grestart.flags[i]; ++ } ++ p->capa.neg.grestart.timeout = p->capa.peer.grestart.timeout; ++ p->capa.neg.grestart.restart = p->capa.peer.grestart.restart; + + return (0); +} @@ -1026,16 +1645,18 @@ diff -u -p -r1.1.1.8 -r1.9 void session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt) { -@@ -2244,7 +2288,7 @@ session_dispatch_imsg(struct imsgbuf *ib +@@ -2244,8 +2574,8 @@ session_dispatch_imsg(struct imsgbuf *ib struct kif *kif; u_char *data; enum reconf_action reconf; - int n, depend_ok; +- u_int8_t errcode, subcode; + int n, depend_ok, restricted; - u_int8_t errcode, subcode; ++ u_int8_t aid, errcode, subcode; if ((n = imsg_read(ibuf)) == -1) -@@ -2332,15 +2376,42 @@ session_dispatch_imsg(struct imsgbuf *ib + fatal("session_dispatch_imsg: imsg_read error"); +@@ -2332,15 +2662,42 @@ session_dispatch_imsg(struct imsgbuf *ib } break; @@ -1079,7 +1700,27 @@ diff -u -p -r1.1.1.8 -r1.9 /* add new peers */ for (p = npeers; p != NULL; p = next) { -@@ -2408,7 +2479,8 @@ session_dispatch_imsg(struct imsgbuf *ib +@@ -2388,6 +2745,8 @@ session_dispatch_imsg(struct imsgbuf *ib + nconf = NULL; + pending_reconf = 0; + log_info("SE reconfigured"); ++ imsg_compose(ibuf_main, IMSG_RECONF_DONE, 0, 0, ++ -1, NULL, 0); + break; + case IMSG_IFINFO: + if (idx != PFD_PIPE_MAIN) +@@ -2397,9 +2756,7 @@ session_dispatch_imsg(struct imsgbuf *ib + fatalx("IFINFO imsg with wrong len"); + kif = imsg.data; + depend_ok = (kif->flags & IFF_UP) && +- (LINK_STATE_IS_UP(kif->link_state) || +- (kif->link_state == LINK_STATE_UNKNOWN && +- kif->media_type != IFT_CARP)); ++ LINK_STATE_IS_UP(kif->link_state); + + for (p = peers; p != NULL; p = p->next) + if (!strcmp(p->conf.if_depend, kif->ifname)) { +@@ -2408,7 +2765,8 @@ session_dispatch_imsg(struct imsgbuf *ib bgp_fsm(p, EVNT_START); } else if (!depend_ok && p->depend_ok) { p->depend_ok = depend_ok; @@ -1089,7 +1730,7 @@ diff -u -p -r1.1.1.8 -r1.9 } } break; -@@ -2456,10 +2528,10 @@ session_dispatch_imsg(struct imsgbuf *ib +@@ -2456,10 +2814,10 @@ session_dispatch_imsg(struct imsgbuf *ib } break; case IMSG_CTL_KROUTE: @@ -1101,7 +1742,7 @@ diff -u -p -r1.1.1.8 -r1.9 if (idx != PFD_PIPE_MAIN) fatalx("ctl kroute request not from parent"); control_imsg_relay(&imsg); -@@ -2469,7 +2541,6 @@ session_dispatch_imsg(struct imsgbuf *ib +@@ -2469,7 +2827,6 @@ session_dispatch_imsg(struct imsgbuf *ib case IMSG_CTL_SHOW_RIB_ATTR: case IMSG_CTL_SHOW_RIB_MEM: case IMSG_CTL_SHOW_NETWORK: @@ -1109,7 +1750,48 @@ diff -u -p -r1.1.1.8 -r1.9 case IMSG_CTL_SHOW_NEIGHBOR: if (idx != PFD_PIPE_ROUTE_CTL) fatalx("ctl rib request not from RDE"); -@@ -2612,29 +2683,23 @@ getpeerbydesc(const char *descr) +@@ -2531,6 +2888,40 @@ session_dispatch_imsg(struct imsgbuf *ib + break; + } + break; ++ case IMSG_SESSION_RESTARTED: ++ if (idx != PFD_PIPE_ROUTE) ++ fatalx("update request not from RDE"); ++ if (imsg.hdr.len < IMSG_HEADER_SIZE + sizeof(aid)) { ++ log_warnx("RDE sent invalid restart msg"); ++ break; ++ } ++ if ((p = getpeerbyid(imsg.hdr.peerid)) == NULL) { ++ log_warnx("no such peer: id=%u", ++ imsg.hdr.peerid); ++ break; ++ } ++ memcpy(&aid, imsg.data, sizeof(aid)); ++ if (aid >= AID_MAX) ++ fatalx("IMSG_SESSION_RESTARTED: bad AID"); ++ if (p->capa.neg.grestart.flags[aid] & ++ CAPA_GR_RESTARTING && ++ p->capa.neg.grestart.flags[aid] & ++ CAPA_GR_FORWARD) { ++ log_peer_warnx(&p->conf, ++ "graceful restart of %s finished", ++ aid2str(aid)); ++ p->capa.neg.grestart.flags[aid] &= ++ ~CAPA_GR_RESTARTING; ++ timer_stop(p, Timer_RestartTimeout); ++ ++ /* signal back to RDE to cleanup stale routes */ ++ if (imsg_compose(ibuf_rde, ++ IMSG_SESSION_RESTARTED, imsg.hdr.peerid, 0, ++ -1, &aid, sizeof(aid)) == -1) ++ fatal("imsg_compose: " ++ "IMSG_SESSION_RESTARTED"); ++ } ++ break; + default: + break; + } +@@ -2612,29 +3003,23 @@ getpeerbydesc(const char *descr) struct peer * getpeerbyip(struct sockaddr *ip) { @@ -1146,7 +1828,7 @@ diff -u -p -r1.1.1.8 -r1.9 if (loose == NULL || loose->conf.remote_masklen < p->conf.remote_masklen) loose = p; -@@ -2653,21 +2718,19 @@ getpeerbyip(struct sockaddr *ip) +@@ -2653,21 +3038,19 @@ getpeerbyip(struct sockaddr *ip) break; } } @@ -1175,7 +1857,7 @@ diff -u -p -r1.1.1.8 -r1.9 newpeer->rbuf = NULL; init_peer(newpeer); bgp_fsm(newpeer, EVNT_START); -@@ -2680,40 +2743,24 @@ getpeerbyip(struct sockaddr *ip) +@@ -2680,40 +3063,24 @@ getpeerbyip(struct sockaddr *ip) } int @@ -1227,7 +1909,7 @@ diff -u -p -r1.1.1.8 -r1.9 return (0); } -@@ -2733,6 +2780,7 @@ getpeerbyid(u_int32_t peerid) +@@ -2733,6 +3100,7 @@ getpeerbyid(u_int32_t peerid) void session_down(struct peer *peer) { @@ -1235,9 +1917,17 @@ diff -u -p -r1.1.1.8 -r1.9 peer->stats.last_updown = time(NULL); if (imsg_compose(ibuf_rde, IMSG_SESSION_DOWN, peer->conf.id, 0, -1, NULL, 0) == -1) -@@ -2748,35 +2796,12 @@ session_up(struct peer *p) - &p->conf, sizeof(p->conf)) == -1) - fatalx("imsg_compose error"); +@@ -2744,39 +3112,17 @@ session_up(struct peer *p) + { + struct session_up sup; + +- if (imsg_compose(ibuf_rde, IMSG_SESSION_ADD, p->conf.id, 0, -1, +- &p->conf, sizeof(p->conf)) == -1) +- fatalx("imsg_compose error"); ++ if (!session_graceful_is_restarting(p)) ++ if (imsg_compose(ibuf_rde, IMSG_SESSION_ADD, p->conf.id, 0, -1, ++ &p->conf, sizeof(p->conf)) == -1) ++ fatalx("imsg_compose error"); - switch (p->sa_local.ss_family) { - case AF_INET: @@ -1274,7 +1964,7 @@ diff -u -p -r1.1.1.8 -r1.9 p->stats.last_updown = time(NULL); if (imsg_compose(ibuf_rde, IMSG_SESSION_UP, p->conf.id, 0, -1, &sup, sizeof(sup)) == -1) -@@ -2784,9 +2809,10 @@ session_up(struct peer *p) +@@ -2784,9 +3130,10 @@ session_up(struct peer *p) } int @@ -1287,7 +1977,7 @@ diff -u -p -r1.1.1.8 -r1.9 } int -@@ -2795,34 +2821,6 @@ imsg_compose_rde(int type, pid_t pid, vo +@@ -2795,34 +3142,6 @@ imsg_compose_rde(int type, pid_t pid, vo return (imsg_compose(ibuf_rde, type, 0, pid, -1, data, datalen)); } @@ -1322,7 +2012,7 @@ diff -u -p -r1.1.1.8 -r1.9 void session_demote(struct peer *p, int level) { -@@ -2837,3 +2835,19 @@ session_demote(struct peer *p, int level +@@ -2837,3 +3156,19 @@ session_demote(struct peer *p, int level p->demoted += level; } diff --git a/net/openbgpd/files/patch-bgpd_session.h b/net/openbgpd/files/patch-bgpd_session.h index 4eb8dbce5f6b..6ffbd79abd1f 100644 --- a/net/openbgpd/files/patch-bgpd_session.h +++ b/net/openbgpd/files/patch-bgpd_session.h @@ -2,13 +2,13 @@ Index: bgpd/session.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/session.h,v retrieving revision 1.1.1.7 -retrieving revision 1.1.1.9 -diff -u -p -r1.1.1.7 -r1.1.1.9 +retrieving revision 1.1.1.10 +diff -u -p -r1.1.1.7 -r1.1.1.10 --- bgpd/session.h 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/session.h 12 Jun 2011 10:44:25 -0000 1.1.1.9 ++++ bgpd/session.h 13 Oct 2012 18:22:50 -0000 1.1.1.10 @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.101 2009/06/05 20:26:38 claudio Exp $ */ -+/* $OpenBSD: session.h,v 1.111 2010/12/09 13:50:41 claudio Exp $ */ ++/* $OpenBSD: session.h,v 1.113 2012/04/12 17:26:09 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -35,7 +35,26 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 enum msg_type type; u_int16_t len; }; -@@ -189,6 +196,7 @@ struct peer { +@@ -155,8 +162,10 @@ struct peer_stats { + u_int64_t msg_sent_rrefresh; + u_int64_t prefix_rcvd_update; + u_int64_t prefix_rcvd_withdraw; ++ u_int64_t prefix_rcvd_eor; + u_int64_t prefix_sent_update; + u_int64_t prefix_sent_withdraw; ++ u_int64_t prefix_sent_eor; + time_t last_updown; + time_t last_read; + u_int32_t prefix_cnt; +@@ -172,6 +181,7 @@ enum Timer { + Timer_IdleHold, + Timer_IdleHoldReset, + Timer_CarpUndemote, ++ Timer_RestartTimeout, + Timer_Max + }; + +@@ -189,6 +199,7 @@ struct peer { struct { struct capabilities ann; struct capabilities peer; @@ -43,7 +62,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 } capa; struct { struct bgpd_addr local_addr; -@@ -201,7 +209,7 @@ struct peer { +@@ -201,7 +212,7 @@ struct peer { struct sockaddr_storage sa_remote; struct peer_timer_head timers; struct msgbuf wbuf; @@ -52,76 +71,118 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 struct peer *next; int fd; int lasterr; -@@ -217,7 +225,7 @@ struct peer { +@@ -217,47 +228,25 @@ struct peer { u_int8_t passive; }; -struct peer *peers; +extern struct peer *peers; ++extern time_t pauseaccept; struct ctl_timer { enum Timer type; -@@ -226,38 +234,36 @@ struct ctl_timer { + time_t val; + }; - /* session.c */ - void session_socket_blockmode(int, enum blockmodes); +-/* session.c */ +-void session_socket_blockmode(int, enum blockmodes); -pid_t session_main(struct bgpd_config *, struct peer *, - struct network_head *, struct filter_head *, - struct mrt_head *, struct rib_names *, - int[2], int[2], int[2], int[2]); -+pid_t session_main(int[2], int[2], int[2], int[2]); - void bgp_fsm(struct peer *, enum session_events); - int session_neighbor_rrefresh(struct peer *p); - struct peer *getpeerbyaddr(struct bgpd_addr *); - struct peer *getpeerbydesc(const char *); +-void bgp_fsm(struct peer *, enum session_events); +-int session_neighbor_rrefresh(struct peer *p); +-struct peer *getpeerbyaddr(struct bgpd_addr *); +-struct peer *getpeerbydesc(const char *); -int imsg_compose_parent(int, pid_t, void *, u_int16_t); -+int imsg_compose_parent(int, u_int32_t, pid_t, void *, u_int16_t); - int imsg_compose_rde(int, pid_t, void *, u_int16_t); -+void session_stop(struct peer *, u_int8_t); - - /* log.c */ - char *log_fmt_peer(const struct peer_config *); - void log_statechange(struct peer *, enum session_state, - enum session_events); - void log_notification(const struct peer *, u_int8_t, u_int8_t, +-int imsg_compose_rde(int, pid_t, void *, u_int16_t); +- +-/* log.c */ +-char *log_fmt_peer(const struct peer_config *); +-void log_statechange(struct peer *, enum session_state, +- enum session_events); +-void log_notification(const struct peer *, u_int8_t, u_int8_t, - u_char *, u_int16_t); -+ u_char *, u_int16_t, const char *); - void log_conn_attempt(const struct peer *, struct sockaddr *); - - /* parse.y */ - int parse_config(char *, struct bgpd_config *, struct mrt_head *, +-void log_conn_attempt(const struct peer *, struct sockaddr *); +- +-/* parse.y */ +-int parse_config(char *, struct bgpd_config *, struct mrt_head *, - struct peer **, struct network_head *, struct filter_head *); -+ struct peer **, struct network_head *, struct filter_head *, -+ struct rdomain_head *); ++/* carp.c */ ++int carp_demote_init(char *, int); ++void carp_demote_shutdown(void); ++int carp_demote_get(char *); ++int carp_demote_set(char *, int); /* config.c */ int merge_config(struct bgpd_config *, struct bgpd_config *, struct peer *, struct listen_addrs *); void prepare_listeners(struct bgpd_config *); -+int get_mpe_label(struct rdomain *); - - /* rde.c */ +- +-/* rde.c */ -pid_t rde_main(struct bgpd_config *, struct peer *, struct network_head *, - struct filter_head *, struct mrt_head *, struct rib_names *, - int[2], int[2], int[2], int[2], int); -+pid_t rde_main(int[2], int[2], int[2], int[2], int); ++int get_mpe_label(struct rdomain *); /* control.c */ int control_init(int, char *); -@@ -267,6 +273,7 @@ int control_dispatch_msg(struct pollfd * +@@ -266,7 +255,27 @@ void control_shutdown(int); + int control_dispatch_msg(struct pollfd *, u_int *); unsigned int control_accept(int, int); ++/* log.c */ ++char *log_fmt_peer(const struct peer_config *); ++void log_statechange(struct peer *, enum session_state, ++ enum session_events); ++void log_notification(const struct peer *, u_int8_t, u_int8_t, ++ u_char *, u_int16_t, const char *); ++void log_conn_attempt(const struct peer *, struct sockaddr *); ++ ++/* mrt.c */ ++void mrt_dump_bgp_msg(struct mrt *, void *, u_int16_t, ++ struct peer *); ++void mrt_dump_state(struct mrt *, u_int16_t, u_int16_t, ++ struct peer *); ++ ++/* parse.y */ ++int parse_config(char *, struct bgpd_config *, struct mrt_head *, ++ struct peer **, struct network_head *, struct filter_head *, ++ struct rdomain_head *); ++ /* pfkey.c */ +int pfkey_read(int, struct sadb_msg *); int pfkey_establish(struct peer *); int pfkey_remove(struct peer *); int pfkey_init(struct bgpd_sysdep *); -@@ -274,7 +281,7 @@ int pfkey_init(struct bgpd_sysdep *); +@@ -274,15 +283,24 @@ int pfkey_init(struct bgpd_sysdep *); /* printconf.c */ void print_config(struct bgpd_config *, struct rib_names *, struct network_head *, struct peer *, struct filter_head *, - struct mrt_head *); + struct mrt_head *, struct rdomain_head *); - /* carp.c */ - int carp_demote_init(char *, int); +-/* carp.c */ +-int carp_demote_init(char *, int); +-void carp_demote_shutdown(void); +-int carp_demote_get(char *); +-int carp_demote_set(char *, int); ++/* rde.c */ ++pid_t rde_main(int[2], int[2], int[2], int[2], int); ++ ++/* session.c */ ++void session_socket_blockmode(int, enum blockmodes); ++pid_t session_main(int[2], int[2], int[2], int[2]); ++void bgp_fsm(struct peer *, enum session_events); ++int session_neighbor_rrefresh(struct peer *p); ++struct peer *getpeerbyaddr(struct bgpd_addr *); ++struct peer *getpeerbydesc(const char *); ++int imsg_compose_parent(int, u_int32_t, pid_t, void *, u_int16_t); ++int imsg_compose_rde(int, pid_t, void *, u_int16_t); ++void session_stop(struct peer *, u_int8_t); + + /* timer.c */ ++time_t getmonotime(void); + struct peer_timer *timer_get(struct peer *, enum Timer); + struct peer_timer *timer_nextisdue(struct peer *); + time_t timer_nextduein(struct peer *); diff --git a/net/openbgpd/files/patch-bgpd_timer.c b/net/openbgpd/files/patch-bgpd_timer.c index 1bace94e1998..1238897b94fa 100644 --- a/net/openbgpd/files/patch-bgpd_timer.c +++ b/net/openbgpd/files/patch-bgpd_timer.c @@ -2,17 +2,26 @@ Index: bgpd/timer.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/timer.c,v retrieving revision 1.1.1.2 -retrieving revision 1.1.1.3 -diff -u -p -r1.1.1.2 -r1.1.1.3 +retrieving revision 1.1.1.4 +diff -u -p -r1.1.1.2 -r1.1.1.4 --- bgpd/timer.c 9 Jul 2009 16:49:54 -0000 1.1.1.2 -+++ bgpd/timer.c 12 Jun 2011 10:44:25 -0000 1.1.1.3 ++++ bgpd/timer.c 13 Oct 2012 18:22:50 -0000 1.1.1.4 @@ -1,4 +1,4 @@ -/* $OpenBSD: timer.c,v 1.13 2009/01/21 20:32:53 henning Exp $ */ +/* $OpenBSD: timer.c,v 1.14 2010/10/24 17:20:08 deraadt Exp $ */ /* * Copyright (c) 2003-2007 Henning Brauer <henning@openbsd.org> -@@ -43,7 +43,7 @@ timer_get(struct peer *p, enum Timer tim +@@ -23,8 +23,6 @@ + #include "bgpd.h" + #include "session.h" + +-time_t getmonotime(void); +- + time_t + getmonotime(void) + { +@@ -43,7 +41,7 @@ timer_get(struct peer *p, enum Timer tim TAILQ_FOREACH(pt, &p->timers, entry) if (pt->type == timer) diff --git a/net/openbgpd/files/patch-bgpd_util.c b/net/openbgpd/files/patch-bgpd_util.c index 213c90a2276e..54e74ec9805f 100644 --- a/net/openbgpd/files/patch-bgpd_util.c +++ b/net/openbgpd/files/patch-bgpd_util.c @@ -2,10 +2,10 @@ Index: bgpd/util.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/util.c,v retrieving revision 1.1.1.6 -retrieving revision 1.6 -diff -u -p -r1.1.1.6 -r1.6 +retrieving revision 1.7 +diff -u -p -r1.1.1.6 -r1.7 --- bgpd/util.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/util.c 2 Jul 2011 16:06:38 -0000 1.6 ++++ bgpd/util.c 13 Oct 2012 18:36:00 -0000 1.7 @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.6 2009/06/12 16:42:53 claudio Exp $ */ +/* $OpenBSD: util.c,v 1.11 2010/03/29 09:04:43 claudio Exp $ */ @@ -43,14 +43,14 @@ diff -u -p -r1.1.1.6 -r1.6 + if (inet_ntop(aid2af(addr->aid), &addr->ba, buf, + sizeof(buf)) == NULL) + return ("?"); -+ return (buf); + return (buf); + case AID_VPN_IPv4: + if (inet_ntop(AF_INET, &addr->vpn4.addr, tbuf, + sizeof(tbuf)) == NULL) + return ("?"); + snprintf(buf, sizeof(buf), "%s %s", log_rd(addr->vpn4.rd), + tbuf); - return (buf); ++ return (buf); + } + return ("???"); } @@ -187,7 +187,142 @@ diff -u -p -r1.1.1.6 -r1.6 } /* ensure that we have a valid C-string especially for empty as path */ if (size > 0) -@@ -276,3 +376,115 @@ inet6applymask(struct in6_addr *dest, co +@@ -235,6 +335,67 @@ aspath_strlen(void *data, u_int16_t len) + return (total_size); + } + ++/* we need to be able to search more than one as */ ++int ++aspath_match(void *data, u_int16_t len, enum as_spec type, u_int32_t as) ++{ ++ u_int8_t *seg; ++ int final; ++ u_int16_t seg_size; ++ u_int8_t i, seg_type, seg_len; ++ ++ if (type == AS_EMPTY) { ++ if (len == 0) ++ return (1); ++ else ++ return (0); ++ } ++ ++ final = 0; ++ seg = data; ++ for (; len > 0; len -= seg_size, seg += seg_size) { ++ seg_type = seg[0]; ++ seg_len = seg[1]; ++ seg_size = 2 + sizeof(u_int32_t) * seg_len; ++ ++ final = (len == seg_size); ++ ++ /* just check the first (leftmost) AS */ ++ if (type == AS_PEER) { ++ if (as == aspath_extract(seg, 0)) ++ return (1); ++ else ++ return (0); ++ } ++ /* just check the final (rightmost) AS */ ++ if (type == AS_SOURCE) { ++ /* not yet in the final segment */ ++ if (!final) ++ continue; ++ ++ if (as == aspath_extract(seg, seg_len - 1)) ++ return (1); ++ else ++ return (0); ++ } ++ ++ /* AS_TRANSIT or AS_ALL */ ++ for (i = 0; i < seg_len; i++) { ++ if (as == aspath_extract(seg, i)) { ++ /* ++ * the source (rightmost) AS is excluded from ++ * AS_TRANSIT matches. ++ */ ++ if (final && i == seg_len - 1 && ++ type == AS_TRANSIT) ++ return (0); ++ return (1); ++ } ++ } ++ } ++ return (0); ++} ++ + /* + * Extract the asnum out of the as segment at the specified position. + * Direct access is not possible because of non-aligned reads. +@@ -251,6 +412,66 @@ aspath_extract(const void *seg, int pos) + return (ntohl(as)); + } + ++int ++prefix_compare(const struct bgpd_addr *a, const struct bgpd_addr *b, ++ int prefixlen) ++{ ++ in_addr_t mask, aa, ba; ++ int i; ++ u_int8_t m; ++ ++ if (a->aid != b->aid) ++ return (a->aid - b->aid); ++ ++ switch (a->aid) { ++ case AID_INET: ++ if (prefixlen > 32) ++ fatalx("prefix_cmp: bad IPv4 prefixlen"); ++ mask = htonl(prefixlen2mask(prefixlen)); ++ aa = ntohl(a->v4.s_addr & mask); ++ ba = ntohl(b->v4.s_addr & mask); ++ if (aa != ba) ++ return (aa - ba); ++ return (0); ++ case AID_INET6: ++ if (prefixlen > 128) ++ fatalx("prefix_cmp: bad IPv6 prefixlen"); ++ for (i = 0; i < prefixlen / 8; i++) ++ if (a->v6.s6_addr[i] != b->v6.s6_addr[i]) ++ return (a->v6.s6_addr[i] - b->v6.s6_addr[i]); ++ i = prefixlen % 8; ++ if (i) { ++ m = 0xff00 >> i; ++ if ((a->v6.s6_addr[prefixlen / 8] & m) != ++ (b->v6.s6_addr[prefixlen / 8] & m)) ++ return ((a->v6.s6_addr[prefixlen / 8] & m) - ++ (b->v6.s6_addr[prefixlen / 8] & m)); ++ } ++ return (0); ++ case AID_VPN_IPv4: ++ if (prefixlen > 32) ++ fatalx("prefix_cmp: bad IPv4 VPN prefixlen"); ++ if (betoh64(a->vpn4.rd) > betoh64(b->vpn4.rd)) ++ return (1); ++ if (betoh64(a->vpn4.rd) < betoh64(b->vpn4.rd)) ++ return (-1); ++ mask = htonl(prefixlen2mask(prefixlen)); ++ aa = ntohl(a->vpn4.addr.s_addr & mask); ++ ba = ntohl(b->vpn4.addr.s_addr & mask); ++ if (aa != ba) ++ return (aa - ba); ++ if (a->vpn4.labellen > b->vpn4.labellen) ++ return (1); ++ if (a->vpn4.labellen < b->vpn4.labellen) ++ return (-1); ++ return (memcmp(a->vpn4.labelstack, b->vpn4.labelstack, ++ a->vpn4.labellen)); ++ default: ++ fatalx("prefix_cmp: unknown af"); ++ } ++ return (-1); ++} ++ + in_addr_t + prefixlen2mask(u_int8_t prefixlen) + { +@@ -276,3 +497,115 @@ inet6applymask(struct in6_addr *dest, co for (i = 0; i < 16; i++) dest->s6_addr[i] = src->s6_addr[i] & mask.s6_addr[i]; } diff --git a/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h b/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h index 312906fefe60..3855a8dd3f95 100644 --- a/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h +++ b/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h @@ -3,10 +3,10 @@ Index: openbsd-compat/openbsd-compat.h RCS file: openbsd-compat/openbsd-compat.h diff -N openbsd-compat/openbsd-compat.h --- /dev/null 1 Jan 1970 00:00:00 -0000 -+++ openbsd-compat/openbsd-compat.h 3 Jul 2011 04:46:38 -0000 1.6 -@@ -0,0 +1,87 @@ ++++ openbsd-compat/openbsd-compat.h 13 Oct 2012 18:50:10 -0000 1.8 +@@ -0,0 +1,91 @@ +/* -+ * $hrs: openbgpd/openbsd-compat/openbsd-compat.h,v 1.6 2011/07/03 04:46:38 hrs Exp $ ++ * $hrs: openbgpd/openbsd-compat/openbsd-compat.h,v 1.8 2012/10/13 18:50:10 hrs Exp $ + */ + +#ifndef _OPENBSD_COMPAT_H @@ -16,7 +16,11 @@ diff -N openbsd-compat/openbsd-compat.h + +/* bgpctl/bgpctl.c */ +#include <sys/endian.h> ++#include <inttypes.h> +#define betoh64(x) (be64toh(x)) ++#ifndef IFT_CARP ++#define IFT_CARP 0xf8 ++#endif + +/* bgpd/irrfilter.c */ +typedef unsigned long ulong; |