diff options
Diffstat (limited to 'net')
41 files changed, 8906 insertions, 967 deletions
diff --git a/net/openbgpd/Makefile b/net/openbgpd/Makefile index 21feb49d6059..e97c0e3ae698 100644 --- a/net/openbgpd/Makefile +++ b/net/openbgpd/Makefile @@ -6,7 +6,7 @@ # PORTNAME= openbgpd -PORTVERSION= 4.7.20100410 +PORTVERSION= 4.9.20110612 CATEGORIES= net MASTER_SITES= ${MASTER_SITE_OPENBSD} MASTER_SITE_SUBDIR= OpenBGPD @@ -33,6 +33,8 @@ MANCOMPRESSED= yes USE_RC_SUBR= ${PORTNAME}.sh PLIST_FILES= sbin/bgpctl sbin/bgpd SUB_FILES= pkg-message +USERS= _bgpd +GROUPS= _bgpd MAN5= bgpd.conf.5 MAN8= bgpctl.8 bgpd.8 @@ -48,7 +50,6 @@ post-patch: ${WRKSRC}/bgpctl/bgpctl.8 post-install: - @${SH} ${PKGINSTALL} ${PKGNAME} POST-INSTALL @${CAT} ${PKGMESSAGE} .include <bsd.port.post.mk> diff --git a/net/openbgpd/files/patch-bgpctl_Makefile b/net/openbgpd/files/patch-bgpctl_Makefile index f39d97bcf14e..faca1083ecf9 100644 --- a/net/openbgpd/files/patch-bgpctl_Makefile +++ b/net/openbgpd/files/patch-bgpctl_Makefile @@ -2,10 +2,10 @@ Index: bgpctl/Makefile =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/Makefile,v retrieving revision 1.1.1.1 -retrieving revision 1.2 -diff -u -p -r1.1.1.1 -r1.2 +retrieving revision 1.3 +diff -u -p -r1.1.1.1 -r1.3 --- bgpctl/Makefile 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpctl/Makefile 30 Jun 2009 06:40:05 -0000 1.2 ++++ bgpctl/Makefile 2 Jul 2011 16:06:35 -0000 1.3 @@ -1,17 +1,18 @@ # $OpenBSD: Makefile,v 1.10 2007/12/20 17:08:48 henning Exp $ @@ -13,10 +13,11 @@ diff -u -p -r1.1.1.1 -r1.2 +.PATH: ${.CURDIR}/../bgpd ${.CURDIR}/../openbsd-compat PROG= bgpctl - SRCS= bgpctl.c parser.c buffer.c imsg.c util.c timer.c +-SRCS= bgpctl.c parser.c buffer.c imsg.c util.c timer.c ++SRCS= bgpctl.c parser.c util.c timer.c SRCS+= irrfilter.c whois.c irr_asset.c irr_prefix.c irr_output.c SRCS+= irr_parser.c -+SRCS+= fmt_scaled.c ++SRCS+= fmt_scaled.c imsg.c imsg-buffer.c CFLAGS+= -Wall CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes CFLAGS+= -Wmissing-declarations diff --git a/net/openbgpd/files/patch-bgpctl_bgpctl.8 b/net/openbgpd/files/patch-bgpctl_bgpctl.8 index 33875d1056c2..a5305b3061b1 100644 --- a/net/openbgpd/files/patch-bgpctl_bgpctl.8 +++ b/net/openbgpd/files/patch-bgpctl_bgpctl.8 @@ -2,10 +2,10 @@ Index: bgpctl/bgpctl.8 =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/bgpctl.8,v retrieving revision 1.1.1.6 -retrieving revision 1.4 -diff -u -p -r1.1.1.6 -r1.4 +retrieving revision 1.5 +diff -u -p -r1.1.1.6 -r1.5 --- bgpctl/bgpctl.8 14 Feb 2010 20:20:13 -0000 1.1.1.6 -+++ bgpctl/bgpctl.8 4 Feb 2010 16:22:26 -0000 1.4 ++++ bgpctl/bgpctl.8 2 Jul 2011 16:06:35 -0000 1.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bgpctl.8,v 1.49 2009/06/06 06:11:17 claudio Exp $ +.\" $OpenBSD: bgpctl.8,v 1.52 2009/11/03 08:09:15 jmc Exp $ @@ -17,11 +17,45 @@ diff -u -p -r1.1.1.6 -r1.4 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: June 6 2009 $ -+.Dd $Mdocdate: November 2 2009 $ ++.Dd $Mdocdate: May 3 2010 $ .Dt BGPCTL 8 .Os .Sh NAME -@@ -79,7 +79,15 @@ The options are as follows: +@@ -32,8 +32,7 @@ The + program controls the + .Xr bgpd 8 + daemon. +-Commands to switch between displays may be abbreviated to the +-minimum unambiguous prefix; for example, ++Commands may be abbreviated to the minimum unambiguous prefix; for example, + .Cm s s + for + .Cm show summary . +@@ -53,11 +52,19 @@ to communicate with + .Pp + The commands are as follows: + .Bl -tag -width xxxxxx +-.It Cm fib couple +-Insert the learned routes into the Forwarding Information Base ++.It Xo ++.Cm fib ++.Op Cm table Ar number ++.Cm couple ++.Xc ++Insert the learned routes into the specified Forwarding Information Base + a.k.a. the kernel routing table. +-.It Cm fib decouple +-Remove the learned routes from the Forwarding Information Base ++.It Xo ++.Cm fib ++.Op Cm table Ar number ++.Cm decouple ++.Xc ++Remove the learned routes from the specified Forwarding Information Base + a.k.a. the kernel routing table. + .It Xo + .Cm irrfilter +@@ -79,7 +86,15 @@ The options are as follows: Use .Ar directory to write the filter files to. @@ -37,7 +71,48 @@ diff -u -p -r1.1.1.6 -r1.4 .It Cm neighbor Ar peer Cm up Take the BGP session to the specified neighbor up. .Ar peer -@@ -246,7 +254,7 @@ in a terse format. +@@ -98,8 +113,10 @@ Note that the neighbor is not obliged to + all, even if it announced the route refresh capability. + .Ar peer + may be the neighbor's address or description. +-.It Cm network add Ar prefix ++.It Cm network add Ar prefix Op Ar arguments + Add the specified prefix to the list of announced networks. ++It is possible to set various path attributes with additional ++.Ar arguments . + .It Cm network delete Ar prefix + Remove the specified prefix from the list of announced networks. + .It Cm network flush +@@ -122,7 +139,7 @@ view of the Forwarding Information Base. + can be an IP address, in which case the route to this address is shown, + or a flag: + .Pp +-.Bl -tag -width connected -compact ++.Bl -tag -width tableXnumber -compact + .It Cm connected + Show only connected routes. + .It Cm static +@@ -133,6 +150,14 @@ Show only routes originating from + itself. + .It Cm nexthop + Show only routes required to reach a BGP nexthop. ++.It Cm inet ++Show only IPv4 routes. ++.It Cm inet6 ++Show only IPv6 routes. ++.It Cm table Ar number ++Show the routing table with ID ++.Ar number ++instead of the default routing table with ID 0. + .El + .It Cm show interfaces + Show the interface states. +@@ -243,10 +268,12 @@ and message counters. + .It Cm show summary terse + Show a list of all neighbors, including information about the session state, + in a terse format. ++.It Cm show tables ++Show a list of all currently loaded fib routing tables. .El .Sh FILES .Bl -tag -width "/var/run/bgpd.sockXXX" -compact diff --git a/net/openbgpd/files/patch-bgpctl_bgpctl.c b/net/openbgpd/files/patch-bgpctl_bgpctl.c index a55bb3e66674..4497b055410f 100644 --- a/net/openbgpd/files/patch-bgpctl_bgpctl.c +++ b/net/openbgpd/files/patch-bgpctl_bgpctl.c @@ -2,10 +2,10 @@ Index: bgpctl/bgpctl.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/bgpctl.c,v retrieving revision 1.1.1.7 -retrieving revision 1.7 -diff -u -p -r1.1.1.7 -r1.7 +retrieving revision 1.8 +diff -u -p -r1.1.1.7 -r1.8 --- bgpctl/bgpctl.c 14 Feb 2010 20:20:14 -0000 1.1.1.7 -+++ bgpctl/bgpctl.c 10 Apr 2010 12:17:18 -0000 1.7 ++++ bgpctl/bgpctl.c 2 Jul 2011 16:06:35 -0000 1.8 @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpctl.c,v 1.142 2009/06/06 06:33:15 eric Exp $ */ +/* $OpenBSD: bgpctl.c,v 1.157 2010/03/08 17:02:19 claudio Exp $ */ @@ -55,7 +55,7 @@ diff -u -p -r1.1.1.7 -r1.7 enum neighbor_views { NV_DEFAULT, NV_TIMERS -@@ -50,7 +66,7 @@ int show_summary_msg(struct imsg *, in +@@ -50,12 +66,13 @@ int show_summary_msg(struct imsg *, in int show_summary_terse_msg(struct imsg *, int); int show_neighbor_terse(struct imsg *); int show_neighbor_msg(struct imsg *, enum neighbor_views); @@ -64,7 +64,13 @@ diff -u -p -r1.1.1.7 -r1.7 void print_neighbor_msgstats(struct peer *); void print_timer(const char *, time_t); static char *fmt_timeframe(time_t t); -@@ -65,7 +81,7 @@ void show_interface_head(void); + static char *fmt_timeframe_core(time_t t); + void show_fib_head(void); ++void show_fib_tables_head(void); + void show_network_head(void); + void show_fib_flags(u_int16_t); + int show_fib_msg(struct imsg *); +@@ -65,7 +82,7 @@ void show_interface_head(void); int ift2ifm(int); const char * get_media_descr(int); const char * get_linkstate(int, int); @@ -73,7 +79,7 @@ diff -u -p -r1.1.1.7 -r1.7 int show_interface_msg(struct imsg *); void show_rib_summary_head(void); void print_prefix(struct bgpd_addr *, u_int8_t, u_int8_t); -@@ -74,7 +90,6 @@ void print_flags(u_int8_t, int); +@@ -74,7 +91,6 @@ void print_flags(u_int8_t, int); int show_rib_summary_msg(struct imsg *); int show_rib_detail_msg(struct imsg *, int); void show_community(u_char *, u_int16_t); @@ -81,7 +87,7 @@ diff -u -p -r1.1.1.7 -r1.7 void show_ext_community(u_char *, u_int16_t); char *fmt_mem(int64_t); int show_rib_memory_msg(struct imsg *); -@@ -98,7 +113,7 @@ int +@@ -98,7 +114,7 @@ int main(int argc, char *argv[]) { struct sockaddr_un sun; @@ -90,7 +96,7 @@ diff -u -p -r1.1.1.7 -r1.7 struct imsg imsg; struct network_config net; struct parse_result *res; -@@ -128,8 +143,11 @@ main(int argc, char *argv[]) +@@ -128,8 +144,11 @@ main(int argc, char *argv[]) if ((res = parse(argc, argv)) == NULL) exit(1); @@ -103,19 +109,23 @@ diff -u -p -r1.1.1.7 -r1.7 memcpy(&neighbor.addr, &res->peeraddr, sizeof(neighbor.addr)); strlcpy(neighbor.descr, res->peerdesc, sizeof(neighbor.descr)); -@@ -164,15 +182,17 @@ main(int argc, char *argv[]) +@@ -164,24 +183,32 @@ main(int argc, char *argv[]) imsg_compose(ibuf, IMSG_CTL_SHOW_TERSE, 0, 0, -1, NULL, 0); break; case SHOW_FIB: - if (!res->addr.af) { +- struct buf *msg; +- +- if ((msg = imsg_create(ibuf, IMSG_CTL_KROUTE, 0, 0, +- sizeof(res->flags) + sizeof(res->af))) == NULL) + if (!res->addr.aid) { - struct buf *msg; ++ struct ibuf *msg; + sa_family_t af; - ++ + af = aid2af(res->aid); - if ((msg = imsg_create(ibuf, IMSG_CTL_KROUTE, 0, 0, -- sizeof(res->flags) + sizeof(res->af))) == NULL) -+ sizeof(res->flags) + sizeof(af))) == NULL) ++ if ((msg = imsg_create(ibuf, IMSG_CTL_KROUTE, ++ res->rtableid, 0, sizeof(res->flags) + ++ sizeof(af))) == NULL) errx(1, "imsg_create failure"); if (imsg_add(msg, &res->flags, sizeof(res->flags)) == -1 || @@ -124,7 +134,24 @@ diff -u -p -r1.1.1.7 -r1.7 errx(1, "imsg_add failure"); imsg_close(ibuf, msg); } else -@@ -192,7 +212,7 @@ main(int argc, char *argv[]) +- imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1, +- &res->addr, sizeof(res->addr)); ++ imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, res->rtableid, ++ 0, -1, &res->addr, sizeof(res->addr)); + show_fib_head(); + break; ++ case SHOW_FIB_TABLES: ++ imsg_compose(ibuf, IMSG_CTL_SHOW_FIB_TABLES, 0, 0, -1, NULL, 0); ++ show_fib_tables_head(); ++ break; + case SHOW_NEXTHOP: +- imsg_compose(ibuf, IMSG_CTL_SHOW_NEXTHOP, 0, 0, -1, NULL, 0); ++ imsg_compose(ibuf, IMSG_CTL_SHOW_NEXTHOP, res->rtableid, 0, -1, ++ NULL, 0); + show_nexthop_head(); + break; + case SHOW_INTERFACE: +@@ -192,7 +219,7 @@ main(int argc, char *argv[]) case SHOW_NEIGHBOR_TIMERS: case SHOW_NEIGHBOR_TERSE: neighbor.show_timers = (res->action == SHOW_NEIGHBOR_TIMERS); @@ -133,7 +160,7 @@ diff -u -p -r1.1.1.7 -r1.7 imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1, &neighbor, sizeof(neighbor)); else -@@ -206,7 +226,7 @@ main(int argc, char *argv[]) +@@ -206,7 +233,7 @@ main(int argc, char *argv[]) memcpy(&ribreq.as, &res->as, sizeof(res->as)); type = IMSG_CTL_SHOW_RIB_AS; } @@ -142,7 +169,7 @@ diff -u -p -r1.1.1.7 -r1.7 memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr)); ribreq.prefixlen = res->prefixlen; type = IMSG_CTL_SHOW_RIB_PREFIX; -@@ -220,7 +240,7 @@ main(int argc, char *argv[]) +@@ -220,7 +247,7 @@ main(int argc, char *argv[]) memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor)); strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib)); @@ -151,7 +178,24 @@ diff -u -p -r1.1.1.7 -r1.7 ribreq.flags = res->flags; imsg_compose(ibuf, type, 0, 0, -1, &ribreq, sizeof(ribreq)); if (!(res->flags & F_CTL_DETAIL)) -@@ -290,12 +310,21 @@ main(int argc, char *argv[]) +@@ -237,12 +264,14 @@ main(int argc, char *argv[]) + errx(1, "action==FIB"); + break; + case FIB_COUPLE: +- imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0); ++ imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, res->rtableid, 0, -1, ++ NULL, 0); + printf("couple request sent.\n"); + done = 1; + break; + case FIB_DECOUPLE: +- imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0); ++ imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, res->rtableid, 0, -1, ++ NULL, 0); + printf("decouple request sent.\n"); + done = 1; + break; +@@ -290,12 +319,21 @@ main(int argc, char *argv[]) break; case NETWORK_SHOW: bzero(&ribreq, sizeof(ribreq)); @@ -174,7 +218,7 @@ diff -u -p -r1.1.1.7 -r1.7 } while (ibuf->w.queued) -@@ -304,13 +333,13 @@ main(int argc, char *argv[]) +@@ -304,13 +342,13 @@ main(int argc, char *argv[]) while (!done) { if ((n = imsg_read(ibuf)) == -1) @@ -190,7 +234,26 @@ diff -u -p -r1.1.1.7 -r1.7 if (n == 0) break; -@@ -373,6 +402,8 @@ main(int argc, char *argv[]) +@@ -329,6 +367,8 @@ main(int argc, char *argv[]) + done = show_summary_terse_msg(&imsg, nodescr); + break; + case SHOW_FIB: ++ case SHOW_FIB_TABLES: ++ case NETWORK_SHOW: + done = show_fib_msg(&imsg); + break; + case SHOW_NEXTHOP: +@@ -356,9 +396,6 @@ main(int argc, char *argv[]) + case SHOW_RIB_MEM: + done = show_rib_memory_msg(&imsg); + break; +- case NETWORK_SHOW: +- done = show_fib_msg(&imsg); +- break; + case NEIGHBOR: + case NEIGHBOR_UP: + case NEIGHBOR_DOWN: +@@ -373,6 +410,8 @@ main(int argc, char *argv[]) case NETWORK_REMOVE: case NETWORK_FLUSH: case IRRFILTER: @@ -199,7 +262,7 @@ diff -u -p -r1.1.1.7 -r1.7 break; } imsg_free(&imsg); -@@ -398,8 +429,8 @@ fmt_peer(const char *descr, const struct +@@ -398,8 +437,8 @@ fmt_peer(const char *descr, const struct } ip = log_addr(remote_addr); @@ -210,7 +273,7 @@ diff -u -p -r1.1.1.7 -r1.7 if (asprintf(&p, "%s/%u", ip, masklen) == -1) err(1, NULL); } else { -@@ -521,13 +552,15 @@ show_neighbor_msg(struct imsg *imsg, enu +@@ -521,13 +560,15 @@ show_neighbor_msg(struct imsg *imsg, enu struct ctl_timer *t; struct in_addr ina; char buf[NI_MAXHOST], pbuf[NI_MAXSERV], *s; @@ -228,7 +291,7 @@ diff -u -p -r1.1.1.7 -r1.7 p->conf.remote_masklen != 128)) { if (asprintf(&s, "%s/%u", log_addr(&p->conf.remote_addr), -@@ -549,6 +582,10 @@ show_neighbor_msg(struct imsg *imsg, enu +@@ -549,6 +590,10 @@ show_neighbor_msg(struct imsg *imsg, enu printf(", Template"); if (p->conf.cloned) printf(", Cloned"); @@ -239,7 +302,7 @@ diff -u -p -r1.1.1.7 -r1.7 printf("\n"); if (p->conf.descr[0]) printf(" Description: %s\n", p->conf.descr); -@@ -563,17 +600,16 @@ show_neighbor_msg(struct imsg *imsg, enu +@@ -563,17 +608,16 @@ show_neighbor_msg(struct imsg *imsg, enu printf(" Last read %s, holdtime %us, keepalive interval %us\n", fmt_timeframe(p->stats.last_read), p->holdtime, p->holdtime/3); @@ -266,7 +329,7 @@ diff -u -p -r1.1.1.7 -r1.7 } if (p->capa.peer.refresh) printf(" Route Refresh\n"); -@@ -633,20 +669,16 @@ show_neighbor_msg(struct imsg *imsg, enu +@@ -633,20 +677,16 @@ show_neighbor_msg(struct imsg *imsg, enu } void @@ -296,7 +359,7 @@ diff -u -p -r1.1.1.7 -r1.7 } void -@@ -680,7 +712,7 @@ print_neighbor_msgstats(struct peer *p) +@@ -680,7 +720,7 @@ print_neighbor_msgstats(struct peer *p) } void @@ -305,7 +368,95 @@ diff -u -p -r1.1.1.7 -r1.7 { printf(" %-20s ", name); -@@ -848,35 +880,70 @@ show_fib_msg(struct imsg *imsg) +@@ -745,6 +785,12 @@ show_fib_head(void) + } + + void ++show_fib_tables_head(void) ++{ ++ printf("%-5s %-20s %-8s\n", "Table", "Description", "State"); ++} ++ ++void + show_network_head(void) + { + printf("flags: S = Static\n"); +@@ -788,56 +834,44 @@ show_fib_flags(u_int16_t flags) + int + show_fib_msg(struct imsg *imsg) + { +- struct kroute *k; +- struct kroute6 *k6; ++ struct kroute_full *kf; ++ struct ktable *kt; + char *p; + + switch (imsg->hdr.type) { + case IMSG_CTL_KROUTE: + case IMSG_CTL_SHOW_NETWORK: +- if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute)) ++ if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(*kf)) + errx(1, "wrong imsg len"); +- k = imsg->data; ++ kf = imsg->data; + +- show_fib_flags(k->flags); ++ show_fib_flags(kf->flags); + +- if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), k->prefixlen) == +- -1) ++ if (asprintf(&p, "%s/%u", log_addr(&kf->prefix), ++ kf->prefixlen) == -1) + err(1, NULL); +- printf("%4i %-20s ", k->priority, p); ++ printf("%4i %-20s ", kf->priority, p); + free(p); + +- if (k->nexthop.s_addr) +- printf("%s", inet_ntoa(k->nexthop)); +- else if (k->flags & F_CONNECTED) +- printf("link#%u", k->ifindex); ++ if (kf->flags & F_CONNECTED) ++ printf("link#%u", kf->ifindex); ++ else ++ printf("%s", log_addr(&kf->nexthop)); + printf("\n"); + + break; +- case IMSG_CTL_KROUTE6: +- case IMSG_CTL_SHOW_NETWORK6: +- if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute6)) ++ case IMSG_CTL_SHOW_FIB_TABLES: ++ if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(*kt)) + errx(1, "wrong imsg len"); +- k6 = imsg->data; ++ kt = imsg->data; + +- show_fib_flags(k6->flags); +- +- if (asprintf(&p, "%s/%u", log_in6addr(&k6->prefix), +- k6->prefixlen) == -1) +- err(1, NULL); +- printf("%4i %-20s ", k6->priority, p); +- free(p); +- +- if (!IN6_IS_ADDR_UNSPECIFIED(&k6->nexthop)) +- printf("%s", log_in6addr(&k6->nexthop)); +- else if (k6->flags & F_CONNECTED) +- printf("link#%u", k6->ifindex); +- printf("\n"); ++ printf("%5i %-20s %-8s%s\n", kt->rtableid, kt->descr, ++ kt->fib_sync ? "coupled" : "decoupled", ++ kt->fib_sync != kt->fib_conf ? "*" : ""); + + break; + case IMSG_CTL_END: + return (1); +- break; + default: + break; + } +@@ -848,35 +882,70 @@ show_fib_msg(struct imsg *imsg) void show_nexthop_head(void) { @@ -385,7 +536,7 @@ diff -u -p -r1.1.1.7 -r1.7 + } else if (asprintf(&s1, ", %s", get_linkstate( + p->kif.media_type, p->kif.link_state)) == -1) + err(1, NULL); -+ if (asprintf(&s, "%s (%s%s)", p->kif.ifname, ++ if (asprintf(&s, "%s (%s%s)", p->kif.ifname, + p->kif.flags & IFF_UP ? "UP" : "DOWN", s1) == -1) + err(1, NULL); + printf("%-15s", s); @@ -394,7 +545,7 @@ diff -u -p -r1.1.1.7 -r1.7 } printf("\n"); break; -@@ -898,9 +965,8 @@ show_interface_head(void) +@@ -898,9 +967,8 @@ show_interface_head(void) "Link state"); } @@ -406,7 +557,7 @@ diff -u -p -r1.1.1.7 -r1.7 const struct ifmedia_description ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; -@@ -936,36 +1002,36 @@ get_media_descr(int media_type) +@@ -936,36 +1004,36 @@ get_media_descr(int media_type) const char * get_linkstate(int media_type, int link_state) { @@ -465,7 +616,7 @@ diff -u -p -r1.1.1.7 -r1.7 } int -@@ -982,17 +1048,12 @@ show_interface_msg(struct imsg *imsg) +@@ -982,17 +1050,12 @@ show_interface_msg(struct imsg *imsg) printf("%-15s", k->flags & IFF_UP ? "UP" : ""); if ((ifms_type = ift2ifm(k->media_type)) != 0) @@ -488,7 +639,7 @@ diff -u -p -r1.1.1.7 -r1.7 printf("\n"); break; case IMSG_CTL_END: -@@ -1011,7 +1072,7 @@ show_rib_summary_head(void) +@@ -1011,7 +1074,7 @@ show_rib_summary_head(void) printf( "flags: * = Valid, > = Selected, I = via IBGP, A = Announced\n"); printf("origin: i = IGP, e = EGP, ? = Incomplete\n\n"); @@ -497,7 +648,42 @@ diff -u -p -r1.1.1.7 -r1.7 "gateway", "lpref", "med", "aspath origin"); } -@@ -1085,7 +1146,7 @@ show_rib_summary_msg(struct imsg *imsg) +@@ -1049,26 +1112,26 @@ print_flags(u_int8_t flags, int sum) + char *p = flagstr; + + if (sum) { +- if (flags & F_RIB_ANNOUNCE) ++ if (flags & F_PREF_ANNOUNCE) + *p++ = 'A'; +- if (flags & F_RIB_INTERNAL) ++ if (flags & F_PREF_INTERNAL) + *p++ = 'I'; +- if (flags & F_RIB_ELIGIBLE) ++ if (flags & F_PREF_ELIGIBLE) + *p++ = '*'; +- if (flags & F_RIB_ACTIVE) ++ if (flags & F_PREF_ACTIVE) + *p++ = '>'; + *p = '\0'; + printf("%-5s ", flagstr); + } else { +- if (flags & F_RIB_INTERNAL) ++ if (flags & F_PREF_INTERNAL) + printf("internal"); + else + printf("external"); +- if (flags & F_RIB_ELIGIBLE) ++ if (flags & F_PREF_ELIGIBLE) + printf(", valid"); +- if (flags & F_RIB_ACTIVE) ++ if (flags & F_PREF_ACTIVE) + printf(", best"); +- if (flags & F_RIB_ANNOUNCE) ++ if (flags & F_PREF_ANNOUNCE) + printf(", announced"); + } + } +@@ -1085,7 +1148,7 @@ show_rib_summary_msg(struct imsg *imsg) memcpy(&rib, imsg->data, sizeof(rib)); print_prefix(&rib.prefix, rib.prefixlen, rib.flags); @@ -506,16 +692,18 @@ diff -u -p -r1.1.1.7 -r1.7 printf(" %5u %5u ", rib.local_pref, rib.med); -@@ -1190,7 +1251,7 @@ show_rib_detail_msg(struct imsg *imsg, i +@@ -1189,8 +1252,8 @@ show_rib_detail_msg(struct imsg *imsg, i + case ATTR_AGGREGATOR: memcpy(&as, data, sizeof(as)); memcpy(&id, data + sizeof(as), sizeof(id)); - printf(" Aggregator: %s [%s]\n", +- printf(" Aggregator: %s [%s]\n", - log_as(htonl(as)), inet_ntoa(id)); ++ printf(" Aggregator: %s [%s]\n", + log_as(ntohl(as)), inet_ntoa(id)); break; case ATTR_ORIGINATOR_ID: memcpy(&id, data, sizeof(id)); -@@ -1236,22 +1297,27 @@ fmt_mem(int64_t num) +@@ -1236,22 +1299,27 @@ fmt_mem(int64_t num) return (buf); } @@ -550,7 +738,7 @@ diff -u -p -r1.1.1.7 -r1.7 printf("%10lld rib entries using %s of memory\n", (long long)stats.rib_cnt, fmt_mem(stats.rib_cnt * sizeof(struct rib_entry))); -@@ -1272,9 +1338,7 @@ show_rib_memory_msg(struct imsg *imsg) +@@ -1272,9 +1340,7 @@ show_rib_memory_msg(struct imsg *imsg) (long long)stats.attr_refs); printf("%10lld BGP attributes using %s of memory\n", (long long)stats.attr_dcnt, fmt_mem(stats.attr_data)); @@ -561,7 +749,7 @@ diff -u -p -r1.1.1.7 -r1.7 stats.prefix_cnt * sizeof(struct prefix) + stats.rib_cnt * sizeof(struct rib_entry) + stats.path_cnt * sizeof(struct rde_aspath) + -@@ -1328,30 +1392,6 @@ show_community(u_char *data, u_int16_t l +@@ -1328,30 +1394,6 @@ show_community(u_char *data, u_int16_t l } } @@ -592,7 +780,7 @@ diff -u -p -r1.1.1.7 -r1.7 void show_ext_community(u_char *data, u_int16_t len) { -@@ -1372,24 +1412,25 @@ show_ext_community(u_char *data, u_int16 +@@ -1372,28 +1414,29 @@ show_ext_community(u_char *data, u_int16 case EXT_COMMUNITY_TWO_AS: memcpy(&as2, data + i + 2, sizeof(as2)); memcpy(&u32, data + i + 4, sizeof(u32)); @@ -620,7 +808,12 @@ diff -u -p -r1.1.1.7 -r1.7 memcpy(&ext, data + i, sizeof(ext)); ext = betoh64(ext) & 0xffffffffffffLL; - printf("%s 0x%llx", get_ext_subtype(subtype), ext); -+ printf("%s 0x%llx", log_ext_subtype(subtype), ext); ++ printf("%s 0x%llx", log_ext_subtype(subtype), ext); break; default: memcpy(&ext, data + i, sizeof(ext)); +- printf("0x%llx", betoh64(ext)); ++ printf("0x%llx", betoh64(ext)); + } + if (i + 8 < len) + printf(", "); diff --git a/net/openbgpd/files/patch-bgpctl_irr_prefix.c b/net/openbgpd/files/patch-bgpctl_irr_prefix.c index 2d1d5217c4cc..da541297f183 100644 --- a/net/openbgpd/files/patch-bgpctl_irr_prefix.c +++ b/net/openbgpd/files/patch-bgpctl_irr_prefix.c @@ -2,13 +2,13 @@ Index: bgpctl/irr_prefix.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_prefix.c,v retrieving revision 1.1.1.5 -retrieving revision 1.1.1.6 -diff -u -p -r1.1.1.5 -r1.1.1.6 +retrieving revision 1.1.1.7 +diff -u -p -r1.1.1.5 -r1.1.1.7 --- bgpctl/irr_prefix.c 14 Feb 2010 20:20:14 -0000 1.1.1.5 -+++ bgpctl/irr_prefix.c 14 Feb 2010 20:27:21 -0000 1.1.1.6 ++++ bgpctl/irr_prefix.c 12 Jun 2011 10:44:54 -0000 1.1.1.7 @@ -1,4 +1,4 @@ -/* $OpenBSD: irr_prefix.c,v 1.15 2007/05/27 18:54:25 henning Exp $ */ -+/* $OpenBSD: irr_prefix.c,v 1.17 2009/09/08 16:11:36 sthen Exp $ */ ++/* $OpenBSD: irr_prefix.c,v 1.18 2010/05/10 02:00:50 krw Exp $ */ /* * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> @@ -112,7 +112,8 @@ diff -u -p -r1.1.1.5 -r1.1.1.6 + return (1); + } - /* see wether we can fold them in one */ +- /* see wether we can fold them in one */ ++ /* see whether we can fold them in one */ if (a->len == b->len && a->len > 1) { - mask = htonl(0xffffffff << (32 - (a->len - 1))); - if ((a->addr.in.s_addr & mask) == diff --git a/net/openbgpd/files/patch-bgpctl_parser.c b/net/openbgpd/files/patch-bgpctl_parser.c index 5efa4ce8cd49..237c6ffc9b92 100644 --- a/net/openbgpd/files/patch-bgpctl_parser.c +++ b/net/openbgpd/files/patch-bgpctl_parser.c @@ -2,10 +2,10 @@ Index: bgpctl/parser.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/parser.c,v retrieving revision 1.1.1.6 -retrieving revision 1.5 -diff -u -p -r1.1.1.6 -r1.5 +retrieving revision 1.6 +diff -u -p -r1.1.1.6 -r1.6 --- bgpctl/parser.c 14 Feb 2010 20:20:14 -0000 1.1.1.6 -+++ bgpctl/parser.c 10 Apr 2010 12:17:18 -0000 1.5 ++++ bgpctl/parser.c 2 Jul 2011 16:06:35 -0000 1.6 @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.c,v 1.54 2009/06/12 16:44:02 claudio Exp $ */ +/* $OpenBSD: parser.c,v 1.61 2010/03/08 17:02:19 claudio Exp $ */ @@ -23,15 +23,27 @@ diff -u -p -r1.1.1.6 -r1.5 #include <sys/types.h> #include <sys/socket.h> -@@ -97,6 +101,7 @@ static const struct token t_prepself[]; +@@ -52,7 +56,8 @@ enum token_type { + PREPSELF, + WEIGHT, + FAMILY, +- GETOPT ++ GETOPT, ++ RTABLE + }; + + enum getopts { +@@ -97,6 +102,9 @@ static const struct token t_prepself[]; static const struct token t_weight[]; static const struct token t_irrfilter[]; static const struct token t_irrfilter_opts[]; +static const struct token t_log[]; ++static const struct token t_fib_table[]; ++static const struct token t_show_fib_table[]; static const struct token t_main[] = { { KEYWORD, "reload", RELOAD, NULL}, -@@ -105,6 +110,7 @@ static const struct token t_main[] = { +@@ -105,6 +113,7 @@ static const struct token t_main[] = { { KEYWORD, "neighbor", NEIGHBOR, t_neighbor}, { KEYWORD, "network", NONE, t_network}, { KEYWORD, "irrfilter", IRRFILTER, t_irrfilter}, @@ -39,7 +51,47 @@ diff -u -p -r1.1.1.6 -r1.5 { ENDTOKEN, "", NONE, NULL} }; -@@ -311,6 +317,12 @@ static const struct token t_irrfilter_op +@@ -116,6 +125,7 @@ static const struct token t_show[] = { + { KEYWORD, "network", NETWORK_SHOW, t_network_show}, + { KEYWORD, "nexthop", SHOW_NEXTHOP, NULL}, + { KEYWORD, "rib", SHOW_RIB, t_show_rib}, ++ { KEYWORD, "tables", SHOW_FIB_TABLES, NULL}, + { KEYWORD, "ip", NONE, t_show_ip}, + { KEYWORD, "summary", SHOW_SUMMARY, t_show_summary}, + { ENDTOKEN, "", NONE, NULL} +@@ -128,14 +138,15 @@ static const struct token t_show_summary + }; + + static const struct token t_show_fib[] = { +- { NOTOKEN, "", NONE, NULL}, +- { FLAG, "connected", F_CONNECTED, t_show_fib}, +- { FLAG, "static", F_STATIC, t_show_fib}, +- { FLAG, "bgp", F_BGPD_INSERTED, t_show_fib}, +- { FLAG, "nexthop", F_NEXTHOP, t_show_fib}, +- { FAMILY, "", NONE, t_show_fib}, +- { ADDRESS, "", NONE, NULL}, +- { ENDTOKEN, "", NONE, NULL} ++ { NOTOKEN, "", NONE, NULL}, ++ { FLAG, "connected", F_CONNECTED, t_show_fib}, ++ { FLAG, "static", F_STATIC, t_show_fib}, ++ { FLAG, "bgp", F_BGPD_INSERTED, t_show_fib}, ++ { FLAG, "nexthop", F_NEXTHOP, t_show_fib}, ++ { KEYWORD, "table", NONE, t_show_fib_table}, ++ { FAMILY, "", NONE, t_show_fib}, ++ { ADDRESS, "", NONE, NULL}, ++ { ENDTOKEN, "", NONE, NULL} + }; + + static const struct token t_show_rib[] = { +@@ -187,6 +198,7 @@ static const struct token t_show_neighbo + static const struct token t_fib[] = { + { KEYWORD, "couple", FIB_COUPLE, NULL}, + { KEYWORD, "decouple", FIB_DECOUPLE, NULL}, ++ { KEYWORD, "table", NONE, t_fib_table}, + { ENDTOKEN, "", NONE, NULL} + }; + +@@ -311,6 +323,22 @@ static const struct token t_irrfilter_op { ENDTOKEN, "", NONE, NULL} }; @@ -49,10 +101,20 @@ diff -u -p -r1.1.1.6 -r1.5 + { ENDTOKEN, "", NONE, NULL} +}; + ++static const struct token t_fib_table[] = { ++ { RTABLE, "", NONE, t_fib}, ++ { ENDTOKEN, "", NONE, NULL} ++}; ++ ++static const struct token t_show_fib_table[] = { ++ { RTABLE, "", NONE, t_show_fib}, ++ { ENDTOKEN, "", NONE, NULL} ++}; ++ static struct parse_result res; const struct token *match_token(int *argc, char **argv[], -@@ -404,15 +416,22 @@ match_token(int *argc, char **argv[], co +@@ -404,15 +432,22 @@ match_token(int *argc, char **argv[], co case FAMILY: if (word == NULL) break; @@ -79,7 +141,25 @@ diff -u -p -r1.1.1.6 -r1.5 } break; case ADDRESS: -@@ -584,7 +603,7 @@ show_valid_args(const struct token table +@@ -485,6 +520,7 @@ match_token(int *argc, char **argv[], co + case PREPNBR: + case PREPSELF: + case WEIGHT: ++ case RTABLE: + if (word != NULL && strlen(word) > 0 && + parse_number(word, &res, table[i].type)) { + match++; +@@ -577,6 +613,9 @@ show_valid_args(const struct token table + case WEIGHT: + fprintf(stderr, " <number>\n"); + break; ++ case RTABLE: ++ fprintf(stderr, " <rtableid>\n"); ++ break; + case NEXTHOP: + fprintf(stderr, " <address>\n"); + break; +@@ -584,7 +623,7 @@ show_valid_args(const struct token table fprintf(stderr, " <pftable>\n"); break; case FAMILY: @@ -88,7 +168,7 @@ diff -u -p -r1.1.1.6 -r1.5 break; case GETOPT: fprintf(stderr, " <options>\n"); -@@ -608,7 +627,7 @@ parse_addr(const char *word, struct bgpd +@@ -608,7 +647,7 @@ parse_addr(const char *word, struct bgpd bzero(&ina, sizeof(ina)); if (inet_net_pton(AF_INET, word, &ina, sizeof(ina)) != -1) { @@ -97,7 +177,7 @@ diff -u -p -r1.1.1.6 -r1.5 addr->v4 = ina; return (1); } -@@ -618,13 +637,7 @@ parse_addr(const char *word, struct bgpd +@@ -618,13 +657,7 @@ parse_addr(const char *word, struct bgpd hints.ai_socktype = SOCK_DGRAM; /*dummy*/ hints.ai_flags = AI_NUMERICHOST; if (getaddrinfo(word, "0", &hints, &r) == 0) { @@ -112,7 +192,7 @@ diff -u -p -r1.1.1.6 -r1.5 freeaddrinfo(r); return (1); } -@@ -663,15 +676,15 @@ parse_prefix(const char *word, struct bg +@@ -663,15 +696,15 @@ parse_prefix(const char *word, struct bg if (parse_addr(word, addr) == 0) return (0); @@ -131,7 +211,7 @@ diff -u -p -r1.1.1.6 -r1.5 if (mask == -1) mask = 128; inet6applymask(&addr->v6, &addr->v6, mask); -@@ -706,7 +719,7 @@ parse_asnum(const char *word, u_int32_t +@@ -706,7 +739,7 @@ parse_asnum(const char *word, u_int32_t if (errstr) errx(1, "AS number is %s: %s", errstr, word); } else { @@ -140,7 +220,19 @@ diff -u -p -r1.1.1.6 -r1.5 if (errstr) errx(1, "AS number is %s: %s", errstr, word); } -@@ -882,8 +895,14 @@ bgpctl_getopt(int *argc, char **argv[], +@@ -730,6 +763,11 @@ parse_number(const char *word, struct pa + errx(1, "number is %s: %s", errstr, word); + + /* number was parseable */ ++ if (type == RTABLE) { ++ r->rtableid = uval; ++ return (1); ++ } ++ + if ((fs = calloc(1, sizeof(struct filter_set))) == NULL) + err(1, NULL); + switch (type) { +@@ -882,8 +920,14 @@ bgpctl_getopt(int *argc, char **argv[], int ch; optind = optreset = 1; diff --git a/net/openbgpd/files/patch-bgpctl_parser.h b/net/openbgpd/files/patch-bgpctl_parser.h index a3bb1fede7af..bf86d255a853 100644 --- a/net/openbgpd/files/patch-bgpctl_parser.h +++ b/net/openbgpd/files/patch-bgpctl_parser.h @@ -2,17 +2,25 @@ Index: bgpctl/parser.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/parser.h,v retrieving revision 1.1.1.6 -retrieving revision 1.1.1.7 -diff -u -p -r1.1.1.6 -r1.1.1.7 +retrieving revision 1.1.1.8 +diff -u -p -r1.1.1.6 -r1.1.1.8 --- bgpctl/parser.h 14 Feb 2010 20:20:14 -0000 1.1.1.6 -+++ bgpctl/parser.h 14 Feb 2010 20:27:21 -0000 1.1.1.7 ++++ bgpctl/parser.h 12 Jun 2011 10:44:54 -0000 1.1.1.8 @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.h,v 1.19 2009/06/06 06:05:41 claudio Exp $ */ -+/* $OpenBSD: parser.h,v 1.21 2010/01/10 00:16:23 claudio Exp $ */ ++/* $OpenBSD: parser.h,v 1.22 2010/05/03 13:11:41 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -37,6 +37,8 @@ enum actions { +@@ -29,6 +29,7 @@ enum actions { + SHOW_NEIGHBOR_TIMERS, + SHOW_NEIGHBOR_TERSE, + SHOW_FIB, ++ SHOW_FIB_TABLES, + SHOW_RIB, + SHOW_RIB_MEM, + SHOW_NEXTHOP, +@@ -37,6 +38,8 @@ enum actions { FIB, FIB_COUPLE, FIB_DECOUPLE, @@ -21,9 +29,13 @@ diff -u -p -r1.1.1.6 -r1.1.1.7 NEIGHBOR, NEIGHBOR_UP, NEIGHBOR_DOWN, -@@ -61,7 +63,7 @@ struct parse_result { +@@ -59,9 +62,10 @@ struct parse_result { + char rib[PEER_DESCR_LEN]; + char *irr_outdir; int flags; - enum actions action; +- enum actions action; ++ u_int rtableid; ++ enum actions action; u_int8_t prefixlen; - sa_family_t af; + u_int8_t aid; diff --git a/net/openbgpd/files/patch-bgpd_Makefile b/net/openbgpd/files/patch-bgpd_Makefile index a7289abf0dc4..9bc06ffb1090 100644 --- a/net/openbgpd/files/patch-bgpd_Makefile +++ b/net/openbgpd/files/patch-bgpd_Makefile @@ -2,25 +2,29 @@ Index: bgpd/Makefile =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/Makefile,v retrieving revision 1.1.1.2 -retrieving revision 1.6 -diff -u -p -r1.1.1.2 -r1.6 +retrieving revision 1.8 +diff -u -p -r1.1.1.2 -r1.8 --- bgpd/Makefile 9 Jul 2009 16:49:54 -0000 1.1.1.2 -+++ bgpd/Makefile 9 Jul 2009 17:22:14 -0000 1.6 -@@ -1,15 +1,23 @@ - # $OpenBSD: Makefile,v 1.28 2009/06/25 14:14:54 deraadt Exp $ - ++++ bgpd/Makefile 3 Jul 2011 04:46:36 -0000 1.8 +@@ -1,15 +1,25 @@ +-# $OpenBSD: Makefile,v 1.28 2009/06/25 14:14:54 deraadt Exp $ ++# $OpenBSD: Makefile,v 1.29 2010/05/26 16:44:32 nicm Exp $ ++ +.PATH: ${.CURDIR}/.. ${.CURDIR}/../openbsd-compat + +CONFFILE?= ${PREFIX}/etc/bgpd.conf -+ + PROG= bgpd - SRCS= bgpd.c buffer.c session.c log.c parse.y config.c imsg.c \ +-SRCS= bgpd.c buffer.c session.c log.c parse.y config.c imsg.c \ ++SRCS= bgpd.c session.c log.c parse.y config.c \ rde.c rde_rib.c rde_decide.c rde_prefix.c mrt.c kroute.c \ - control.c pfkey.c rde_update.c rde_attr.c printconf.c \ +- rde_filter.c pftable.c name2id.c util.c carp.c timer.c + control.c pfkey_compat.c rde_update.c rde_attr.c printconf.c \ - rde_filter.c pftable.c name2id.c util.c carp.c timer.c --CFLAGS+= -Wall -I${.CURDIR} -+CFLAGS+= -Wall -I${.CURDIR} -I${.CURDIR}/../openbsd-compat ++ rde_filter.c pftable.c name2id.c util.c carp.c timer.c \ ++ imsg.c imsg-buffer.c + CFLAGS+= -Wall -I${.CURDIR} ++CFLAGS+= -I${.CURDIR}/../openbsd-compat CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes CFLAGS+= -Wmissing-declarations CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual diff --git a/net/openbgpd/files/patch-bgpd_bgpd.8 b/net/openbgpd/files/patch-bgpd_bgpd.8 index aa748ec1035f..e666cb96d92c 100644 --- a/net/openbgpd/files/patch-bgpd_bgpd.8 +++ b/net/openbgpd/files/patch-bgpd_bgpd.8 @@ -2,10 +2,10 @@ Index: bgpd/bgpd.8 =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.8,v retrieving revision 1.1.1.8 -retrieving revision 1.8 -diff -u -p -r1.1.1.8 -r1.8 +retrieving revision 1.9 +diff -u -p -r1.1.1.8 -r1.9 --- bgpd/bgpd.8 14 Feb 2010 20:19:57 -0000 1.1.1.8 -+++ bgpd/bgpd.8 2 Mar 2010 05:48:19 -0000 1.8 ++++ bgpd/bgpd.8 2 Jul 2011 16:06:38 -0000 1.9 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bgpd.8,v 1.28 2009/01/13 23:01:36 sthen Exp $ +.\" $OpenBSD: bgpd.8,v 1.33 2009/12/16 15:40:55 claudio Exp $ @@ -17,24 +17,32 @@ diff -u -p -r1.1.1.8 -r1.8 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: January 13 2009 $ -+.Dd $Mdocdate: December 16 2009 $ ++.Dd $Mdocdate: June 27 2010 $ .Dt BGPD 8 .Os .Sh NAME -@@ -24,9 +24,9 @@ +@@ -24,12 +24,8 @@ .Nm bgpd .Bk -words .Op Fl cdnv -.Oo Xo -.Fl D Ar macro Ns = Ns Ar value Oc -.Xc -+.Oo -+.Fl D Ar macro Ns = Ns Ar value -+.Oc ++.Op Fl D Ar macro Ns = Ns Ar value .Op Fl f Ar file - .Op Fl r Ar path - .Op Fl s Ar path -@@ -48,9 +48,9 @@ Please refer to that document for more i +-.Op Fl r Ar path +-.Op Fl s Ar path + .Ek + .Sh DESCRIPTION + .Nm +@@ -42,15 +38,15 @@ concerning + with other BGP systems. + .Nm + uses the Border Gateway Protocol, Version 4, +-as described in RFC 1771. ++as described in RFC 4271. + Please refer to that document for more information about BGP. + .Pp .Nm is usually started at boot time, and can be enabled by setting the following in @@ -46,7 +54,7 @@ diff -u -p -r1.1.1.8 -r1.8 .Pp See .Xr rc 8 -@@ -117,7 +117,7 @@ Use +@@ -117,25 +113,16 @@ Use .Ar file as the configuration file, instead of the default @@ -55,7 +63,17 @@ diff -u -p -r1.1.1.8 -r1.8 .It Fl n Configtest mode. Only check the configuration file for validity. -@@ -135,7 +135,7 @@ Produce more verbose output. +-.It Fl r Ar path +-Open a second, restricted, control socket that +-.Xr bgpctl 8 +-can use. +-Only +-.Em show +-requests are allowed on this socket. +-.It Fl s Ar path +-Use an alternate location for the default control socket. + .It Fl v + Produce more verbose output. .El .Sh FILES .Bl -tag -width "/var/run/bgpd.sockXXX" -compact @@ -64,7 +82,19 @@ diff -u -p -r1.1.1.8 -r1.8 default .Nm configuration file -@@ -165,6 +165,11 @@ control socket +@@ -150,9 +137,9 @@ control socket + .Xr bgplg 8 , + .Xr bgplgsh 8 + .Rs +-.%R RFC 1771 ++.%R RFC 4271 + .%T "A Border Gateway Protocol 4 (BGP-4)" +-.%D March 1995 ++.%D January 2006 + .Re + .Rs + .%R RFC 1997 +@@ -165,6 +152,11 @@ control socket .%D August 1998 .Re .Rs @@ -76,7 +106,7 @@ diff -u -p -r1.1.1.8 -r1.8 .%R RFC 2796 .%T "BGP Route Reflection - An Alternative to Full Mesh IBGP" .%D April 2000 -@@ -175,11 +180,6 @@ control socket +@@ -175,11 +167,6 @@ control socket .%D September 2000 .Re .Rs @@ -88,7 +118,7 @@ diff -u -p -r1.1.1.8 -r1.8 .%R RFC 3682 .%T "The Generalized TTL Security Mechanism (GTSM)" .%D February 2004 -@@ -190,6 +190,16 @@ control socket +@@ -190,6 +177,21 @@ control socket .%D April 2004 .Re .Rs @@ -97,6 +127,11 @@ diff -u -p -r1.1.1.8 -r1.8 +.%D February 2006 +.Re +.Rs ++.%R RFC 4364 ++.%T "BGP/MPLS IP Virtual Private Networks (VPNs)" ++.%D February 2006 ++.Re ++.Rs +.%R RFC 4486 +.%T "BGP Cease Notification Message Subcodes" +.%D April 2006 @@ -105,7 +140,7 @@ diff -u -p -r1.1.1.8 -r1.8 .%R RFC 4760 .%T "Multiprotocol Extensions for BGP-4" .%D January 2007 -@@ -199,6 +209,16 @@ control socket +@@ -199,6 +201,21 @@ control socket .%T "BGP Support for Four-octet AS Number Space" .%D May 2007 .Re @@ -119,6 +154,11 @@ diff -u -p -r1.1.1.8 -r1.8 +.%T "Error Handling for Optional Transitive BGP Attributes" +.%D April 2009 +.Re ++.Rs ++.%R draft-ietf-idr-fsm-subcode-00 ++.%T "Subcodes for BGP Finite State Machine Error" ++.%D September 2010 ++.Re .Sh HISTORY The .Nm diff --git a/net/openbgpd/files/patch-bgpd_bgpd.c b/net/openbgpd/files/patch-bgpd_bgpd.c index 788b053a2d48..73190ce9b93f 100644 --- a/net/openbgpd/files/patch-bgpd_bgpd.c +++ b/net/openbgpd/files/patch-bgpd_bgpd.c @@ -2,26 +2,71 @@ Index: bgpd/bgpd.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.c,v retrieving revision 1.1.1.7 -retrieving revision 1.1.1.9 -diff -u -p -r1.1.1.7 -r1.1.1.9 +diff -u -p -r1.1.1.7 bgpd.c --- bgpd/bgpd.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/bgpd.c 10 Apr 2010 12:13:04 -0000 1.1.1.9 ++++ bgpd/bgpd.c 3 Jul 2011 04:34:14 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.c,v 1.148 2009/06/07 00:30:23 claudio Exp $ */ -+/* $OpenBSD: bgpd.c,v 1.156 2010/03/29 09:09:25 claudio Exp $ */ ++/* $OpenBSD: bgpd.c,v 1.167 2011/05/01 10:42:28 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -42,7 +42,7 @@ int main(int, char *[]); +@@ -32,8 +32,8 @@ + #include <string.h> + #include <unistd.h> + +-#include "mrt.h" + #include "bgpd.h" ++#include "mrt.h" + #include "session.h" + + void sighdlr(int); +@@ -42,23 +42,22 @@ int main(int, char *[]); int check_child(pid_t, const char *); int send_filterset(struct imsgbuf *, struct filter_set_head *); int reconfigure(char *, struct bgpd_config *, struct mrt_head *, - struct peer **, struct filter_head *); + struct peer **); int dispatch_imsg(struct imsgbuf *, int); ++int control_setup(struct bgpd_config *); int rfd = -1; -@@ -101,15 +101,10 @@ int +-int cflags = 0; +-struct filter_set_head *connectset; +-struct filter_set_head *connectset6; +-struct filter_set_head *staticset; +-struct filter_set_head *staticset6; +-volatile sig_atomic_t mrtdump = 0; +-volatile sig_atomic_t quit = 0; +-volatile sig_atomic_t sigchld = 0; +-volatile sig_atomic_t reconfig = 0; +-pid_t reconfpid = 0; ++int cflags; ++volatile sig_atomic_t mrtdump; ++volatile sig_atomic_t quit; ++volatile sig_atomic_t sigchld; ++volatile sig_atomic_t reconfig; ++pid_t reconfpid; + struct imsgbuf *ibuf_se; + struct imsgbuf *ibuf_rde; + struct rib_names ribnames = SIMPLEQ_HEAD_INITIALIZER(ribnames); ++char *cname; ++char *rcname; + + void + sighdlr(int sig) +@@ -86,8 +85,8 @@ usage(void) + { + extern char *__progname; + +- fprintf(stderr, "usage: %s [-cdnv] ", __progname); +- fprintf(stderr, "[-D macro=value] [-f file] [-r path] [-s path]\n"); ++ fprintf(stderr, "usage: %s [-cdnv] [-D macro=value] [-f file]\n", ++ __progname); + exit(1); + } + +@@ -101,15 +100,10 @@ int main(int argc, char *argv[]) { struct bgpd_config conf; @@ -38,7 +83,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 struct pollfd pfd[POLL_MAX]; pid_t io_pid = 0, rde_pid = 0, pid; char *conffile; -@@ -125,13 +120,8 @@ main(int argc, char *argv[]) +@@ -125,17 +119,11 @@ main(int argc, char *argv[]) log_init(1); /* log to stderr until daemonized */ @@ -50,17 +95,28 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 - TAILQ_INIT(&net_l); - TAILQ_INIT(rules_l); peer_l = NULL; - conf.csock = SOCKET_NAME; +- conf.csock = SOCKET_NAME; -@@ -158,6 +148,7 @@ main(int argc, char *argv[]) +- while ((ch = getopt(argc, argv, "cdD:f:nr:s:v")) != -1) { ++ while ((ch = getopt(argc, argv, "cdD:f:nv")) != -1) { + switch (ch) { + case 'c': + conf.opts |= BGPD_OPT_FORCE_DEMOTE; +@@ -158,12 +146,7 @@ main(int argc, char *argv[]) if (conf.opts & BGPD_OPT_VERBOSE) conf.opts |= BGPD_OPT_VERBOSE2; conf.opts |= BGPD_OPT_VERBOSE; +- break; +- case 'r': +- conf.rcsock = optarg; +- break; +- case 's': +- conf.csock = optarg; + log_verbose(1); break; - case 'r': - conf.rcsock = optarg; -@@ -176,14 +167,16 @@ main(int argc, char *argv[]) + default: + usage(); +@@ -176,24 +159,22 @@ main(int argc, char *argv[]) if (argc > 0) usage(); @@ -71,19 +127,31 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 - if (conf.opts & BGPD_OPT_NOACTION) { + struct network_head net_l; ++ struct rdomain_head rdom_l; + struct filter_head rules_l; + + if (parse_config(conffile, &conf, &mrt_l, &peer_l, &net_l, -+ &rules_l)) ++ &rules_l, &rdom_l)) + exit(1); + if (conf.opts & BGPD_OPT_VERBOSE) - print_config(&conf, &ribnames, &net_l, peer_l, rules_l, +- &mrt_l); + print_config(&conf, &ribnames, &net_l, peer_l, &rules_l, - &mrt_l); ++ &mrt_l, &rdom_l); else fprintf(stderr, "configuration OK\n"); -@@ -225,13 +218,10 @@ main(int argc, char *argv[]) + exit(0); + } +- cflags = conf.flags; +- connectset = &conf.connectset; +- staticset = &conf.staticset; +- connectset6 = &conf.connectset6; +- staticset6 = &conf.staticset6; + + if (geteuid()) + errx(1, "need root privileges"); +@@ -225,13 +206,9 @@ main(int argc, char *argv[]) session_socket_blockmode(pipe_s2r_c[0], BM_NONBLOCK); session_socket_blockmode(pipe_s2r_c[1], BM_NONBLOCK); @@ -95,19 +163,19 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 - io_pid = session_main(&conf, peer_l, &net_l, rules_l, &mrt_l, &ribnames, - pipe_m2s, pipe_s2r, pipe_m2r, pipe_s2r_c); + rde_pid = rde_main(pipe_m2r, pipe_s2r, pipe_m2s, pipe_s2r_c, debug); -+ io_pid = session_main(pipe_m2s, pipe_s2r, pipe_m2r, pipe_s2r_c, -+ conf.csock, conf.rcsock); ++ io_pid = session_main(pipe_m2s, pipe_s2r, pipe_m2r, pipe_s2r_c); setproctitle("parent"); -@@ -254,33 +244,13 @@ main(int argc, char *argv[]) +@@ -254,33 +231,12 @@ main(int argc, char *argv[]) imsg_init(ibuf_se, pipe_m2s[0]); imsg_init(ibuf_rde, pipe_m2r[0]); mrt_init(ibuf_rde, ibuf_se); -+ quit = reconfigure(conffile, &conf, &mrt_l, &peer_l); - if ((rfd = kr_init(!(conf.flags & BGPD_FLAG_NO_FIB_UPDATE), - conf.rtableid)) == -1) +- if ((rfd = kr_init(!(conf.flags & BGPD_FLAG_NO_FIB_UPDATE), +- conf.rtableid)) == -1) ++ if ((rfd = kr_init()) == -1) quit = 1; ++ quit = reconfigure(conffile, &conf, &mrt_l, &peer_l); if (pftable_clear_all() != 0) quit = 1; @@ -135,7 +203,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 while (quit == 0) { bzero(pfd, sizeof(pfd)); pfd[PFD_PIPE_SESSION].fd = ibuf_se->fd; -@@ -336,8 +306,7 @@ main(int argc, char *argv[]) +@@ -336,8 +292,7 @@ main(int argc, char *argv[]) reconfig = 0; log_info("rereading config"); @@ -145,7 +213,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 case -1: /* fatal error */ quit = 1; break; -@@ -389,13 +358,13 @@ main(int argc, char *argv[]) +@@ -389,13 +344,13 @@ main(int argc, char *argv[]) LIST_REMOVE(m, entry); free(m); } @@ -165,7 +233,16 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 control_cleanup(conf.csock); control_cleanup(conf.rcsock); carp_demote_shutdown(); -@@ -452,18 +421,23 @@ send_filterset(struct imsgbuf *i, struct +@@ -413,6 +368,8 @@ main(int argc, char *argv[]) + free(ibuf_se); + msgbuf_clear(&ibuf_rde->w); + free(ibuf_rde); ++ free(rcname); ++ free(cname); + + log_info("Terminating"); + return (0); +@@ -452,27 +409,25 @@ send_filterset(struct imsgbuf *i, struct int reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l, @@ -173,41 +250,168 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 + struct peer **peer_l) { struct network_head net_l; +- struct network *n; ++ struct rdomain_head rdom_l; + struct filter_head rules_l; - struct network *n; struct peer *p; struct filter_rule *r; struct listen_addr *la; struct rde_rib *rr; ++ struct rdomain *rd; - if (parse_config(conffile, conf, mrt_l, peer_l, &net_l, rules_l)) { -+ if (parse_config(conffile, conf, mrt_l, peer_l, &net_l, &rules_l)) { ++ if (parse_config(conffile, conf, mrt_l, peer_l, &net_l, &rules_l, ++ &rdom_l)) { log_warnx("config file %s has errors, not reloading", conffile); -+ while ((rr = SIMPLEQ_FIRST(&ribnames))) { -+ SIMPLEQ_REMOVE_HEAD(&ribnames, entry); -+ free(rr); -+ } return (1); } -@@ -525,13 +499,13 @@ reconfigure(char *conffile, struct bgpd_ + cflags = conf->flags; +- connectset = &conf->connectset; +- staticset = &conf->staticset; +- connectset6 = &conf->connectset6; +- staticset6 = &conf->staticset6; +- + prepare_listeners(conf); + + /* start reconfiguration */ +@@ -483,12 +438,6 @@ reconfigure(char *conffile, struct bgpd_ + conf, sizeof(struct bgpd_config)) == -1) + return (-1); + +- /* send peer list and listeners to the SE */ +- for (p = *peer_l; p != NULL; p = p->next) +- if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1, +- &p->conf, sizeof(struct peer_config)) == -1) +- return (-1); +- + TAILQ_FOREACH(la, conf->listen_addrs, entry) { + if (imsg_compose(ibuf_se, IMSG_RECONF_LISTENER, 0, 0, la->fd, + la, sizeof(struct listen_addr)) == -1) +@@ -496,51 +445,104 @@ reconfigure(char *conffile, struct bgpd_ + la->fd = -1; + } + ++ if (control_setup(conf) == -1) ++ return (-1); ++ ++ /* adjust fib syncing on reload */ ++ ktable_preload(); ++ + /* RIBs for the RDE */ + while ((rr = SIMPLEQ_FIRST(&ribnames))) { + SIMPLEQ_REMOVE_HEAD(&ribnames, entry); ++ if (ktable_update(rr->rtableid, rr->name, NULL, ++ rr->flags) == -1) { ++ log_warnx("failed to load rdomain %d", ++ rr->rtableid); ++ return (-1); ++ } + if (imsg_compose(ibuf_rde, IMSG_RECONF_RIB, 0, 0, -1, + rr, sizeof(struct rde_rib)) == -1) + return (-1); + free(rr); + } + +- /* networks for the RDE */ +- while ((n = TAILQ_FIRST(&net_l)) != NULL) { +- if (imsg_compose(ibuf_rde, IMSG_NETWORK_ADD, 0, 0, -1, +- &n->net, sizeof(struct network_config)) == -1) +- return (-1); +- if (send_filterset(ibuf_rde, &n->net.attrset) == -1) +- return (-1); +- if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, +- NULL, 0) == -1) +- return (-1); +- TAILQ_REMOVE(&net_l, n, entry); +- filterset_free(&n->net.attrset); +- free(n); ++ /* send peer list and listeners to the SE and RDE */ ++ for (p = *peer_l; p != NULL; p = p->next) { ++ if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1, ++ &p->conf, sizeof(struct peer_config)) == -1) ++ return (-1); ++ if (imsg_compose(ibuf_rde, IMSG_RECONF_PEER, p->conf.id, 0, -1, ++ &p->conf, sizeof(struct peer_config)) == -1) ++ return (-1); + } + +- /* redistribute list needs to be reloaded too */ +- if (kr_reload() == -1) ++ /* networks go via kroute to the RDE */ ++ if (kr_net_reload(0, &net_l)) return (-1); /* filters for the RDE */ - while ((r = TAILQ_FIRST(rules_l)) != NULL) { + while ((r = TAILQ_FIRST(&rules_l)) != NULL) { ++ TAILQ_REMOVE(&rules_l, r, entry); if (imsg_compose(ibuf_rde, IMSG_RECONF_FILTER, 0, 0, -1, r, sizeof(struct filter_rule)) == -1) return (-1); if (send_filterset(ibuf_rde, &r->set) == -1) return (-1); - TAILQ_REMOVE(rules_l, r, entry); -+ TAILQ_REMOVE(&rules_l, r, entry); filterset_free(&r->set); free(r); } -@@ -550,8 +524,8 @@ int + ++ while ((rd = SIMPLEQ_FIRST(&rdom_l)) != NULL) { ++ SIMPLEQ_REMOVE_HEAD(&rdom_l, entry); ++ if (ktable_update(rd->rtableid, rd->descr, rd->ifmpe, ++ rd->flags) == -1) { ++ log_warnx("failed to load rdomain %d", ++ rd->rtableid); ++ return (-1); ++ } ++ /* networks go via kroute to the RDE */ ++ if (kr_net_reload(rd->rtableid, &rd->net_l)) ++ return (-1); ++ ++ if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN, 0, 0, -1, ++ rd, sizeof(*rd)) == -1) ++ return (-1); ++ ++ /* export targets */ ++ if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN_EXPORT, 0, 0, ++ -1, NULL, 0) == -1) ++ return (-1); ++ if (send_filterset(ibuf_rde, &rd->export) == -1) ++ return (-1); ++ filterset_free(&rd->export); ++ ++ /* import targets */ ++ if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN_IMPORT, 0, 0, ++ -1, NULL, 0) == -1) ++ return (-1); ++ if (send_filterset(ibuf_rde, &rd->import) == -1) ++ return (-1); ++ filterset_free(&rd->import); ++ ++ if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN_DONE, 0, 0, ++ -1, NULL, 0) == -1) ++ return (-1); ++ ++ free(rd); ++ } ++ + /* signal both childs to replace their config */ + if (imsg_compose(ibuf_se, IMSG_RECONF_DONE, 0, 0, -1, NULL, 0) == -1 || + imsg_compose(ibuf_rde, IMSG_RECONF_DONE, 0, 0, -1, NULL, 0) == -1) + return (-1); + ++ /* fix kroute information */ ++ ktable_postload(); ++ ++ /* redistribute list needs to be reloaded too */ ++ if (kr_reload() == -1) ++ return (-1); ++ + /* mrt changes can be sent out of bound */ + mrt_reconfigure(mrt_l); + return (0); +@@ -550,8 +552,8 @@ int dispatch_imsg(struct imsgbuf *ibuf, int idx) { struct imsg imsg; @@ -218,7 +422,94 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 if ((n = imsg_read(ibuf)) == -1) return (-1); -@@ -692,6 +666,11 @@ dispatch_imsg(struct imsgbuf *ibuf, int +@@ -573,46 +575,39 @@ dispatch_imsg(struct imsgbuf *ibuf, int + case IMSG_KROUTE_CHANGE: + if (idx != PFD_PIPE_ROUTE) + log_warnx("route request not from RDE"); +- else if (kr_change(imsg.data)) ++ else if (imsg.hdr.len != IMSG_HEADER_SIZE + ++ sizeof(struct kroute_full)) ++ log_warnx("wrong imsg len"); ++ else if (kr_change(imsg.hdr.peerid, imsg.data)) + rv = -1; + break; + case IMSG_KROUTE_DELETE: + if (idx != PFD_PIPE_ROUTE) + log_warnx("route request not from RDE"); +- else if (kr_delete(imsg.data)) +- rv = -1; +- break; +- case IMSG_KROUTE6_CHANGE: +- if (idx != PFD_PIPE_ROUTE) +- log_warnx("route request not from RDE"); +- else if (kr6_change(imsg.data)) +- rv = -1; +- break; +- case IMSG_KROUTE6_DELETE: +- if (idx != PFD_PIPE_ROUTE) +- log_warnx("route request not from RDE"); +- else if (kr6_delete(imsg.data)) ++ else if (imsg.hdr.len != IMSG_HEADER_SIZE + ++ sizeof(struct kroute_full)) ++ log_warnx("wrong imsg len"); ++ else if (kr_delete(imsg.hdr.peerid, imsg.data)) + rv = -1; + break; + case IMSG_NEXTHOP_ADD: + if (idx != PFD_PIPE_ROUTE) + log_warnx("nexthop request not from RDE"); +- else +- if (imsg.hdr.len != IMSG_HEADER_SIZE + +- sizeof(struct bgpd_addr)) +- log_warnx("wrong imsg len"); +- else if (kr_nexthop_add(imsg.data) == -1) +- rv = -1; ++ else if (imsg.hdr.len != IMSG_HEADER_SIZE + ++ sizeof(struct bgpd_addr)) ++ log_warnx("wrong imsg len"); ++ else if (kr_nexthop_add(imsg.hdr.peerid, imsg.data) == ++ -1) ++ rv = -1; + break; + case IMSG_NEXTHOP_REMOVE: + if (idx != PFD_PIPE_ROUTE) + log_warnx("nexthop request not from RDE"); ++ else if (imsg.hdr.len != IMSG_HEADER_SIZE + ++ sizeof(struct bgpd_addr)) ++ log_warnx("wrong imsg len"); + else +- if (imsg.hdr.len != IMSG_HEADER_SIZE + +- sizeof(struct bgpd_addr)) +- log_warnx("wrong imsg len"); +- else +- kr_nexthop_delete(imsg.data); ++ kr_nexthop_delete(imsg.hdr.peerid, imsg.data); + break; + case IMSG_PFTABLE_ADD: + if (idx != PFD_PIPE_ROUTE) +@@ -654,18 +649,19 @@ dispatch_imsg(struct imsgbuf *ibuf, int + if (idx != PFD_PIPE_SESSION) + log_warnx("couple request not from SE"); + else +- kr_fib_couple(); ++ kr_fib_couple(imsg.hdr.peerid); + break; + case IMSG_CTL_FIB_DECOUPLE: + if (idx != PFD_PIPE_SESSION) + log_warnx("decouple request not from SE"); + else +- kr_fib_decouple(); ++ kr_fib_decouple(imsg.hdr.peerid); + break; + case IMSG_CTL_KROUTE: + case IMSG_CTL_KROUTE_ADDR: + case IMSG_CTL_SHOW_NEXTHOP: + case IMSG_CTL_SHOW_INTERFACE: ++ case IMSG_CTL_SHOW_FIB_TABLES: + if (idx != PFD_PIPE_SESSION) + log_warnx("kroute request not from SE"); + else +@@ -692,6 +688,11 @@ dispatch_imsg(struct imsgbuf *ibuf, int carp_demote_set(msg->demote_group, msg->level); } break; @@ -230,7 +521,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 default: break; } -@@ -707,7 +686,7 @@ send_nexthop_update(struct kroute_nextho +@@ -707,7 +708,7 @@ send_nexthop_update(struct kroute_nextho { char *gw = NULL; @@ -239,7 +530,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 if (asprintf(&gw, ": via %s", log_addr(&msg->gateway)) == -1) { log_warn("send_nexthop_update"); -@@ -717,7 +696,7 @@ send_nexthop_update(struct kroute_nextho +@@ -717,7 +718,7 @@ send_nexthop_update(struct kroute_nextho log_info("nexthop %s now %s%s%s", log_addr(&msg->nexthop), msg->valid ? "valid" : "invalid", msg->connected ? ": directly connected" : "", @@ -248,23 +539,110 @@ diff -u -p -r1.1.1.7 -r1.1.1.9 free(gw); -@@ -758,17 +737,16 @@ bgpd_redistribute(int type, struct krout - fatalx("bgpd_redistribute: unable to redistribute v4 and v6" - "together"); - if (kr != NULL) { +@@ -733,56 +734,20 @@ send_imsg_session(int type, pid_t pid, v + } + + int +-bgpd_redistribute(int type, struct kroute *kr, struct kroute6 *kr6) ++send_network(int type, struct network_config *net, struct filter_set_head *h) + { +- struct network_config net; +- struct filter_set_head *h; +- +- if ((cflags & BGPD_FLAG_REDIST_CONNECTED) && kr && +- (kr->flags & F_CONNECTED)) +- h = connectset; +- else if ((cflags & BGPD_FLAG_REDIST_STATIC) && kr && +- (kr->flags & F_STATIC)) +- h = staticset; +- else if ((cflags & BGPD_FLAG_REDIST6_CONNECTED) && kr6 && +- (kr6->flags & F_CONNECTED)) +- h = connectset6; +- else if ((cflags & BGPD_FLAG_REDIST6_STATIC) && kr6 && +- (kr6->flags & F_STATIC)) +- h = staticset6; +- else +- return (0); +- +- bzero(&net, sizeof(net)); +- if (kr && kr6) +- fatalx("bgpd_redistribute: unable to redistribute v4 and v6" +- "together"); +- if (kr != NULL) { - net.prefix.af = AF_INET; -+ net.prefix.aid = AID_INET; - net.prefix.v4.s_addr = kr->prefix.s_addr; - net.prefixlen = kr->prefixlen; - } - if (kr6 != NULL) { +- net.prefix.v4.s_addr = kr->prefix.s_addr; +- net.prefixlen = kr->prefixlen; +- } +- if (kr6 != NULL) { - net.prefix.af = AF_INET6; -+ net.prefix.aid = AID_INET6; - memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr)); - net.prefixlen = kr6->prefixlen; - } - +- memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr)); +- net.prefixlen = kr6->prefixlen; +- } +- - - if (imsg_compose(ibuf_rde, type, 0, 0, -1, &net, +- if (imsg_compose(ibuf_rde, type, 0, 0, -1, &net, ++ if (imsg_compose(ibuf_rde, type, 0, 0, -1, net, sizeof(struct network_config)) == -1) return (-1); +- + /* networks that get deleted don't need to send the filter set */ + if (type == IMSG_NETWORK_REMOVE) +- return (1); +- ++ return (0); + if (send_filterset(ibuf_rde, h) == -1) + return (-1); + if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0) == -1) + return (-1); + +- return (1); ++ return (0); + } + + int +@@ -810,3 +775,45 @@ bgpd_filternexthop(struct kroute *kr, st + + return (1); + } ++ ++int ++control_setup(struct bgpd_config *conf) ++{ ++ int fd, restricted; ++ ++ /* control socket is outside chroot */ ++ if (!cname || strcmp(cname, conf->csock)) { ++ if (cname) { ++ control_cleanup(cname); ++ free(cname); ++ } ++ if ((cname = strdup(conf->csock)) == NULL) ++ fatal("strdup"); ++ if ((fd = control_init(0, cname)) == -1) ++ fatalx("control socket setup failed"); ++ restricted = 0; ++ if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd, ++ &restricted, sizeof(restricted)) == -1) ++ return (-1); ++ } ++ if (!conf->rcsock) { ++ /* remove restricted socket */ ++ control_cleanup(rcname); ++ free(rcname); ++ rcname = NULL; ++ } else if (!rcname || strcmp(rcname, conf->rcsock)) { ++ if (rcname) { ++ control_cleanup(rcname); ++ free(rcname); ++ } ++ if ((rcname = strdup(conf->rcsock)) == NULL) ++ fatal("strdup"); ++ if ((fd = control_init(1, rcname)) == -1) ++ fatalx("control socket setup failed"); ++ restricted = 1; ++ if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd, ++ &restricted, sizeof(restricted)) == -1) ++ return (-1); ++ } ++ return (0); ++} diff --git a/net/openbgpd/files/patch-bgpd_bgpd.conf.5 b/net/openbgpd/files/patch-bgpd_bgpd.conf.5 index 3c658e499a18..3b8afd260fd6 100644 --- a/net/openbgpd/files/patch-bgpd_bgpd.conf.5 +++ b/net/openbgpd/files/patch-bgpd_bgpd.conf.5 @@ -2,10 +2,10 @@ Index: bgpd/bgpd.conf.5 =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.conf.5,v retrieving revision 1.1.1.7 -retrieving revision 1.7 -diff -u -p -r1.1.1.7 -r1.7 +retrieving revision 1.8 +diff -u -p -r1.1.1.7 -r1.8 --- bgpd/bgpd.conf.5 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/bgpd.conf.5 10 Apr 2010 12:16:23 -0000 1.7 ++++ bgpd/bgpd.conf.5 2 Jul 2011 16:06:38 -0000 1.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bgpd.conf.5,v 1.94 2009/06/07 00:31:22 claudio Exp $ +.\" $OpenBSD: bgpd.conf.5,v 1.104 2010/03/05 15:25:00 claudio Exp $ @@ -17,11 +17,29 @@ diff -u -p -r1.1.1.7 -r1.7 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: June 7 2009 $ -+.Dd $Mdocdate: December 16 2009 $ ++.Dd $Mdocdate: October 23 2010 $ .Dt BGPD.CONF 5 .Os .Sh NAME -@@ -93,7 +93,7 @@ Set the local +@@ -26,7 +26,7 @@ + The + .Xr bgpd 8 + daemon implements the Border Gateway Protocol version 4 as described +-in RFC 1771. ++in RFC 4271. + .Sh SECTIONS + The + .Nm +@@ -38,6 +38,8 @@ configuration file. + .It Sy Global Configuration + Global settings for + .Xr bgpd 8 . ++.It Sy Routing Domain Configuration ++The definition and properties for BGP MPLS VPNs are set in this section. + .It Sy Neighbors and Groups + .Xr bgpd 8 + establishes sessions with +@@ -93,7 +95,7 @@ Set the local .Em autonomous system number to .Ar as-number . @@ -30,16 +48,86 @@ diff -u -p -r1.1.1.7 -r1.7 2-byte AS number which is used for neighbors which do not support 4-byte AS numbers. The default for the secondary AS is 23456. -@@ -313,7 +313,7 @@ is only compared between peers belonging +@@ -143,13 +145,13 @@ The default is 120 seconds. + .It Xo + .Ic dump + .Op Ic rib Ar name +-.Pq Ic table Ns \&| Ns Ic table-mp ++.Pq Ic table Ns | Ns Ic table-mp + .Ar file Op Ar timeout + .Xc + .It Xo + .Ic dump +-.Pq Ic all Ns \&| Ns Ic updates +-.Pq Ic in Ns \&| Ns Ic out ++.Pq Ic all Ns | Ns Ic updates ++.Pq Ic in Ns | Ns Ic out + .Ar file Op Ar timeout + .Xc + Dump the RIB, a.k.a. the +@@ -195,7 +197,7 @@ dump updates out "/tmp/updates-out-%H%M" + .Pp + .It Xo + .Ic fib-update +-.Pq Ic yes Ns \&| Ns Ic no ++.Pq Ic yes Ns | Ns Ic no + .Xc + If set to + .Ic no , +@@ -242,12 +244,12 @@ Log received and sent updates. + .Xc + .It Xo + .Ic network +-.Pq Ic inet Ns \&| Ns Ic inet6 ++.Pq Ic inet Ns | Ns Ic inet6 + .Ic static Op Ic set ...\& + .Xc + .It Xo + .Ic network +-.Pq Ic inet Ns \&| Ns Ic inet6 ++.Pq Ic inet Ns | Ns Ic inet6 + .Ic connected Op Ic set ...\& + .Xc + Announce the specified network as belonging to our AS. +@@ -278,7 +280,7 @@ section. + .Ic nexthop + .Ic qualify + .Ic via +-.Pq Ic bgp Ns \&| Ns Ic default ++.Pq Ic bgp Ns | Ns Ic default + .Xc + If set to + .Ic bgp , +@@ -295,7 +297,7 @@ daemons like + .Ic rde + .Ic med + .Ic compare +-.Pq Ic always Ns \&| Ns Ic strict ++.Pq Ic always Ns | Ns Ic strict + .Xc + If set to + .Ic always , +@@ -313,20 +315,31 @@ is only compared between peers belonging .Ic rib Ar name .Op Ic no Ic evaluate .Xc -Creat an additional RIB named ++.It Xo ++.Ic rde ++.Ic rib Ar name ++.Op Ic rtable Ar number ++.Xc +Create an additional RIB named .Ar name . It is possible to disable the decision process per RIB with the .Ic no Ic evaluate -@@ -321,7 +321,7 @@ flag. + flag. ++If a ++.Ic rtable ++is specified, routes will be exported to the given kernel routing table. ++Currently the routing table must belong to the default routing domain and ++nexthop verification happens on table 0. ++Routes in the specified table will not be considered for nexthop verification. .Ic Adj-RIB-In and .Ic Loc-RIB @@ -48,12 +136,189 @@ diff -u -p -r1.1.1.7 -r1.7 .Pp .It Xo .Ic rde -@@ -483,6 +483,17 @@ Only routes for that address family and + .Ic route-age +-.Pq Ic ignore Ns \&| Ns Ic evaluate ++.Pq Ic ignore Ns | Ns Ic evaluate + .Xc + If set to + .Ic evaluate , +@@ -339,7 +352,7 @@ The default is + .Pp + .It Xo + .Ic route-collector +-.Pq Ic yes Ns \&| Ns Ic no ++.Pq Ic yes Ns | Ns Ic no + .Xc + If set to + .Ic yes , +@@ -361,13 +374,24 @@ to the local machine. + Work with the given kernel routing table + instead of the default table, + .Ar 0 . +-Note that this table is used for nexthop verification as well. +-Directly connected networks are always taken into account, even though +-their routes live in table 0. ++Note that table 0 is used for nexthop verification. ++Routes in the specified table will not be considered for nexthop verification. ++This is the same as using the following syntax: ++.Bd -literal -offset indent ++rde rib Loc-RIB rtable number ++.Ed ++.Pp ++.It Ic socket Qo Ar path Qc Op Ic restricted ++Set the control socket location to ++.Ar path . ++If ++.Ic restricted ++is specified a restricted control socket will be created. ++By default /var/run/bgpd.sock is used and no restricted socket is created. + .Pp + .It Xo + .Ic transparent-as +-.Pq Ic yes Ns \&| Ns Ic no ++.Pq Ic yes Ns | Ns Ic no + .Xc + If set to + .Ic yes , +@@ -376,6 +400,111 @@ to EBGP neighbors are not prepended with + The default is + .Ic no . + .El ++.Sh ROUTING DOMAIN CONFIGURATION ++.Xr bgpd 8 ++supports the setup and distribution of Virtual Private Networks. ++It is possible to import and export prefixes between routing domains. ++Each routing domain is specified by an ++.Ic rdomain ++section, which allows properties to be set specifically for that rdomain: ++.Bd -literal -offset indent ++rdomain 1 { ++ descr "a rdomain" ++ rd 65002:1 ++ import-target rt 65002:42 ++ export-target rt 65002:42 ++ network 192.168.1/24 ++ depend on mpe0 ++} ++.Ed ++.Pp ++There are several routing domain properties: ++.Pp ++.Bl -tag -width Ds -compact ++.It Ic depend on Ar interface ++Routes added to the rdomain will use this interface as the outgoing interface. ++Normally this will be an MPLS Provider Edge, ++.Xr mpe 4 , ++interface that is part of the rdomain. ++Local networks will be announced with the MPLS label specified on the interface. ++.Pp ++.It Ic descr Ar description ++Add a description. ++The description is used when logging but has no further meaning to ++.Xr bgpd 8 . ++.Pp ++.It Ic export-target Ar subtype Ar as-number Ns Li : Ns Ar local ++.It Ic export-target Ar subtype Ar IP Ns Li : Ns Ar local ++Specify an extended community which will be attached to announced networks. ++More than one ++.Ic export-target ++can be specified. ++See also the ++.Sx ATTRIBUTE SET ++section for further information about the encoding. ++The ++.Ar subtype ++should be set to ++.Ar rt ++for best compatibility with other implementations. ++.Pp ++.It Xo ++.Ic fib-update ++.Pq Ic yes Ns | Ns Ic no ++.Xc ++If set to ++.Ic no , ++do not update the Forwarding Information Base, a.k.a. the kernel ++routing table. ++The default is ++.Ic yes . ++.Pp ++.It Ic import-target Ar subtype Ar as-number Ns Li : Ns Ar local ++.It Ic import-target Ar subtype Ar IP Ns Li : Ns Ar local ++Only prefixes matching one of the specified ++.Ic import-targets ++will be imported into the rdomain. ++More than one ++.Ic import-target ++can be specified. ++See also the ++.Sx ATTRIBUTE SET ++section for further information about the encoding of extended communities. ++The ++.Ar subtype ++should be set to ++.Ar rt ++for best compatibility with other implementations. ++.Pp ++.It Ic network Ar arguments ... ++Define which networks should be exported into this VPN. ++See also the ++.Ic nexthop ++section in ++.Sx GLOBAL CONFIGURATION ++for further information about the arguments. ++.Pp ++.It Ic rd Ar as-number Ns Li : Ns Ar local ++.It Ic rd Ar IP Ns Li : Ns Ar local ++The Route Distinguishers uniquely identifies a set of VPN prefixes. ++Only prefixes matching the ++.Ic rd ++will be imported into the routing domain. ++The purpose of the ++.Ic rd ++is solely to allow one to create distinct routes to a common address prefix. ++The ++.Ar as-number ++or ++.Ar IP ++of a ++.Ic rd ++should be set to a number or IP that was assigned by an appropriate authority. ++Whereas ++.Ar local ++can be chosen by the local operator. ++.Pp ++.El + .Sh NEIGHBORS AND GROUPS + .Xr bgpd 8 + establishes TCP connections to other BGP speakers called +@@ -470,21 +599,35 @@ The default for IBGP peers is + .Pp + .It Xo + .Ic announce +-.Pq Ic IPv4 Ns \&| Ns Ic IPv6 +-.Pq Ic none Ns \&| Ns Ic unicast ++.Pq Ic IPv4 Ns | Ns Ic IPv6 ++.Pq Ic none Ns | Ns Ic unicast Ns | Ns Ic vpn + .Xc + For the given address family, control which subsequent address families + (at the moment, only + .Em none , +-which disables the announcement of that address family, and +-.Em unicast +-are supported) are announced during the capabilities negotiation. ++which disables the announcement of that address family, ++.Em unicast , ++and ++.Em vpn , ++which allows the distribution of BGP MPLS VPNs, are supported) are announced ++during the capabilities negotiation. + Only routes for that address family and subsequent address family will be announced and processed. .Pp .It Xo +.Ic announce as-4byte -+.Pq Ic yes Ns \&| Ns Ic no ++.Pq Ic yes Ns | Ns Ic no +.Xc +If set to +.Ic no , @@ -64,15 +329,18 @@ diff -u -p -r1.1.1.7 -r1.7 +.Pp +.It Xo .Ic announce capabilities - .Pq Ic yes Ns \&| Ns Ic no +-.Pq Ic yes Ns \&| Ns Ic no ++.Pq Ic yes Ns | Ns Ic no .Xc -@@ -493,6 +504,29 @@ This can be helpful to connect to old or + If set to + .Ic no , +@@ -493,6 +636,29 @@ This can be helpful to connect to old or The default is .Ic yes . .Pp +.It Xo +.Ic announce refresh -+.Pq Ic yes Ns \&| Ns Ic no ++.Pq Ic yes Ns | Ns Ic no +.Xc +If set to +.Ic no , @@ -82,7 +350,7 @@ diff -u -p -r1.1.1.7 -r1.7 +.Pp +.It Xo +.Ic announce restart -+.Pq Ic yes Ns \&| Ns Ic no ++.Pq Ic yes Ns | Ns Ic no +.Xc +If set to +.Ic yes , @@ -96,7 +364,7 @@ diff -u -p -r1.1.1.7 -r1.7 .It Ic demote Ar group Increase the .Xr carp 4 -@@ -504,7 +538,7 @@ The demotion counter will be increased a +@@ -504,7 +670,7 @@ The demotion counter will be increased a .Xr bgpd 8 starts and decreased 60 seconds after the session went to state @@ -105,7 +373,27 @@ diff -u -p -r1.1.1.7 -r1.7 For neighbors added at runtime, the demotion counter is only increased after the session has been .Em ESTABLISHED -@@ -589,6 +623,12 @@ Inherited from the global configuration +@@ -548,8 +714,8 @@ Do not start the session when bgpd comes + .Pp + .It Xo + .Ic dump +-.Pq Ic all Ns \&| Ns Ic updates +-.Pq Ic in Ns \&| Ns Ic out ++.Pq Ic all Ns | Ns Ic updates ++.Pq Ic in Ns | Ns Ic out + .Ar file Op Ar timeout + .Xc + Do a peer specific MRT dump. +@@ -564,7 +730,7 @@ section in + .Pp + .It Xo + .Ic enforce neighbor-as +-.Pq Ic yes Ns \&| Ns Ic no ++.Pq Ic yes Ns | Ns Ic no + .Xc + If set to + .Ic yes , +@@ -589,10 +755,16 @@ Inherited from the global configuration Set the minimal acceptable holdtime. Inherited from the global configuration if not given. .Pp @@ -117,8 +405,23 @@ diff -u -p -r1.1.1.7 -r1.7 +.Pp .It Xo .Ic ipsec - .Pq Ic ah Ns \&| Ns Ic esp -@@ -639,11 +679,11 @@ is responsible for managing the session +-.Pq Ic ah Ns \&| Ns Ic esp +-.Pq Ic in Ns \&| Ns Ic out ++.Pq Ic ah Ns | Ns Ic esp ++.Pq Ic in Ns | Ns Ic out + .Ic spi Ar spi-number authspec Op Ar encspec + .Xc + Enable IPsec with static keying. +@@ -627,7 +799,7 @@ Keys must be given in hexadecimal format + .Pp + .It Xo + .Ic ipsec +-.Pq Ic ah Ns \&| Ns Ic esp ++.Pq Ic ah Ns | Ns Ic esp + .Ic ike + .Xc + Enable IPsec with dynamic keying. +@@ -639,11 +811,11 @@ is responsible for managing the session With .Xr isakmpd 8 , it is sufficient to copy the peer's public key, found in @@ -132,7 +435,7 @@ diff -u -p -r1.1.1.7 -r1.7 The local public key must be copied to the peer in the same way. As .Xr bgpd 8 -@@ -698,7 +738,7 @@ Do not attempt to actively open a TCP co +@@ -698,7 +870,7 @@ Do not attempt to actively open a TCP co .It Ic remote-as Ar as-number Set the AS number of the remote system. .Pp @@ -141,10 +444,51 @@ diff -u -p -r1.1.1.7 -r1.7 Bind the neighbor to the specified RIB. .Pp .It Ic route-reflector Op Ar address -@@ -917,6 +957,31 @@ may be set to +@@ -732,8 +904,8 @@ These sets are rewritten into filter rul + .Pp + .It Xo + .Ic softreconfig +-.Pq Ic in Ns \&| Ns Ic out +-.Pq Ic yes Ns \&| Ns Ic no ++.Pq Ic in Ns | Ns Ic out ++.Pq Ic yes Ns | Ns Ic no + .Xc + Turn soft reconfiguration on or off for the specified direction. + If soft reconfiguration is turned on, filter changes will be applied on +@@ -760,7 +932,7 @@ tcp md5sig key deadbeef + .Pp + .It Xo + .Ic transparent-as +-.Pq Ic yes Ns \&| Ns Ic no ++.Pq Ic yes Ns | Ns Ic no + .Xc + If set to + .Ic yes , +@@ -772,7 +944,7 @@ setting. + .Pp + .It Xo + .Ic ttl-security +-.Pq Ic yes Ns \&| Ns Ic no ++.Pq Ic yes Ns | Ns Ic no + .Xc + Enable or disable ttl-security. + When enabled, +@@ -849,6 +1021,10 @@ is matched against a part of the + .Em AS path + specified by the + .Ar as-type . ++.Ar as-number ++may be set to ++.Ic neighbor-as , ++which is expanded to the current neighbor remote AS number. + .Ar as-type + is one of the following operators: + .Pp +@@ -917,7 +1093,32 @@ may be set to which is expanded to the current neighbor remote AS number. .Pp .It Xo +-.Pq Ic from Ns \&| Ns Ic to +.Ic ext-community +.Ar subtype Ar as-number Ns Li : Ns Ar local +.Xc @@ -170,10 +514,45 @@ diff -u -p -r1.1.1.7 -r1.7 +section for further information about the encoding. +.Pp +.It Xo - .Pq Ic from Ns \&| Ns Ic to ++.Pq Ic from Ns | Ns Ic to .Ar peer .Xc -@@ -1028,6 +1093,12 @@ matches a rule which has the + This rule applies only to +@@ -945,7 +1146,7 @@ if enclosed in curly brackets: + deny from { 128.251.16.1, 251.128.16.2, group hojo } + .Ed + .Pp +-.It Pq Ic inet Ns \&| Ns Ic inet6 ++.It Pq Ic inet Ns | Ns Ic inet6 + This rule applies only to routes matching the stated address family. + The address family needs to be set only in rules that use + .Ic prefixlen +@@ -953,6 +1154,24 @@ without specifying a + .Ic prefix + beforehand. + .Pp ++.It Ic max-as-len Ar len ++This rule applies only to ++.Em UPDATES ++where the ++.Em AS path ++has more than ++.Ar len ++elements. ++.Pp ++.It Ic max-as-seq Ar len ++This rule applies only to ++.Em UPDATES ++where a single ++.Em AS number ++is repeated more than ++.Ar len ++times. ++.Pp + .It Xo + .Ic prefix + .Ar address Ns Li / Ns Ar len +@@ -1028,6 +1247,12 @@ matches a rule which has the option set, this rule is considered the last matching rule, and evaluation of subsequent rules is skipped. .Pp @@ -186,7 +565,7 @@ diff -u -p -r1.1.1.7 -r1.7 .It Ic set Ar attribute ... All matching rules can set the .Em AS path attributes -@@ -1079,6 +1150,48 @@ Alternately, well-known communities may +@@ -1079,6 +1304,48 @@ Alternately, well-known communities may or .Ic NO_PEER . .Pp @@ -235,7 +614,7 @@ diff -u -p -r1.1.1.7 -r1.7 .It Ic localpref Ar number Set the .Em LOCAL_PREF -@@ -1108,6 +1221,20 @@ otherwise it will be set to +@@ -1108,6 +1375,20 @@ otherwise it will be set to .Ar number . .Pp .It Xo @@ -256,7 +635,19 @@ diff -u -p -r1.1.1.7 -r1.7 .Ic nexthop .Sm off .Po Ar address \*(Ba -@@ -1181,8 +1308,8 @@ For prefixes with equally long paths, th +@@ -1157,9 +1438,8 @@ times to the + .Em AS path . + .Pp + .It Ic rtlabel Ar label +-Add the prefix with the specified +-.Ar label +-to the kernel routing table. ++Add the prefix to the kernel routing table with the specified ++.Ar label . + .Pp + .It Ic weight Ar number + The +@@ -1181,8 +1461,8 @@ For prefixes with equally long paths, th is selected. .El .Sh FILES diff --git a/net/openbgpd/files/patch-bgpd_bgpd.h b/net/openbgpd/files/patch-bgpd_bgpd.h index d522bad36b14..c374b981553c 100644 --- a/net/openbgpd/files/patch-bgpd_bgpd.h +++ b/net/openbgpd/files/patch-bgpd_bgpd.h @@ -2,17 +2,25 @@ Index: bgpd/bgpd.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.h,v retrieving revision 1.1.1.8 -retrieving revision 1.11 -diff -u -p -r1.1.1.8 -r1.11 +retrieving revision 1.12 +diff -u -p -r1.1.1.8 -r1.12 --- bgpd/bgpd.h 14 Feb 2010 20:19:57 -0000 1.1.1.8 -+++ bgpd/bgpd.h 10 Apr 2010 12:16:23 -0000 1.11 ++++ bgpd/bgpd.h 2 Jul 2011 16:06:38 -0000 1.12 @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.241 2009/06/12 16:42:53 claudio Exp $ */ +/* $OpenBSD: bgpd.h,v 1.255 2010/04/06 13:25:08 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -30,11 +30,16 @@ +@@ -21,6 +21,7 @@ + #include <sys/types.h> + #include <sys/socket.h> + #include <sys/queue.h> ++#include <sys/tree.h> + #include <net/route.h> + #include <netinet/in.h> + #include <arpa/inet.h> +@@ -30,11 +31,16 @@ #include <poll.h> #include <stdarg.h> @@ -30,7 +38,7 @@ diff -u -p -r1.1.1.8 -r1.11 #define BGPD_USER "_bgpd" #define PEER_DESCR_LEN 32 #define PFTABLE_LEN 16 -@@ -42,8 +47,6 @@ +@@ -42,8 +48,6 @@ #define IPSEC_ENC_KEY_LEN 32 #define IPSEC_AUTH_KEY_LEN 20 @@ -39,7 +47,30 @@ diff -u -p -r1.1.1.8 -r1.11 #define MAX_PKTSIZE 4096 #define MIN_HOLDTIME 3 #define READ_BUF_SIZE 65535 -@@ -109,18 +112,74 @@ enum reconf_action { +@@ -55,13 +59,8 @@ + #define BGPD_OPT_NOACTION 0x0004 + #define BGPD_OPT_FORCE_DEMOTE 0x0008 + +-#define BGPD_FLAG_NO_FIB_UPDATE 0x0001 + #define BGPD_FLAG_NO_EVALUATE 0x0002 + #define BGPD_FLAG_REFLECTOR 0x0004 +-#define BGPD_FLAG_REDIST_STATIC 0x0008 +-#define BGPD_FLAG_REDIST_CONNECTED 0x0010 +-#define BGPD_FLAG_REDIST6_STATIC 0x0020 +-#define BGPD_FLAG_REDIST6_CONNECTED 0x0040 + #define BGPD_FLAG_NEXTHOP_BGP 0x0080 + #define BGPD_FLAG_NEXTHOP_DEFAULT 0x1000 + #define BGPD_FLAG_DECISION_MASK 0x0f00 +@@ -83,6 +82,8 @@ + #define F_REJECT 0x0080 + #define F_BLACKHOLE 0x0100 + #define F_LONGER 0x0200 ++#define F_MPLS 0x0400 ++#define F_REDISTRIBUTED 0x0800 + #define F_CTL_DETAIL 0x1000 /* only used by bgpctl */ + #define F_CTL_ADJ_IN 0x2000 + #define F_CTL_ADJ_OUT 0x4000 +@@ -109,18 +110,74 @@ enum reconf_action { RECONF_DELETE }; @@ -118,7 +149,25 @@ diff -u -p -r1.1.1.8 -r1.11 #define addr8 ba.addr8 #define addr16 ba.addr16 #define addr32 ba.addr32 -@@ -205,11 +264,10 @@ struct peer_auth { +@@ -141,17 +198,12 @@ TAILQ_HEAD(listen_addrs, listen_addr); + TAILQ_HEAD(filter_set_head, filter_set); + + struct bgpd_config { +- struct filter_set_head connectset; +- struct filter_set_head connectset6; +- struct filter_set_head staticset; +- struct filter_set_head staticset6; + struct listen_addrs *listen_addrs; + char *csock; + char *rcsock; + int opts; + int flags; + int log; +- u_int rtableid; + u_int32_t bgpid; + u_int32_t clusterid; + u_int32_t as; +@@ -205,11 +257,10 @@ struct peer_auth { }; struct capabilities { @@ -134,7 +183,7 @@ diff -u -p -r1.1.1.8 -r1.11 }; struct peer_config { -@@ -248,6 +306,7 @@ struct peer_config { +@@ -248,21 +299,31 @@ struct peer_config { u_int8_t ttlsec; /* TTL security hack */ u_int8_t flags; u_int8_t pad[3]; @@ -142,15 +191,119 @@ diff -u -p -r1.1.1.8 -r1.11 }; #define PEERFLAG_TRANS_AS 0x01 -@@ -292,6 +351,7 @@ enum imsg_type { + ++enum network_type { ++ NETWORK_DEFAULT, ++ NETWORK_STATIC, ++ NETWORK_CONNECTED ++}; ++ + struct network_config { + struct bgpd_addr prefix; + struct filter_set_head attrset; ++ u_int rtableid; ++ enum network_type type; + u_int8_t prefixlen; ++ u_int8_t old; /* used for reloading */ + }; + + TAILQ_HEAD(network_head, network); + + struct network { +- struct network_config net; +- TAILQ_ENTRY(network) entry; ++ struct network_config net; ++ TAILQ_ENTRY(network) entry; + }; + + enum imsg_type { +@@ -276,7 +337,6 @@ enum imsg_type { + IMSG_CTL_NEIGHBOR_CLEAR, + IMSG_CTL_NEIGHBOR_RREFRESH, + IMSG_CTL_KROUTE, +- IMSG_CTL_KROUTE6, + IMSG_CTL_KROUTE_ADDR, + IMSG_CTL_RESULT, + IMSG_CTL_SHOW_NEIGHBOR, +@@ -288,10 +348,11 @@ enum imsg_type { + IMSG_CTL_SHOW_RIB_ATTR, + IMSG_CTL_SHOW_RIB_COMMUNITY, + IMSG_CTL_SHOW_NETWORK, +- IMSG_CTL_SHOW_NETWORK6, IMSG_CTL_SHOW_RIB_MEM, IMSG_CTL_SHOW_TERSE, IMSG_CTL_SHOW_TIMER, + IMSG_CTL_LOG_VERBOSE, ++ IMSG_CTL_SHOW_FIB_TABLES, IMSG_NETWORK_ADD, IMSG_NETWORK_REMOVE, IMSG_NETWORK_FLUSH, -@@ -400,14 +460,12 @@ struct kroute6 { +@@ -302,6 +363,11 @@ enum imsg_type { + IMSG_RECONF_PEER, + IMSG_RECONF_FILTER, + IMSG_RECONF_LISTENER, ++ IMSG_RECONF_CTRL, ++ IMSG_RECONF_RDOMAIN, ++ IMSG_RECONF_RDOMAIN_EXPORT, ++ IMSG_RECONF_RDOMAIN_IMPORT, ++ IMSG_RECONF_RDOMAIN_DONE, + IMSG_RECONF_DONE, + IMSG_UPDATE, + IMSG_UPDATE_ERR, +@@ -313,8 +379,6 @@ enum imsg_type { + IMSG_MRT_CLOSE, + IMSG_KROUTE_CHANGE, + IMSG_KROUTE_DELETE, +- IMSG_KROUTE6_CHANGE, +- IMSG_KROUTE6_DELETE, + IMSG_NEXTHOP_ADD, + IMSG_NEXTHOP_REMOVE, + IMSG_NEXTHOP_UPDATE, +@@ -379,9 +443,43 @@ enum suberr_cease { + ERR_CEASE_RSRC_EXHAUST + }; + ++struct kroute_node; ++struct kroute6_node; ++struct knexthop_node; ++RB_HEAD(kroute_tree, kroute_node); ++RB_HEAD(kroute6_tree, kroute6_node); ++RB_HEAD(knexthop_tree, knexthop_node); ++ ++struct ktable { ++ char descr[PEER_DESCR_LEN]; ++ char ifmpe[IFNAMSIZ]; ++ struct kroute_tree krt; ++ struct kroute6_tree krt6; ++ struct knexthop_tree knt; ++ struct network_head krn; ++ u_int rtableid; ++ u_int nhtableid; /* rdomain id for nexthop lookup */ ++ u_int ifindex; /* ifindex of ifmpe */ ++ int nhrefcnt; /* refcnt for nexthop table */ ++ enum reconf_action state; ++ u_int8_t fib_conf; /* configured FIB sync flag */ ++ u_int8_t fib_sync; /* is FIB synced with kernel? */ ++}; ++ ++struct kroute_full { ++ struct bgpd_addr prefix; ++ struct bgpd_addr nexthop; ++ char label[RTLABEL_LEN]; ++ u_int16_t flags; ++ u_short ifindex; ++ u_int8_t prefixlen; ++ u_int8_t priority; ++}; ++ + struct kroute { + struct in_addr prefix; + struct in_addr nexthop; ++ u_int32_t mplslabel; + u_int16_t flags; + u_int16_t labelid; + u_short ifindex; +@@ -400,14 +498,12 @@ struct kroute6 { }; struct kroute_nexthop { @@ -167,7 +320,7 @@ diff -u -p -r1.1.1.8 -r1.11 }; struct kif { -@@ -423,8 +481,7 @@ struct kif { +@@ -423,8 +519,7 @@ struct kif { struct session_up { struct bgpd_addr local_addr; struct bgpd_addr remote_addr; @@ -177,7 +330,7 @@ diff -u -p -r1.1.1.8 -r1.11 u_int32_t remote_bgpid; u_int16_t short_as; }; -@@ -437,8 +494,13 @@ struct pftable_msg { +@@ -437,8 +532,13 @@ struct pftable_msg { struct ctl_show_nexthop { struct bgpd_addr addr; @@ -188,14 +341,66 @@ diff -u -p -r1.1.1.8 -r1.11 + struct kroute6 kr6; + } kr; + u_int8_t valid; -+ u_int8_t krvalid;; ++ u_int8_t krvalid; }; struct ctl_neighbor { -@@ -508,6 +570,28 @@ struct filter_community { - int type; +@@ -447,20 +547,10 @@ struct ctl_neighbor { + int show_timers; + }; + +-struct kroute_label { +- struct kroute kr; +- char label[RTLABEL_LEN]; +-}; +- +-struct kroute6_label { +- struct kroute6 kr; +- char label[RTLABEL_LEN]; +-}; +- +-#define F_RIB_ELIGIBLE 0x01 +-#define F_RIB_ACTIVE 0x02 +-#define F_RIB_INTERNAL 0x04 +-#define F_RIB_ANNOUNCE 0x08 ++#define F_PREF_ELIGIBLE 0x01 ++#define F_PREF_ACTIVE 0x02 ++#define F_PREF_INTERNAL 0x04 ++#define F_PREF_ANNOUNCE 0x08 + + struct ctl_show_rib { + struct bgpd_addr true_nexthop; +@@ -498,16 +588,52 @@ enum as_spec { + AS_EMPTY + }; + ++enum aslen_spec { ++ ASLEN_NONE, ++ ASLEN_MAX, ++ ASLEN_SEQ ++}; ++ + struct filter_as { +- enum as_spec type; + u_int32_t as; ++ u_int16_t flags; ++ enum as_spec type; }; ++struct filter_aslen { ++ u_int aslen; ++ enum aslen_spec type; ++}; ++ ++#define AS_FLAG_NEIGHBORAS 0x01 ++ + struct filter_community { +- int as; +- int type; ++ int as; ++ int type; ++}; ++ +struct filter_extcommunity { + u_int16_t flags; + u_int8_t type; @@ -215,13 +420,13 @@ diff -u -p -r1.1.1.8 -r1.11 + } ext_ip; + u_int64_t ext_opaq; /* only 48 bits */ + } data; -+}; -+ + }; + + struct ctl_show_rib_request { char rib[PEER_DESCR_LEN]; struct ctl_neighbor neighbor; -@@ -518,8 +602,8 @@ struct ctl_show_rib_request { +@@ -518,8 +644,8 @@ struct ctl_show_rib_request { pid_t pid; u_int16_t flags; enum imsg_type type; @@ -231,7 +436,7 @@ diff -u -p -r1.1.1.8 -r1.11 }; enum filter_actions { -@@ -585,6 +669,28 @@ struct filter_peers { +@@ -585,6 +711,28 @@ struct filter_peers { #define EXT_COMMUNITY_OSPF_RTR_TYPE 6 /* RFC 4577 */ #define EXT_COMMUNITY_OSPF_RTR_ID 7 /* RFC 4577 */ #define EXT_COMMUNITY_BGP_COLLECT 8 /* RFC 4384 */ @@ -260,7 +465,7 @@ diff -u -p -r1.1.1.8 -r1.11 struct filter_prefix { -@@ -594,16 +700,17 @@ struct filter_prefix { +@@ -594,16 +742,18 @@ struct filter_prefix { struct filter_prefixlen { enum comp_ops op; @@ -278,12 +483,13 @@ diff -u -p -r1.1.1.8 -r1.11 + struct filter_prefix prefix; + struct filter_prefixlen prefixlen; + struct filter_as as; ++ struct filter_aslen aslen; + struct filter_community community; + struct filter_extcommunity ext_community; }; TAILQ_HEAD(filter_head, filter_rule); -@@ -635,10 +742,13 @@ enum action_types { +@@ -635,10 +785,13 @@ enum action_types { ACTION_SET_NEXTHOP_SELF, ACTION_SET_COMMUNITY, ACTION_DEL_COMMUNITY, @@ -298,7 +504,7 @@ diff -u -p -r1.1.1.8 -r1.11 }; struct filter_set { -@@ -650,23 +760,31 @@ struct filter_set { +@@ -650,23 +803,53 @@ struct filter_set { int32_t relative; struct bgpd_addr nexthop; struct filter_community community; @@ -313,15 +519,37 @@ diff -u -p -r1.1.1.8 -r1.11 -struct rrefresh { - u_int16_t afi; - u_int8_t safi; ++struct rdomain { ++ SIMPLEQ_ENTRY(rdomain) entry; ++ char descr[PEER_DESCR_LEN]; ++ char ifmpe[IFNAMSIZ]; ++ struct filter_set_head import; ++ struct filter_set_head export; ++ struct network_head net_l; ++ u_int64_t rd; ++ u_int rtableid; ++ u_int label; ++ int flags; ++}; ++SIMPLEQ_HEAD(rdomain_head, rdomain); ++ +struct rde_rib { + SIMPLEQ_ENTRY(rde_rib) entry; + char name[PEER_DESCR_LEN]; ++ u_int rtableid; + u_int16_t id; + u_int16_t flags; }; +SIMPLEQ_HEAD(rib_names, rde_rib); +extern struct rib_names ribnames; + ++/* rde_rib flags */ ++#define F_RIB_ENTRYLOCK 0x0001 ++#define F_RIB_NOEVALUATE 0x0002 ++#define F_RIB_NOFIB 0x0004 ++#define F_RIB_NOFIBSYNC 0x0008 ++#define F_RIB_HASNOFIB (F_RIB_NOFIB | F_RIB_NOEVALUATE) ++ +/* 4-byte magic AS number */ +#define AS_TRANS 23456 @@ -335,7 +563,7 @@ diff -u -p -r1.1.1.8 -r1.11 int64_t nexthop_cnt; int64_t aspath_cnt; int64_t aspath_size; -@@ -677,28 +795,17 @@ struct rde_memstats { +@@ -677,38 +860,29 @@ struct rde_memstats { int64_t attr_dcnt; }; @@ -375,7 +603,12 @@ diff -u -p -r1.1.1.8 -r1.11 /* prototypes */ /* bgpd.c */ -@@ -709,6 +816,7 @@ int bgpd_filternexthop(struct kroute * + void send_nexthop_update(struct kroute_nexthop *); + void send_imsg_session(int, pid_t, void *, u_int16_t); +-int bgpd_redistribute(int, struct kroute *, struct kroute6 *); ++int send_network(int, struct network_config *, ++ struct filter_set_head *); + int bgpd_filternexthop(struct kroute *, struct kroute6 *); /* log.c */ void log_init(int); @@ -383,7 +616,48 @@ diff -u -p -r1.1.1.8 -r1.11 void vlog(int, const char *, va_list); void log_peer_warn(const struct peer_config *, const char *, ...); void log_peer_warnx(const struct peer_config *, const char *, ...); -@@ -779,11 +887,20 @@ const char *log_addr(const struct bgpd_a +@@ -726,19 +900,22 @@ int cmdline_symset(char *); + int host(const char *, struct bgpd_addr *, u_int8_t *); + + /* kroute.c */ +-int kr_init(int, u_int); +-int kr_change(struct kroute_label *); +-int kr_delete(struct kroute_label *); +-int kr6_change(struct kroute6_label *); +-int kr6_delete(struct kroute6_label *); ++int kr_init(void); ++int ktable_update(u_int, char *, char *, int); ++void ktable_preload(void); ++void ktable_postload(void); ++int ktable_exists(u_int, u_int *); ++int kr_change(u_int, struct kroute_full *); ++int kr_delete(u_int, struct kroute_full *); + void kr_shutdown(void); +-void kr_fib_couple(void); +-void kr_fib_decouple(void); ++void kr_fib_couple(u_int); ++void kr_fib_decouple(u_int); + int kr_dispatch_msg(void); +-int kr_nexthop_add(struct bgpd_addr *); +-void kr_nexthop_delete(struct bgpd_addr *); ++int kr_nexthop_add(u_int32_t, struct bgpd_addr *); ++void kr_nexthop_delete(u_int32_t, struct bgpd_addr *); + void kr_show_route(struct imsg *); + void kr_ifinfo(char *); ++int kr_net_reload(u_int, struct network_head *); + int kr_reload(void); + struct in6_addr *prefixlen2mask6(u_int8_t prefixlen); + +@@ -772,6 +949,8 @@ void pftable_ref(u_int16_t); + /* rde_filter.c */ + void filterset_free(struct filter_set_head *); + int filterset_cmp(struct filter_set *, struct filter_set *); ++void filterset_move(struct filter_set_head *, ++ struct filter_set_head *); + const char *filterset_name(enum action_types); + + /* util.c */ +@@ -779,11 +958,20 @@ const char *log_addr(const struct bgpd_a const char *log_in6addr(const struct in6_addr *); const char *log_sockaddr(struct sockaddr *); const char *log_as(u_int32_t); diff --git a/net/openbgpd/files/patch-bgpd_buffer.c b/net/openbgpd/files/patch-bgpd_buffer.c index 875b789f68b3..7ca7a41c1438 100644 --- a/net/openbgpd/files/patch-bgpd_buffer.c +++ b/net/openbgpd/files/patch-bgpd_buffer.c @@ -1,39 +1,182 @@ Index: bgpd/buffer.c =================================================================== -RCS file: /home/cvs/private/hrs/openbgpd/bgpd/buffer.c,v -retrieving revision 1.1.1.7 -retrieving revision 1.1.1.8 -diff -u -p -r1.1.1.7 -r1.1.1.8 +RCS file: bgpd/buffer.c +diff -N bgpd/buffer.c --- bgpd/buffer.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/buffer.c 14 Feb 2010 20:27:06 -0000 1.1.1.8 -@@ -1,4 +1,4 @@ ++++ /dev/null 1 Jan 1970 00:00:00 -0000 +@@ -1,305 +0,0 @@ -/* $OpenBSD: buffer.c,v 1.43 2009/06/06 06:33:15 eric Exp $ */ -+/* $OpenBSD: buffer.c,v 1.44 2009/07/23 18:58:42 eric Exp $ */ - - /* - * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -144,7 +144,7 @@ int - buf_write(struct msgbuf *msgbuf) - { - struct iovec iov[IOV_MAX]; +- +-/* +- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> +- * +- * Permission to use, copy, modify, and distribute this software for any +- * purpose with or without fee is hereby granted, provided that the above +- * copyright notice and this permission notice appear in all copies. +- * +- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- */ +- +-#include <sys/param.h> +-#include <sys/queue.h> +-#include <sys/socket.h> +-#include <sys/uio.h> +- +-#include <errno.h> +-#include <stdlib.h> +-#include <string.h> +-#include <unistd.h> +- +-#include "imsg.h" +- +-int buf_realloc(struct buf *, size_t); +-void buf_enqueue(struct msgbuf *, struct buf *); +-void buf_dequeue(struct msgbuf *, struct buf *); +- +-struct buf * +-buf_open(size_t len) +-{ +- struct buf *buf; +- +- if ((buf = calloc(1, sizeof(struct buf))) == NULL) +- return (NULL); +- if ((buf->buf = malloc(len)) == NULL) { +- free(buf); +- return (NULL); +- } +- buf->size = buf->max = len; +- buf->fd = -1; +- +- return (buf); +-} +- +-struct buf * +-buf_dynamic(size_t len, size_t max) +-{ +- struct buf *buf; +- +- if (max < len) +- return (NULL); +- +- if ((buf = buf_open(len)) == NULL) +- return (NULL); +- +- if (max > 0) +- buf->max = max; +- +- return (buf); +-} +- +-int +-buf_realloc(struct buf *buf, size_t len) +-{ +- u_char *b; +- +- /* on static buffers max is eq size and so the following fails */ +- if (buf->wpos + len > buf->max) { +- errno = ENOMEM; +- return (-1); +- } +- +- b = realloc(buf->buf, buf->wpos + len); +- if (b == NULL) +- return (-1); +- buf->buf = b; +- buf->size = buf->wpos + len; +- +- return (0); +-} +- +-int +-buf_add(struct buf *buf, const void *data, size_t len) +-{ +- if (buf->wpos + len > buf->size) +- if (buf_realloc(buf, len) == -1) +- return (-1); +- +- memcpy(buf->buf + buf->wpos, data, len); +- buf->wpos += len; +- return (0); +-} +- +-void * +-buf_reserve(struct buf *buf, size_t len) +-{ +- void *b; +- +- if (buf->wpos + len > buf->size) +- if (buf_realloc(buf, len) == -1) +- return (NULL); +- +- b = buf->buf + buf->wpos; +- buf->wpos += len; +- return (b); +-} +- +-void * +-buf_seek(struct buf *buf, size_t pos, size_t len) +-{ +- /* only allowed to seek in already written parts */ +- if (pos + len > buf->wpos) +- return (NULL); +- +- return (buf->buf + pos); +-} +- +-size_t +-buf_size(struct buf *buf) +-{ +- return (buf->wpos); +-} +- +-size_t +-buf_left(struct buf *buf) +-{ +- return (buf->max - buf->wpos); +-} +- +-void +-buf_close(struct msgbuf *msgbuf, struct buf *buf) +-{ +- buf_enqueue(msgbuf, buf); +-} +- +-int +-buf_write(struct msgbuf *msgbuf) +-{ +- struct iovec iov[IOV_MAX]; - struct buf *buf, *next; -+ struct buf *buf; - unsigned int i = 0; - ssize_t n; - -@@ -153,7 +153,7 @@ buf_write(struct msgbuf *msgbuf) - if (i >= IOV_MAX) - break; - iov[i].iov_base = buf->buf + buf->rpos; +- unsigned int i = 0; +- ssize_t n; +- +- bzero(&iov, sizeof(iov)); +- TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { +- if (i >= IOV_MAX) +- break; +- iov[i].iov_base = buf->buf + buf->rpos; - iov[i].iov_len = buf->size - buf->rpos; -+ iov[i].iov_len = buf->wpos - buf->rpos; - i++; - } - -@@ -170,17 +170,7 @@ buf_write(struct msgbuf *msgbuf) - return (-2); - } - +- i++; +- } +- +- if ((n = writev(msgbuf->fd, iov, i)) == -1) { +- if (errno == EAGAIN || errno == ENOBUFS || +- errno == EINTR) /* try later */ +- return (0); +- else +- return (-1); +- } +- +- if (n == 0) { /* connection closed */ +- errno = 0; +- return (-2); +- } +- - for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; - buf = next) { - next = TAILQ_NEXT(buf, entry); @@ -45,48 +188,95 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 - n = 0; - } - } -+ msgbuf_drain(msgbuf, n); - - return (0); - } -@@ -201,6 +191,24 @@ msgbuf_init(struct msgbuf *msgbuf) - } - - void -+msgbuf_drain(struct msgbuf *msgbuf, size_t n) -+{ -+ struct buf *buf, *next; -+ -+ for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; -+ buf = next) { -+ next = TAILQ_NEXT(buf, entry); -+ if (buf->rpos + n >= buf->wpos) { -+ n -= buf->wpos - buf->rpos; -+ buf_dequeue(msgbuf, buf); -+ } else { -+ buf->rpos += n; -+ n = 0; -+ } -+ } -+} -+ -+void - msgbuf_clear(struct msgbuf *msgbuf) - { - struct buf *buf; -@@ -213,7 +221,7 @@ int - msgbuf_write(struct msgbuf *msgbuf) - { - struct iovec iov[IOV_MAX]; +- +- return (0); +-} +- +-void +-buf_free(struct buf *buf) +-{ +- free(buf->buf); +- free(buf); +-} +- +-void +-msgbuf_init(struct msgbuf *msgbuf) +-{ +- msgbuf->queued = 0; +- msgbuf->fd = -1; +- TAILQ_INIT(&msgbuf->bufs); +-} +- +-void +-msgbuf_clear(struct msgbuf *msgbuf) +-{ +- struct buf *buf; +- +- while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL) +- buf_dequeue(msgbuf, buf); +-} +- +-int +-msgbuf_write(struct msgbuf *msgbuf) +-{ +- struct iovec iov[IOV_MAX]; - struct buf *buf, *next; -+ struct buf *buf; - unsigned int i = 0; - ssize_t n; - struct msghdr msg; -@@ -270,17 +278,7 @@ msgbuf_write(struct msgbuf *msgbuf) - buf->fd = -1; - } - +- unsigned int i = 0; +- ssize_t n; +- struct msghdr msg; +- struct cmsghdr *cmsg; +- union { +- struct cmsghdr hdr; +- char buf[CMSG_SPACE(sizeof(int))]; +- } cmsgbuf; +- +- bzero(&iov, sizeof(iov)); +- bzero(&msg, sizeof(msg)); +- TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { +- if (i >= IOV_MAX) +- break; +- iov[i].iov_base = buf->buf + buf->rpos; +- iov[i].iov_len = buf->wpos - buf->rpos; +- i++; +- if (buf->fd != -1) +- break; +- } +- +- msg.msg_iov = iov; +- msg.msg_iovlen = i; +- +- if (buf != NULL && buf->fd != -1) { +- msg.msg_control = (caddr_t)&cmsgbuf.buf; +- msg.msg_controllen = sizeof(cmsgbuf.buf); +- cmsg = CMSG_FIRSTHDR(&msg); +- cmsg->cmsg_len = CMSG_LEN(sizeof(int)); +- cmsg->cmsg_level = SOL_SOCKET; +- cmsg->cmsg_type = SCM_RIGHTS; +- *(int *)CMSG_DATA(cmsg) = buf->fd; +- } +- +- if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) { +- if (errno == EAGAIN || errno == ENOBUFS || +- errno == EINTR) /* try later */ +- return (0); +- else +- return (-1); +- } +- +- if (n == 0) { /* connection closed */ +- errno = 0; +- return (-2); +- } +- +- /* +- * assumption: fd got sent if sendmsg sent anything +- * this works because fds are passed one at a time +- */ +- if (buf != NULL && buf->fd != -1) { +- close(buf->fd); +- buf->fd = -1; +- } +- - for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; - buf = next) { - next = TAILQ_NEXT(buf, entry); @@ -98,7 +288,25 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 - n = 0; - } - } -+ msgbuf_drain(msgbuf, n); - - return (0); - } +- +- return (0); +-} +- +-void +-buf_enqueue(struct msgbuf *msgbuf, struct buf *buf) +-{ +- TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry); +- msgbuf->queued++; +-} +- +-void +-buf_dequeue(struct msgbuf *msgbuf, struct buf *buf) +-{ +- TAILQ_REMOVE(&msgbuf->bufs, buf, entry); +- +- if (buf->fd != -1) +- close(buf->fd); +- +- msgbuf->queued--; +- buf_free(buf); +-} diff --git a/net/openbgpd/files/patch-bgpd_config.c b/net/openbgpd/files/patch-bgpd_config.c index 77598e255fa6..3df03c1b3795 100644 --- a/net/openbgpd/files/patch-bgpd_config.c +++ b/net/openbgpd/files/patch-bgpd_config.c @@ -2,17 +2,57 @@ Index: bgpd/config.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/config.c,v retrieving revision 1.1.1.6 -retrieving revision 1.1.1.7 -diff -u -p -r1.1.1.6 -r1.1.1.7 +retrieving revision 1.2 +diff -u -p -r1.1.1.6 -r1.2 --- bgpd/config.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/config.c 14 Feb 2010 20:27:06 -0000 1.1.1.7 ++++ bgpd/config.c 2 Jul 2011 16:06:38 -0000 1.2 @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.51 2009/01/26 23:10:02 claudio Exp $ */ -+/* $OpenBSD: config.c,v 1.52 2009/12/01 14:28:05 claudio Exp $ */ ++/* $OpenBSD: config.c,v 1.56 2010/10/24 17:20:08 deraadt Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> -@@ -208,7 +208,7 @@ host_v4(const char *s, struct bgpd_addr +@@ -20,6 +20,11 @@ + #include <sys/socket.h> + #include <sys/stat.h> + #include <sys/mman.h> ++#include <sys/ioctl.h> ++ ++#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */ ++#include <netmpls/mpls.h> ++#endif + + #include <errno.h> + #include <ifaddrs.h> +@@ -47,8 +52,6 @@ merge_config(struct bgpd_config *xconf, + + /* preserve cmd line opts */ + conf->opts = xconf->opts; +- conf->csock = xconf->csock; +- conf->rcsock = xconf->rcsock; + + if (!conf->as) { + log_warnx("configuration error: AS not given"); +@@ -64,6 +67,9 @@ merge_config(struct bgpd_config *xconf, + if ((conf->flags & BGPD_FLAG_REFLECTOR) && conf->clusterid == 0) + conf->clusterid = conf->bgpid; + ++ free(xconf->csock); ++ free(xconf->rcsock); ++ + conf->listen_addrs = xconf->listen_addrs; + memcpy(xconf, conf, sizeof(struct bgpd_config)); + +@@ -74,7 +80,7 @@ merge_config(struct bgpd_config *xconf, + nla->reconf = RECONF_REINIT; + + } else { +- /* ++ /* + * merge new listeners: + * -flag all existing ones as to be deleted + * -those that are in both new and old: flag to keep +@@ -208,7 +214,7 @@ host_v4(const char *s, struct bgpd_addr return (0); } @@ -21,7 +61,7 @@ diff -u -p -r1.1.1.6 -r1.1.1.7 h->v4.s_addr = ina.s_addr; *len = bits; -@@ -225,13 +225,7 @@ host_v6(const char *s, struct bgpd_addr +@@ -225,13 +231,7 @@ host_v6(const char *s, struct bgpd_addr hints.ai_socktype = SOCK_DGRAM; /*dummy*/ hints.ai_flags = AI_NUMERICHOST; if (getaddrinfo(s, "0", &hints, &res) == 0) { @@ -36,3 +76,34 @@ diff -u -p -r1.1.1.6 -r1.1.1.7 freeaddrinfo(res); return (1); } +@@ -317,3 +317,30 @@ prepare_listeners(struct bgpd_config *co + } + } + } ++ ++int ++get_mpe_label(struct rdomain *r) ++{ ++#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */ ++ struct ifreq ifr; ++ struct shim_hdr shim; ++ int s; ++ ++ s = socket(AF_INET, SOCK_DGRAM, 0); ++ if (s == -1) ++ return (-1); ++ ++ bzero(&shim, sizeof(shim)); ++ bzero(&ifr, sizeof(ifr)); ++ strlcpy(ifr.ifr_name, r->ifmpe, sizeof(ifr.ifr_name)); ++ ifr.ifr_data = (caddr_t)&shim; ++ ++ if (ioctl(s, SIOCGETLABEL, (caddr_t)&ifr) == -1) { ++ close(s); ++ return (-1); ++ } ++ close(s); ++ r->label = shim.shim_label; ++#endif ++ return (0); ++} diff --git a/net/openbgpd/files/patch-bgpd_control.c b/net/openbgpd/files/patch-bgpd_control.c index 70b1dfd9393a..09c2ac85a831 100644 --- a/net/openbgpd/files/patch-bgpd_control.c +++ b/net/openbgpd/files/patch-bgpd_control.c @@ -2,13 +2,13 @@ Index: bgpd/control.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/control.c,v retrieving revision 1.1.1.7 -retrieving revision 1.1.1.8 -diff -u -p -r1.1.1.7 -r1.1.1.8 +retrieving revision 1.1.1.9 +diff -u -p -r1.1.1.7 -r1.1.1.9 --- bgpd/control.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/control.c 14 Feb 2010 20:27:06 -0000 1.1.1.8 ++++ bgpd/control.c 12 Jun 2011 10:44:24 -0000 1.1.1.9 @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.61 2009/05/05 20:09:19 sthen Exp $ */ -+/* $OpenBSD: control.c,v 1.68 2010/01/13 06:02:37 claudio Exp $ */ ++/* $OpenBSD: control.c,v 1.70 2010/10/29 12:51:53 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -32,8 +32,9 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 session_socket_blockmode(connfd, BM_NONBLOCK); - if ((ctl_conn = malloc(sizeof(struct ctl_conn))) == NULL) { +- if ((ctl_conn = malloc(sizeof(struct ctl_conn))) == NULL) { - log_warn("session_control_accept"); ++ if ((ctl_conn = calloc(1, sizeof(struct ctl_conn))) == NULL) { + log_warn("control_accept"); close(connfd); return (0); @@ -48,7 +49,17 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 struct peer *p; struct ctl_neighbor *neighbor; struct ctl_show_rib_request *ribreq; -@@ -328,13 +329,19 @@ control_dispatch_msg(struct pollfd *pfd, +@@ -305,7 +306,8 @@ control_dispatch_msg(struct pollfd *pfd, + break; + case IMSG_CTL_FIB_COUPLE: + case IMSG_CTL_FIB_DECOUPLE: +- imsg_compose_parent(imsg.hdr.type, 0, NULL, 0); ++ imsg_compose_parent(imsg.hdr.type, imsg.hdr.peerid, ++ 0, NULL, 0); + break; + case IMSG_CTL_NEIGHBOR_UP: + case IMSG_CTL_NEIGHBOR_DOWN: +@@ -328,13 +330,19 @@ control_dispatch_msg(struct pollfd *pfd, control_result(c, CTL_RES_OK); break; case IMSG_CTL_NEIGHBOR_DOWN: @@ -72,7 +83,30 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 control_result(c, CTL_RES_OK); break; case IMSG_CTL_NEIGHBOR_RREFRESH: -@@ -370,7 +377,7 @@ control_dispatch_msg(struct pollfd *pfd, +@@ -352,13 +360,19 @@ control_dispatch_msg(struct pollfd *pfd, + "wrong length"); + break; + case IMSG_CTL_RELOAD: ++ case IMSG_CTL_SHOW_INTERFACE: ++ case IMSG_CTL_SHOW_FIB_TABLES: ++ c->ibuf.pid = imsg.hdr.pid; ++ imsg_compose_parent(imsg.hdr.type, 0, imsg.hdr.pid, ++ imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); ++ break; + case IMSG_CTL_KROUTE: + case IMSG_CTL_KROUTE_ADDR: + case IMSG_CTL_SHOW_NEXTHOP: +- case IMSG_CTL_SHOW_INTERFACE: + c->ibuf.pid = imsg.hdr.pid; +- imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid, +- imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); ++ imsg_compose_parent(imsg.hdr.type, imsg.hdr.peerid, ++ imsg.hdr.pid, imsg.data, imsg.hdr.len - ++ IMSG_HEADER_SIZE); + break; + case IMSG_CTL_SHOW_RIB: + case IMSG_CTL_SHOW_RIB_AS: +@@ -370,7 +384,7 @@ control_dispatch_msg(struct pollfd *pfd, neighbor->descr[PEER_DESCR_LEN - 1] = 0; ribreq->peerid = 0; p = NULL; @@ -81,7 +115,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 p = getpeerbyaddr(&neighbor->addr); if (p == NULL) { control_result(c, -@@ -397,8 +404,7 @@ control_dispatch_msg(struct pollfd *pfd, +@@ -397,8 +411,7 @@ control_dispatch_msg(struct pollfd *pfd, break; } if ((imsg.hdr.type == IMSG_CTL_SHOW_RIB_PREFIX) @@ -91,7 +125,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 /* malformed request, must specify af */ control_result(c, CTL_RES_PARSE_ERROR); break; -@@ -425,6 +431,20 @@ control_dispatch_msg(struct pollfd *pfd, +@@ -425,6 +438,20 @@ control_dispatch_msg(struct pollfd *pfd, imsg_compose_rde(imsg.hdr.type, 0, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); break; @@ -101,7 +135,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 + break; + + /* forward to other processes */ -+ imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid, ++ imsg_compose_parent(imsg.hdr.type, 0, imsg.hdr.pid, + imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); + imsg_compose_rde(imsg.hdr.type, 0, + imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); diff --git a/net/openbgpd/files/patch-bgpd_imsg.c b/net/openbgpd/files/patch-bgpd_imsg.c index 0cd9ad061d24..0ae6c8a603e7 100644 --- a/net/openbgpd/files/patch-bgpd_imsg.c +++ b/net/openbgpd/files/patch-bgpd_imsg.c @@ -1,35 +1,275 @@ Index: bgpd/imsg.c =================================================================== -RCS file: /home/cvs/private/hrs/openbgpd/bgpd/imsg.c,v -retrieving revision 1.1.1.6 -retrieving revision 1.1.1.8 -diff -u -p -r1.1.1.6 -r1.1.1.8 +RCS file: bgpd/imsg.c +diff -N bgpd/imsg.c --- bgpd/imsg.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/imsg.c 10 Apr 2010 12:13:04 -0000 1.1.1.8 -@@ -1,4 +1,4 @@ ++++ /dev/null 1 Jan 1970 00:00:00 -0000 +@@ -1,268 +0,0 @@ -/* $OpenBSD: imsg.c,v 1.47 2009/06/08 08:30:06 dlg Exp $ */ -+/* $OpenBSD: imsg.c,v 1.49 2010/04/07 18:09:39 nicm Exp $ */ - - /* - * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -79,7 +79,7 @@ imsg_read(struct imsgbuf *ibuf) - cmsg->cmsg_type == SCM_RIGHTS) { - fd = (*(int *)CMSG_DATA(cmsg)); - if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) { +- +-/* +- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> +- * +- * Permission to use, copy, modify, and distribute this software for any +- * purpose with or without fee is hereby granted, provided that the above +- * copyright notice and this permission notice appear in all copies. +- * +- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- */ +- +-#include <sys/param.h> +-#include <sys/queue.h> +-#include <sys/socket.h> +-#include <sys/uio.h> +- +-#include <errno.h> +-#include <stdlib.h> +-#include <string.h> +-#include <unistd.h> +- +-#include "imsg.h" +- +-int imsg_get_fd(struct imsgbuf *); +- +-void +-imsg_init(struct imsgbuf *ibuf, int fd) +-{ +- msgbuf_init(&ibuf->w); +- bzero(&ibuf->r, sizeof(ibuf->r)); +- ibuf->fd = fd; +- ibuf->w.fd = fd; +- ibuf->pid = getpid(); +- TAILQ_INIT(&ibuf->fds); +-} +- +-ssize_t +-imsg_read(struct imsgbuf *ibuf) +-{ +- struct msghdr msg; +- struct cmsghdr *cmsg; +- union { +- struct cmsghdr hdr; +- char buf[CMSG_SPACE(sizeof(int) * 16)]; +- } cmsgbuf; +- struct iovec iov; +- ssize_t n; +- int fd; +- struct imsg_fd *ifd; +- +- bzero(&msg, sizeof(msg)); +- +- iov.iov_base = ibuf->r.buf + ibuf->r.wpos; +- iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos; +- msg.msg_iov = &iov; +- msg.msg_iovlen = 1; +- msg.msg_control = &cmsgbuf.buf; +- msg.msg_controllen = sizeof(cmsgbuf.buf); +- +- if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) { +- if (errno != EINTR && errno != EAGAIN) { +- return (-1); +- } +- return (-2); +- } +- +- ibuf->r.wpos += n; +- +- for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; +- cmsg = CMSG_NXTHDR(&msg, cmsg)) { +- if (cmsg->cmsg_level == SOL_SOCKET && +- cmsg->cmsg_type == SCM_RIGHTS) { +- fd = (*(int *)CMSG_DATA(cmsg)); +- if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) { - /* XXX: this return can leak */ -+ close(fd); - return (-1); - } - ifd->fd = fd; -@@ -263,6 +263,9 @@ imsg_flush(struct imsgbuf *ibuf) - void - imsg_clear(struct imsgbuf *ibuf) - { +- return (-1); +- } +- ifd->fd = fd; +- TAILQ_INSERT_TAIL(&ibuf->fds, ifd, entry); +- } +- /* we do not handle other ctl data level */ +- } +- +- return (n); +-} +- +-ssize_t +-imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) +-{ +- size_t av, left, datalen; +- +- av = ibuf->r.wpos; +- +- if (IMSG_HEADER_SIZE > av) +- return (0); +- +- memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr)); +- if (imsg->hdr.len < IMSG_HEADER_SIZE || +- imsg->hdr.len > MAX_IMSGSIZE) { +- errno = ERANGE; +- return (-1); +- } +- if (imsg->hdr.len > av) +- return (0); +- datalen = imsg->hdr.len - IMSG_HEADER_SIZE; +- ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE; +- if ((imsg->data = malloc(datalen)) == NULL) +- return (-1); +- +- if (imsg->hdr.flags & IMSGF_HASFD) +- imsg->fd = imsg_get_fd(ibuf); +- else +- imsg->fd = -1; +- +- memcpy(imsg->data, ibuf->r.rptr, datalen); +- +- if (imsg->hdr.len < av) { +- left = av - imsg->hdr.len; +- memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left); +- ibuf->r.wpos = left; +- } else +- ibuf->r.wpos = 0; +- +- return (datalen + IMSG_HEADER_SIZE); +-} +- +-int +-imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, +- pid_t pid, int fd, void *data, u_int16_t datalen) +-{ +- struct buf *wbuf; +- +- if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) +- return (-1); +- +- if (imsg_add(wbuf, data, datalen) == -1) +- return (-1); +- +- wbuf->fd = fd; +- +- imsg_close(ibuf, wbuf); +- +- return (1); +-} +- +-int +-imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, +- pid_t pid, int fd, const struct iovec *iov, int iovcnt) +-{ +- struct buf *wbuf; +- int i, datalen = 0; +- +- for (i = 0; i < iovcnt; i++) +- datalen += iov[i].iov_len; +- +- if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) +- return (-1); +- +- for (i = 0; i < iovcnt; i++) +- if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1) +- return (-1); +- +- wbuf->fd = fd; +- +- imsg_close(ibuf, wbuf); +- +- return (1); +-} +- +-/* ARGSUSED */ +-struct buf * +-imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, +- pid_t pid, u_int16_t datalen) +-{ +- struct buf *wbuf; +- struct imsg_hdr hdr; +- +- datalen += IMSG_HEADER_SIZE; +- if (datalen > MAX_IMSGSIZE) { +- errno = ERANGE; +- return (NULL); +- } +- +- hdr.type = type; +- hdr.flags = 0; +- hdr.peerid = peerid; +- if ((hdr.pid = pid) == 0) +- hdr.pid = ibuf->pid; +- if ((wbuf = buf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) { +- return (NULL); +- } +- if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1) +- return (NULL); +- +- return (wbuf); +-} +- +-int +-imsg_add(struct buf *msg, void *data, u_int16_t datalen) +-{ +- if (datalen) +- if (buf_add(msg, data, datalen) == -1) { +- buf_free(msg); +- return (-1); +- } +- return (datalen); +-} +- +-void +-imsg_close(struct imsgbuf *ibuf, struct buf *msg) +-{ +- struct imsg_hdr *hdr; +- +- hdr = (struct imsg_hdr *)msg->buf; +- +- hdr->flags &= ~IMSGF_HASFD; +- if (msg->fd != -1) +- hdr->flags |= IMSGF_HASFD; +- +- hdr->len = (u_int16_t)msg->wpos; +- +- buf_close(&ibuf->w, msg); +-} +- +-void +-imsg_free(struct imsg *imsg) +-{ +- free(imsg->data); +-} +- +-int +-imsg_get_fd(struct imsgbuf *ibuf) +-{ +- int fd; +- struct imsg_fd *ifd; +- +- if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL) +- return (-1); +- +- fd = ifd->fd; +- TAILQ_REMOVE(&ibuf->fds, ifd, entry); +- free(ifd); +- +- return (fd); +-} +- +-int +-imsg_flush(struct imsgbuf *ibuf) +-{ +- while (ibuf->w.queued) +- if (msgbuf_write(&ibuf->w) < 0) +- return (-1); +- return (0); +-} +- +-void +-imsg_clear(struct imsgbuf *ibuf) +-{ - while (ibuf->w.queued) - msgbuf_clear(&ibuf->w); -+ int fd; -+ -+ msgbuf_clear(&ibuf->w); -+ while ((fd = imsg_get_fd(ibuf)) != -1) -+ close(fd); - } +-} diff --git a/net/openbgpd/files/patch-bgpd_imsg.h b/net/openbgpd/files/patch-bgpd_imsg.h index a7b0c120c556..09fe037f51eb 100644 --- a/net/openbgpd/files/patch-bgpd_imsg.h +++ b/net/openbgpd/files/patch-bgpd_imsg.h @@ -1,16 +1,115 @@ Index: bgpd/imsg.h =================================================================== -RCS file: /home/cvs/private/hrs/openbgpd/bgpd/imsg.h,v -retrieving revision 1.1.1.5 -retrieving revision 1.1.1.6 -diff -u -p -r1.1.1.5 -r1.1.1.6 +RCS file: bgpd/imsg.h +diff -N bgpd/imsg.h --- bgpd/imsg.h 14 Feb 2010 20:19:57 -0000 1.1.1.5 -+++ bgpd/imsg.h 14 Feb 2010 20:27:06 -0000 1.1.1.6 -@@ -90,6 +90,7 @@ void buf_free(struct buf *); - void msgbuf_init(struct msgbuf *); - void msgbuf_clear(struct msgbuf *); - int msgbuf_write(struct msgbuf *); -+void msgbuf_drain(struct msgbuf *, size_t); - - /* imsg.c */ - void imsg_init(struct imsgbuf *, int); ++++ /dev/null 1 Jan 1970 00:00:00 -0000 +@@ -1,108 +0,0 @@ +-/* $OpenBSD: imsg.h,v 1.3 2009/06/07 05:56:24 eric Exp $ */ +- +-/* +- * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org> +- * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org> +- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> +- * +- * Permission to use, copy, modify, and distribute this software for any +- * purpose with or without fee is hereby granted, provided that the above +- * copyright notice and this permission notice appear in all copies. +- * +- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- */ +- +-#include <sys/tree.h> +- +-#define READ_BUF_SIZE 65535 +-#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr) +-#define MAX_IMSGSIZE 16384 +- +-struct buf { +- TAILQ_ENTRY(buf) entry; +- u_char *buf; +- size_t size; +- size_t max; +- size_t wpos; +- size_t rpos; +- int fd; +-}; +- +-struct msgbuf { +- TAILQ_HEAD(, buf) bufs; +- u_int32_t queued; +- int fd; +-}; +- +-struct buf_read { +- u_char buf[READ_BUF_SIZE]; +- u_char *rptr; +- size_t wpos; +-}; +- +-struct imsg_fd { +- TAILQ_ENTRY(imsg_fd) entry; +- int fd; +-}; +- +-struct imsgbuf { +- TAILQ_HEAD(, imsg_fd) fds; +- struct buf_read r; +- struct msgbuf w; +- int fd; +- pid_t pid; +-}; +- +-#define IMSGF_HASFD 1 +- +-struct imsg_hdr { +- u_int32_t type; +- u_int16_t len; +- u_int16_t flags; +- u_int32_t peerid; +- u_int32_t pid; +-}; +- +-struct imsg { +- struct imsg_hdr hdr; +- int fd; +- void *data; +-}; +- +- +-/* buffer.c */ +-struct buf *buf_open(size_t); +-struct buf *buf_dynamic(size_t, size_t); +-int buf_add(struct buf *, const void *, size_t); +-void *buf_reserve(struct buf *, size_t); +-void *buf_seek(struct buf *, size_t, size_t); +-size_t buf_size(struct buf *); +-size_t buf_left(struct buf *); +-void buf_close(struct msgbuf *, struct buf *); +-int buf_write(struct msgbuf *); +-void buf_free(struct buf *); +-void msgbuf_init(struct msgbuf *); +-void msgbuf_clear(struct msgbuf *); +-int msgbuf_write(struct msgbuf *); +- +-/* imsg.c */ +-void imsg_init(struct imsgbuf *, int); +-ssize_t imsg_read(struct imsgbuf *); +-ssize_t imsg_get(struct imsgbuf *, struct imsg *); +-int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, +- int, void *, u_int16_t); +-int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, +- int, const struct iovec *, int); +-struct buf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, +- u_int16_t); +-int imsg_add(struct buf *, void *, u_int16_t); +-void imsg_close(struct imsgbuf *, struct buf *); +-void imsg_free(struct imsg *); +-int imsg_flush(struct imsgbuf *); +-void imsg_clear(struct imsgbuf *); diff --git a/net/openbgpd/files/patch-bgpd_kroute.c b/net/openbgpd/files/patch-bgpd_kroute.c index 08bb5eacbf50..6f93029d60cd 100644 --- a/net/openbgpd/files/patch-bgpd_kroute.c +++ b/net/openbgpd/files/patch-bgpd_kroute.c @@ -2,17 +2,912 @@ Index: bgpd/kroute.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/kroute.c,v retrieving revision 1.1.1.7 -retrieving revision 1.9 -diff -u -p -r1.1.1.7 -r1.9 +retrieving revision 1.12 +diff -u -p -r1.1.1.7 -r1.12 --- bgpd/kroute.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/kroute.c 10 Apr 2010 12:16:23 -0000 1.9 ++++ bgpd/kroute.c 3 Jul 2011 04:46:36 -0000 1.12 @@ -1,4 +1,4 @@ -/* $OpenBSD: kroute.c,v 1.169 2009/06/25 15:54:22 claudio Exp $ */ +/* $OpenBSD: kroute.c,v 1.176 2010/04/06 13:25:08 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -463,25 +463,30 @@ kr_nexthop_add(struct bgpd_addr *addr) +@@ -27,6 +27,9 @@ + #include <net/if.h> + #include <net/if_dl.h> + #include <net/route.h> ++#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */ ++#include <netmpls/mpls.h> ++#endif + #include <err.h> + #include <errno.h> + #include <fcntl.h> +@@ -37,11 +40,12 @@ + + #include "bgpd.h" + ++struct ktable **krt; ++u_int krt_size; ++ + struct { + u_int32_t rtseq; + pid_t pid; +- u_int rtableid; +- int fib_sync; + int fd; + } kr_state; + +@@ -83,32 +87,52 @@ struct kif_node { + struct kif_kr6_head kroute6_l; + }; + +-int kr_redistribute(int, struct kroute *); +-int kr_redistribute6(int, struct kroute6 *); ++int ktable_new(u_int, u_int, char *, char *, int); ++void ktable_free(u_int); ++void ktable_destroy(struct ktable *); ++struct ktable *ktable_get(u_int); ++ ++int kr4_change(struct ktable *, struct kroute_full *); ++int kr6_change(struct ktable *, struct kroute_full *); ++int krVPN4_change(struct ktable *, struct kroute_full *); ++int kr4_delete(struct ktable *, struct kroute_full *); ++int kr6_delete(struct ktable *, struct kroute_full *); ++int krVPN4_delete(struct ktable *, struct kroute_full *); ++void kr_net_delete(struct network *); ++struct network *kr_net_match(struct ktable *, struct kroute *); ++struct network *kr_net_match6(struct ktable *, struct kroute6 *); ++struct network *kr_net_find(struct ktable *, struct network *); ++int kr_redistribute(int, struct ktable *, struct kroute *); ++int kr_redistribute6(int, struct ktable *, struct kroute6 *); ++struct kroute_full *kr_tofull(struct kroute *); ++struct kroute_full *kr6_tofull(struct kroute6 *); + int kroute_compare(struct kroute_node *, struct kroute_node *); + int kroute6_compare(struct kroute6_node *, struct kroute6_node *); + int knexthop_compare(struct knexthop_node *, struct knexthop_node *); + int kif_compare(struct kif_node *, struct kif_node *); + +-struct kroute_node *kroute_find(in_addr_t, u_int8_t, u_int8_t); ++struct kroute_node *kroute_find(struct ktable *, in_addr_t, u_int8_t, ++ u_int8_t); + struct kroute_node *kroute_matchgw(struct kroute_node *, + struct sockaddr_in *); +-int kroute_insert(struct kroute_node *); +-int kroute_remove(struct kroute_node *); +-void kroute_clear(void); ++int kroute_insert(struct ktable *, struct kroute_node *); ++int kroute_remove(struct ktable *, struct kroute_node *); ++void kroute_clear(struct ktable *); + +-struct kroute6_node *kroute6_find(const struct in6_addr *, u_int8_t, +- u_int8_t); ++struct kroute6_node *kroute6_find(struct ktable *, const struct in6_addr *, ++ u_int8_t, u_int8_t); + struct kroute6_node *kroute6_matchgw(struct kroute6_node *, + struct sockaddr_in6 *); +-int kroute6_insert(struct kroute6_node *); +-int kroute6_remove(struct kroute6_node *); +-void kroute6_clear(void); +- +-struct knexthop_node *knexthop_find(struct bgpd_addr *); +-int knexthop_insert(struct knexthop_node *); +-int knexthop_remove(struct knexthop_node *); +-void knexthop_clear(void); ++int kroute6_insert(struct ktable *, struct kroute6_node *); ++int kroute6_remove(struct ktable *, struct kroute6_node *); ++void kroute6_clear(struct ktable *); ++ ++struct knexthop_node *knexthop_find(struct ktable *, struct bgpd_addr *); ++int knexthop_insert(struct ktable *, ++ struct knexthop_node *); ++int knexthop_remove(struct ktable *, ++ struct knexthop_node *); ++void knexthop_clear(struct ktable *); + + struct kif_node *kif_find(int); + int kif_insert(struct kif_node *); +@@ -124,13 +148,15 @@ int kif_kr6_remove(struct kroute6_nod + int kif_validate(struct kif *); + int kroute_validate(struct kroute *); + int kroute6_validate(struct kroute6 *); +-void knexthop_validate(struct knexthop_node *); +-void knexthop_track(void *); +-struct kroute_node *kroute_match(in_addr_t, int); +-struct kroute6_node *kroute6_match(struct in6_addr *, int); +-void kroute_detach_nexthop(struct knexthop_node *); ++void knexthop_validate(struct ktable *, ++ struct knexthop_node *); ++void knexthop_track(struct ktable *, void *); ++struct kroute_node *kroute_match(struct ktable *, in_addr_t, int); ++struct kroute6_node *kroute6_match(struct ktable *, struct in6_addr *, int); ++void kroute_detach_nexthop(struct ktable *, ++ struct knexthop_node *); + +-int protect_lo(void); ++int protect_lo(struct ktable *); + u_int8_t prefixlen_classful(in_addr_t); + u_int8_t mask2prefixlen(in_addr_t); + u_int8_t mask2prefixlen6(struct sockaddr_in6 *); +@@ -138,23 +164,20 @@ void get_rtaddrs(int, struct sockaddr * + void if_change(u_short, int, struct if_data *); + void if_announce(void *); + +-int send_rtmsg(int, int, struct kroute *); +-int send_rt6msg(int, int, struct kroute6 *); ++int send_rtmsg(int, int, struct ktable *, struct kroute *); ++int send_rt6msg(int, int, struct ktable *, struct kroute6 *); + int dispatch_rtmsg(void); +-int fetchtable(u_int, int); ++int fetchtable(struct ktable *); + int fetchifs(int); + int dispatch_rtmsg_addr(struct rt_msghdr *, +- struct sockaddr *[RTAX_MAX], int); ++ struct sockaddr *[RTAX_MAX], struct ktable *); + +-RB_HEAD(kroute_tree, kroute_node) krt; + RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare) + RB_GENERATE(kroute_tree, kroute_node, entry, kroute_compare) + +-RB_HEAD(kroute6_tree, kroute6_node) krt6; + RB_PROTOTYPE(kroute6_tree, kroute6_node, entry, kroute6_compare) + RB_GENERATE(kroute6_tree, kroute6_node, entry, kroute6_compare) + +-RB_HEAD(knexthop_tree, knexthop_node) knt; + RB_PROTOTYPE(knexthop_tree, knexthop_node, entry, knexthop_compare) + RB_GENERATE(knexthop_tree, knexthop_node, entry, knexthop_compare) + +@@ -162,19 +185,21 @@ RB_HEAD(kif_tree, kif_node) kit; + RB_PROTOTYPE(kif_tree, kif_node, entry, kif_compare) + RB_GENERATE(kif_tree, kif_node, entry, kif_compare) + ++#define KT2KNT(x) (&(ktable_get((x)->nhtableid)->knt)) ++ + /* + * exported functions + */ + + int +-kr_init(int fs, u_int rtableid) ++kr_init(void) + { + int opt = 0, rcvbuf, default_rcvbuf; ++#if !defined(__FreeBSD__) /* FreeBSD does not have ROUTE_TABLEFILTER. */ ++ unsigned int tid = RTABLE_ANY; ++#endif + socklen_t optlen; + +- kr_state.rtableid = rtableid; +- kr_state.fib_sync = fs; +- + if ((kr_state.fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) { + log_warn("kr_init: socket"); + return (-1); +@@ -198,194 +223,533 @@ kr_init(int fs, u_int rtableid) + rcvbuf /= 2) + ; /* nothing */ + ++#if !defined(__FreeBSD__) /* FreeBSD does not have ROUTE_TABLEFILTER. */ ++ if (setsockopt(kr_state.fd, AF_ROUTE, ROUTE_TABLEFILTER, &tid, ++ sizeof(tid)) == -1) { ++ log_warn("kr_init: setsockopt AF_ROUTE ROUTE_TABLEFILTER"); ++ return (-1); ++ } ++#endif ++ + kr_state.pid = getpid(); + kr_state.rtseq = 1; + +- RB_INIT(&krt); +- RB_INIT(&krt6); +- RB_INIT(&knt); + RB_INIT(&kit); + + if (fetchifs(0) == -1) + return (-1); + +- if (fetchtable(kr_state.rtableid, 0) == -1) +- return (-1); +- if (kr_state.rtableid != 0) +- if (fetchtable(0, 1) == -1) ++ return (kr_state.fd); ++} ++ ++int ++ktable_new(u_int rtableid, u_int rdomid, char *name, char *ifname, int fs) ++{ ++ struct ktable **xkrt; ++ struct ktable *kt; ++ size_t newsize, oldsize; ++ ++ /* resize index table if needed */ ++ if (rtableid >= krt_size) { ++ oldsize = sizeof(struct ktable *) * krt_size; ++ newsize = sizeof(struct ktable *) * (rtableid + 1); ++ if ((xkrt = realloc(krt, newsize)) == NULL) { ++ log_warn("ktable_new"); + return (-1); ++ } ++ krt = xkrt; ++ krt_size = rtableid + 1; ++ bzero((char *)krt + oldsize, newsize - oldsize); ++ } ++ ++ if (krt[rtableid]) ++ fatalx("ktable_new: table already exists."); + +- if (protect_lo() == -1) ++ /* allocate new element */ ++ kt = krt[rtableid] = calloc(1, sizeof(struct ktable)); ++ if (kt == NULL) { ++ log_warn("ktable_new"); + return (-1); ++ } + +- return (kr_state.fd); ++ /* initialize structure ... */ ++ strlcpy(kt->descr, name, sizeof(kt->descr)); ++ RB_INIT(&kt->krt); ++ RB_INIT(&kt->krt6); ++ RB_INIT(&kt->knt); ++ TAILQ_INIT(&kt->krn); ++ kt->fib_conf = kt->fib_sync = fs; ++ kt->rtableid = rtableid; ++ kt->nhtableid = rdomid; ++ /* bump refcount of rdomain table for the nexthop lookups */ ++ ktable_get(kt->nhtableid)->nhrefcnt++; ++ if (ifname) { ++ strlcpy(kt->ifmpe, ifname, IFNAMSIZ); ++ kt->ifindex = if_nametoindex(ifname); ++ } ++ ++ /* ... and load it */ ++ if (fetchtable(kt) == -1) ++ return (-1); ++ if (protect_lo(kt) == -1) ++ return (-1); ++ ++ /* everything is up and running */ ++ kt->state = RECONF_REINIT; ++ log_debug("new ktable %s for rtableid %d", name, rtableid); ++ return (0); ++} ++ ++void ++ktable_free(u_int rtableid) ++{ ++ struct ktable *kt, *nkt; ++ ++ if ((kt = ktable_get(rtableid)) == NULL) ++ return; ++ ++ /* decouple from kernel, no new routes will be entered from here */ ++ kr_fib_decouple(kt->rtableid); ++ ++ /* first unhook from the nexthop table */ ++ nkt = ktable_get(kt->nhtableid); ++ nkt->nhrefcnt--; ++ ++ /* ++ * Evil little details: ++ * If kt->nhrefcnt > 0 then kt == nkt and nothing needs to be done. ++ * If kt != nkt then kt->nhrefcnt must be 0 and kt must be killed. ++ * If nkt is no longer referenced it must be killed (possible double ++ * free so check that kt != nkt). ++ */ ++ if (kt != nkt && nkt->nhrefcnt <= 0) ++ ktable_destroy(nkt); ++ if (kt->nhrefcnt <= 0) ++ ktable_destroy(kt); ++} ++ ++void ++ktable_destroy(struct ktable *kt) ++{ ++ /* decouple just to be sure, does not hurt */ ++ kr_fib_decouple(kt->rtableid); ++ ++ log_debug("freeing ktable %s rtableid %u", kt->descr, kt->rtableid); ++ knexthop_clear(kt); ++ kroute_clear(kt); ++ kroute6_clear(kt); ++ ++ krt[kt->rtableid] = NULL; ++ free(kt); ++} ++ ++struct ktable * ++ktable_get(u_int rtableid) ++{ ++ if (rtableid >= krt_size) ++ return (NULL); ++ return (krt[rtableid]); ++} ++ ++int ++ktable_update(u_int rtableid, char *name, char *ifname, int flags) ++{ ++ struct ktable *kt, *rkt; ++ u_int rdomid; ++ ++ if (!ktable_exists(rtableid, &rdomid)) ++ fatalx("King Bula lost a table"); /* may not happen */ ++ ++ if (rdomid != rtableid || flags & F_RIB_NOFIB) { ++ rkt = ktable_get(rdomid); ++ if (rkt == NULL) { ++ char buf[32]; ++ snprintf(buf, sizeof(buf), "rdomain_%d", rdomid); ++ if (ktable_new(rdomid, rdomid, buf, NULL, 0)) ++ return (-1); ++ } else { ++ /* there is no need for full fib synchronisation if ++ * the table is only used for nexthop lookups. ++ */ ++ if (rkt->state == RECONF_DELETE) { ++ rkt->fib_conf = 0; ++ rkt->state = RECONF_KEEP; ++ } ++ } ++ } ++ ++ if (flags & (F_RIB_NOEVALUATE | F_RIB_NOFIB)) ++ /* only rdomain table must exist */ ++ return (0); ++ ++ kt = ktable_get(rtableid); ++ if (kt == NULL) { ++ if (ktable_new(rtableid, rdomid, name, ifname, ++ !(flags & F_RIB_NOFIBSYNC))) ++ return (-1); ++ } else { ++ /* fib sync has higher preference then no sync */ ++ if (kt->state == RECONF_DELETE) { ++ kt->fib_conf = !(flags & F_RIB_NOFIBSYNC); ++ kt->state = RECONF_KEEP; ++ } else if (!kt->fib_conf) ++ kt->fib_conf = !(flags & F_RIB_NOFIBSYNC); ++ ++ strlcpy(kt->descr, name, sizeof(kt->descr)); ++ } ++ return (0); ++} ++ ++void ++ktable_preload(void) ++{ ++ struct ktable *kt; ++ u_int i; ++ ++ for (i = 0; i < krt_size; i++) { ++ if ((kt = ktable_get(i)) == NULL) ++ continue; ++ kt->state = RECONF_DELETE; ++ } ++} ++ ++void ++ktable_postload(void) ++{ ++ struct ktable *kt; ++ u_int i; ++ ++ for (i = krt_size; i > 0; i--) { ++ if ((kt = ktable_get(i - 1)) == NULL) ++ continue; ++ if (kt->state == RECONF_DELETE) ++ ktable_free(i - 1); ++ else if (kt->state == RECONF_REINIT) ++ kt->fib_sync = kt->fib_conf; ++ } ++} ++ ++int ++ktable_exists(u_int rtableid, u_int *rdomid) ++{ ++#if !defined(__FreeBSD__) /* FreeBSD does not have NET_RT_TABLE. */ ++ size_t len; ++ struct rt_tableinfo info; ++ int mib[6]; ++ ++ mib[0] = CTL_NET; ++ mib[1] = AF_ROUTE; ++ mib[2] = 0; ++ mib[3] = 0; ++ mib[4] = NET_RT_TABLE; ++ mib[5] = rtableid; ++ ++ len = sizeof(info); ++ if (sysctl(mib, 6, &info, &len, NULL, 0) == -1) { ++ if (errno == ENOENT) ++ /* table nonexistent */ ++ return (0); ++ log_warn("sysctl"); ++ /* must return 0 so that the table is considered non-existent */ ++ return (0); ++ } ++ if (rdomid) ++ *rdomid = info.rti_domainid; ++#else ++ *rdomid = 0; ++#endif ++ return (1); + } + + int +-kr_change(struct kroute_label *kl) ++kr_change(u_int rtableid, struct kroute_full *kl) ++{ ++ struct ktable *kt; ++ ++ if ((kt = ktable_get(rtableid)) == NULL) ++ /* too noisy during reloads, just ignore */ ++ return (0); ++ switch (kl->prefix.aid) { ++ case AID_INET: ++ return (kr4_change(kt, kl)); ++ case AID_INET6: ++ return (kr6_change(kt, kl)); ++ case AID_VPN_IPv4: ++ return (krVPN4_change(kt, kl)); ++ } ++ log_warnx("kr_change: not handled AID"); ++ return (-1); ++} ++ ++int ++kr4_change(struct ktable *kt, struct kroute_full *kl) + { + struct kroute_node *kr; + int action = RTM_ADD; ++ u_int16_t labelid; + +- if ((kr = kroute_find(kl->kr.prefix.s_addr, kl->kr.prefixlen, RTP_BGP)) +- != NULL) ++ if ((kr = kroute_find(kt, kl->prefix.v4.s_addr, kl->prefixlen, ++ RTP_BGP)) != NULL) + action = RTM_CHANGE; + + /* nexthop within 127/8 -> ignore silently */ +- if ((kl->kr.nexthop.s_addr & htonl(IN_CLASSA_NET)) == ++ if ((kl->nexthop.v4.s_addr & htonl(IN_CLASSA_NET)) == + htonl(INADDR_LOOPBACK & IN_CLASSA_NET)) + return (0); + +- if (kr) +- rtlabel_unref(kr->r.labelid); +- kl->kr.labelid = rtlabel_name2id(kl->label); ++ labelid = rtlabel_name2id(kl->label); + + /* for blackhole and reject routes nexthop needs to be 127.0.0.1 */ +- if (kl->kr.flags & (F_BLACKHOLE|F_REJECT)) +- kl->kr.nexthop.s_addr = htonl(INADDR_LOOPBACK); +- +- if (send_rtmsg(kr_state.fd, action, &kl->kr) == -1) +- return (-1); ++ if (kl->flags & (F_BLACKHOLE|F_REJECT)) ++ kl->nexthop.v4.s_addr = htonl(INADDR_LOOPBACK); + + if (action == RTM_ADD) { + if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) { + log_warn("kr_change"); + return (-1); + } +- kr->r.prefix.s_addr = kl->kr.prefix.s_addr; +- kr->r.prefixlen = kl->kr.prefixlen; +- kr->r.nexthop.s_addr = kl->kr.nexthop.s_addr; +- kr->r.flags = kl->kr.flags | F_BGPD_INSERTED; ++ kr->r.prefix.s_addr = kl->prefix.v4.s_addr; ++ kr->r.prefixlen = kl->prefixlen; ++ kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr; ++ kr->r.flags = kl->flags | F_BGPD_INSERTED; + kr->r.priority = RTP_BGP; +- kr->r.labelid = kl->kr.labelid; ++ kr->r.labelid = labelid; + +- if (kroute_insert(kr) == -1) ++ if (kroute_insert(kt, kr) == -1) + free(kr); + } else { +- kr->r.nexthop.s_addr = kl->kr.nexthop.s_addr; +- kr->r.labelid = kl->kr.labelid; +- if (kl->kr.flags & F_BLACKHOLE) ++ kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr; ++ rtlabel_unref(kr->r.labelid); ++ kr->r.labelid = labelid; ++ if (kl->flags & F_BLACKHOLE) + kr->r.flags |= F_BLACKHOLE; + else + kr->r.flags &= ~F_BLACKHOLE; +- if (kl->kr.flags & F_REJECT) ++ if (kl->flags & F_REJECT) + kr->r.flags |= F_REJECT; + else + kr->r.flags &= ~F_REJECT; + } + ++ if (send_rtmsg(kr_state.fd, action, kt, &kr->r) == -1) ++ return (-1); ++ + return (0); + } + + int +-kr_delete(struct kroute_label *kl) ++kr6_change(struct ktable *kt, struct kroute_full *kl) + { +- struct kroute_node *kr; ++ struct kroute6_node *kr6; ++ struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; ++ int action = RTM_ADD; ++ u_int16_t labelid; + +- if ((kr = kroute_find(kl->kr.prefix.s_addr, kl->kr.prefixlen, RTP_BGP)) +- == NULL) +- return (0); ++ if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen, RTP_BGP)) != ++ NULL) ++ action = RTM_CHANGE; + +- if (!(kr->r.flags & F_BGPD_INSERTED)) ++ /* nexthop to loopback -> ignore silently */ ++ if (IN6_IS_ADDR_LOOPBACK(&kl->nexthop.v6)) + return (0); + +- /* nexthop within 127/8 -> ignore silently */ +- if ((kl->kr.nexthop.s_addr & htonl(IN_CLASSA_NET)) == +- htonl(INADDR_LOOPBACK & IN_CLASSA_NET)) +- return (0); ++ labelid = rtlabel_name2id(kl->label); + +- if (send_rtmsg(kr_state.fd, RTM_DELETE, &kl->kr) == -1) +- return (-1); ++ /* for blackhole and reject routes nexthop needs to be ::1 */ ++ if (kl->flags & (F_BLACKHOLE|F_REJECT)) ++ bcopy(&lo6, &kl->nexthop.v6, sizeof(kl->nexthop.v6)); ++ ++ if (action == RTM_ADD) { ++ if ((kr6 = calloc(1, sizeof(struct kroute6_node))) == NULL) { ++ log_warn("kr_change"); ++ return (-1); ++ } ++ memcpy(&kr6->r.prefix, &kl->prefix.v6, sizeof(struct in6_addr)); ++ kr6->r.prefixlen = kl->prefixlen; ++ memcpy(&kr6->r.nexthop, &kl->nexthop.v6, ++ sizeof(struct in6_addr)); ++ kr6->r.flags = kl->flags | F_BGPD_INSERTED; ++ kr6->r.priority = RTP_BGP; ++ kr6->r.labelid = labelid; + +- rtlabel_unref(kl->kr.labelid); ++ if (kroute6_insert(kt, kr6) == -1) ++ free(kr6); ++ } else { ++ memcpy(&kr6->r.nexthop, &kl->nexthop.v6, ++ sizeof(struct in6_addr)); ++ rtlabel_unref(kr6->r.labelid); ++ kr6->r.labelid = labelid; ++ if (kl->flags & F_BLACKHOLE) ++ kr6->r.flags |= F_BLACKHOLE; ++ else ++ kr6->r.flags &= ~F_BLACKHOLE; ++ if (kl->flags & F_REJECT) ++ kr6->r.flags |= F_REJECT; ++ else ++ kr6->r.flags &= ~F_REJECT; ++ } + +- if (kroute_remove(kr) == -1) ++ if (send_rt6msg(kr_state.fd, action, kt, &kr6->r) == -1) + return (-1); + + return (0); + } + + int +-kr6_change(struct kroute6_label *kl) ++krVPN4_change(struct ktable *kt, struct kroute_full *kl) + { +- struct kroute6_node *kr6; ++ struct kroute_node *kr; + int action = RTM_ADD; +- struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; ++ u_int32_t mplslabel = 0; ++ u_int16_t labelid; + +- if ((kr6 = kroute6_find(&kl->kr.prefix, kl->kr.prefixlen, RTP_BGP)) +- != NULL) ++ if ((kr = kroute_find(kt, kl->prefix.vpn4.addr.s_addr, kl->prefixlen, ++ RTP_BGP)) != NULL) + action = RTM_CHANGE; + +- /* nexthop to loopback -> ignore silently */ +- if (IN6_IS_ADDR_LOOPBACK(&kl->kr.nexthop)) ++ /* nexthop within 127/8 -> ignore silently */ ++ if ((kl->nexthop.v4.s_addr & htonl(IN_CLASSA_NET)) == ++ htonl(INADDR_LOOPBACK & IN_CLASSA_NET)) + return (0); + +- if (kr6) +- rtlabel_unref(kr6->r.labelid); +- kl->kr.labelid = rtlabel_name2id(kl->label); ++ /* only single MPLS label are supported for now */ ++ if (kl->prefix.vpn4.labellen != 3) { ++ log_warnx("krVPN4_change: %s/%u has not a single label", ++ log_addr(&kl->prefix), kl->prefixlen); ++ return (0); ++ } ++ mplslabel = (kl->prefix.vpn4.labelstack[0] << 24) | ++ (kl->prefix.vpn4.labelstack[1] << 16) | ++ (kl->prefix.vpn4.labelstack[2] << 8); ++ mplslabel = htonl(mplslabel); + +- /* for blackhole and reject routes nexthop needs to be ::1 */ +- if (kl->kr.flags & (F_BLACKHOLE|F_REJECT)) +- bcopy(&lo6, &kl->kr.nexthop, sizeof(kl->kr.nexthop)); ++ labelid = rtlabel_name2id(kl->label); + +- if (send_rt6msg(kr_state.fd, action, &kl->kr) == -1) +- return (-1); ++ /* for blackhole and reject routes nexthop needs to be 127.0.0.1 */ ++ if (kl->flags & (F_BLACKHOLE|F_REJECT)) ++ kl->nexthop.v4.s_addr = htonl(INADDR_LOOPBACK); + + if (action == RTM_ADD) { +- if ((kr6 = calloc(1, sizeof(struct kroute6_node))) == NULL) { ++ if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) { + log_warn("kr_change"); + return (-1); + } +- memcpy(&kr6->r.prefix, &kl->kr.prefix, +- sizeof(struct in6_addr)); +- kr6->r.prefixlen = kl->kr.prefixlen; +- memcpy(&kr6->r.nexthop, &kl->kr.nexthop, +- sizeof(struct in6_addr)); +- kr6->r.flags = kl->kr.flags | F_BGPD_INSERTED; +- kr6->r.priority = RTP_BGP; +- kr6->r.labelid = kl->kr.labelid; ++ kr->r.prefix.s_addr = kl->prefix.vpn4.addr.s_addr; ++ kr->r.prefixlen = kl->prefixlen; ++ kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr; ++ kr->r.flags = kl->flags | F_BGPD_INSERTED | F_MPLS; ++ kr->r.priority = RTP_BGP; ++ kr->r.labelid = labelid; ++ kr->r.mplslabel = mplslabel; + +- if (kroute6_insert(kr6) == -1) +- free(kr6); ++ if (kroute_insert(kt, kr) == -1) ++ free(kr); + } else { +- memcpy(&kr6->r.nexthop, &kl->kr.nexthop, +- sizeof(struct in6_addr)); +- kr6->r.labelid = kl->kr.labelid; +- if (kl->kr.flags & F_BLACKHOLE) +- kr6->r.flags |= F_BLACKHOLE; ++ kr->r.mplslabel = mplslabel; ++ kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr; ++ rtlabel_unref(kr->r.labelid); ++ kr->r.labelid = labelid; ++ if (kl->flags & F_BLACKHOLE) ++ kr->r.flags |= F_BLACKHOLE; + else +- kr6->r.flags &= ~F_BLACKHOLE; +- if (kl->kr.flags & F_REJECT) +- kr6->r.flags |= F_REJECT; ++ kr->r.flags &= ~F_BLACKHOLE; ++ if (kl->flags & F_REJECT) ++ kr->r.flags |= F_REJECT; + else +- kr6->r.flags &= ~F_REJECT; ++ kr->r.flags &= ~F_REJECT; ++ } ++ ++ if (send_rtmsg(kr_state.fd, action, kt, &kr->r) == -1) ++ return (-1); ++ ++ return (0); ++} ++ ++int ++kr_delete(u_int rtableid, struct kroute_full *kl) ++{ ++ struct ktable *kt; ++ ++ if ((kt = ktable_get(rtableid)) == NULL) ++ /* too noisy during reloads, just ignore */ ++ return (0); ++ ++ switch (kl->prefix.aid) { ++ case AID_INET: ++ return (kr4_delete(kt, kl)); ++ case AID_INET6: ++ return (kr6_delete(kt, kl)); ++ case AID_VPN_IPv4: ++ return (krVPN4_delete(kt, kl)); + } ++ log_warnx("kr_change: not handled AID"); ++ return (-1); ++} ++ ++int ++kr4_delete(struct ktable *kt, struct kroute_full *kl) ++{ ++ struct kroute_node *kr; ++ ++ if ((kr = kroute_find(kt, kl->prefix.v4.s_addr, kl->prefixlen, ++ RTP_BGP)) == NULL) ++ return (0); ++ ++ if (!(kr->r.flags & F_BGPD_INSERTED)) ++ return (0); ++ ++ if (send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r) == -1) ++ return (-1); ++ ++ rtlabel_unref(kr->r.labelid); ++ ++ if (kroute_remove(kt, kr) == -1) ++ return (-1); + + return (0); + } + + int +-kr6_delete(struct kroute6_label *kl) ++kr6_delete(struct ktable *kt, struct kroute_full *kl) + { + struct kroute6_node *kr6; + +- if ((kr6 = kroute6_find(&kl->kr.prefix, kl->kr.prefixlen, RTP_BGP)) +- == NULL) ++ if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen, RTP_BGP)) == ++ NULL) + return (0); + + if (!(kr6->r.flags & F_BGPD_INSERTED)) + return (0); + +- /* nexthop to loopback -> ignore silently */ +- if (IN6_IS_ADDR_LOOPBACK(&kl->kr.nexthop)) ++ if (send_rt6msg(kr_state.fd, RTM_DELETE, kt, &kr6->r) == -1) ++ return (-1); ++ ++ rtlabel_unref(kr6->r.labelid); ++ ++ if (kroute6_remove(kt, kr6) == -1) ++ return (-1); ++ ++ return (0); ++} ++ ++int ++krVPN4_delete(struct ktable *kt, struct kroute_full *kl) ++{ ++ struct kroute_node *kr; ++ ++ if ((kr = kroute_find(kt, kl->prefix.vpn4.addr.s_addr, kl->prefixlen, ++ RTP_BGP)) == NULL) + return (0); + +- if (send_rt6msg(kr_state.fd, RTM_DELETE, &kl->kr) == -1) ++ if (!(kr->r.flags & F_BGPD_INSERTED)) ++ return (0); ++ ++ if (send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r) == -1) + return (-1); + +- rtlabel_unref(kl->kr.labelid); ++ rtlabel_unref(kr->r.labelid); + +- if (kroute6_remove(kr6) == -1) ++ if (kroute_remove(kt, kr) == -1) + return (-1); + + return (0); +@@ -394,53 +758,63 @@ kr6_delete(struct kroute6_label *kl) + void + kr_shutdown(void) + { +- kr_fib_decouple(); +- knexthop_clear(); +- kroute_clear(); +- kroute6_clear(); ++ u_int i; ++ ++ for (i = krt_size; i > 0; i--) ++ ktable_free(i - 1); + kif_clear(); + } + + void +-kr_fib_couple(void) ++kr_fib_couple(u_int rtableid) + { ++ struct ktable *kt; + struct kroute_node *kr; + struct kroute6_node *kr6; + +- if (kr_state.fib_sync == 1) /* already coupled */ ++ if ((kt = ktable_get(rtableid)) == NULL) /* table does not exist */ + return; + +- kr_state.fib_sync = 1; ++ if (kt->fib_sync) /* already coupled */ ++ return; ++ ++ kt->fib_sync = 1; + +- RB_FOREACH(kr, kroute_tree, &krt) ++ RB_FOREACH(kr, kroute_tree, &kt->krt) + if ((kr->r.flags & F_BGPD_INSERTED)) +- send_rtmsg(kr_state.fd, RTM_ADD, &kr->r); +- RB_FOREACH(kr6, kroute6_tree, &krt6) ++ send_rtmsg(kr_state.fd, RTM_ADD, kt, &kr->r); ++ RB_FOREACH(kr6, kroute6_tree, &kt->krt6) + if ((kr6->r.flags & F_BGPD_INSERTED)) +- send_rt6msg(kr_state.fd, RTM_ADD, &kr6->r); ++ send_rt6msg(kr_state.fd, RTM_ADD, kt, &kr6->r); + +- log_info("kernel routing table coupled"); ++ log_info("kernel routing table %u (%s) coupled", kt->rtableid, ++ kt->descr); + } + + void +-kr_fib_decouple(void) ++kr_fib_decouple(u_int rtableid) + { ++ struct ktable *kt; + struct kroute_node *kr; + struct kroute6_node *kr6; + +- if (kr_state.fib_sync == 0) /* already decoupled */ ++ if ((kt = ktable_get(rtableid)) == NULL) /* table does not exist */ ++ return; ++ ++ if (!kt->fib_sync) /* already decoupled */ + return; + +- RB_FOREACH(kr, kroute_tree, &krt) ++ RB_FOREACH(kr, kroute_tree, &kt->krt) + if ((kr->r.flags & F_BGPD_INSERTED)) +- send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r); +- RB_FOREACH(kr6, kroute6_tree, &krt6) ++ send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r); ++ RB_FOREACH(kr6, kroute6_tree, &kt->krt6) + if ((kr6->r.flags & F_BGPD_INSERTED)) +- send_rt6msg(kr_state.fd, RTM_DELETE, &kr6->r); ++ send_rt6msg(kr_state.fd, RTM_DELETE, kt, &kr6->r); + +- kr_state.fib_sync = 0; ++ kt->fib_sync = 0; + +- log_info("kernel routing table decoupled"); ++ log_info("kernel routing table %u (%s) decoupled", kt->rtableid, ++ kt->descr); + } + + int +@@ -450,11 +824,16 @@ kr_dispatch_msg(void) + } + + int +-kr_nexthop_add(struct bgpd_addr *addr) ++kr_nexthop_add(u_int rtableid, struct bgpd_addr *addr) + { ++ struct ktable *kt; + struct knexthop_node *h; + +- if ((h = knexthop_find(addr)) != NULL) { ++ if ((kt = ktable_get(rtableid)) == NULL) { ++ log_warnx("kr_nexthop_add: non-existent rtableid %d", rtableid); ++ return (0); ++ } ++ if ((h = knexthop_find(kt, addr)) != NULL) { + /* should not happen... this is actually an error path */ + struct kroute_nexthop nh; + struct kroute_node *k; +@@ -463,25 +842,30 @@ kr_nexthop_add(struct bgpd_addr *addr) bzero(&nh, sizeof(nh)); memcpy(&nh.nexthop, addr, sizeof(nh.nexthop)); nh.valid = 1; @@ -49,25 +944,159 @@ diff -u -p -r1.1.1.7 -r1.9 } send_nexthop_update(&nh); -@@ -563,14 +568,14 @@ kr_show_route(struct imsg *imsg) +@@ -492,7 +876,7 @@ kr_nexthop_add(struct bgpd_addr *addr) + } + memcpy(&h->nexthop, addr, sizeof(h->nexthop)); + +- if (knexthop_insert(h) == -1) ++ if (knexthop_insert(kt, h) == -1) + return (-1); + } + +@@ -500,19 +884,25 @@ kr_nexthop_add(struct bgpd_addr *addr) + } + + void +-kr_nexthop_delete(struct bgpd_addr *addr) ++kr_nexthop_delete(u_int rtableid, struct bgpd_addr *addr) + { ++ struct ktable *kt; + struct knexthop_node *kn; + +- if ((kn = knexthop_find(addr)) == NULL) ++ if ((kt = ktable_get(rtableid)) == NULL) { ++ log_warnx("kr_nexthop_add: non-existent rtableid %d", rtableid); ++ return; ++ } ++ if ((kn = knexthop_find(kt, addr)) == NULL) + return; + +- knexthop_remove(kn); ++ knexthop_remove(kt, kn); + } + + void + kr_show_route(struct imsg *imsg) + { ++ struct ktable *kt; + struct kroute_node *kr, *kn; + struct kroute6_node *kr6, *kn6; + struct bgpd_addr *addr; +@@ -521,6 +911,7 @@ kr_show_route(struct imsg *imsg) + struct ctl_show_nexthop snh; + struct knexthop_node *h; + struct kif_node *kif; ++ u_int i; + u_short ifindex = 0; + + switch (imsg->hdr.type) { +@@ -528,70 +919,96 @@ kr_show_route(struct imsg *imsg) + if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(flags) + + sizeof(af)) { + log_warnx("kr_show_route: wrong imsg len"); +- return; ++ break; ++ } ++ kt = ktable_get(imsg->hdr.peerid); ++ if (kt == NULL) { ++ log_warnx("kr_show_route: table %u does not exist", ++ imsg->hdr.peerid); ++ break; + } + memcpy(&flags, imsg->data, sizeof(flags)); + memcpy(&af, (char *)imsg->data + sizeof(flags), sizeof(af)); + if (!af || af == AF_INET) +- RB_FOREACH(kr, kroute_tree, &krt) +- if (!flags || kr->r.flags & flags) { +- kn = kr; +- do { +- send_imsg_session( +- IMSG_CTL_KROUTE, +- imsg->hdr.pid, &kn->r, +- sizeof(kn->r)); +- } while ((kn = kn->next) != NULL); +- } ++ RB_FOREACH(kr, kroute_tree, &kt->krt) { ++ if (flags && (kr->r.flags & flags) == 0) ++ continue; ++ kn = kr; ++ do { ++ send_imsg_session(IMSG_CTL_KROUTE, ++ imsg->hdr.pid, kr_tofull(&kn->r), ++ sizeof(struct kroute_full)); ++ } while ((kn = kn->next) != NULL); ++ } + if (!af || af == AF_INET6) +- RB_FOREACH(kr6, kroute6_tree, &krt6) +- if (!flags || kr6->r.flags & flags) { +- kn6 = kr6; +- do { +- send_imsg_session( +- IMSG_CTL_KROUTE6, +- imsg->hdr.pid, &kn6->r, +- sizeof(kn6->r)); +- } while ((kn6 = kn6->next) != NULL); +- } ++ RB_FOREACH(kr6, kroute6_tree, &kt->krt6) { ++ if (flags && (kr6->r.flags & flags) == 0) ++ continue; ++ kn6 = kr6; ++ do { ++ send_imsg_session(IMSG_CTL_KROUTE, ++ imsg->hdr.pid, kr6_tofull(&kn6->r), ++ sizeof(struct kroute_full)); ++ } while ((kn6 = kn6->next) != NULL); ++ } + break; + case IMSG_CTL_KROUTE_ADDR: + if (imsg->hdr.len != IMSG_HEADER_SIZE + + sizeof(struct bgpd_addr)) { + log_warnx("kr_show_route: wrong imsg len"); +- return; ++ break; ++ } ++ kt = ktable_get(imsg->hdr.peerid); ++ if (kt == NULL) { ++ log_warnx("kr_show_route: table %u does not exist", ++ imsg->hdr.peerid); ++ break; } addr = imsg->data; kr = NULL; - switch (addr->af) { - case AF_INET: +- kr = kroute_match(addr->v4.s_addr, 1); + switch (addr->aid) { + case AID_INET: - kr = kroute_match(addr->v4.s_addr, 1); ++ kr = kroute_match(kt, addr->v4.s_addr, 1); if (kr != NULL) send_imsg_session(IMSG_CTL_KROUTE, - imsg->hdr.pid, &kr->r, sizeof(kr->r)); +- imsg->hdr.pid, &kr->r, sizeof(kr->r)); ++ imsg->hdr.pid, kr_tofull(&kr->r), ++ sizeof(struct kroute_full)); break; - case AF_INET6: +- kr6 = kroute6_match(&addr->v6, 1); + case AID_INET6: - kr6 = kroute6_match(&addr->v6, 1); ++ kr6 = kroute6_match(kt, &addr->v6, 1); if (kr6 != NULL) - send_imsg_session(IMSG_CTL_KROUTE6, -@@ -583,15 +588,21 @@ kr_show_route(struct imsg *imsg) +- send_imsg_session(IMSG_CTL_KROUTE6, +- imsg->hdr.pid, &kr6->r, sizeof(kr6->r)); ++ send_imsg_session(IMSG_CTL_KROUTE, ++ imsg->hdr.pid, kr6_tofull(&kr6->r), ++ sizeof(struct kroute_full)); + break; + } + break; + case IMSG_CTL_SHOW_NEXTHOP: +- RB_FOREACH(h, knexthop_tree, &knt) { ++ kt = ktable_get(imsg->hdr.peerid); ++ if (kt == NULL) { ++ log_warnx("kr_show_route: table %u does not exist", ++ imsg->hdr.peerid); ++ break; ++ } ++ RB_FOREACH(h, knexthop_tree, KT2KNT(kt)) { bzero(&snh, sizeof(snh)); memcpy(&snh.addr, &h->nexthop, sizeof(snh.addr)); if (h->kroute != NULL) { @@ -92,7 +1121,407 @@ diff -u -p -r1.1.1.7 -r1.9 ifindex = kr6->r.ifindex; break; } -@@ -846,26 +857,28 @@ kroute6_compare(struct kroute6_node *a, +@@ -608,6 +1025,24 @@ kr_show_route(struct imsg *imsg) + send_imsg_session(IMSG_CTL_SHOW_INTERFACE, + imsg->hdr.pid, &kif->k, sizeof(kif->k)); + break; ++ case IMSG_CTL_SHOW_FIB_TABLES: ++ for (i = 0; i < krt_size; i++) { ++ struct ktable ktab; ++ ++ if ((kt = ktable_get(i)) == NULL) ++ continue; ++ ++ ktab = *kt; ++ /* do not leak internal information */ ++ RB_INIT(&ktab.krt); ++ RB_INIT(&ktab.krt6); ++ RB_INIT(&ktab.knt); ++ TAILQ_INIT(&ktab.krn); ++ ++ send_imsg_session(IMSG_CTL_SHOW_FIB_TABLES, ++ imsg->hdr.pid, &ktab, sizeof(ktab)); ++ } ++ break; + default: /* nada */ + break; + } +@@ -628,21 +1063,146 @@ kr_ifinfo(char *ifname) + } + } + +-struct redist_node { +- LIST_ENTRY(redist_node) entry; +- struct kroute *kr; +- struct kroute6 *kr6; +-}; ++void ++kr_net_delete(struct network *n) ++{ ++ filterset_free(&n->net.attrset); ++ free(n); ++} ++ ++struct network * ++kr_net_match(struct ktable *kt, struct kroute *kr) ++{ ++ struct network *xn; ++ ++ TAILQ_FOREACH(xn, &kt->krn, entry) { ++ if (xn->net.prefix.aid != AID_INET) ++ continue; ++ switch (xn->net.type) { ++ case NETWORK_DEFAULT: ++ if (xn->net.prefixlen == kr->prefixlen && ++ xn->net.prefix.v4.s_addr == kr->prefix.s_addr) ++ /* static match already redistributed */ ++ return (NULL); ++ break; ++ case NETWORK_STATIC: ++ if (kr->flags & F_STATIC) ++ return (xn); ++ break; ++ case NETWORK_CONNECTED: ++ if (kr->flags & F_CONNECTED) ++ return (xn); ++ break; ++ } ++ } ++ return (NULL); ++} ++ ++struct network * ++kr_net_match6(struct ktable *kt, struct kroute6 *kr6) ++{ ++ struct network *xn; ++ ++ TAILQ_FOREACH(xn, &kt->krn, entry) { ++ if (xn->net.prefix.aid != AID_INET6) ++ continue; ++ switch (xn->net.type) { ++ case NETWORK_DEFAULT: ++ if (xn->net.prefixlen == kr6->prefixlen && ++ memcmp(&xn->net.prefix.v6, &kr6->prefix, ++ sizeof(struct in6_addr)) == 0) ++ /* static match already redistributed */ ++ return (NULL); ++ break; ++ case NETWORK_STATIC: ++ if (kr6->flags & F_STATIC) ++ return (xn); ++ break; ++ case NETWORK_CONNECTED: ++ if (kr6->flags & F_CONNECTED) ++ return (xn); ++ break; ++ } ++ } ++ return (NULL); ++} ++ ++struct network * ++kr_net_find(struct ktable *kt, struct network *n) ++{ ++ struct network *xn; ++ ++ TAILQ_FOREACH(xn, &kt->krn, entry) { ++ if (n->net.type != xn->net.type || ++ n->net.prefixlen != xn->net.prefixlen || ++ n->net.rtableid != xn->net.rtableid) ++ continue; ++ if (memcmp(&n->net.prefix, &xn->net.prefix, ++ sizeof(n->net.prefix)) == 0) ++ return (xn); ++ } ++ return (NULL); ++} ++ ++int ++kr_net_reload(u_int rtableid, struct network_head *nh) ++{ ++ struct network *n, *xn; ++ struct ktable *kt; ++ ++ if ((kt = ktable_get(rtableid)) == NULL) { ++ log_warnx("kr_net_reload: non-existent rtableid %d", rtableid); ++ return (-1); ++ } ++ ++ TAILQ_FOREACH(n, &kt->krn, entry) ++ n->net.old = 1; ++ ++ while ((n = TAILQ_FIRST(nh)) != NULL) { ++ TAILQ_REMOVE(nh, n, entry); ++ n->net.old = 0; ++ n->net.rtableid = rtableid; ++ xn = kr_net_find(kt, n); ++ if (xn) { ++ xn->net.old = 0; ++ filterset_free(&xn->net.attrset); ++ filterset_move(&n->net.attrset, &xn->net.attrset); ++ kr_net_delete(n); ++ } else ++ TAILQ_INSERT_TAIL(&kt->krn, n, entry); ++ } + ++ for (n = TAILQ_FIRST(&kt->krn); n != NULL; n = xn) { ++ xn = TAILQ_NEXT(n, entry); ++ if (n->net.old) { ++ if (n->net.type == NETWORK_DEFAULT) ++ if (send_network(IMSG_NETWORK_REMOVE, &n->net, ++ NULL)) ++ return (-1); ++ TAILQ_REMOVE(&kt->krn, n, entry); ++ kr_net_delete(n); ++ } ++ } + +-LIST_HEAD(, redist_node) redistlist; ++ return (0); ++} + + int +-kr_redistribute(int type, struct kroute *kr) ++kr_redistribute(int type, struct ktable *kt, struct kroute *kr) + { +- struct redist_node *rn; ++ struct network *match; ++ struct network_config net; + u_int32_t a; + ++ /* shortcut for removals */ ++ if (type == IMSG_NETWORK_REMOVE) { ++ if (!(kr->flags & F_REDISTRIBUTED)) ++ return (0); /* no match, don't redistribute */ ++ kr->flags &= ~F_REDISTRIBUTED; ++ match = NULL; ++ goto sendit; ++ } ++ + if (!(kr->flags & F_KERNEL)) + return (0); + +@@ -670,41 +1230,40 @@ kr_redistribute(int type, struct kroute + if (kr->prefix.s_addr == INADDR_ANY && kr->prefixlen == 0) + return (0); + +- /* Add or delete kr from list ... */ +- LIST_FOREACH(rn, &redistlist, entry) +- if (rn->kr == kr) +- break; +- +- switch (type) { +- case IMSG_NETWORK_ADD: +- if (rn == NULL) { +- if ((rn = calloc(1, sizeof(struct redist_node))) == +- NULL) { +- log_warn("kr_redistribute"); +- return (-1); +- } +- rn->kr = kr; +- LIST_INSERT_HEAD(&redistlist, rn, entry); +- } +- break; +- case IMSG_NETWORK_REMOVE: +- if (rn != NULL) { +- LIST_REMOVE(rn, entry); +- free(rn); +- } +- break; +- default: +- errno = EINVAL; +- return (-1); +- } +- +- return (bgpd_redistribute(type, kr, NULL)); ++ match = kr_net_match(kt, kr); ++ if (match == NULL) { ++ if (!(kr->flags & F_REDISTRIBUTED)) ++ return (0); /* no match, don't redistribute */ ++ /* route no longer matches but is redistributed, so remove */ ++ kr->flags &= ~F_REDISTRIBUTED; ++ type = IMSG_NETWORK_REMOVE; ++ } else ++ kr->flags |= F_REDISTRIBUTED; ++ ++sendit: ++ bzero(&net, sizeof(net)); ++ net.prefix.aid = AID_INET; ++ net.prefix.v4.s_addr = kr->prefix.s_addr; ++ net.prefixlen = kr->prefixlen; ++ net.rtableid = kt->rtableid; ++ ++ return (send_network(type, &net, match ? &match->net.attrset : NULL)); + } + + int +-kr_redistribute6(int type, struct kroute6 *kr6) +-{ +- struct redist_node *rn; ++kr_redistribute6(int type, struct ktable *kt, struct kroute6 *kr6) ++{ ++ struct network *match; ++ struct network_config net; ++ ++ /* shortcut for removals */ ++ if (type == IMSG_NETWORK_REMOVE) { ++ if (!(kr6->flags & F_REDISTRIBUTED)) ++ return (0); /* no match, don't redistribute */ ++ kr6->flags &= ~F_REDISTRIBUTED; ++ match = NULL; ++ goto sendit; ++ } + + if (!(kr6->flags & F_KERNEL)) + return (0); +@@ -736,60 +1295,107 @@ kr_redistribute6(int type, struct kroute + * never allow ::/0 the default route can only be redistributed + * with announce default. + */ +- if (memcmp(&kr6->prefix, &in6addr_any, sizeof(struct in6_addr)) == 0 && +- kr6->prefixlen == 0) ++ if (kr6->prefixlen == 0 && ++ memcmp(&kr6->prefix, &in6addr_any, sizeof(struct in6_addr)) == 0) + return (0); + +- /* Add or delete kr from list ... +- * using a linear list to store the redistributed networks will hurt +- * as soon as redistribute ospf comes but until then keep it simple. +- */ +- LIST_FOREACH(rn, &redistlist, entry) +- if (rn->kr6 == kr6) +- break; +- +- switch (type) { +- case IMSG_NETWORK_ADD: +- if (rn == NULL) { +- if ((rn = calloc(1, sizeof(struct redist_node))) == +- NULL) { +- log_warn("kr_redistribute"); +- return (-1); +- } +- rn->kr6 = kr6; +- LIST_INSERT_HEAD(&redistlist, rn, entry); +- } +- break; +- case IMSG_NETWORK_REMOVE: +- if (rn != NULL) { +- LIST_REMOVE(rn, entry); +- free(rn); +- } +- break; +- default: +- errno = EINVAL; +- return (-1); +- } ++ match = kr_net_match6(kt, kr6); ++ if (match == NULL) { ++ if (!(kr6->flags & F_REDISTRIBUTED)) ++ return (0); /* no match, don't redistribute */ ++ /* route no longer matches but is redistributed, so remove */ ++ kr6->flags &= ~F_REDISTRIBUTED; ++ type = IMSG_NETWORK_REMOVE; ++ } else ++ kr6->flags |= F_REDISTRIBUTED; ++sendit: ++ bzero(&net, sizeof(net)); ++ net.prefix.aid = AID_INET6; ++ memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr)); ++ net.prefixlen = kr6->prefixlen; ++ net.rtableid = kt->rtableid; + +- return (bgpd_redistribute(type, NULL, kr6)); ++ return (send_network(type, &net, match ? &match->net.attrset : NULL)); + } + + int + kr_reload(void) + { +- struct redist_node *rn; ++ struct ktable *kt; ++ struct kroute_node *kr; ++ struct kroute6_node *kr6; + struct knexthop_node *nh; ++ struct network *n; ++ u_int rid; ++ int hasdyn = 0; + +- LIST_FOREACH(rn, &redistlist, entry) +- if (bgpd_redistribute(IMSG_NETWORK_ADD, rn->kr, rn->kr6) == -1) +- return (-1); ++ for (rid = 0; rid < krt_size; rid++) { ++ if ((kt = ktable_get(rid)) == NULL) ++ continue; + +- RB_FOREACH(nh, knexthop_tree, &knt) +- knexthop_validate(nh); ++ RB_FOREACH(nh, knexthop_tree, KT2KNT(kt)) ++ knexthop_validate(kt, nh); ++ ++ TAILQ_FOREACH(n, &kt->krn, entry) ++ if (n->net.type == NETWORK_DEFAULT) { ++ if (send_network(IMSG_NETWORK_ADD, &n->net, ++ &n->net.attrset)) ++ return (-1); ++ } else ++ hasdyn = 1; ++ ++ if (hasdyn) { ++ /* only evaluate the full tree if we need */ ++ RB_FOREACH(kr, kroute_tree, &kt->krt) ++ kr_redistribute(IMSG_NETWORK_ADD, kt, &kr->r); ++ RB_FOREACH(kr6, kroute6_tree, &kt->krt6) ++ kr_redistribute6(IMSG_NETWORK_ADD, kt, &kr6->r); ++ } ++ } + + return (0); + } + ++struct kroute_full * ++kr_tofull(struct kroute *kr) ++{ ++ static struct kroute_full kf; ++ ++ bzero(&kf, sizeof(kf)); ++ ++ kf.prefix.aid = AID_INET; ++ kf.prefix.v4.s_addr = kr->prefix.s_addr; ++ kf.nexthop.aid = AID_INET; ++ kf.nexthop.v4.s_addr = kr->nexthop.s_addr; ++ strlcpy(kf.label, rtlabel_id2name(kr->labelid), sizeof(kf.label)); ++ kf.flags = kr->flags; ++ kf.ifindex = kr->ifindex; ++ kf.prefixlen = kr->prefixlen; ++ kf.priority = kr->priority; ++ ++ return (&kf); ++} ++ ++struct kroute_full * ++kr6_tofull(struct kroute6 *kr6) ++{ ++ static struct kroute_full kf; ++ ++ bzero(&kf, sizeof(kf)); ++ ++ kf.prefix.aid = AID_INET6; ++ memcpy(&kf.prefix.v6, &kr6->prefix, sizeof(struct in6_addr)); ++ kf.nexthop.aid = AID_INET6; ++ memcpy(&kf.nexthop.v6, &kr6->nexthop, sizeof(struct in6_addr)); ++ strlcpy(kf.label, rtlabel_id2name(kr6->labelid), sizeof(kf.label)); ++ kf.flags = kr6->flags; ++ kf.ifindex = kr6->ifindex; ++ kf.prefixlen = kr6->prefixlen; ++ kf.priority = kr6->priority; ++ ++ return (&kf); ++} ++ + /* + * RB-tree compare functions + */ +@@ -846,26 +1452,28 @@ kroute6_compare(struct kroute6_node *a, int knexthop_compare(struct knexthop_node *a, struct knexthop_node *b) { @@ -137,16 +1566,165 @@ diff -u -p -r1.1.1.7 -r1.9 } return (0); -@@ -945,7 +958,7 @@ kroute_insert(struct kroute_node *kr) +@@ -883,7 +1491,8 @@ kif_compare(struct kif_node *a, struct k + */ + + struct kroute_node * +-kroute_find(in_addr_t prefix, u_int8_t prefixlen, u_int8_t prio) ++kroute_find(struct ktable *kt, in_addr_t prefix, u_int8_t prefixlen, ++ u_int8_t prio) + { + struct kroute_node s; + struct kroute_node *kn, *tmp; +@@ -892,15 +1501,15 @@ kroute_find(in_addr_t prefix, u_int8_t p + s.r.prefixlen = prefixlen; + s.r.priority = prio; + +- kn = RB_FIND(kroute_tree, &krt, &s); ++ kn = RB_FIND(kroute_tree, &kt->krt, &s); + if (kn && prio == RTP_ANY) { +- tmp = RB_PREV(kroute_tree, &krt, kn); ++ tmp = RB_PREV(kroute_tree, &kt->krt, kn); + while (tmp) { + if (kroute_compare(&s, tmp) == 0) + kn = tmp; + else + break; +- tmp = RB_PREV(kroute_tree, &krt, kn); ++ tmp = RB_PREV(kroute_tree, &kt->krt, kn); + } + } + return (kn); +@@ -927,13 +1536,13 @@ kroute_matchgw(struct kroute_node *kr, s + } + + int +-kroute_insert(struct kroute_node *kr) ++kroute_insert(struct ktable *kt, struct kroute_node *kr) + { + struct kroute_node *krm; + struct knexthop_node *h; + in_addr_t mask, ina; + +- if ((krm = RB_INSERT(kroute_tree, &krt, kr)) != NULL) { ++ if ((krm = RB_INSERT(kroute_tree, &kt->krt, kr)) != NULL) { + /* multipath route, add at end of list */ + while (krm->next != NULL) + krm = krm->next; +@@ -944,10 +1553,10 @@ kroute_insert(struct kroute_node *kr) + if (kr->r.flags & F_KERNEL) { mask = prefixlen2mask(kr->r.prefixlen); ina = ntohl(kr->r.prefix.s_addr); - RB_FOREACH(h, knexthop_tree, &knt) +- RB_FOREACH(h, knexthop_tree, &knt) - if (h->nexthop.af == AF_INET && ++ RB_FOREACH(h, knexthop_tree, KT2KNT(kt)) + if (h->nexthop.aid == AID_INET && (ntohl(h->nexthop.v4.s_addr) & mask) == ina) - knexthop_validate(h); +- knexthop_validate(h); ++ knexthop_validate(kt, h); + + if (kr->r.flags & F_CONNECTED) + if (kif_kr_insert(kr) == -1) +@@ -955,19 +1564,19 @@ kroute_insert(struct kroute_node *kr) + + if (krm == NULL) + /* redistribute multipath routes only once */ +- kr_redistribute(IMSG_NETWORK_ADD, &kr->r); ++ kr_redistribute(IMSG_NETWORK_ADD, kt, &kr->r); + } + return (0); + } -@@ -1065,7 +1078,7 @@ kroute6_matchgw(struct kroute6_node *kr, + + int +-kroute_remove(struct kroute_node *kr) ++kroute_remove(struct ktable *kt, struct kroute_node *kr) + { + struct kroute_node *krm; + struct knexthop_node *s; + +- if ((krm = RB_FIND(kroute_tree, &krt, kr)) == NULL) { ++ if ((krm = RB_FIND(kroute_tree, &kt->krt, kr)) == NULL) { + log_warnx("kroute_remove failed to find %s/%u", + inet_ntoa(kr->r.prefix), kr->r.prefixlen); + return (-1); +@@ -975,13 +1584,14 @@ kroute_remove(struct kroute_node *kr) + + if (krm == kr) { + /* head element */ +- if (RB_REMOVE(kroute_tree, &krt, kr) == NULL) { ++ if (RB_REMOVE(kroute_tree, &kt->krt, kr) == NULL) { + log_warnx("kroute_remove failed for %s/%u", + inet_ntoa(kr->r.prefix), kr->r.prefixlen); + return (-1); + } + if (kr->next != NULL) { +- if (RB_INSERT(kroute_tree, &krt, kr->next) != NULL) { ++ if (RB_INSERT(kroute_tree, &kt->krt, kr->next) != ++ NULL) { + log_warnx("kroute_remove failed to add %s/%u", + inet_ntoa(kr->r.prefix), kr->r.prefixlen); + return (-1); +@@ -1002,13 +1612,13 @@ kroute_remove(struct kroute_node *kr) + + /* check whether a nexthop depends on this kroute */ + if ((kr->r.flags & F_KERNEL) && (kr->r.flags & F_NEXTHOP)) +- RB_FOREACH(s, knexthop_tree, &knt) ++ RB_FOREACH(s, knexthop_tree, KT2KNT(kt)) + if (s->kroute == kr) +- knexthop_validate(s); ++ knexthop_validate(kt, s); + + if (kr->r.flags & F_KERNEL && kr == krm && kr->next == NULL) + /* again remove only once */ +- kr_redistribute(IMSG_NETWORK_REMOVE, &kr->r); ++ kr_redistribute(IMSG_NETWORK_REMOVE, kt, &kr->r); + + if (kr->r.flags & F_CONNECTED) + if (kif_kr_remove(kr) == -1) { +@@ -1021,16 +1631,17 @@ kroute_remove(struct kroute_node *kr) + } + + void +-kroute_clear(void) ++kroute_clear(struct ktable *kt) + { + struct kroute_node *kr; + +- while ((kr = RB_MIN(kroute_tree, &krt)) != NULL) +- kroute_remove(kr); ++ while ((kr = RB_MIN(kroute_tree, &kt->krt)) != NULL) ++ kroute_remove(kt, kr); + } + + struct kroute6_node * +-kroute6_find(const struct in6_addr *prefix, u_int8_t prefixlen, u_int8_t prio) ++kroute6_find(struct ktable *kt, const struct in6_addr *prefix, ++ u_int8_t prefixlen, u_int8_t prio) + { + struct kroute6_node s; + struct kroute6_node *kn6, *tmp; +@@ -1039,15 +1650,15 @@ kroute6_find(const struct in6_addr *pref + s.r.prefixlen = prefixlen; + s.r.priority = prio; + +- kn6 = RB_FIND(kroute6_tree, &krt6, &s); ++ kn6 = RB_FIND(kroute6_tree, &kt->krt6, &s); + if (kn6 && prio == RTP_ANY) { +- tmp = RB_PREV(kroute6_tree, &krt6, kn6); ++ tmp = RB_PREV(kroute6_tree, &kt->krt6, kn6); + while (tmp) { + if (kroute6_compare(&s, tmp) == 0) + kn6 = tmp; +- else ++ else + break; +- tmp = RB_PREV(kroute6_tree, &krt6, kn6); ++ tmp = RB_PREV(kroute6_tree, &kt->krt6, kn6); + } + } + return (kn6); +@@ -1065,7 +1676,7 @@ kroute6_matchgw(struct kroute6_node *kr, memcpy(&nexthop, &sa_in6->sin6_addr, sizeof(nexthop)); while (kr) { @@ -155,24 +1733,213 @@ diff -u -p -r1.1.1.7 -r1.9 return (kr); kr = kr->next; } -@@ -1091,7 +1104,7 @@ kroute6_insert(struct kroute6_node *kr) +@@ -1074,13 +1685,13 @@ kroute6_matchgw(struct kroute6_node *kr, + } + + int +-kroute6_insert(struct kroute6_node *kr) ++kroute6_insert(struct ktable *kt, struct kroute6_node *kr) + { + struct kroute6_node *krm; + struct knexthop_node *h; + struct in6_addr ina, inb; + +- if ((krm = RB_INSERT(kroute6_tree, &krt6, kr)) != NULL) { ++ if ((krm = RB_INSERT(kroute6_tree, &kt->krt6, kr)) != NULL) { + /* multipath route, add at end of list */ + while (krm->next != NULL) + krm = krm->next; +@@ -1090,12 +1701,12 @@ kroute6_insert(struct kroute6_node *kr) + if (kr->r.flags & F_KERNEL) { inet6applymask(&ina, &kr->r.prefix, kr->r.prefixlen); - RB_FOREACH(h, knexthop_tree, &knt) +- RB_FOREACH(h, knexthop_tree, &knt) - if (h->nexthop.af == AF_INET6) { ++ RB_FOREACH(h, knexthop_tree, KT2KNT(kt)) + if (h->nexthop.aid == AID_INET6) { inet6applymask(&inb, &h->nexthop.v6, kr->r.prefixlen); if (memcmp(&ina, &inb, sizeof(ina)) == 0) -@@ -1184,6 +1197,7 @@ knexthop_find(struct bgpd_addr *addr) +- knexthop_validate(h); ++ knexthop_validate(kt, h); + } + + if (kr->r.flags & F_CONNECTED) +@@ -1104,19 +1715,19 @@ kroute6_insert(struct kroute6_node *kr) + + if (krm == NULL) + /* redistribute multipath routes only once */ +- kr_redistribute6(IMSG_NETWORK_ADD, &kr->r); ++ kr_redistribute6(IMSG_NETWORK_ADD, kt, &kr->r); + } + + return (0); + } + + int +-kroute6_remove(struct kroute6_node *kr) ++kroute6_remove(struct ktable *kt, struct kroute6_node *kr) + { + struct kroute6_node *krm; + struct knexthop_node *s; + +- if ((krm = RB_FIND(kroute6_tree, &krt6, kr)) == NULL) { ++ if ((krm = RB_FIND(kroute6_tree, &kt->krt6, kr)) == NULL) { + log_warnx("kroute6_remove failed for %s/%u", + log_in6addr(&kr->r.prefix), kr->r.prefixlen); + return (-1); +@@ -1124,13 +1735,14 @@ kroute6_remove(struct kroute6_node *kr) + + if (krm == kr) { + /* head element */ +- if (RB_REMOVE(kroute6_tree, &krt6, kr) == NULL) { ++ if (RB_REMOVE(kroute6_tree, &kt->krt6, kr) == NULL) { + log_warnx("kroute6_remove failed for %s/%u", + log_in6addr(&kr->r.prefix), kr->r.prefixlen); + return (-1); + } + if (kr->next != NULL) { +- if (RB_INSERT(kroute6_tree, &krt6, kr->next) != NULL) { ++ if (RB_INSERT(kroute6_tree, &kt->krt6, kr->next) != ++ NULL) { + log_warnx("kroute6_remove failed to add %s/%u", + log_in6addr(&kr->r.prefix), + kr->r.prefixlen); +@@ -1152,13 +1764,13 @@ kroute6_remove(struct kroute6_node *kr) + + /* check whether a nexthop depends on this kroute */ + if ((kr->r.flags & F_KERNEL) && (kr->r.flags & F_NEXTHOP)) +- RB_FOREACH(s, knexthop_tree, &knt) ++ RB_FOREACH(s, knexthop_tree, KT2KNT(kt)) + if (s->kroute == kr) +- knexthop_validate(s); ++ knexthop_validate(kt, s); + + if (kr->r.flags & F_KERNEL && kr == krm && kr->next == NULL) + /* again remove only once */ +- kr_redistribute6(IMSG_NETWORK_REMOVE, &kr->r); ++ kr_redistribute6(IMSG_NETWORK_REMOVE, kt, &kr->r); + + if (kr->r.flags & F_CONNECTED) + if (kif_kr6_remove(kr) == -1) { +@@ -1171,45 +1783,46 @@ kroute6_remove(struct kroute6_node *kr) + } + + void +-kroute6_clear(void) ++kroute6_clear(struct ktable *kt) + { + struct kroute6_node *kr; + +- while ((kr = RB_MIN(kroute6_tree, &krt6)) != NULL) +- kroute6_remove(kr); ++ while ((kr = RB_MIN(kroute6_tree, &kt->krt6)) != NULL) ++ kroute6_remove(kt, kr); + } + + struct knexthop_node * +-knexthop_find(struct bgpd_addr *addr) ++knexthop_find(struct ktable *kt, struct bgpd_addr *addr) { struct knexthop_node s; + bzero(&s, sizeof(s)); memcpy(&s.nexthop, addr, sizeof(s.nexthop)); - return (RB_FIND(knexthop_tree, &knt, &s)); -@@ -1480,17 +1494,17 @@ knexthop_validate(struct knexthop_node * +- return (RB_FIND(knexthop_tree, &knt, &s)); ++ return (RB_FIND(knexthop_tree, KT2KNT(kt), &s)); + } + + int +-knexthop_insert(struct knexthop_node *kn) ++knexthop_insert(struct ktable *kt, struct knexthop_node *kn) + { +- if (RB_INSERT(knexthop_tree, &knt, kn) != NULL) { ++ if (RB_INSERT(knexthop_tree, KT2KNT(kt), kn) != NULL) { + log_warnx("knexthop_tree insert failed for %s", + log_addr(&kn->nexthop)); + free(kn); + return (-1); + } + +- knexthop_validate(kn); ++ knexthop_validate(kt, kn); + + return (0); + } + + int +-knexthop_remove(struct knexthop_node *kn) ++knexthop_remove(struct ktable *kt, struct knexthop_node *kn) + { +- kroute_detach_nexthop(kn); ++ kroute_detach_nexthop(kt, kn); + +- if (RB_REMOVE(knexthop_tree, &knt, kn) == NULL) { ++ if (RB_REMOVE(knexthop_tree, KT2KNT(kt), kn) == NULL) { + log_warnx("knexthop_remove failed for %s", + log_addr(&kn->nexthop)); + return (-1); +@@ -1220,12 +1833,12 @@ knexthop_remove(struct knexthop_node *kn + } + + void +-knexthop_clear(void) ++knexthop_clear(struct ktable *kt) + { + struct knexthop_node *kn; + +- while ((kn = RB_MIN(knexthop_tree, &knt)) != NULL) +- knexthop_remove(kn); ++ while ((kn = RB_MIN(knexthop_tree, KT2KNT(kt))) != NULL) ++ knexthop_remove(kt, kn); + } + + struct kif_node * +@@ -1257,6 +1870,7 @@ kif_insert(struct kif_node *kif) + int + kif_remove(struct kif_node *kif) + { ++ struct ktable *kt; + struct kif_kr *kkr; + struct kif_kr6 *kkr6; + +@@ -1265,20 +1879,23 @@ kif_remove(struct kif_node *kif) + return (-1); + } + ++ if ((kt = ktable_get(/* XXX */ 0)) == NULL) ++ goto done; ++ + while ((kkr = LIST_FIRST(&kif->kroute_l)) != NULL) { + LIST_REMOVE(kkr, entry); + kkr->kr->r.flags &= ~F_NEXTHOP; +- kroute_remove(kkr->kr); ++ kroute_remove(kt, kkr->kr); + free(kkr); + } + + while ((kkr6 = LIST_FIRST(&kif->kroute6_l)) != NULL) { + LIST_REMOVE(kkr6, entry); + kkr6->kr->r.flags &= ~F_NEXTHOP; +- kroute6_remove(kkr6->kr); ++ kroute6_remove(kt, kkr6->kr); + free(kkr6); + } +- ++done: + free(kif); + return (0); + } +@@ -1473,25 +2090,25 @@ kroute6_validate(struct kroute6 *kr) + } + + void +-knexthop_validate(struct knexthop_node *kn) ++knexthop_validate(struct ktable *kt, struct knexthop_node *kn) + { + struct kroute_node *kr; + struct kroute6_node *kr6; struct kroute_nexthop n; int was_valid = 0; @@ -185,16 +1952,19 @@ diff -u -p -r1.1.1.7 -r1.9 bzero(&n, sizeof(n)); memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop)); - kroute_detach_nexthop(kn); +- kroute_detach_nexthop(kn); ++ kroute_detach_nexthop(kt, kn); - switch (kn->nexthop.af) { - case AF_INET: +- if ((kr = kroute_match(kn->nexthop.v4.s_addr, 0)) == NULL) { + switch (kn->nexthop.aid) { + case AID_INET: - if ((kr = kroute_match(kn->nexthop.v4.s_addr, 0)) == NULL) { ++ if ((kr = kroute_match(kt, kn->nexthop.v4.s_addr, 0)) == NULL) { if (was_valid) send_nexthop_update(&n); -@@ -1500,8 +1514,10 @@ knexthop_validate(struct knexthop_node * + } else { /* match */ +@@ -1500,8 +2117,10 @@ knexthop_validate(struct knexthop_node * n.connected = kr->r.flags & F_CONNECTED; if ((n.gateway.v4.s_addr = kr->r.nexthop.s_addr) != 0) @@ -207,16 +1977,18 @@ diff -u -p -r1.1.1.7 -r1.9 send_nexthop_update(&n); } else /* down */ if (was_valid) -@@ -1511,7 +1527,7 @@ knexthop_validate(struct knexthop_node * +@@ -1511,8 +2130,8 @@ knexthop_validate(struct knexthop_node * kr->r.flags |= F_NEXTHOP; } break; - case AF_INET6: +- if ((kr6 = kroute6_match(&kn->nexthop.v6, 0)) == NULL) { + case AID_INET6: - if ((kr6 = kroute6_match(&kn->nexthop.v6, 0)) == NULL) { ++ if ((kr6 = kroute6_match(kt, &kn->nexthop.v6, 0)) == NULL) { if (was_valid) send_nexthop_update(&n); -@@ -1521,11 +1537,14 @@ knexthop_validate(struct knexthop_node * + } else { /* match */ +@@ -1521,11 +2140,14 @@ knexthop_validate(struct knexthop_node * n.connected = kr6->r.flags & F_CONNECTED; if (memcmp(&kr6->r.nexthop, &in6addr_any, sizeof(struct in6_addr)) != 0) { @@ -233,15 +2005,31 @@ diff -u -p -r1.1.1.7 -r1.9 send_nexthop_update(&n); } else /* down */ if (was_valid) -@@ -1551,27 +1570,32 @@ knexthop_track(void *krn) +@@ -1539,39 +2161,44 @@ knexthop_validate(struct knexthop_node * + } + + void +-knexthop_track(void *krn) ++knexthop_track(struct ktable *kt, void *krp) + { + struct knexthop_node *kn; + struct kroute_node *kr; + struct kroute6_node *kr6; + struct kroute_nexthop n; + +- RB_FOREACH(kn, knexthop_tree, &knt) +- if (kn->kroute == krn) { ++ RB_FOREACH(kn, knexthop_tree, KT2KNT(kt)) ++ if (kn->kroute == krp) { bzero(&n, sizeof(n)); memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop)); - switch (kn->nexthop.af) { - case AF_INET: +- kr = krn; + switch (kn->nexthop.aid) { + case AID_INET: - kr = krn; ++ kr = krp; n.valid = 1; n.connected = kr->r.flags & F_CONNECTED; if ((n.gateway.v4.s_addr = @@ -254,8 +2042,9 @@ diff -u -p -r1.1.1.7 -r1.9 + n.netlen = kr->r.prefixlen; break; - case AF_INET6: +- kr6 = krn; + case AID_INET6: - kr6 = krn; ++ kr6 = krp; n.valid = 1; n.connected = kr6->r.flags & F_CONNECTED; if (memcmp(&kr6->r.nexthop, &in6addr_any, @@ -273,7 +2062,73 @@ diff -u -p -r1.1.1.7 -r1.9 break; } send_nexthop_update(&n); -@@ -1645,12 +1669,12 @@ kroute_detach_nexthop(struct knexthop_no +@@ -1579,7 +2206,7 @@ knexthop_track(void *krn) + } + + struct kroute_node * +-kroute_match(in_addr_t key, int matchall) ++kroute_match(struct ktable *kt, in_addr_t key, int matchall) + { + int i; + struct kroute_node *kr; +@@ -1589,13 +2216,13 @@ kroute_match(in_addr_t key, int matchall + + /* we will never match the default route */ + for (i = 32; i > 0; i--) +- if ((kr = kroute_find(htonl(ina & prefixlen2mask(i)), i, ++ if ((kr = kroute_find(kt, htonl(ina & prefixlen2mask(i)), i, + RTP_ANY)) != NULL) + if (matchall || bgpd_filternexthop(&kr->r, NULL) == 0) + return (kr); + + /* if we don't have a match yet, try to find a default route */ +- if ((kr = kroute_find(0, 0, RTP_ANY)) != NULL) ++ if ((kr = kroute_find(kt, 0, 0, RTP_ANY)) != NULL) + if (matchall || bgpd_filternexthop(&kr->r, NULL) == 0) + return (kr); + +@@ -1603,7 +2230,7 @@ kroute_match(in_addr_t key, int matchall + } + + struct kroute6_node * +-kroute6_match(struct in6_addr *key, int matchall) ++kroute6_match(struct ktable *kt, struct in6_addr *key, int matchall) + { + int i; + struct kroute6_node *kr6; +@@ -1612,13 +2239,13 @@ kroute6_match(struct in6_addr *key, int + /* we will never match the default route */ + for (i = 128; i > 0; i--) { + inet6applymask(&ina, key, i); +- if ((kr6 = kroute6_find(&ina, i, RTP_ANY)) != NULL) ++ if ((kr6 = kroute6_find(kt, &ina, i, RTP_ANY)) != NULL) + if (matchall || bgpd_filternexthop(NULL, &kr6->r) == 0) + return (kr6); + } + + /* if we don't have a match yet, try to find a default route */ +- if ((kr6 = kroute6_find(&in6addr_any, 0, RTP_ANY)) != NULL) ++ if ((kr6 = kroute6_find(kt, &in6addr_any, 0, RTP_ANY)) != NULL) + if (matchall || bgpd_filternexthop(NULL, &kr6->r) == 0) + return (kr6); + +@@ -1626,7 +2253,7 @@ kroute6_match(struct in6_addr *key, int + } + + void +-kroute_detach_nexthop(struct knexthop_node *kn) ++kroute_detach_nexthop(struct ktable *kt, struct knexthop_node *kn) + { + struct knexthop_node *s; + struct kroute_node *k; +@@ -1640,17 +2267,17 @@ kroute_detach_nexthop(struct knexthop_no + if (kn->kroute == NULL) + return; + +- for (s = RB_MIN(knexthop_tree, &knt); s != NULL && +- s->kroute != kn->kroute; s = RB_NEXT(knexthop_tree, &knt, s)) ++ for (s = RB_MIN(knexthop_tree, KT2KNT(kt)); s != NULL && ++ s->kroute != kn->kroute; s = RB_NEXT(knexthop_tree, KT2KNT(kt), s)) ; /* nothing */ if (s == NULL) { @@ -289,7 +2144,16 @@ diff -u -p -r1.1.1.7 -r1.9 k6 = kn->kroute; k6->r.flags &= ~F_NEXTHOP; break; -@@ -1675,7 +1699,7 @@ protect_lo(void) +@@ -1665,7 +2292,7 @@ kroute_detach_nexthop(struct knexthop_no + */ + + int +-protect_lo(void) ++protect_lo(struct ktable *kt) + { + struct kroute_node *kr; + struct kroute6_node *kr6; +@@ -1675,11 +2302,11 @@ protect_lo(void) log_warn("protect_lo"); return (-1); } @@ -298,16 +2162,56 @@ diff -u -p -r1.1.1.7 -r1.9 kr->r.prefixlen = 8; kr->r.flags = F_KERNEL|F_CONNECTED; -@@ -1689,7 +1713,7 @@ protect_lo(void) +- if (RB_INSERT(kroute_tree, &krt, kr) != NULL) ++ if (RB_INSERT(kroute_tree, &kt->krt, kr) != NULL) + free(kr); /* kernel route already there, no problem */ + + /* special protection for loopback */ +@@ -1689,9 +2316,9 @@ protect_lo(void) } memcpy(&kr6->r.prefix, &in6addr_loopback, sizeof(kr6->r.prefix)); kr6->r.prefixlen = 128; - kr->r.flags = F_KERNEL|F_CONNECTED; + kr6->r.flags = F_KERNEL|F_CONNECTED; - if (RB_INSERT(kroute6_tree, &krt6, kr6) != NULL) +- if (RB_INSERT(kroute6_tree, &krt6, kr6) != NULL) ++ if (RB_INSERT(kroute6_tree, &kt->krt6, kr6) != NULL) free(kr6); /* kernel route already there, no problem */ -@@ -1788,7 +1812,7 @@ prefixlen2mask6(u_int8_t prefixlen) + + return (0); +@@ -1726,17 +2353,17 @@ mask2prefixlen(in_addr_t ina) + u_int8_t + mask2prefixlen6(struct sockaddr_in6 *sa_in6) + { +- u_int8_t l = 0, i, len; ++ u_int8_t l = 0, *ap, *ep; + + /* + * sin6_len is the size of the sockaddr so substract the offset of + * the possibly truncated sin6_addr struct. + */ +- len = sa_in6->sin6_len - +- (u_int8_t)(&((struct sockaddr_in6 *)NULL)->sin6_addr); +- for (i = 0; i < len; i++) { ++ ap = (u_int8_t *)&sa_in6->sin6_addr; ++ ep = (u_int8_t *)sa_in6 + sa_in6->sin6_len; ++ for (; ap < ep; ap++) { + /* this "beauty" is adopted from sbin/route/show.c ... */ +- switch (sa_in6->sin6_addr.s6_addr[i]) { ++ switch (*ap) { + case 0xff: + l += 8; + break; +@@ -1764,7 +2391,7 @@ mask2prefixlen6(struct sockaddr_in6 *sa_ + case 0x00: + return (l); + default: +- fatalx("non continguous inet6 netmask"); ++ fatalx("non contiguous inet6 netmask"); + } + } + +@@ -1788,7 +2415,7 @@ prefixlen2mask6(u_int8_t prefixlen) } #define ROUNDUP(a) \ @@ -316,7 +2220,35 @@ diff -u -p -r1.1.1.7 -r1.9 void get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) -@@ -1849,10 +1873,11 @@ if_change(u_short ifindex, int flags, st +@@ -1808,6 +2435,7 @@ get_rtaddrs(int addrs, struct sockaddr * + void + if_change(u_short ifindex, int flags, struct if_data *ifd) + { ++ struct ktable *kt; + struct kif_node *kif; + struct kif_kr *kkr; + struct kif_kr6 *kkr6; +@@ -1833,13 +2461,18 @@ if_change(u_short ifindex, int flags, st + + kif->k.nh_reachable = reachable; + ++ kt = ktable_get(/* XXX */ 0); ++ + LIST_FOREACH(kkr, &kif->kroute_l, entry) { + if (reachable) + kkr->kr->r.flags &= ~F_DOWN; + else + kkr->kr->r.flags |= F_DOWN; + +- RB_FOREACH(n, knexthop_tree, &knt) ++ if (kt == NULL) ++ continue; ++ ++ RB_FOREACH(n, knexthop_tree, KT2KNT(kt)) + if (n->kroute == kkr->kr) { + bzero(&nh, sizeof(nh)); + memcpy(&nh.nexthop, &n->nexthop, +@@ -1849,10 +2482,11 @@ if_change(u_short ifindex, int flags, st nh.connected = 1; if ((nh.gateway.v4.s_addr = kkr->kr->r.nexthop.s_addr) != 0) @@ -331,7 +2263,18 @@ diff -u -p -r1.1.1.7 -r1.9 send_nexthop_update(&nh); } } -@@ -1873,14 +1898,16 @@ if_change(u_short ifindex, int flags, st +@@ -1862,7 +2496,9 @@ if_change(u_short ifindex, int flags, st + else + kkr6->kr->r.flags |= F_DOWN; + +- RB_FOREACH(n, knexthop_tree, &knt) ++ if (kt == NULL) ++ continue; ++ RB_FOREACH(n, knexthop_tree, KT2KNT(kt)) + if (n->kroute == kkr6->kr) { + bzero(&nh, sizeof(nh)); + memcpy(&nh.nexthop, &n->nexthop, +@@ -1873,14 +2509,16 @@ if_change(u_short ifindex, int flags, st if (memcmp(&kkr6->kr->r.nexthop, &in6addr_any, sizeof(struct in6_addr))) { @@ -351,39 +2294,88 @@ diff -u -p -r1.1.1.7 -r1.9 send_nexthop_update(&nh); } } -@@ -1924,7 +1951,9 @@ send_rtmsg(int fd, int action, struct kr +@@ -1917,25 +2555,38 @@ if_announce(void *msg) + */ + + int +-send_rtmsg(int fd, int action, struct kroute *kroute) ++send_rtmsg(int fd, int action, struct ktable *kt, struct kroute *kroute) + { +- struct iovec iov[5]; ++ struct iovec iov[7]; + struct rt_msghdr hdr; struct sockaddr_in prefix; struct sockaddr_in nexthop; struct sockaddr_in mask; ++ struct { ++ struct sockaddr_dl dl; ++ char pad[sizeof(long)]; ++ } ifp; +#if !defined(__FreeBSD__) /* FreeBSD has no route labeling. */ ++ struct sockaddr_mpls mpls; struct sockaddr_rtlabel label; +#endif /* !defined(__FreeBSD__) */ int iovcnt = 0; - if (kr_state.fib_sync == 0) -@@ -1934,8 +1963,13 @@ send_rtmsg(int fd, int action, struct kr +- if (kr_state.fib_sync == 0) ++ if (!kt->fib_sync) + return (0); + + /* initialize header */ bzero(&hdr, sizeof(hdr)); hdr.rtm_version = RTM_VERSION; hdr.rtm_type = action; +- hdr.rtm_tableid = kr_state.rtableid; +#if !defined(__FreeBSD__) /* XXX: FreeBSD has no multiple routing tables */ - hdr.rtm_tableid = kr_state.rtableid; ++ hdr.rtm_tableid = kt->rtableid; +#endif /* !defined(__FreeBSD__) */ -+ hdr.rtm_flags = RTF_PROTO1; +#if !defined(__FreeBSD__) /* XXX: FreeBSD has no rtm_priority */ hdr.rtm_priority = RTP_BGP; ++#else ++ hdr.rtm_flags = RTF_PROTO1; +#endif /* !defined(__FreeBSD__) */ if (kroute->flags & F_BLACKHOLE) hdr.rtm_flags |= RTF_BLACKHOLE; if (kroute->flags & F_REJECT) -@@ -1984,6 +2018,7 @@ send_rtmsg(int fd, int action, struct kr +@@ -1984,6 +2635,37 @@ send_rtmsg(int fd, int action, struct kr iov[iovcnt].iov_base = &mask; iov[iovcnt++].iov_len = sizeof(mask); ++ if (kt->ifindex) { ++ bzero(&ifp, sizeof(ifp)); ++ ifp.dl.sdl_len = sizeof(struct sockaddr_dl); ++ ifp.dl.sdl_family = AF_LINK; ++ ifp.dl.sdl_index = kt->ifindex; ++ /* adjust header */ ++ hdr.rtm_addrs |= RTA_IFP; ++ hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_dl)); ++ /* adjust iovec */ ++ iov[iovcnt].iov_base = &ifp; ++ iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_dl)); ++ } ++ ++#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */ ++ if (kroute->flags & F_MPLS) { ++ bzero(&mpls, sizeof(mpls)); ++ mpls.smpls_len = sizeof(mpls); ++ mpls.smpls_family = AF_MPLS; ++ mpls.smpls_label = kroute->mplslabel; ++ /* adjust header */ ++ hdr.rtm_flags |= RTF_MPLS; ++ hdr.rtm_mpls = MPLS_OP_PUSH; ++ hdr.rtm_addrs |= RTA_SRC; ++ hdr.rtm_msglen += sizeof(mpls); ++ /* adjust iovec */ ++ iov[iovcnt].iov_base = &mpls; ++ iov[iovcnt++].iov_len = sizeof(mpls); ++ } ++#endif ++ +#if !defined(__FreeBSD__) /* FreeBSD has no route labeling. */ if (kroute->labelid) { bzero(&label, sizeof(label)); label.sr_len = sizeof(label); -@@ -1996,6 +2031,7 @@ send_rtmsg(int fd, int action, struct kr +@@ -1996,11 +2678,11 @@ send_rtmsg(int fd, int action, struct kr iov[iovcnt].iov_base = &label; iov[iovcnt++].iov_len = sizeof(label); } @@ -391,7 +2383,45 @@ diff -u -p -r1.1.1.7 -r1.9 retry: if (writev(fd, iov, iovcnt) == -1) { -@@ -2037,7 +2073,9 @@ send_rt6msg(int fd, int action, struct k +- switch (errno) { +- case ESRCH: ++ if (errno == ESRCH) { + if (hdr.rtm_type == RTM_CHANGE) { + hdr.rtm_type = RTM_ADD; + goto retry; +@@ -2009,27 +2691,18 @@ retry: + inet_ntoa(kroute->prefix), + kroute->prefixlen); + return (0); +- } else { +- log_warnx("send_rtmsg: action %u, " +- "prefix %s/%u: %s", hdr.rtm_type, +- inet_ntoa(kroute->prefix), +- kroute->prefixlen, strerror(errno)); +- return (0); + } +- break; +- default: +- log_warnx("send_rtmsg: action %u, prefix %s/%u: %s", +- hdr.rtm_type, inet_ntoa(kroute->prefix), +- kroute->prefixlen, strerror(errno)); +- return (0); + } ++ log_warn("send_rtmsg: action %u, prefix %s/%u", hdr.rtm_type, ++ inet_ntoa(kroute->prefix), kroute->prefixlen); ++ return (0); + } + + return (0); + } + + int +-send_rt6msg(int fd, int action, struct kroute6 *kroute) ++send_rt6msg(int fd, int action, struct ktable *kt, struct kroute6 *kroute) + { + struct iovec iov[5]; + struct rt_msghdr hdr; +@@ -2037,17 +2710,23 @@ send_rt6msg(int fd, int action, struct k struct sockaddr_in6 addr; char pad[sizeof(long)]; } prefix, nexthop, mask; @@ -400,19 +2430,23 @@ diff -u -p -r1.1.1.7 -r1.9 +#endif /* !defined(__FreeBSD__) */ int iovcnt = 0; - if (kr_state.fib_sync == 0) -@@ -2047,7 +2085,10 @@ send_rt6msg(int fd, int action, struct k +- if (kr_state.fib_sync == 0) ++ if (!kt->fib_sync) + return (0); + + /* initialize header */ bzero(&hdr, sizeof(hdr)); hdr.rtm_version = RTM_VERSION; hdr.rtm_type = action; +#if !defined(__FreeBSD__) /* XXX: FreeBSD has no multiple routing tables */ hdr.rtm_tableid = kr_state.rtableid; -+#endif /* !defined(__FreeBSD__) */ ++#else + hdr.rtm_flags = RTF_PROTO1; ++#endif /* !defined(__FreeBSD__) */ if (kroute->flags & F_BLACKHOLE) hdr.rtm_flags |= RTF_BLACKHOLE; if (kroute->flags & F_REJECT) -@@ -2100,6 +2141,7 @@ send_rt6msg(int fd, int action, struct k +@@ -2100,6 +2779,7 @@ send_rt6msg(int fd, int action, struct k iov[iovcnt].iov_base = &mask; iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6)); @@ -420,7 +2454,7 @@ diff -u -p -r1.1.1.7 -r1.9 if (kroute->labelid) { bzero(&label, sizeof(label)); label.sr_len = sizeof(label); -@@ -2112,6 +2154,7 @@ send_rt6msg(int fd, int action, struct k +@@ -2112,11 +2792,11 @@ send_rt6msg(int fd, int action, struct k iov[iovcnt].iov_base = &label; iov[iovcnt++].iov_len = sizeof(label); } @@ -428,42 +2462,104 @@ diff -u -p -r1.1.1.7 -r1.9 retry: if (writev(fd, iov, iovcnt) == -1) { -@@ -2147,8 +2190,8 @@ retry: +- switch (errno) { +- case ESRCH: ++ if (errno == ESRCH) { + if (hdr.rtm_type == RTM_CHANGE) { + hdr.rtm_type = RTM_ADD; + goto retry; +@@ -2125,31 +2805,26 @@ retry: + log_in6addr(&kroute->prefix), + kroute->prefixlen); + return (0); +- } else { +- log_warnx("send_rt6msg: action %u, " +- "prefix %s/%u: %s", hdr.rtm_type, +- log_in6addr(&kroute->prefix), +- kroute->prefixlen, strerror(errno)); +- return (0); + } +- break; +- default: +- log_warnx("send_rt6msg: action %u, prefix %s/%u: %s", +- hdr.rtm_type, log_in6addr(&kroute->prefix), +- kroute->prefixlen, strerror(errno)); +- return (0); + } ++ log_warn("send_rt6msg: action %u, prefix %s/%u", hdr.rtm_type, ++ log_in6addr(&kroute->prefix), kroute->prefixlen); ++ return (0); + } + + return (0); + } + int - fetchtable(u_int rtableid, int connected_only) +-fetchtable(u_int rtableid, int connected_only) ++fetchtable(struct ktable *kt) { -- size_t len; -- int mib[7]; -+ size_t len; -+ int mib[6]; - char *buf, *next, *lim; + size_t len; ++#if !defined(__FreeBSD__) /* FreeBSD has no table id. */ + int mib[7]; +- char *buf, *next, *lim; ++#else ++ int mib[6]; ++#endif ++ char *buf = NULL, *next, *lim; struct rt_msghdr *rtm; struct sockaddr *sa, *gw, *rti_info[RTAX_MAX]; -@@ -2163,9 +2206,8 @@ fetchtable(u_int rtableid, int connected + struct sockaddr_in *sa_in; +@@ -2163,22 +2838,35 @@ fetchtable(u_int rtableid, int connected mib[3] = 0; mib[4] = NET_RT_DUMP; mib[5] = 0; - mib[6] = rtableid; ++#if !defined(__FreeBSD__) /* FreeBSD has no table id. */ ++ mib[6] = kt->rtableid; ++#endif -- if (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) { ++#if !defined(__FreeBSD__) /* FreeBSD has no table id. */ + if (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) { +- if (rtableid != 0 && errno == EINVAL) /* table nonexistent */ ++#else + if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) { - if (rtableid != 0 && errno == EINVAL) /* table nonexistent */ ++#endif ++ if (kt->rtableid != 0 && errno == EINVAL) ++ /* table nonexistent */ return (0); log_warn("sysctl"); -@@ -2175,7 +2217,7 @@ fetchtable(u_int rtableid, int connected - log_warn("fetchtable"); return (-1); } +- if ((buf = malloc(len)) == NULL) { +- log_warn("fetchtable"); +- return (-1); +- } - if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) { -+ if (sysctl(mib, 6, buf, &len, NULL, 0) == -1) { - log_warn("sysctl"); - free(buf); - return (-1); -@@ -2186,7 +2228,11 @@ fetchtable(u_int rtableid, int connected +- log_warn("sysctl"); +- free(buf); +- return (-1); ++ if (len > 0) { ++ if ((buf = malloc(len)) == NULL) { ++ log_warn("fetchtable"); ++ return (-1); ++ } ++#if !defined(__FreeBSD__) /* FreeBSD has no table id. */ ++ if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) { ++#else ++ if (sysctl(mib, 6, buf, &len, NULL, 0) == -1) { ++#endif ++ log_warn("sysctl2"); ++ free(buf); ++ return (-1); ++ } + } + + lim = buf + len; +@@ -2186,7 +2874,11 @@ fetchtable(u_int rtableid, int connected rtm = (struct rt_msghdr *)next; if (rtm->rtm_version != RTM_VERSION) continue; -+#if !defined(__FreeBSD__) /* no rtm_hdrlen on FreeBSD */ ++#if !defined(__FreeBSD__) sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); +#else + sa = (struct sockaddr *)(next + sizeof(struct rt_msghdr)); @@ -471,7 +2567,7 @@ diff -u -p -r1.1.1.7 -r1.9 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); if ((sa = rti_info[RTAX_DST]) == NULL) -@@ -2205,7 +2251,11 @@ fetchtable(u_int rtableid, int connected +@@ -2205,7 +2897,11 @@ fetchtable(u_int rtableid, int connected } kr->r.flags = F_KERNEL; @@ -483,7 +2579,7 @@ diff -u -p -r1.1.1.7 -r1.9 kr->r.ifindex = rtm->rtm_index; kr->r.prefix.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; -@@ -2223,8 +2273,12 @@ fetchtable(u_int rtableid, int connected +@@ -2223,8 +2919,12 @@ fetchtable(u_int rtableid, int connected break; kr->r.prefixlen = mask2prefixlen(sa_in->sin_addr.s_addr); @@ -497,7 +2593,7 @@ diff -u -p -r1.1.1.7 -r1.9 else kr->r.prefixlen = prefixlen_classful(kr->r.prefix.s_addr); -@@ -2238,7 +2292,11 @@ fetchtable(u_int rtableid, int connected +@@ -2238,7 +2938,11 @@ fetchtable(u_int rtableid, int connected } kr6->r.flags = F_KERNEL; @@ -509,7 +2605,7 @@ diff -u -p -r1.1.1.7 -r1.9 kr6->r.ifindex = rtm->rtm_index; memcpy(&kr6->r.prefix, &((struct sockaddr_in6 *)sa)->sin6_addr, -@@ -2257,8 +2315,12 @@ fetchtable(u_int rtableid, int connected +@@ -2257,8 +2961,12 @@ fetchtable(u_int rtableid, int connected if (sa_in6->sin6_len == 0) break; kr6->r.prefixlen = mask2prefixlen6(sa_in6); @@ -523,37 +2619,70 @@ diff -u -p -r1.1.1.7 -r1.9 else fatalx("INET6 route without netmask"); break; -@@ -2290,7 +2352,12 @@ fetchtable(u_int rtableid, int connected +@@ -2290,23 +2998,28 @@ fetchtable(u_int rtableid, int connected } if (sa->sa_family == AF_INET) { +#if !defined(__FreeBSD__) /* no rtm_priority on FreeBSD */ if (rtm->rtm_priority == RTP_BGP) { +- send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r); +- free(kr); +- } else if (connected_only && +- !(kr->r.flags & F_CONNECTED)) +#else + /* never delete route */ + if (0) { +#endif - send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r); ++ send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r); free(kr); - } else if (connected_only && -@@ -2299,7 +2366,12 @@ fetchtable(u_int rtableid, int connected - else - kroute_insert(kr); +- else +- kroute_insert(kr); ++ } else ++ kroute_insert(kt, kr); } else if (sa->sa_family == AF_INET6) { +#if !defined(__FreeBSD__) /* no rtm_priority on FreeBSD */ if (rtm->rtm_priority == RTP_BGP) { +- send_rt6msg(kr_state.fd, RTM_DELETE, &kr6->r); +- free(kr6); +- } else if (connected_only && +- !(kr6->r.flags & F_CONNECTED)) +#else + /* never delete route */ + if (0) { +#endif - send_rt6msg(kr_state.fd, RTM_DELETE, &kr6->r); ++ send_rt6msg(kr_state.fd, RTM_DELETE, kt, ++ &kr6->r); free(kr6); - } else if (connected_only && -@@ -2418,7 +2490,11 @@ dispatch_rtmsg(void) +- else +- kroute6_insert(kr6); ++ } else ++ kroute6_insert(kt, kr6); + } + } + free(buf); +@@ -2327,7 +3040,7 @@ fetchifs(int ifindex) + mib[0] = CTL_NET; + mib[1] = AF_ROUTE; + mib[2] = 0; +- mib[3] = AF_INET; ++ mib[3] = AF_INET; /* AF does not matter but AF_INET is shorter */ + mib[4] = NET_RT_IFLIST; + mib[5] = ifindex; + +@@ -2396,7 +3109,7 @@ dispatch_rtmsg(void) + struct rt_msghdr *rtm; + struct if_msghdr ifm; + struct sockaddr *sa, *rti_info[RTAX_MAX]; +- int connected_only; ++ struct ktable *kt; + + if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) { + log_warn("dispatch_rtmsg: read error"); +@@ -2418,7 +3131,11 @@ dispatch_rtmsg(void) case RTM_ADD: case RTM_CHANGE: case RTM_DELETE: -+#if !defined(__FreeBSD__) /* no rtm_hdrlen on FreeBSD */ ++#if !defined(__FreeBSD__) sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); +#else + sa = (struct sockaddr *)(next + sizeof(struct rt_msghdr)); @@ -561,22 +2690,40 @@ diff -u -p -r1.1.1.7 -r1.9 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); if (rtm->rtm_pid == kr_state.pid) /* cause by us */ -@@ -2431,12 +2507,14 @@ dispatch_rtmsg(void) +@@ -2430,16 +3147,14 @@ dispatch_rtmsg(void) + if (rtm->rtm_flags & RTF_LLINFO) /* arp cache */ continue; - connected_only = 0; -+#if !defined(__FreeBSD__) /* XXX: FreeBSD has no multiple routing tables */ - if (rtm->rtm_tableid != kr_state.rtableid) { - if (rtm->rtm_tableid == 0) - connected_only = 1; - else - continue; - } -+#endif /* !defined(__FreeBSD__) */ +- connected_only = 0; +- if (rtm->rtm_tableid != kr_state.rtableid) { +- if (rtm->rtm_tableid == 0) +- connected_only = 1; +- else +- continue; +- } ++#if !defined(__FreeBSD__) /* FreeBSD has no rtm_tableid. */ ++ if ((kt = ktable_get(rtm->rtm_tableid)) == NULL) ++#else ++ if ((kt = ktable_get(0)) == NULL) ++#endif ++ continue; + +- if (dispatch_rtmsg_addr(rtm, rti_info, +- connected_only) == -1) ++ if (dispatch_rtmsg_addr(rtm, rti_info, kt) == -1) + return (-1); + break; + case RTM_IFINFO: +@@ -2460,7 +3175,7 @@ dispatch_rtmsg(void) - if (dispatch_rtmsg_addr(rtm, rti_info, - connected_only) == -1) -@@ -2494,31 +2572,44 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt + int + dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr *rti_info[RTAX_MAX], +- int connected_only) ++ struct ktable *kt) + { + struct sockaddr *sa; + struct sockaddr_in *sa_in; +@@ -2494,31 +3209,44 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt mpath = 1; #endif @@ -625,7 +2772,7 @@ diff -u -p -r1.1.1.7 -r1.9 else fatalx("in6 net addr without netmask"); break; -@@ -2537,8 +2628,8 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt +@@ -2537,10 +3265,10 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt } if (rtm->rtm_type == RTM_DELETE) { @@ -634,18 +2781,45 @@ diff -u -p -r1.1.1.7 -r1.9 + switch (prefix.aid) { + case AID_INET: sa_in = (struct sockaddr_in *)sa; - if ((kr = kroute_find(prefix.v4.s_addr, +- if ((kr = kroute_find(prefix.v4.s_addr, ++ if ((kr = kroute_find(kt, prefix.v4.s_addr, prefixlen, prio)) == NULL) -@@ -2557,7 +2648,7 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt - if (kroute_remove(kr) == -1) + return (0); + if (!(kr->r.flags & F_KERNEL)) +@@ -2554,12 +3282,12 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt + return (0); + } + +- if (kroute_remove(kr) == -1) ++ if (kroute_remove(kt, kr) == -1) return (-1); break; - case AF_INET6: + case AID_INET6: sa_in6 = (struct sockaddr_in6 *)sa; - if ((kr6 = kroute6_find(&prefix.v6, prefixlen, +- if ((kr6 = kroute6_find(&prefix.v6, prefixlen, ++ if ((kr6 = kroute6_find(kt, &prefix.v6, prefixlen, prio)) == NULL) -@@ -2590,8 +2681,8 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt + return (0); + if (!(kr6->r.flags & F_KERNEL)) +@@ -2574,26 +3302,23 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt + return (0); + } + +- if (kroute6_remove(kr6) == -1) ++ if (kroute6_remove(kt, kr6) == -1) + return (-1); + break; + } + return (0); + } + +- if (connected_only && !(flags & F_CONNECTED)) +- return (0); +- + if (sa == NULL && !(flags & F_CONNECTED)) { + log_warnx("dispatch_rtmsg no nexthop for %s/%u", + log_addr(&prefix), prefixlen); return (0); } @@ -654,14 +2828,74 @@ diff -u -p -r1.1.1.7 -r1.9 + switch (prefix.aid) { + case AID_INET: sa_in = (struct sockaddr_in *)sa; - if ((kr = kroute_find(prefix.v4.s_addr, prefixlen, +- if ((kr = kroute_find(prefix.v4.s_addr, prefixlen, ++ if ((kr = kroute_find(kt, prefix.v4.s_addr, prefixlen, prio)) != NULL) { -@@ -2654,7 +2745,7 @@ add4: - kroute_insert(kr); + if (kr->r.flags & F_KERNEL) { + /* get the correct route */ +@@ -2619,16 +3344,16 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt + !(flags & F_CONNECTED)) { + kif_kr_remove(kr); + kr_redistribute(IMSG_NETWORK_REMOVE, +- &kr->r); ++ kt, &kr->r); + } + if ((flags & F_CONNECTED) && + !(oflags & F_CONNECTED)) { + kif_kr_insert(kr); + kr_redistribute(IMSG_NETWORK_ADD, +- &kr->r); ++ kt, &kr->r); + } + if (kr->r.flags & F_NEXTHOP) +- knexthop_track(kr); ++ knexthop_track(kt, kr); + } + } else if (rtm->rtm_type == RTM_CHANGE) { + log_warnx("change req for %s/%u: not in table", +@@ -2651,12 +3376,13 @@ add4: + kr->r.ifindex = ifindex; + kr->r.priority = prio; + +- kroute_insert(kr); ++ kroute_insert(kt, kr); } break; - case AF_INET6: + case AID_INET6: sa_in6 = (struct sockaddr_in6 *)sa; - if ((kr6 = kroute6_find(&prefix.v6, prefixlen, prio)) != NULL) { +- if ((kr6 = kroute6_find(&prefix.v6, prefixlen, prio)) != NULL) { ++ if ((kr6 = kroute6_find(kt, &prefix.v6, prefixlen, prio)) != ++ NULL) { if (kr6->r.flags & F_KERNEL) { + /* get the correct route */ + if (mpath && rtm->rtm_type == RTM_CHANGE && +@@ -2685,16 +3411,16 @@ add4: + !(flags & F_CONNECTED)) { + kif_kr6_remove(kr6); + kr_redistribute6(IMSG_NETWORK_REMOVE, +- &kr6->r); ++ kt, &kr6->r); + } + if ((flags & F_CONNECTED) && + !(oflags & F_CONNECTED)) { + kif_kr6_insert(kr6); + kr_redistribute6(IMSG_NETWORK_ADD, +- &kr6->r); ++ kt, &kr6->r); + } + if (kr6->r.flags & F_NEXTHOP) +- knexthop_track(kr6); ++ knexthop_track(kt, kr6); + } + } else if (rtm->rtm_type == RTM_CHANGE) { + log_warnx("change req for %s/%u: not in table", +@@ -2720,7 +3446,7 @@ add6: + kr6->r.ifindex = ifindex; + kr6->r.priority = prio; + +- kroute6_insert(kr6); ++ kroute6_insert(kt, kr6); + } + break; + } diff --git a/net/openbgpd/files/patch-bgpd_log.c b/net/openbgpd/files/patch-bgpd_log.c index 603711ce1158..ca58a9bcfa0c 100644 --- a/net/openbgpd/files/patch-bgpd_log.c +++ b/net/openbgpd/files/patch-bgpd_log.c @@ -2,13 +2,13 @@ Index: bgpd/log.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/log.c,v retrieving revision 1.1.1.5 -retrieving revision 1.1.1.6 -diff -u -p -r1.1.1.5 -r1.1.1.6 +retrieving revision 1.1.1.7 +diff -u -p -r1.1.1.5 -r1.1.1.7 --- bgpd/log.c 14 Feb 2010 20:19:57 -0000 1.1.1.5 -+++ bgpd/log.c 14 Feb 2010 20:27:06 -0000 1.1.1.6 ++++ bgpd/log.c 12 Jun 2011 10:44:25 -0000 1.1.1.7 @@ -1,4 +1,4 @@ -/* $OpenBSD: log.c,v 1.50 2007/04/23 13:04:24 claudio Exp $ */ -+/* $OpenBSD: log.c,v 1.53 2009/12/03 19:20:35 claudio Exp $ */ ++/* $OpenBSD: log.c,v 1.54 2010/11/18 12:51:24 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -62,7 +62,48 @@ diff -u -p -r1.1.1.5 -r1.1.1.6 va_start(ap, emsg); vlog(LOG_DEBUG, emsg, ap); va_end(ap); -@@ -318,6 +327,9 @@ log_conn_attempt(const struct peer *peer +@@ -250,7 +259,7 @@ log_statechange(struct peer *peer, enum + + void + log_notification(const struct peer *peer, u_int8_t errcode, u_int8_t subcode, +- u_char *data, u_int16_t datalen) ++ u_char *data, u_int16_t datalen, const char *dir) + { + char *p; + const char *suberrname = NULL; +@@ -287,23 +296,22 @@ log_notification(const struct peer *peer + uk = 1; + break; + default: +- logit(LOG_CRIT, "%s: received notification, unknown errcode " +- "%u, subcode %u", p, errcode, subcode); ++ logit(LOG_CRIT, "%s: %s notification, unknown errcode " ++ "%u, subcode %u", p, dir, errcode, subcode); + free(p); + return; + } + + if (uk) +- logit(LOG_CRIT, +- "%s: received notification: %s, unknown subcode %u", +- p, errnames[errcode], subcode); ++ logit(LOG_CRIT, "%s: %s notification: %s, unknown subcode %u", ++ p, dir, errnames[errcode], subcode); + else { + if (suberrname == NULL) +- logit(LOG_CRIT, "%s: received notification: %s", +- p, errnames[errcode]); ++ logit(LOG_CRIT, "%s: %s notification: %s", p, ++ dir, errnames[errcode]); + else +- logit(LOG_CRIT, "%s: received notification: %s, %s", +- p, errnames[errcode], suberrname); ++ logit(LOG_CRIT, "%s: %s notification: %s, %s", ++ p, dir, errnames[errcode], suberrname); + } + free(p); + } +@@ -318,6 +326,9 @@ log_conn_attempt(const struct peer *peer b = log_sockaddr(sa); logit(LOG_INFO, "connection from non-peer %s refused", b); } else { diff --git a/net/openbgpd/files/patch-bgpd_mrt.c b/net/openbgpd/files/patch-bgpd_mrt.c index c35359ac5f39..4b5248a73d4e 100644 --- a/net/openbgpd/files/patch-bgpd_mrt.c +++ b/net/openbgpd/files/patch-bgpd_mrt.c @@ -2,26 +2,228 @@ Index: bgpd/mrt.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/mrt.c,v retrieving revision 1.1.1.7 -retrieving revision 1.1.1.8 -diff -u -p -r1.1.1.7 -r1.1.1.8 +retrieving revision 1.1.1.9 +diff -u -p -r1.1.1.7 -r1.1.1.9 --- bgpd/mrt.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/mrt.c 14 Feb 2010 20:27:06 -0000 1.1.1.8 ++++ bgpd/mrt.c 12 Jun 2011 10:44:25 -0000 1.1.1.9 @@ -1,4 +1,4 @@ -/* $OpenBSD: mrt.c,v 1.63 2009/06/29 12:22:16 claudio Exp $ */ -+/* $OpenBSD: mrt.c,v 1.66 2009/12/01 14:28:05 claudio Exp $ */ ++/* $OpenBSD: mrt.c,v 1.70 2010/09/02 14:03:21 sobrado Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> -@@ -194,7 +194,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struc +@@ -32,20 +32,20 @@ + + #include "mrt.h" + +-int mrt_attr_dump(struct buf *, struct rde_aspath *, struct bgpd_addr *); ++int mrt_attr_dump(struct ibuf *, struct rde_aspath *, struct bgpd_addr *); + int mrt_dump_entry_mp(struct mrt *, struct prefix *, u_int16_t, + struct rde_peer*); + int mrt_dump_entry(struct mrt *, struct prefix *, u_int16_t, struct rde_peer*); +-int mrt_dump_hdr_se(struct buf **, struct peer *, u_int16_t, u_int16_t, ++int mrt_dump_hdr_se(struct ibuf **, struct peer *, u_int16_t, u_int16_t, + u_int32_t, int); +-int mrt_dump_hdr_rde(struct buf **, u_int16_t type, u_int16_t, u_int32_t); ++int mrt_dump_hdr_rde(struct ibuf **, u_int16_t type, u_int16_t, u_int32_t); + int mrt_open(struct mrt *, time_t); + + #define DUMP_BYTE(x, b) \ + do { \ + u_char t = (b); \ +- if (buf_add((x), &t, sizeof(t)) == -1) { \ +- log_warnx("mrt_dump1: buf_add error"); \ ++ if (ibuf_add((x), &t, sizeof(t)) == -1) { \ ++ log_warnx("mrt_dump1: ibuf_add error"); \ + goto fail; \ + } \ + } while (0) +@@ -54,8 +54,8 @@ int mrt_open(struct mrt *, time_t); + do { \ + u_int16_t t; \ + t = htons((s)); \ +- if (buf_add((x), &t, sizeof(t)) == -1) { \ +- log_warnx("mrt_dump2: buf_add error"); \ ++ if (ibuf_add((x), &t, sizeof(t)) == -1) { \ ++ log_warnx("mrt_dump2: ibuf_add error"); \ + goto fail; \ + } \ + } while (0) +@@ -64,8 +64,8 @@ int mrt_open(struct mrt *, time_t); + do { \ + u_int32_t t; \ + t = htonl((l)); \ +- if (buf_add((x), &t, sizeof(t)) == -1) { \ +- log_warnx("mrt_dump3: buf_add error"); \ ++ if (ibuf_add((x), &t, sizeof(t)) == -1) { \ ++ log_warnx("mrt_dump3: ibuf_add error"); \ + goto fail; \ + } \ + } while (0) +@@ -73,8 +73,8 @@ int mrt_open(struct mrt *, time_t); + #define DUMP_NLONG(x, l) \ + do { \ + u_int32_t t = (l); \ +- if (buf_add((x), &t, sizeof(t)) == -1) { \ +- log_warnx("mrt_dump4: buf_add error"); \ ++ if (ibuf_add((x), &t, sizeof(t)) == -1) { \ ++ log_warnx("mrt_dump4: ibuf_add error"); \ + goto fail; \ + } \ + } while (0) +@@ -83,55 +83,63 @@ void + mrt_dump_bgp_msg(struct mrt *mrt, void *pkg, u_int16_t pkglen, + struct peer *peer) + { +- struct buf *buf; ++ struct ibuf *buf; + int incoming = 0; ++ u_int16_t subtype = BGP4MP_MESSAGE; ++ ++ if (peer->capa.neg.as4byte) ++ subtype = BGP4MP_MESSAGE_AS4; + + /* get the direction of the message to swap address and AS fields */ + if (mrt->type == MRT_ALL_IN || mrt->type == MRT_UPDATE_IN) + incoming = 1; + +- if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE, ++ if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, subtype, + pkglen, incoming) == -1) + return; + +- if (buf_add(buf, pkg, pkglen) == -1) { ++ if (ibuf_add(buf, pkg, pkglen) == -1) { + log_warnx("mrt_dump_bgp_msg: buf_add error"); +- buf_free(buf); ++ ibuf_free(buf); + return; + } + +- buf_close(&mrt->wbuf, buf); ++ ibuf_close(&mrt->wbuf, buf); + } + + void + mrt_dump_state(struct mrt *mrt, u_int16_t old_state, u_int16_t new_state, + struct peer *peer) + { +- struct buf *buf; ++ struct ibuf *buf; ++ u_int16_t subtype = BGP4MP_STATE_CHANGE; ++ ++ if (peer->capa.neg.as4byte) ++ subtype = BGP4MP_STATE_CHANGE_AS4; + +- if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE, ++ if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, subtype, + 2 * sizeof(short), 0) == -1) + return; + + DUMP_SHORT(buf, old_state); + DUMP_SHORT(buf, new_state); + +- buf_close(&mrt->wbuf, buf); ++ ibuf_close(&mrt->wbuf, buf); + return; + + fail: +- buf_free(buf); ++ ibuf_free(buf); + } + + int +-mrt_attr_dump(struct buf *buf, struct rde_aspath *a, struct bgpd_addr *nexthop) ++mrt_attr_dump(struct ibuf *buf, struct rde_aspath *a, struct bgpd_addr *nexthop) + { + struct attr *oa; + u_char *pdata; + u_int32_t tmp; + int neednewpath = 0; +- u_int16_t plen; +- u_int8_t l; ++ u_int16_t plen, afi; ++ u_int8_t l, mpattr[21]; + + /* origin */ + if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ORIGIN, +@@ -141,11 +149,14 @@ mrt_attr_dump(struct buf *buf, struct rd + /* aspath */ + pdata = aspath_prepend(a->aspath, rde_local_as(), 0, &plen); + pdata = aspath_deflate(pdata, &plen, &neednewpath); +- if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ASPATH, pdata, plen) == -1) ++ if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ASPATH, pdata, ++ plen) == -1) { ++ free(pdata); + return (-1); ++ } + free(pdata); + +- if (nexthop) { ++ if (nexthop && nexthop->aid == AID_INET) { + /* nexthop, already network byte order */ + if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_NEXTHOP, + &nexthop->v4.s_addr, 4) == -1) +@@ -173,12 +184,27 @@ mrt_attr_dump(struct buf *buf, struct rd + return (-1); + } + ++ if (nexthop && nexthop->aid != AID_INET) { ++ if (aid2afi(nexthop->aid, &afi, &mpattr[2])) ++ return (-1); ++ afi = htons(afi); ++ memcpy(mpattr, &afi, sizeof(afi)); ++ mpattr[3] = sizeof(struct in6_addr); ++ memcpy(&mpattr[4], &nexthop->v6, sizeof(struct in6_addr)); ++ mpattr[20] = 0; /* Reserved must be 0 */ ++ if (attr_writebuf(buf, ATTR_OPTIONAL, ATTR_MP_REACH_NLRI, ++ mpattr, sizeof(mpattr)) == -1) ++ return (-1); ++ } ++ + if (neednewpath) { + pdata = aspath_prepend(a->aspath, rde_local_as(), 0, &plen); + if (plen != 0) + if (attr_writebuf(buf, ATTR_OPTIONAL|ATTR_TRANSITIVE, +- ATTR_AS4_PATH, pdata, plen) == -1) ++ ATTR_AS4_PATH, pdata, plen) == -1) { ++ free(pdata); + return (-1); ++ } + free(pdata); + } + +@@ -189,14 +215,14 @@ int + mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum, + struct rde_peer *peer) + { +- struct buf *buf, *hbuf = NULL, *h2buf = NULL; ++ struct ibuf *buf, *hbuf = NULL, *h2buf = NULL; + void *bptr; struct bgpd_addr addr, nexthop, *nh; u_int16_t len; u_int8_t p_len; - sa_family_t af; + u_int8_t aid; - if ((buf = buf_dynamic(0, MAX_PKTSIZE)) == NULL) { +- if ((buf = buf_dynamic(0, MAX_PKTSIZE)) == NULL) { ++ if ((buf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) { + log_warn("mrt_dump_entry_mp: buf_dynamic"); + return (-1); + } +@@ -205,9 +231,9 @@ mrt_dump_entry_mp(struct mrt *mrt, struc + log_warnx("mrt_dump_entry_mp: mrt_attr_dump error"); + goto fail; + } +- len = buf_size(buf); ++ len = ibuf_size(buf); + +- if ((h2buf = buf_dynamic(MRT_BGP4MP_IPv4_HEADER_SIZE + ++ if ((h2buf = ibuf_dynamic(MRT_BGP4MP_IPv4_HEADER_SIZE + + MRT_BGP4MP_IPv4_ENTRY_SIZE, MRT_BGP4MP_IPv6_HEADER_SIZE + + MRT_BGP4MP_IPv6_ENTRY_SIZE + MRT_BGP4MP_MAX_PREFIXLEN)) == NULL) { log_warn("mrt_dump_entry_mp: buf_dynamic"); -@@ -219,14 +219,15 @@ mrt_dump_entry_mp(struct mrt *mrt, struc +@@ -219,25 +245,26 @@ mrt_dump_entry_mp(struct mrt *mrt, struc DUMP_SHORT(h2buf, /* ifindex */ 0); /* XXX is this for peer self? */ @@ -39,9 +241,14 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 - case AF_INET6: + case AID_INET6: DUMP_SHORT(h2buf, AFI_IPv6); - if (buf_add(h2buf, &peer->local_v6_addr.v6, +- if (buf_add(h2buf, &peer->local_v6_addr.v6, ++ if (ibuf_add(h2buf, &peer->local_v6_addr.v6, sizeof(struct in6_addr)) == -1 || -@@ -237,7 +238,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struc +- buf_add(h2buf, &peer->remote_addr.v6, ++ ibuf_add(h2buf, &peer->remote_addr.v6, + sizeof(struct in6_addr)) == -1) { + log_warnx("mrt_dump_entry_mp: buf_add error"); + goto fail; } break; default: @@ -50,7 +257,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 goto fail; } -@@ -247,20 +248,20 @@ mrt_dump_entry_mp(struct mrt *mrt, struc +@@ -247,24 +274,24 @@ mrt_dump_entry_mp(struct mrt *mrt, struc if (p->aspath->nexthop == NULL) { bzero(&nexthop, sizeof(struct bgpd_addr)); @@ -75,35 +282,153 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 DUMP_SHORT(h2buf, AFI_IPv6); /* afi */ DUMP_BYTE(h2buf, SAFI_UNICAST); /* safi */ DUMP_BYTE(h2buf, 16); /* nhlen */ -@@ -300,7 +301,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struc +- if (buf_add(h2buf, &nh->v6, sizeof(struct in6_addr)) == -1) { ++ if (ibuf_add(h2buf, &nh->v6, sizeof(struct in6_addr)) == -1) { + log_warnx("mrt_dump_entry_mp: buf_add error"); + goto fail; + } +@@ -275,7 +302,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struc + } + + p_len = PREFIX_SIZE(p->prefix->prefixlen); +- if ((bptr = buf_reserve(h2buf, p_len)) == NULL) { ++ if ((bptr = ibuf_reserve(h2buf, p_len)) == NULL) { + log_warnx("mrt_dump_entry_mp: buf_reserve error"); + goto fail; + } +@@ -285,24 +312,24 @@ mrt_dump_entry_mp(struct mrt *mrt, struc + } + + DUMP_SHORT(h2buf, len); +- len += buf_size(h2buf); ++ len += ibuf_size(h2buf); + + if (mrt_dump_hdr_rde(&hbuf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY, + len) == -1) + goto fail; + +- buf_close(&mrt->wbuf, hbuf); +- buf_close(&mrt->wbuf, h2buf); +- buf_close(&mrt->wbuf, buf); ++ ibuf_close(&mrt->wbuf, hbuf); ++ ibuf_close(&mrt->wbuf, h2buf); ++ ibuf_close(&mrt->wbuf, buf); + + return (len + MRT_HEADER_SIZE); + fail: if (hbuf) - buf_free(hbuf); +- buf_free(hbuf); - if (h2buf); +- buf_free(h2buf); +- buf_free(buf); ++ ibuf_free(hbuf); + if (h2buf) - buf_free(h2buf); - buf_free(buf); ++ ibuf_free(h2buf); ++ ibuf_free(buf); return (-1); -@@ -314,7 +315,8 @@ mrt_dump_entry(struct mrt *mrt, struct p + } + +@@ -310,34 +337,37 @@ int + mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum, + struct rde_peer *peer) + { +- struct buf *buf, *hbuf; ++ struct ibuf *buf, *hbuf; struct bgpd_addr addr, *nh; size_t len; ++ u_int16_t subtype; ++ u_int8_t dummy; - if (p->prefix->af != AF_INET && peer->remote_addr.af == AF_INET) -+ if (p->prefix->aid != AID_INET && -+ peer->remote_addr.aid == AID_INET) - /* only able to dump IPv4 */ +- /* only able to dump IPv4 */ ++ if (p->prefix->aid != peer->remote_addr.aid && ++ p->prefix->aid != AID_INET && p->prefix->aid != AID_INET6) ++ /* only able to dump pure IPv4/IPv6 */ return (0); -@@ -325,7 +327,7 @@ mrt_dump_entry(struct mrt *mrt, struct p +- if ((buf = buf_dynamic(0, MAX_PKTSIZE)) == NULL) { ++ if ((buf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) { + log_warnx("mrt_dump_entry: buf_dynamic"); + return (-1); + } if (p->aspath->nexthop == NULL) { bzero(&addr, sizeof(struct bgpd_addr)); - addr.af = AF_INET; -+ addr.aid = AID_INET; ++ addr.aid = p->prefix->aid; nh = &addr; } else nh = &p->aspath->nexthop->exit_nexthop; -@@ -387,7 +389,7 @@ mrt_dump_upcall(struct rib_entry *re, vo + if (mrt_attr_dump(buf, p->aspath, nh) == -1) { + log_warnx("mrt_dump_entry: mrt_attr_dump error"); +- buf_free(buf); ++ ibuf_free(buf); + return (-1); + } +- len = buf_size(buf); +- +- if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP, AFI_IPv4, len) == -1) { +- buf_free(buf); ++ len = ibuf_size(buf); ++ aid2afi(p->prefix->aid, &subtype, &dummy); ++ if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP, subtype, len) == -1) { ++ ibuf_free(buf); + return (-1); + } + +@@ -345,23 +375,44 @@ mrt_dump_entry(struct mrt *mrt, struct p + DUMP_SHORT(hbuf, snum); + + pt_getaddr(p->prefix, &addr); +- DUMP_NLONG(hbuf, addr.v4.s_addr); ++ switch (p->prefix->aid) { ++ case AID_INET: ++ DUMP_NLONG(hbuf, addr.v4.s_addr); ++ break; ++ case AID_INET6: ++ if (ibuf_add(hbuf, &addr.v6, sizeof(struct in6_addr)) == -1) { ++ log_warnx("mrt_dump_entry: buf_add error"); ++ goto fail; ++ } ++ break; ++ } + DUMP_BYTE(hbuf, p->prefix->prefixlen); + + DUMP_BYTE(hbuf, 1); /* state */ + DUMP_LONG(hbuf, p->lastchange); /* originated */ +- DUMP_NLONG(hbuf, peer->remote_addr.v4.s_addr); ++ switch (p->prefix->aid) { ++ case AID_INET: ++ DUMP_NLONG(hbuf, peer->remote_addr.v4.s_addr); ++ break; ++ case AID_INET6: ++ if (ibuf_add(hbuf, &peer->remote_addr.v6, ++ sizeof(struct in6_addr)) == -1) { ++ log_warnx("mrt_dump_entry: buf_add error"); ++ goto fail; ++ } ++ break; ++ } + DUMP_SHORT(hbuf, peer->short_as); + DUMP_SHORT(hbuf, len); + +- buf_close(&mrt->wbuf, hbuf); +- buf_close(&mrt->wbuf, buf); ++ ibuf_close(&mrt->wbuf, hbuf); ++ ibuf_close(&mrt->wbuf, buf); + + return (len + MRT_HEADER_SIZE); + + fail: +- buf_free(hbuf); +- buf_free(buf); ++ ibuf_free(hbuf); ++ ibuf_free(buf); + return (-1); + } + +@@ -387,7 +438,7 @@ mrt_dump_upcall(struct rib_entry *re, vo } void @@ -112,11 +437,120 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 { struct mrt *mrtbuf = ptr; -@@ -541,6 +543,7 @@ mrt_write(struct mrt *mrt) - if ((r = buf_write(&mrt->wbuf)) < 0) { +@@ -395,12 +446,12 @@ mrt_dump_done(void *ptr) + } + + int +-mrt_dump_hdr_se(struct buf ** bp, struct peer *peer, u_int16_t type, ++mrt_dump_hdr_se(struct ibuf ** bp, struct peer *peer, u_int16_t type, + u_int16_t subtype, u_int32_t len, int swap) + { + time_t now; + +- if ((*bp = buf_dynamic(MRT_HEADER_SIZE, MRT_HEADER_SIZE + ++ if ((*bp = ibuf_dynamic(MRT_HEADER_SIZE, MRT_HEADER_SIZE + + MRT_BGP4MP_AS4_IPv6_HEADER_SIZE + len)) == NULL) { + log_warnx("mrt_dump_hdr_se: buf_open error"); + return (-1); +@@ -468,20 +519,20 @@ mrt_dump_hdr_se(struct buf ** bp, struct + case AF_INET6: + DUMP_SHORT(*bp, AFI_IPv6); + if (!swap) +- if (buf_add(*bp, &((struct sockaddr_in6 *) ++ if (ibuf_add(*bp, &((struct sockaddr_in6 *) + &peer->sa_local)->sin6_addr, + sizeof(struct in6_addr)) == -1) { + log_warnx("mrt_dump_hdr_se: buf_add error"); + goto fail; + } +- if (buf_add(*bp, ++ if (ibuf_add(*bp, + &((struct sockaddr_in6 *)&peer->sa_remote)->sin6_addr, + sizeof(struct in6_addr)) == -1) { + log_warnx("mrt_dump_hdr_se: buf_add error"); + goto fail; + } + if (swap) +- if (buf_add(*bp, &((struct sockaddr_in6 *) ++ if (ibuf_add(*bp, &((struct sockaddr_in6 *) + &peer->sa_local)->sin6_addr, + sizeof(struct in6_addr)) == -1) { + log_warnx("mrt_dump_hdr_se: buf_add error"); +@@ -493,17 +544,17 @@ mrt_dump_hdr_se(struct buf ** bp, struct + return (0); + + fail: +- buf_free(*bp); ++ ibuf_free(*bp); + return (-1); + } + + int +-mrt_dump_hdr_rde(struct buf **bp, u_int16_t type, u_int16_t subtype, ++mrt_dump_hdr_rde(struct ibuf **bp, u_int16_t type, u_int16_t subtype, + u_int32_t len) + { + time_t now; + +- if ((*bp = buf_dynamic(MRT_HEADER_SIZE, MRT_HEADER_SIZE + ++ if ((*bp = ibuf_dynamic(MRT_HEADER_SIZE, MRT_HEADER_SIZE + + MRT_BGP4MP_AS4_IPv6_HEADER_SIZE + MRT_BGP4MP_IPv6_ENTRY_SIZE)) == + NULL) { + log_warnx("mrt_dump_hdr_rde: buf_dynamic error"); +@@ -517,7 +568,15 @@ mrt_dump_hdr_rde(struct buf **bp, u_int1 + + switch (type) { + case MSG_TABLE_DUMP: +- DUMP_LONG(*bp, MRT_DUMP_HEADER_SIZE + len); ++ switch (subtype) { ++ case AFI_IPv4: ++ len += MRT_DUMP_HEADER_SIZE; ++ break; ++ case AFI_IPv6: ++ len += MRT_DUMP_HEADER_SIZE_V6; ++ break; ++ } ++ DUMP_LONG(*bp, len); + break; + case MSG_PROTOCOL_BGP4MP: + DUMP_LONG(*bp, len); +@@ -525,11 +584,11 @@ mrt_dump_hdr_rde(struct buf **bp, u_int1 + default: + log_warnx("mrt_dump_hdr_rde: unsupported type"); + goto fail; +- } ++ } + return (0); + + fail: +- buf_free(*bp); ++ ibuf_free(*bp); + return (-1); + } + +@@ -538,21 +597,22 @@ mrt_write(struct mrt *mrt) + { + int r; + +- if ((r = buf_write(&mrt->wbuf)) < 0) { ++ if ((r = ibuf_write(&mrt->wbuf)) < 0) { log_warn("mrt dump aborted, mrt_write"); mrt_clean(mrt); + mrt_done(mrt); } } + void + mrt_clean(struct mrt *mrt) + { +- struct buf *b; ++ struct ibuf *b; + + close(mrt->wbuf.fd); + while ((b = TAILQ_FIRST(&mrt->wbuf.bufs))) { + TAILQ_REMOVE(&mrt->wbuf.bufs, b, entry); +- buf_free(b); ++ ibuf_free(b); + } + mrt->wbuf.queued = 0; + } diff --git a/net/openbgpd/files/patch-bgpd_mrt.h b/net/openbgpd/files/patch-bgpd_mrt.h index a2ef64adf59f..7bf1857d39eb 100644 --- a/net/openbgpd/files/patch-bgpd_mrt.h +++ b/net/openbgpd/files/patch-bgpd_mrt.h @@ -2,17 +2,60 @@ Index: bgpd/mrt.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/mrt.h,v retrieving revision 1.1.1.6 -retrieving revision 1.1.1.7 -diff -u -p -r1.1.1.6 -r1.1.1.7 +retrieving revision 1.1.1.8 +diff -u -p -r1.1.1.6 -r1.1.1.8 --- bgpd/mrt.h 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/mrt.h 14 Feb 2010 20:27:06 -0000 1.1.1.7 ++++ bgpd/mrt.h 12 Jun 2011 10:44:25 -0000 1.1.1.8 @@ -1,4 +1,4 @@ -/* $OpenBSD: mrt.h,v 1.23 2009/06/29 12:22:16 claudio Exp $ */ -+/* $OpenBSD: mrt.h,v 1.24 2009/10/26 09:27:58 claudio Exp $ */ ++/* $OpenBSD: mrt.h,v 1.27 2010/06/04 10:13:00 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> -@@ -303,7 +303,7 @@ void mrt_dump_state(struct mrt *, u_in +@@ -18,12 +18,10 @@ + #ifndef __MRT_H__ + #define __MRT_H__ + +-#include "bgpd.h" +- + /* + * MRT binary packet format + * For more info see: +- * draft-ietf-grow-mrt-04.txt, "MRT routing information export format" ++ * draft-ietf-grow-mrt-11.txt, "MRT routing information export format" + * http://www.quagga.net/docs/docs-multi/Packet-Binary-Dump-Format.html + */ + +@@ -75,8 +73,10 @@ enum MRT_BGP4MP_TYPES { + BGP4MP_MESSAGE, /* bgp message */ + BGP4MP_ENTRY, /* table dumps (deprecated) */ + BGP4MP_SNAPSHOT, /* file name for dump (deprecated) */ ++ BGP4MP_MESSAGE_AS4, /* same as BGP4MP_MESSAGE with 4byte AS */ + BGP4MP_STATE_CHANGE_AS4, +- BGP4MP_MESSAGE_AS4 /* same as BGP4MP_MESSAGE with 4byte AS */ ++ BGP4MP_MESSAGE_LOCAL, /* same as BGP4MP_MESSAGE but for self */ ++ BGP4MP_MESSAGE_AS4_LOCAL /* originated updates. Not implemented */ + }; + + /* size of the BGP4MP headers without payload */ +@@ -184,6 +184,7 @@ enum MRT_BGP4MP_TYPES { + + /* size of the dump header until attr_len */ + #define MRT_DUMP_HEADER_SIZE 22 ++#define MRT_DUMP_HEADER_SIZE_V6 46 + + /* + * OLD MRT message headers. These structs are here for completion but +@@ -235,7 +236,7 @@ enum MRT_BGP_TYPES { + * | new_state | + * +--------+--------+ + * +- * State are defined in RFC 1771. ++ * State are defined in RFC 1771/4271. + */ + + /* +@@ -303,7 +304,7 @@ void mrt_dump_state(struct mrt *, u_in struct peer *); void mrt_clear_seq(void); void mrt_dump_upcall(struct rib_entry *, void *); diff --git a/net/openbgpd/files/patch-bgpd_parse.y b/net/openbgpd/files/patch-bgpd_parse.y index fd81af9709ae..64e9081f287d 100644 --- a/net/openbgpd/files/patch-bgpd_parse.y +++ b/net/openbgpd/files/patch-bgpd_parse.y @@ -2,17 +2,42 @@ Index: bgpd/parse.y =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/parse.y,v retrieving revision 1.1.1.8 -retrieving revision 1.8 -diff -u -p -r1.1.1.8 -r1.8 +diff -u -p -r1.1.1.8 parse.y --- bgpd/parse.y 14 Feb 2010 20:19:57 -0000 1.1.1.8 -+++ bgpd/parse.y 10 Apr 2010 12:16:23 -0000 1.8 ++++ bgpd/parse.y 3 Jul 2011 04:43:32 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.231 2009/06/06 01:10:29 claudio Exp $ */ +/* $OpenBSD: parse.y,v 1.250 2010/03/31 18:53:23 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -105,7 +105,7 @@ struct filter_match_l { +@@ -25,7 +25,10 @@ + #include <sys/stat.h> + #include <netinet/in.h> + #include <arpa/inet.h> +- ++#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */ ++#include <netmpls/mpls.h> ++#endif ++ + #include <ctype.h> + #include <err.h> + #include <unistd.h> +@@ -74,10 +77,12 @@ char *symget(const char *); + + static struct bgpd_config *conf; + static struct mrt_head *mrtconf; +-static struct network_head *netconf; ++static struct network_head *netconf, *gnetconf; + static struct peer *peer_l, *peer_l_old; + static struct peer *curpeer; + static struct peer *curgroup; ++static struct rdomain *currdom; ++static struct rdomain_head *rdom_l; + static struct filter_head *filter_l; + static struct filter_head *peerfilter_l; + static struct filter_head *groupfilter_l; +@@ -105,7 +110,7 @@ struct filter_match_l { struct filter_match m; struct filter_prefix_l *prefix_l; struct filter_as_l *as_l; @@ -21,7 +46,23 @@ diff -u -p -r1.1.1.8 -r1.8 } fmopts; struct peer *alloc_peer(void); -@@ -128,7 +128,11 @@ void move_filterset(struct filter_set_ +@@ -113,8 +118,8 @@ struct peer *new_peer(void); + struct peer *new_group(void); + int add_mrtconfig(enum mrt_type, char *, time_t, struct peer *, + char *); +-int add_rib(char *, u_int16_t); +-int find_rib(char *); ++int add_rib(char *, u_int, u_int16_t); ++struct rde_rib *find_rib(char *); + int get_id(struct peer *); + int expand_rule(struct filter_rule *, struct filter_peers_l *, + struct filter_match_l *, struct filter_set_head *); +@@ -123,12 +128,14 @@ int neighbor_consistent(struct peer *) + int merge_filterset(struct filter_set_head *, struct filter_set *); + void copy_filterset(struct filter_set_head *, + struct filter_set_head *); +-void move_filterset(struct filter_set_head *, +- struct filter_set_head *); struct filter_rule *get_rule(enum action_types); int getcommunity(char *); @@ -34,26 +75,30 @@ diff -u -p -r1.1.1.8 -r1.8 typedef struct { union { -@@ -161,9 +165,9 @@ typedef struct { +@@ -159,29 +166,33 @@ typedef struct { + %} + %token AS ROUTERID HOLDTIME YMIN LISTEN ON FIBUPDATE RTABLE ++%token RDOMAIN RD EXPORTTRGT IMPORTTRGT %token RDE RIB EVALUATE IGNORE COMPARE %token GROUP NEIGHBOR NETWORK -%token REMOTEAS DESCR LOCALADDR MULTIHOP PASSIVE MAXPREFIX RESTART -%token ANNOUNCE DEMOTE CONNECTRETRY -%token ENFORCE NEIGHBORAS CAPABILITIES REFLECTOR DEPEND DOWN SOFTRECONFIG +-%token DUMP IN OUT +%token REMOTEAS DESCR LLIFACE LOCALADDR MULTIHOP PASSIVE MAXPREFIX RESTART +%token ANNOUNCE CAPABILITIES REFRESH AS4BYTE CONNECTRETRY +%token DEMOTE ENFORCE NEIGHBORAS REFLECTOR DEPEND DOWN SOFTRECONFIG - %token DUMP IN OUT ++%token DUMP IN OUT SOCKET RESTRICTED %token LOG ROUTECOLL TRANSPARENT %token TCP MD5SIG PASSWORD KEY TTLSECURITY -@@ -171,17 +175,19 @@ typedef struct { + %token ALLOW DENY MATCH %token QUICK %token FROM TO ANY %token CONNECTED STATIC -%token PREFIX PREFIXLEN SOURCEAS TRANSITAS PEERAS COMMUNITY DELETE +%token COMMUNITY EXTCOMMUNITY -+%token PREFIX PREFIXLEN SOURCEAS TRANSITAS PEERAS DELETE ++%token PREFIX PREFIXLEN SOURCEAS TRANSITAS PEERAS DELETE MAXASLEN MAXASSEQ %token SET LOCALPREF MED METRIC NEXTHOP REJECT BLACKHOLE NOMODIFY SELF -%token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL +%token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL ORIGIN @@ -64,13 +109,23 @@ diff -u -p -r1.1.1.8 -r1.8 +%token NE LE GE XRANGE %token <v.string> STRING %token <v.number> NUMBER - %type <v.number> asnumber as4number optnumber yesno inout +-%type <v.number> asnumber as4number optnumber yesno inout -%type <v.number> espah family restart -+%type <v.number> espah family restart origincode ++%type <v.number> asnumber as4number optnumber ++%type <v.number> espah family restart origincode nettype ++%type <v.number> yesno inout restricted %type <v.string> string filter_rib %type <v.addr> address %type <v.prefix> prefix addrspec -@@ -211,8 +217,12 @@ grammar : /* empty */ +@@ -204,6 +215,7 @@ grammar : /* empty */ + | grammar include '\n' + | grammar conf_main '\n' + | grammar varset '\n' ++ | grammar rdomain '\n' + | grammar neighbor '\n' + | grammar group '\n' + | grammar filterrule '\n' +@@ -211,8 +223,12 @@ grammar : /* empty */ ; asnumber : NUMBER { @@ -85,7 +140,7 @@ diff -u -p -r1.1.1.8 -r1.8 YYERROR; } } -@@ -274,6 +284,8 @@ yesno : STRING { +@@ -274,6 +290,8 @@ yesno : STRING { else if (!strcmp($1, "no")) $$ = 0; else { @@ -94,7 +149,7 @@ diff -u -p -r1.1.1.8 -r1.8 free($1); YYERROR; } -@@ -318,7 +330,7 @@ conf_main : AS as4number { +@@ -318,7 +336,7 @@ conf_main : AS as4number { conf->short_as = $3; } | ROUTERID address { @@ -103,7 +158,7 @@ diff -u -p -r1.1.1.8 -r1.8 yyerror("router-id must be an IPv4 address"); YYERROR; } -@@ -342,35 +354,13 @@ conf_main : AS as4number { +@@ -342,42 +360,25 @@ conf_main : AS as4number { } | LISTEN ON address { struct listen_addr *la; @@ -140,19 +195,103 @@ diff -u -p -r1.1.1.8 -r1.8 TAILQ_INSERT_TAIL(listen_addrs, la, entry); } | FIBUPDATE yesno { -@@ -397,7 +387,7 @@ conf_main : AS as4number { ++ struct rde_rib *rr; ++ rr = find_rib("Loc-RIB"); ++ if (rr == NULL) ++ fatalx("RTABLE can not find the main RIB!"); ++ + if ($2 == 0) +- conf->flags |= BGPD_FLAG_NO_FIB_UPDATE; ++ rr->flags |= F_RIB_NOFIBSYNC; + else +- conf->flags &= ~BGPD_FLAG_NO_FIB_UPDATE; ++ rr->flags &= ~F_RIB_NOFIBSYNC; + } + | ROUTECOLL yesno { + if ($2 == 1) +@@ -386,7 +387,7 @@ conf_main : AS as4number { + conf->flags &= ~BGPD_FLAG_NO_EVALUATE; + } + | RDE RIB STRING { +- if (add_rib($3, F_RIB_NOFIB)) { ++ if (add_rib($3, 0, F_RIB_NOFIB)) { + free($3); + YYERROR; + } +@@ -395,9 +396,27 @@ conf_main : AS as4number { + | RDE RIB STRING yesno EVALUATE { + if ($4) { free($3); ++ yyerror("bad rde rib definition"); YYERROR; } - if (!add_rib($3, F_RIB_NOEVALUATE)) { -+ if (!add_rib($3, F_RIB_NOFIB | F_RIB_NOEVALUATE)) { ++ if (add_rib($3, 0, F_RIB_NOFIB | F_RIB_NOEVALUATE)) { ++ free($3); ++ YYERROR; ++ } ++ free($3); ++ } ++ | RDE RIB STRING RTABLE NUMBER { ++ if (add_rib($3, $5, 0)) { ++ free($3); ++ YYERROR; ++ } ++ free($3); ++ } ++ | RDE RIB STRING RTABLE NUMBER FIBUPDATE yesno { ++ int flags = 0; ++ if ($7 == 0) ++ flags = F_RIB_NOFIBSYNC; ++ if (add_rib($3, $5, flags)) { free($3); YYERROR; } -@@ -459,18 +449,6 @@ conf_main : AS as4number { +@@ -418,59 +437,7 @@ conf_main : AS as4number { } - free($4); + free($2); } +- | NETWORK prefix filter_set { +- struct network *n; +- +- if ((n = calloc(1, sizeof(struct network))) == NULL) +- fatal("new_network"); +- memcpy(&n->net.prefix, &$2.prefix, +- sizeof(n->net.prefix)); +- n->net.prefixlen = $2.len; +- move_filterset($3, &n->net.attrset); +- free($3); +- +- TAILQ_INSERT_TAIL(netconf, n, entry); +- } +- | NETWORK family STATIC filter_set { +- if ($2 == AFI_IPv4) { +- conf->flags |= BGPD_FLAG_REDIST_STATIC; +- move_filterset($4, &conf->staticset); +- } else if ($2 == AFI_IPv6) { +- conf->flags |= BGPD_FLAG_REDIST6_STATIC; +- move_filterset($4, &conf->staticset6); +- } else { +- yyerror("unknown family"); +- free($4); +- YYERROR; +- } +- free($4); +- } +- | NETWORK family CONNECTED filter_set { +- if ($2 == AFI_IPv4) { +- conf->flags |= BGPD_FLAG_REDIST_CONNECTED; +- move_filterset($4, &conf->connectset); +- } else if ($2 == AFI_IPv6) { +- conf->flags |= BGPD_FLAG_REDIST6_CONNECTED; +- move_filterset($4, &conf->connectset6); +- } else { +- yyerror("unknown family"); +- free($4); +- YYERROR; +- } +- free($4); +- } - | NETWORK STATIC filter_set { - /* keep for compatibility till after next release */ - conf->flags |= BGPD_FLAG_REDIST_STATIC; @@ -165,27 +304,99 @@ diff -u -p -r1.1.1.8 -r1.8 - move_filterset($3, &conf->connectset); - free($3); - } ++ | network | DUMP STRING STRING optnumber { int action; -@@ -575,11 +553,16 @@ conf_main : AS as4number { +@@ -575,11 +542,20 @@ conf_main : AS as4number { free($4); } | RTABLE NUMBER { +- if ($2 > RT_TABLEID_MAX || $2 < 0) { +- yyerror("invalid rtable id"); +#if defined(__FreeBSD__) /* FreeBSD does not support RTABLE */ + yyerror("rtable id not supported in FreeBSD, yet"); + YYERROR; +#else - if ($2 > RT_TABLEID_MAX || $2 < 0) { - yyerror("invalid rtable id"); ++ struct rde_rib *rr; ++ if (ktable_exists($2, NULL) != 1) { ++ yyerror("rtable id %lld does not exist", $2); YYERROR; } - conf->rtableid = $2; +- conf->rtableid = $2; ++ rr = find_rib("Loc-RIB"); ++ if (rr == NULL) ++ fatalx("RTABLE can not find the main RIB!"); ++ rr->rtableid = $2; +#endif /* defined(__FreeBSD__) */ } | CONNECTRETRY NUMBER { if ($2 > USHRT_MAX || $2 < 1) { -@@ -635,11 +618,11 @@ address : STRING { +@@ -588,6 +564,15 @@ conf_main : AS as4number { + } + conf->connectretry = $2; + } ++ | SOCKET STRING restricted { ++ if ($3) { ++ free(conf->rcsock); ++ conf->rcsock = $2; ++ } else { ++ free(conf->csock); ++ conf->csock = $2; ++ } ++ } + ; + + mrtdump : DUMP STRING inout STRING optnumber { +@@ -620,10 +605,47 @@ mrtdump : DUMP STRING inout STRING optn + } + ; + ++network : NETWORK prefix filter_set { ++ struct network *n; ++ ++ if ((n = calloc(1, sizeof(struct network))) == NULL) ++ fatal("new_network"); ++ memcpy(&n->net.prefix, &$2.prefix, ++ sizeof(n->net.prefix)); ++ n->net.prefixlen = $2.len; ++ filterset_move($3, &n->net.attrset); ++ free($3); ++ ++ TAILQ_INSERT_TAIL(netconf, n, entry); ++ } ++ | NETWORK family nettype filter_set { ++ struct network *n; ++ ++ if ((n = calloc(1, sizeof(struct network))) == NULL) ++ fatal("new_network"); ++ if (afi2aid($2, SAFI_UNICAST, &n->net.prefix.aid) == ++ -1) { ++ yyerror("unknown family"); ++ filterset_free($4); ++ free($4); ++ YYERROR; ++ } ++ n->net.type = $3 ? NETWORK_STATIC : NETWORK_CONNECTED; ++ filterset_move($4, &n->net.attrset); ++ free($4); ++ ++ TAILQ_INSERT_TAIL(netconf, n, entry); ++ } ++ ; ++ + inout : IN { $$ = 1; } + | OUT { $$ = 0; } + ; + ++restricted : RESTRICTED { $$ = 1; } ++ | /* nothing */ { $$ = 0; } ++ ; ++ + address : STRING { + u_int8_t len; + +@@ -635,11 +657,11 @@ address : STRING { } free($1); @@ -200,7 +411,25 @@ diff -u -p -r1.1.1.8 -r1.8 YYERROR; } } -@@ -686,7 +669,7 @@ prefix : STRING '/' NUMBER { +@@ -653,7 +675,7 @@ prefix : STRING '/' NUMBER { + free($1); + YYERROR; + } +- if (asprintf(&s, "%s/%lld", $1, $3) == -1) ++ if (asprintf(&s, "%s/%lld", $1, (long long int)$3) == -1) + fatal(NULL); + free($1); + +@@ -672,7 +694,7 @@ prefix : STRING '/' NUMBER { + yyerror("bad prefix %lld/%lld", $1, $3); + YYERROR; + } +- if (asprintf(&s, "%lld/%lld", $1, $3) == -1) ++ if (asprintf(&s, "%lld/%lld", (long long int)$1, (long long int)$3) == -1) + fatal(NULL); + + if (!host(s, &$$.prefix, &$$.len)) { +@@ -686,7 +708,7 @@ prefix : STRING '/' NUMBER { addrspec : address { memcpy(&$$.prefix, &$1, sizeof(struct bgpd_addr)); @@ -209,7 +438,144 @@ diff -u -p -r1.1.1.8 -r1.8 $$.len = 32; else $$.len = 128; -@@ -710,9 +693,13 @@ neighbor : { curpeer = new_peer(); } +@@ -705,14 +727,150 @@ optnumber : /* empty */ { $$ = 0; } + | NUMBER + ; + ++rdomain : RDOMAIN NUMBER optnl '{' optnl { ++ if (ktable_exists($2, NULL) != 1) { ++ yyerror("rdomain %lld does not exist", $2); ++ YYERROR; ++ } ++ if (!(currdom = calloc(1, sizeof(struct rdomain)))) ++ fatal(NULL); ++ currdom->rtableid = $2; ++ TAILQ_INIT(&currdom->import); ++ TAILQ_INIT(&currdom->export); ++ TAILQ_INIT(&currdom->net_l); ++ netconf = &currdom->net_l; ++ } ++ rdomainopts_l '}' { ++ /* insert into list */ ++ SIMPLEQ_INSERT_TAIL(rdom_l, currdom, entry); ++ currdom = NULL; ++ netconf = gnetconf; ++ } ++ ++rdomainopts_l : rdomainopts_l rdomainoptsl ++ | rdomainoptsl ++ ; ++ ++rdomainoptsl : rdomainopts nl ++ ; ++ ++rdomainopts : RD STRING { ++ struct filter_extcommunity ext; ++ u_int64_t rd; ++ ++ if (parseextcommunity(&ext, "rt", $2) == -1) { ++ free($2); ++ YYERROR; ++ } ++ free($2); ++ /* ++ * RD is almost encode like an ext-community, ++ * but only almost so convert here. ++ */ ++ if (community_ext_conv(&ext, 0, &rd)) { ++ yyerror("bad encoding of rd"); ++ YYERROR; ++ } ++ rd = betoh64(rd) & 0xffffffffffffULL; ++ switch (ext.type) { ++ case EXT_COMMUNITY_TWO_AS: ++ rd |= (0ULL << 48); ++ break; ++ case EXT_COMMUNITY_IPV4: ++ rd |= (1ULL << 48); ++ break; ++ case EXT_COMMUNITY_FOUR_AS: ++ rd |= (2ULL << 48); ++ break; ++ default: ++ yyerror("bad encoding of rd"); ++ YYERROR; ++ } ++ currdom->rd = htobe64(rd); ++ } ++ | EXPORTTRGT STRING STRING { ++ struct filter_set *set; ++ ++ if ((set = calloc(1, sizeof(struct filter_set))) == ++ NULL) ++ fatal(NULL); ++ set->type = ACTION_SET_EXT_COMMUNITY; ++ if (parseextcommunity(&set->action.ext_community, ++ $2, $3) == -1) { ++ free($3); ++ free($2); ++ free(set); ++ YYERROR; ++ } ++ free($3); ++ free($2); ++ TAILQ_INSERT_TAIL(&currdom->export, set, entry); ++ } ++ | IMPORTTRGT STRING STRING { ++ struct filter_set *set; ++ ++ if ((set = calloc(1, sizeof(struct filter_set))) == ++ NULL) ++ fatal(NULL); ++ set->type = ACTION_SET_EXT_COMMUNITY; ++ if (parseextcommunity(&set->action.ext_community, ++ $2, $3) == -1) { ++ free($3); ++ free($2); ++ free(set); ++ YYERROR; ++ } ++ free($3); ++ free($2); ++ TAILQ_INSERT_TAIL(&currdom->import, set, entry); ++ } ++ | DESCR string { ++ if (strlcpy(currdom->descr, $2, ++ sizeof(currdom->descr)) >= ++ sizeof(currdom->descr)) { ++ yyerror("descr \"%s\" too long: max %u", ++ $2, sizeof(currdom->descr) - 1); ++ free($2); ++ YYERROR; ++ } ++ free($2); ++ } ++ | FIBUPDATE yesno { ++ if ($2 == 0) ++ currdom->flags |= F_RIB_NOFIBSYNC; ++ else ++ currdom->flags &= ~F_RIB_NOFIBSYNC; ++ } ++ | network ++ | DEPEND ON STRING { ++ /* XXX this is a hack */ ++ if (if_nametoindex($3) == 0) { ++ yyerror("interface %s does not exist", $3); ++ free($3); ++ YYERROR; ++ } ++ strlcpy(currdom->ifmpe, $3, IFNAMSIZ); ++ free($3); ++ if (get_mpe_label(currdom)) { ++ yyerror("failed to get mpls label from %s", ++ currdom->ifmpe); ++ YYERROR; ++ } ++ } ++ ; ++ + neighbor : { curpeer = new_peer(); } + NEIGHBOR addrspec { memcpy(&curpeer->conf.remote_addr, &$3.prefix, sizeof(curpeer->conf.remote_addr)); curpeer->conf.remote_masklen = $3.len; @@ -225,7 +591,7 @@ diff -u -p -r1.1.1.8 -r1.8 if (get_id(curpeer)) { yyerror("get_id failed"); YYERROR; -@@ -802,6 +789,17 @@ peeropts : REMOTEAS as4number { +@@ -802,6 +960,17 @@ peeropts : REMOTEAS as4number { } free($2); } @@ -243,7 +609,7 @@ diff -u -p -r1.1.1.8 -r1.8 | LOCALADDR address { memcpy(&curpeer->conf.local_addr, &$2, sizeof(curpeer->conf.local_addr)); -@@ -852,13 +850,17 @@ peeropts : REMOTEAS as4number { +@@ -852,13 +1021,17 @@ peeropts : REMOTEAS as4number { curpeer->conf.min_holdtime = $3; } | ANNOUNCE family STRING { @@ -266,7 +632,7 @@ diff -u -p -r1.1.1.8 -r1.8 yyerror("unknown/unsupported SAFI \"%s\"", $3); free($3); -@@ -866,25 +868,31 @@ peeropts : REMOTEAS as4number { +@@ -866,25 +1039,31 @@ peeropts : REMOTEAS as4number { } free($3); @@ -308,7 +674,7 @@ diff -u -p -r1.1.1.8 -r1.8 curpeer->conf.announce_type = ANNOUNCE_NONE; else if (!strcmp($2, "all")) curpeer->conf.announce_type = ANNOUNCE_ALL; -@@ -1083,7 +1091,7 @@ peeropts : REMOTEAS as4number { +@@ -1083,7 +1262,7 @@ peeropts : REMOTEAS as4number { curpeer->conf.reflector_client = 1; } | REFLECTOR address { @@ -317,7 +683,18 @@ diff -u -p -r1.1.1.8 -r1.8 yyerror("route reflector cluster-id must be " "an IPv4 address"); YYERROR; -@@ -1336,12 +1344,12 @@ filter_prefix_l : filter_prefix { $$ +@@ -1157,6 +1336,10 @@ family : IPV4 { $$ = AFI_IPv4; } + | IPV6 { $$ = AFI_IPv6; } + ; + ++nettype : STATIC { $$ = 1; }, ++ | CONNECTED { $$ = 0; } ++ ; ++ + espah : ESP { $$ = 1; } + | AH { $$ = 0; } + ; +@@ -1336,12 +1519,12 @@ filter_prefix_l : filter_prefix { $$ ; filter_prefix : prefix { @@ -332,7 +709,20 @@ diff -u -p -r1.1.1.8 -r1.8 if (($$ = calloc(1, sizeof(struct filter_prefix_l))) == NULL) fatal(NULL); -@@ -1437,18 +1445,18 @@ filter_elm : filter_prefix_h { +@@ -1410,6 +1593,12 @@ filter_as : as4number { + fatal(NULL); + $$->a.as = $1; + } ++ | NEIGHBORAS { ++ if (($$ = calloc(1, sizeof(struct filter_as_l))) == ++ NULL) ++ fatal(NULL); ++ $$->a.flags = AS_FLAG_NEIGHBORAS; ++ } + ; + + filter_match_h : /* empty */ { +@@ -1437,18 +1626,18 @@ filter_elm : filter_prefix_h { fmopts.prefix_l = $1; } | PREFIXLEN prefixlenop { @@ -354,7 +744,37 @@ diff -u -p -r1.1.1.8 -r1.8 } | filter_as_h { if (fmopts.as_l != NULL) { -@@ -1463,26 +1471,43 @@ filter_elm : filter_prefix_h { +@@ -1457,32 +1646,73 @@ filter_elm : filter_prefix_h { + } + fmopts.as_l = $1; + } ++ | MAXASLEN NUMBER { ++ if (fmopts.m.aslen.type != ASLEN_NONE) { ++ yyerror("AS length filters already specified"); ++ YYERROR; ++ } ++ if ($2 < 0 || $2 > UINT_MAX) { ++ yyerror("bad max-as-len %lld", $2); ++ YYERROR; ++ } ++ fmopts.m.aslen.type = ASLEN_MAX; ++ fmopts.m.aslen.aslen = $2; ++ } ++ | MAXASSEQ NUMBER { ++ if (fmopts.m.aslen.type != ASLEN_NONE) { ++ yyerror("AS length filters already specified"); ++ YYERROR; ++ } ++ if ($2 < 0 || $2 > UINT_MAX) { ++ yyerror("bad max-as-seq %lld", $2); ++ YYERROR; ++ } ++ fmopts.m.aslen.type = ASLEN_SEQ; ++ fmopts.m.aslen.aslen = $2; ++ } + | COMMUNITY STRING { + if (fmopts.m.community.as != COMMUNITY_UNSET) { + yyerror("\"community\" already specified"); free($2); YYERROR; } @@ -404,7 +824,7 @@ diff -u -p -r1.1.1.8 -r1.8 } ; -@@ -1782,8 +1807,7 @@ filter_set_opt : LOCALPREF NUMBER { +@@ -1782,8 +2012,7 @@ filter_set_opt : LOCALPREF NUMBER { else $$->type = ACTION_SET_COMMUNITY; @@ -414,7 +834,7 @@ diff -u -p -r1.1.1.8 -r1.8 free($3); free($$); YYERROR; -@@ -1796,40 +1820,62 @@ filter_set_opt : LOCALPREF NUMBER { +@@ -1796,40 +2025,62 @@ filter_set_opt : LOCALPREF NUMBER { free($$); YYERROR; } @@ -497,7 +917,7 @@ diff -u -p -r1.1.1.8 -r1.8 ; %% -@@ -1873,6 +1919,7 @@ lookup(char *s) +@@ -1873,6 +2124,7 @@ lookup(char *s) { "allow", ALLOW}, { "announce", ANNOUNCE}, { "any", ANY}, @@ -505,15 +925,20 @@ diff -u -p -r1.1.1.8 -r1.8 { "blackhole", BLACKHOLE}, { "capabilities", CAPABILITIES}, { "community", COMMUNITY}, -@@ -1889,6 +1936,7 @@ lookup(char *s) +@@ -1889,16 +2141,22 @@ lookup(char *s) { "enforce", ENFORCE}, { "esp", ESP}, { "evaluate", EVALUATE}, ++ { "export-target", EXPORTTRGT}, + { "ext-community", EXTCOMMUNITY}, { "fib-update", FIBUPDATE}, { "from", FROM}, { "group", GROUP}, -@@ -1899,6 +1947,9 @@ lookup(char *s) + { "holdtime", HOLDTIME}, + { "ignore", IGNORE}, + { "ike", IKE}, ++ { "import-target", IMPORTTRGT}, + { "in", IN}, { "include", INCLUDE}, { "inet", IPV4}, { "inet6", IPV6}, @@ -523,7 +948,16 @@ diff -u -p -r1.1.1.8 -r1.8 { "ipsec", IPSEC}, { "key", KEY}, { "listen", LISTEN}, -@@ -1918,6 +1969,7 @@ lookup(char *s) +@@ -1906,6 +2164,8 @@ lookup(char *s) + { "localpref", LOCALPREF}, + { "log", LOG}, + { "match", MATCH}, ++ { "max-as-len", MAXASLEN}, ++ { "max-as-seq", MAXASSEQ}, + { "max-prefix", MAXPREFIX}, + { "md5sig", MD5SIG}, + { "med", MED}, +@@ -1918,6 +2178,7 @@ lookup(char *s) { "nexthop", NEXTHOP}, { "no-modify", NOMODIFY}, { "on", ON}, @@ -531,15 +965,43 @@ diff -u -p -r1.1.1.8 -r1.8 { "out", OUT}, { "passive", PASSIVE}, { "password", PASSWORD}, -@@ -1930,6 +1982,7 @@ lookup(char *s) +@@ -1929,10 +2190,14 @@ lookup(char *s) + { "prepend-self", PREPEND_SELF}, { "qualify", QUALIFY}, { "quick", QUICK}, ++ { "rd", RD}, { "rde", RDE}, ++ { "rdomain", RDOMAIN}, + { "refresh", REFRESH }, { "reject", REJECT}, { "remote-as", REMOTEAS}, { "restart", RESTART}, -@@ -2135,6 +2188,26 @@ top: ++ { "restricted", RESTRICTED}, + { "rib", RIB}, + { "route-collector", ROUTECOLL}, + { "route-reflector", REFLECTOR}, +@@ -1941,6 +2206,7 @@ lookup(char *s) + { "rtlabel", RTLABEL}, + { "self", SELF}, + { "set", SET}, ++ { "socket", SOCKET }, + { "softreconfig", SOFTRECONFIG}, + { "source-as", SOURCEAS}, + { "spi", SPI}, +@@ -2117,9 +2383,10 @@ top: + return (0); + if (next == quotec || c == ' ' || c == '\t') + c = next; +- else if (next == '\n') ++ else if (next == '\n') { ++ file->lineno++; + continue; +- else ++ } else + lungetc(next); + } else if (c == quotec) { + *p = '\0'; +@@ -2135,6 +2402,26 @@ top: if (yylval.v.string == NULL) fatal("yylex: strdup"); return (STRING); @@ -548,7 +1010,7 @@ diff -u -p -r1.1.1.8 -r1.8 + if (next == '=') + return (NE); + lungetc(next); -+ break; ++ break; + case '<': + next = lgetc(0); + if (next == '=') @@ -566,7 +1028,104 @@ diff -u -p -r1.1.1.8 -r1.8 } #define allowed_to_end_number(x) \ -@@ -2505,27 +2578,27 @@ getcommunity(char *s) +@@ -2274,18 +2561,21 @@ popfile(void) + int + parse_config(char *filename, struct bgpd_config *xconf, + struct mrt_head *xmconf, struct peer **xpeers, struct network_head *nc, +- struct filter_head *xfilter_l) ++ struct filter_head *xfilter_l, struct rdomain_head *xrdom_l) + { + struct sym *sym, *next; + struct peer *p, *pnext; + struct listen_addr *la; + struct network *n; + struct filter_rule *r; ++ struct rde_rib *rr; ++ struct rdomain *rd; + int errors = 0; + + if ((conf = calloc(1, sizeof(struct bgpd_config))) == NULL) + fatal(NULL); + conf->opts = xconf->opts; ++ conf->csock = strdup(SOCKET_NAME); + + if ((file = pushfile(filename, 1)) == NULL) { + free(conf); +@@ -2316,13 +2606,15 @@ parse_config(char *filename, struct bgpd + id = 1; + + /* network list is always empty in the parent */ +- netconf = nc; ++ gnetconf = netconf = nc; + TAILQ_INIT(netconf); + /* init the empty filter list for later */ + TAILQ_INIT(xfilter_l); ++ SIMPLEQ_INIT(xrdom_l); ++ rdom_l = xrdom_l; + +- add_rib("Adj-RIB-In", F_RIB_NOEVALUATE); +- add_rib("Loc-RIB", 0); ++ add_rib("Adj-RIB-In", 0, F_RIB_NOFIB | F_RIB_NOEVALUATE); ++ add_rib("Loc-RIB", 0, 0); + + yyparse(); + errors = file->errors; +@@ -2344,6 +2636,9 @@ parse_config(char *filename, struct bgpd + + if (errors) { + /* XXX more leaks in this case */ ++ free(conf->csock); ++ free(conf->rcsock); ++ + while ((la = TAILQ_FIRST(listen_addrs)) != NULL) { + TAILQ_REMOVE(listen_addrs, la, entry); + free(la); +@@ -2357,23 +2652,44 @@ parse_config(char *filename, struct bgpd + + while ((n = TAILQ_FIRST(netconf)) != NULL) { + TAILQ_REMOVE(netconf, n, entry); ++ filterset_free(&n->net.attrset); + free(n); + } + + while ((r = TAILQ_FIRST(filter_l)) != NULL) { + TAILQ_REMOVE(filter_l, r, entry); ++ filterset_free(&r->set); + free(r); + } + + while ((r = TAILQ_FIRST(peerfilter_l)) != NULL) { + TAILQ_REMOVE(peerfilter_l, r, entry); ++ filterset_free(&r->set); + free(r); + } + + while ((r = TAILQ_FIRST(groupfilter_l)) != NULL) { + TAILQ_REMOVE(groupfilter_l, r, entry); ++ filterset_free(&r->set); + free(r); + } ++ while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) { ++ SIMPLEQ_REMOVE_HEAD(&ribnames, entry); ++ free(rr); ++ } ++ while ((rd = SIMPLEQ_FIRST(rdom_l)) != NULL) { ++ SIMPLEQ_REMOVE_HEAD(rdom_l, entry); ++ filterset_free(&rd->export); ++ filterset_free(&rd->import); ++ ++ while ((n = TAILQ_FIRST(&rd->net_l)) != NULL) { ++ TAILQ_REMOVE(&rd->net_l, n, entry); ++ filterset_free(&n->net.attrset); ++ free(n); ++ } ++ ++ free(rd); ++ } + } else { + errors += merge_config(xconf, conf, peer_l, listen_addrs); + errors += mrt_mergeconfig(xmconf, mrtconf); +@@ -2505,27 +2821,27 @@ getcommunity(char *s) } int @@ -604,7 +1163,7 @@ diff -u -p -r1.1.1.8 -r1.8 return (0); } -@@ -2537,23 +2610,176 @@ parsecommunity(char *s, int *as, int *ty +@@ -2537,23 +2853,176 @@ parsecommunity(char *s, int *as, int *ty if ((i = getcommunity(s)) == COMMUNITY_ERROR) return (-1); @@ -784,7 +1343,7 @@ diff -u -p -r1.1.1.8 -r1.8 if ((p = calloc(1, sizeof(struct peer))) == NULL) fatal("new_peer"); -@@ -2564,11 +2790,11 @@ alloc_peer(void) +@@ -2564,11 +3033,11 @@ alloc_peer(void) p->conf.distance = 1; p->conf.announce_type = ANNOUNCE_UNDEF; p->conf.announce_capa = 1; @@ -799,7 +1358,7 @@ diff -u -p -r1.1.1.8 -r1.8 p->conf.local_as = conf->as; p->conf.local_short_as = conf->short_as; p->conf.softreconfig_in = 1; -@@ -2592,6 +2818,9 @@ new_peer(void) +@@ -2592,6 +3061,9 @@ new_peer(void) if (strlcpy(p->conf.descr, curgroup->conf.descr, sizeof(p->conf.descr)) >= sizeof(p->conf.descr)) fatalx("new_peer descr strlcpy"); @@ -809,7 +1368,72 @@ diff -u -p -r1.1.1.8 -r1.8 p->conf.groupid = curgroup->conf.id; p->conf.local_as = curgroup->conf.local_as; p->conf.local_short_as = curgroup->conf.local_short_as; -@@ -2715,7 +2944,7 @@ get_id(struct peer *newpeer) +@@ -2674,39 +3146,52 @@ add_mrtconfig(enum mrt_type type, char * + } + + int +-add_rib(char *name, u_int16_t flags) ++add_rib(char *name, u_int rtableid, u_int16_t flags) + { + struct rde_rib *rr; ++ u_int rdom; + +- if (find_rib(name)) { +- yyerror("rib \"%s\" allready exists.", name); +- return (-1); +- } +- +- if ((rr = calloc(1, sizeof(*rr))) == NULL) { +- log_warn("add_rib"); +- return (-1); ++ if ((rr = find_rib(name)) == NULL) { ++ if ((rr = calloc(1, sizeof(*rr))) == NULL) { ++ log_warn("add_rib"); ++ return (-1); ++ } + } + if (strlcpy(rr->name, name, sizeof(rr->name)) >= sizeof(rr->name)) { + yyerror("rib name \"%s\" too long: max %u", + name, sizeof(rr->name) - 1); ++ free(rr); + return (-1); + } + rr->flags |= flags; ++ if ((rr->flags & F_RIB_HASNOFIB) == 0) { ++ if (ktable_exists(rtableid, &rdom) != 1) { ++ yyerror("rtable id %lld does not exist", rtableid); ++ free(rr); ++ return (-1); ++ } ++ if (rdom != 0) { ++ yyerror("rtable %lld does not belong to rdomain 0", ++ rtableid); ++ free(rr); ++ return (-1); ++ } ++ rr->rtableid = rtableid; ++ } + SIMPLEQ_INSERT_TAIL(&ribnames, rr, entry); + return (0); + } + +-int ++struct rde_rib * + find_rib(char *name) + { + struct rde_rib *rr; + + SIMPLEQ_FOREACH(rr, &ribnames, entry) { + if (!strcmp(rr->name, name)) +- return (1); ++ return (rr); + } +- return (0); ++ return (NULL); + } + + int +@@ -2715,7 +3200,7 @@ get_id(struct peer *newpeer) struct peer *p; for (p = peer_l_old; p != NULL; p = p->next) @@ -818,7 +1442,7 @@ diff -u -p -r1.1.1.8 -r1.8 if (!memcmp(&p->conf.remote_addr, &newpeer->conf.remote_addr, sizeof(p->conf.remote_addr))) { -@@ -2856,9 +3085,11 @@ str2key(char *s, char *dest, size_t max_ +@@ -2856,9 +3341,11 @@ str2key(char *s, char *dest, size_t max_ int neighbor_consistent(struct peer *p) { @@ -832,7 +1456,7 @@ diff -u -p -r1.1.1.8 -r1.8 yyerror("local-address and neighbor address " "must be of the same address family"); return (-1); -@@ -2869,7 +3100,7 @@ neighbor_consistent(struct peer *p) +@@ -2869,7 +3356,7 @@ neighbor_consistent(struct peer *p) p->conf.auth.method == AUTH_IPSEC_IKE_AH || p->conf.auth.method == AUTH_IPSEC_MANUAL_ESP || p->conf.auth.method == AUTH_IPSEC_MANUAL_AH) && @@ -841,7 +1465,7 @@ diff -u -p -r1.1.1.8 -r1.8 yyerror("neighbors with any form of IPsec configured " "need local-address to be specified"); return (-1); -@@ -2889,10 +3120,6 @@ neighbor_consistent(struct peer *p) +@@ -2889,10 +3376,6 @@ neighbor_consistent(struct peer *p) return (-1); } @@ -852,7 +1476,7 @@ diff -u -p -r1.1.1.8 -r1.8 /* set default values if they where undefined */ p->conf.ebgp = (p->conf.remote_as != conf->as); if (p->conf.announce_type == ANNOUNCE_UNDEF) -@@ -2909,6 +3136,11 @@ neighbor_consistent(struct peer *p) +@@ -2909,6 +3392,11 @@ neighbor_consistent(struct peer *p) return (-1); } @@ -864,7 +1488,7 @@ diff -u -p -r1.1.1.8 -r1.8 return (0); } -@@ -2927,6 +3159,11 @@ merge_filterset(struct filter_set_head * +@@ -2927,6 +3415,11 @@ merge_filterset(struct filter_set_head * yyerror("community is already set"); else if (s->type == ACTION_DEL_COMMUNITY) yyerror("community will already be deleted"); @@ -876,7 +1500,7 @@ diff -u -p -r1.1.1.8 -r1.8 else yyerror("redefining set parameter %s", filterset_name(s->type)); -@@ -2953,9 +3190,18 @@ merge_filterset(struct filter_set_head * +@@ -2953,9 +3446,18 @@ merge_filterset(struct filter_set_head * return (0); } break; @@ -897,3 +1521,26 @@ diff -u -p -r1.1.1.8 -r1.8 TAILQ_INSERT_BEFORE(t, s, entry); return (0); } +@@ -2985,22 +3487,6 @@ copy_filterset(struct filter_set_head *s + } + } + +-void +-move_filterset(struct filter_set_head *source, struct filter_set_head *dest) +-{ +- struct filter_set *s; +- +- TAILQ_INIT(dest); +- +- if (source == NULL) +- return; +- +- while ((s = TAILQ_FIRST(source)) != NULL) { +- TAILQ_REMOVE(source, s, entry); +- TAILQ_INSERT_TAIL(dest, s, entry); +- } +-} +- + struct filter_rule * + get_rule(enum action_types type) + { diff --git a/net/openbgpd/files/patch-bgpd_pfkey.c b/net/openbgpd/files/patch-bgpd_pfkey.c index a7d261db35ea..f8e6845f1661 100644 --- a/net/openbgpd/files/patch-bgpd_pfkey.c +++ b/net/openbgpd/files/patch-bgpd_pfkey.c @@ -2,13 +2,13 @@ Index: bgpd/pfkey.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/pfkey.c,v retrieving revision 1.1.1.6 -retrieving revision 1.1.1.7 -diff -u -p -r1.1.1.6 -r1.1.1.7 +retrieving revision 1.1.1.8 +diff -u -p -r1.1.1.6 -r1.1.1.8 --- bgpd/pfkey.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/pfkey.c 14 Feb 2010 20:27:06 -0000 1.1.1.7 ++++ bgpd/pfkey.c 12 Jun 2011 10:44:25 -0000 1.1.1.8 @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkey.c,v 1.37 2009/04/21 15:25:52 henning Exp $ */ -+/* $OpenBSD: pfkey.c,v 1.40 2009/12/14 17:38:18 claudio Exp $ */ ++/* $OpenBSD: pfkey.c,v 1.41 2010/12/09 13:50:41 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -118,3 +118,81 @@ diff -u -p -r1.1.1.6 -r1.1.1.7 dmask.ss_len = sizeof(struct sockaddr_in6); dmask.ss_family = AF_INET6; memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr, +@@ -411,6 +402,33 @@ pfkey_send(int sd, uint8_t satype, uint8 + } + + int ++pfkey_read(int sd, struct sadb_msg *h) ++{ ++ struct sadb_msg hdr; ++ ++ if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) { ++ log_warn("pfkey peek"); ++ return (-1); ++ } ++ ++ /* XXX: Only one message can be outstanding. */ ++ if (hdr.sadb_msg_seq == sadb_msg_seq && ++ hdr.sadb_msg_pid == pid) { ++ if (h) ++ bcopy(&hdr, h, sizeof(hdr)); ++ return (0); ++ } ++ ++ /* not ours, discard */ ++ if (read(sd, &hdr, sizeof(hdr)) == -1) { ++ log_warn("pfkey read"); ++ return (-1); ++ } ++ ++ return (1); ++} ++ ++int + pfkey_reply(int sd, u_int32_t *spip) + { + struct sadb_msg hdr, *msg; +@@ -418,23 +436,13 @@ pfkey_reply(int sd, u_int32_t *spip) + struct sadb_sa *sa; + u_int8_t *data; + ssize_t len; ++ int rv; + +- for (;;) { +- if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) { +- log_warn("pfkey peek"); ++ do { ++ rv = pfkey_read(sd, &hdr); ++ if (rv == -1) + return (-1); +- } +- +- if (hdr.sadb_msg_seq == sadb_msg_seq && +- hdr.sadb_msg_pid == pid) +- break; +- +- /* not ours, discard */ +- if (read(sd, &hdr, sizeof(hdr)) == -1) { +- log_warn("pfkey read"); +- return (-1); +- } +- } ++ } while (rv); + + if (hdr.sadb_msg_errno != 0) { + errno = hdr.sadb_msg_errno; +@@ -730,11 +738,9 @@ pfkey_init(struct bgpd_sysdep *sysdep) + if (errno == EPROTONOSUPPORT) { + log_warnx("PF_KEY not available, disabling ipsec"); + sysdep->no_pfkey = 1; +- return (0); +- } else { +- log_warn("PF_KEY socket"); + return (-1); +- } ++ } else ++ fatal("pfkey setup failed"); + } +- return (0); ++ return (fd); + } diff --git a/net/openbgpd/files/patch-bgpd_printconf.c b/net/openbgpd/files/patch-bgpd_printconf.c index ee5be19032af..82fb337ccb7b 100644 --- a/net/openbgpd/files/patch-bgpd_printconf.c +++ b/net/openbgpd/files/patch-bgpd_printconf.c @@ -2,17 +2,21 @@ Index: bgpd/printconf.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/printconf.c,v retrieving revision 1.1.1.7 -retrieving revision 1.7 -diff -u -p -r1.1.1.7 -r1.7 +retrieving revision 1.8 +diff -u -p -r1.1.1.7 -r1.8 --- bgpd/printconf.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/printconf.c 10 Apr 2010 12:16:23 -0000 1.7 ++++ bgpd/printconf.c 2 Jul 2011 16:06:38 -0000 1.8 @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.70 2009/06/06 01:10:29 claudio Exp $ */ +/* $OpenBSD: printconf.c,v 1.79 2010/03/05 15:25:00 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -19,6 +19,9 @@ +@@ -16,9 +16,13 @@ + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + ++#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -22,7 +26,7 @@ diff -u -p -r1.1.1.7 -r1.7 #include "bgpd.h" #include "mrt.h" -@@ -27,6 +30,8 @@ +@@ -27,14 +31,19 @@ void print_op(enum comp_ops); void print_community(int, int); @@ -30,8 +34,11 @@ diff -u -p -r1.1.1.7 -r1.7 +void print_origin(u_int8_t); void print_set(struct filter_set_head *); void print_mainconf(struct bgpd_config *); ++void print_rdomain_targets(struct filter_set_head *, const char *); ++void print_rdomain(struct rdomain *); ++const char *print_af(u_int8_t); void print_network(struct network_config *); -@@ -34,7 +39,7 @@ void print_peer(struct peer_config *, + void print_peer(struct peer_config *, struct bgpd_config *, const char *); const char *print_auth_alg(u_int8_t); const char *print_enc_alg(u_int8_t); @@ -40,7 +47,7 @@ diff -u -p -r1.1.1.7 -r1.7 void print_rule(struct peer *, struct filter_rule *); const char * mrt_type(enum mrt_type); void print_mrt(u_int32_t, u_int32_t, const char *, const char *); -@@ -94,6 +99,45 @@ print_community(int as, int type) +@@ -94,6 +103,45 @@ print_community(int as, int type) } void @@ -61,10 +68,10 @@ diff -u -p -r1.1.1.7 -r1.7 + break; + case EXT_COMMUNITY_OPAQUE: + printf("%s 0x%llx ", log_ext_subtype(c->subtype), -+ c->data.ext_opaq); ++ (long long unsigned int)c->data.ext_opaq); + break; + default: -+ printf("0x%x 0x%llx ", c->type, c->data.ext_opaq); ++ printf("0x%x 0x%llx ", c->type, (long long unsigned int)c->data.ext_opaq); + break; + } +} @@ -86,7 +93,7 @@ diff -u -p -r1.1.1.7 -r1.7 print_set(struct filter_set_head *set) { struct filter_set *s; -@@ -161,11 +205,23 @@ print_set(struct filter_set_head *set) +@@ -161,11 +209,23 @@ print_set(struct filter_set_head *set) case ACTION_RTLABEL: printf("rtlabel %s ", s->action.rtlabel); break; @@ -110,16 +117,127 @@ diff -u -p -r1.1.1.7 -r1.7 } } printf("}"); -@@ -236,7 +292,7 @@ print_mainconf(struct bgpd_config *conf) - print_set(&conf->connectset6); +@@ -182,6 +242,10 @@ print_mainconf(struct bgpd_config *conf) + printf(" %u", conf->short_as); + ina.s_addr = conf->bgpid; + printf("\nrouter-id %s\n", inet_ntoa(ina)); ++ ++ printf("socket \"%s\"\n", conf->csock); ++ if (conf->rcsock) ++ printf("socket \"%s\" restricted\n", conf->rcsock); + if (conf->holdtime) + printf("holdtime %u\n", conf->holdtime); + if (conf->min_holdtime) +@@ -189,11 +253,6 @@ print_mainconf(struct bgpd_config *conf) + if (conf->connectretry) + printf("connect-retry %u\n", conf->connectretry); + +- if (conf->flags & BGPD_FLAG_NO_FIB_UPDATE) +- printf("fib-update no\n"); +- else +- printf("fib-update yes\n"); +- + if (conf->flags & BGPD_FLAG_NO_EVALUATE) + printf("route-collector yes\n"); + +@@ -214,43 +273,67 @@ print_mainconf(struct bgpd_config *conf) + printf("nexthop qualify via bgp\n"); + if (conf->flags & BGPD_FLAG_NEXTHOP_DEFAULT) + printf("nexthop qualify via default\n"); ++} + +- if (conf->flags & BGPD_FLAG_REDIST_CONNECTED) { +- printf("network inet connected"); +- if (!TAILQ_EMPTY(&conf->connectset)) +- printf(" "); +- print_set(&conf->connectset); +- printf("\n"); +- } +- if (conf->flags & BGPD_FLAG_REDIST_STATIC) { +- printf("network inet static"); +- if (!TAILQ_EMPTY(&conf->staticset)) +- printf(" "); +- print_set(&conf->staticset); +- printf("\n"); +- } +- if (conf->flags & BGPD_FLAG_REDIST6_CONNECTED) { +- printf("network inet6 connected"); +- if (!TAILQ_EMPTY(&conf->connectset6)) +- printf(" "); +- print_set(&conf->connectset6); +- printf("\n"); +- } +- if (conf->flags & BGPD_FLAG_REDIST_STATIC) { +- printf("network inet6 static"); +- if (!TAILQ_EMPTY(&conf->staticset6)) +- printf(" "); +- print_set(&conf->staticset6); ++void ++print_rdomain_targets(struct filter_set_head *set, const char *tgt) ++{ ++ struct filter_set *s; ++ TAILQ_FOREACH(s, set, entry) { ++ printf("\t%s ", tgt); ++ print_extcommunity(&s->action.ext_community); printf("\n"); } -- if (conf->flags & BGPD_FLAG_REDIST_STATIC) { -+ if (conf->flags & BGPD_FLAG_REDIST6_STATIC) { - printf("network inet6 static"); - if (!TAILQ_EMPTY(&conf->staticset6)) - printf(" "); -@@ -263,8 +319,8 @@ print_peer(struct peer_config *p, struct +- if (conf->rtableid) +- printf("rtable %u\n", conf->rtableid); ++} ++ ++void ++print_rdomain(struct rdomain *r) ++{ ++ printf("rdomain %u {\n", r->rtableid); ++ printf("\tdescr \"%s\"\n", r->descr); ++ if (r->flags & F_RIB_NOFIBSYNC) ++ printf("\tfib-update no\n"); ++ else ++ printf("\tfib-update yes\n"); ++ printf("\tdepend on %s\n", r->ifmpe); ++ ++ printf("\n\t%s\n", log_rd(r->rd)); ++ ++ print_rdomain_targets(&r->export, "export-target"); ++ print_rdomain_targets(&r->import, "import-target"); ++ ++ printf("}\n"); ++} ++ ++const char * ++print_af(u_int8_t aid) ++{ ++ /* ++ * Hack around the fact that aid2str() will return "IPv4 unicast" ++ * for AID_INET. AID_INET and AID_INET6 need special handling and ++ * the other AID should never end up here (at least for now). ++ */ ++ if (aid == AID_INET) ++ return ("inet"); ++ if (aid == AID_INET6) ++ return ("inet6"); ++ return (aid2str(aid)); + } + + void + print_network(struct network_config *n) + { +- printf("network %s/%u", log_addr(&n->prefix), n->prefixlen); ++ switch (n->type) { ++ case NETWORK_STATIC: ++ printf("network %s static", print_af(n->prefix.aid)); ++ break; ++ case NETWORK_CONNECTED: ++ printf("network %s connected", print_af(n->prefix.aid)); ++ break; ++ default: ++ printf("network %s/%u", log_addr(&n->prefix), n->prefixlen); ++ break; ++ } + if (!TAILQ_EMPTY(&n->attrset)) + printf(" "); + print_set(&n->attrset); +@@ -263,8 +346,8 @@ print_peer(struct peer_config *p, struct char *method; struct in_addr ina; @@ -130,7 +248,7 @@ diff -u -p -r1.1.1.7 -r1.7 printf("%sneighbor %s/%u {\n", c, log_addr(&p->remote_addr), p->remote_masklen); else -@@ -281,7 +337,7 @@ print_peer(struct peer_config *p, struct +@@ -281,7 +364,7 @@ print_peer(struct peer_config *p, struct printf("%s\tmultihop %u\n", c, p->distance); if (p->passive) printf("%s\tpassive\n", c); @@ -139,7 +257,7 @@ diff -u -p -r1.1.1.7 -r1.7 printf("%s\tlocal-address %s\n", c, log_addr(&p->local_addr)); if (p->max_prefix) { printf("%s\tmax-prefix %u", c, p->max_prefix); -@@ -295,6 +351,12 @@ print_peer(struct peer_config *p, struct +@@ -295,6 +378,12 @@ print_peer(struct peer_config *p, struct printf("%s\tholdtime min %u\n", c, p->min_holdtime); if (p->announce_capa == 0) printf("%s\tannounce capabilities no\n", c); @@ -152,7 +270,7 @@ diff -u -p -r1.1.1.7 -r1.7 if (p->announce_type == ANNOUNCE_SELF) printf("%s\tannounce self\n", c); else if (p->announce_type == ANNOUNCE_NONE) -@@ -324,6 +386,10 @@ print_peer(struct peer_config *p, struct +@@ -324,6 +413,10 @@ print_peer(struct peer_config *p, struct printf("%s\tdepend on \"%s\"\n", c, p->if_depend); if (p->flags & PEERFLAG_TRANS_AS) printf("%s\ttransparent-as yes\n", c); @@ -163,7 +281,7 @@ diff -u -p -r1.1.1.7 -r1.7 if (p->auth.method == AUTH_MD5SIG) printf("%s\ttcp md5sig\n", c); -@@ -354,8 +420,7 @@ print_peer(struct peer_config *p, struct +@@ -354,8 +447,7 @@ print_peer(struct peer_config *p, struct if (p->ttlsec) printf("%s\tttl-security yes\n", c); @@ -173,7 +291,7 @@ diff -u -p -r1.1.1.7 -r1.7 if (p->softreconfig_in == 1) printf("%s\tsoftreconfig in yes\n", c); -@@ -399,17 +464,14 @@ print_enc_alg(u_int8_t alg) +@@ -399,17 +491,14 @@ print_enc_alg(u_int8_t alg) } } @@ -198,7 +316,7 @@ diff -u -p -r1.1.1.7 -r1.7 } void -@@ -455,14 +517,14 @@ print_rule(struct peer *peer_l, struct f +@@ -455,14 +544,14 @@ print_rule(struct peer *peer_l, struct f } else printf("any "); @@ -217,7 +335,17 @@ diff -u -p -r1.1.1.7 -r1.7 printf("inet6 "); } -@@ -497,6 +559,10 @@ print_rule(struct peer *peer_l, struct f +@@ -492,11 +581,20 @@ print_rule(struct peer *peer_l, struct f + printf("unfluffy-as %s ", log_as(r->match.as.as)); + } + ++ if (r->match.aslen.type) { ++ printf("%s %u ", r->match.aslen.type == ASLEN_MAX ? ++ "max-as-len" : "max-as-seq", r->match.aslen.aslen); ++ } ++ + if (r->match.community.as != COMMUNITY_UNSET) { + printf("community "); print_community(r->match.community.as, r->match.community.type); } @@ -228,3 +356,53 @@ diff -u -p -r1.1.1.7 -r1.7 print_set(&r->set); +@@ -547,7 +645,7 @@ print_mrt(u_int32_t pid, u_int32_t gid, + else + printf("%s %s %d\n", mrt_type(m->type), + MRT2MC(m)->name, +- MRT2MC(m)->ReopenTimerInterval); ++ (int)MRT2MC(m)->ReopenTimerInterval); + } + } + +@@ -612,26 +710,34 @@ peer_compare(const void *aa, const void + void + print_config(struct bgpd_config *conf, struct rib_names *rib_l, + struct network_head *net_l, struct peer *peer_l, +- struct filter_head *rules_l, struct mrt_head *mrt_l) ++ struct filter_head *rules_l, struct mrt_head *mrt_l, ++ struct rdomain_head *rdom_l) + { + struct filter_rule *r; + struct network *n; + struct rde_rib *rr; ++ struct rdomain *rd; + + xmrt_l = mrt_l; +- printf("\n"); + print_mainconf(conf); + printf("\n"); ++ TAILQ_FOREACH(n, net_l, entry) ++ print_network(&n->net); ++ printf("\n"); ++ SIMPLEQ_FOREACH(rd, rdom_l, entry) ++ print_rdomain(rd); ++ printf("\n"); + SIMPLEQ_FOREACH(rr, rib_l, entry) { + if (rr->flags & F_RIB_NOEVALUATE) + printf("rde rib %s no evaluate\n", rr->name); +- else ++ else if (rr->flags & F_RIB_NOFIB) + printf("rde rib %s\n", rr->name); ++ else ++ printf("rde rib %s rtable %u fib-update %s\n", rr->name, ++ rr->rtableid, rr->flags & F_RIB_NOFIBSYNC ? ++ "no" : "yes"); + } + printf("\n"); +- TAILQ_FOREACH(n, net_l, entry) +- print_network(&n->net); +- printf("\n"); + print_mrt(0, 0, "", ""); + printf("\n"); + print_groups(conf, peer_l); diff --git a/net/openbgpd/files/patch-bgpd_rde.c b/net/openbgpd/files/patch-bgpd_rde.c index 55e10012aa47..a62bcf26fdc7 100644 --- a/net/openbgpd/files/patch-bgpd_rde.c +++ b/net/openbgpd/files/patch-bgpd_rde.c @@ -2,17 +2,25 @@ Index: bgpd/rde.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde.c,v retrieving revision 1.1.1.8 -retrieving revision 1.9 -diff -u -p -r1.1.1.8 -r1.9 +diff -u -p -r1.1.1.8 rde.c --- bgpd/rde.c 14 Feb 2010 20:19:57 -0000 1.1.1.8 -+++ bgpd/rde.c 10 Apr 2010 12:16:23 -0000 1.9 ++++ bgpd/rde.c 3 Jul 2011 04:43:59 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.264 2009/06/29 12:22:16 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.290 2010/03/30 15:43:30 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -51,12 +51,16 @@ void rde_update_withdraw(struct rde_pe +@@ -18,6 +18,8 @@ + + #include <sys/types.h> + #include <sys/socket.h> ++#include <sys/time.h> ++#include <sys/resource.h> + + #include <errno.h> + #include <ifaddrs.h> +@@ -51,12 +53,16 @@ void rde_update_withdraw(struct rde_pe int rde_attr_parse(u_char *, u_int16_t, struct rde_peer *, struct rde_aspath *, struct mpattr *); u_int8_t rde_attr_missing(struct rde_aspath *, int, u_int16_t); @@ -31,18 +39,24 @@ diff -u -p -r1.1.1.8 -r1.9 void rde_update_err(struct rde_peer *, u_int8_t , u_int8_t, void *, u_int16_t); void rde_update_log(const char *, u_int16_t, -@@ -81,8 +85,9 @@ void rde_dump_done(void *); +@@ -78,11 +84,15 @@ void rde_dump_ctx_new(struct ctl_show_ + void rde_dump_mrt_new(struct mrt *, pid_t, int); + void rde_dump_done(void *); + ++int rde_rdomain_import(struct rde_aspath *, struct rdomain *); void rde_up_dump_upcall(struct rib_entry *, void *); void rde_softreconfig_out(struct rib_entry *, void *); void rde_softreconfig_in(struct rib_entry *, void *); +void rde_softreconfig_load(struct rib_entry *, void *); ++void rde_softreconfig_load_peer(struct rib_entry *, void *); ++void rde_softreconfig_unload_peer(struct rib_entry *, void *); void rde_update_queue_runner(void); -void rde_update6_queue_runner(void); +void rde_update6_queue_runner(u_int8_t); void peer_init(u_int32_t); void peer_shutdown(void); -@@ -91,8 +96,8 @@ struct rde_peer *peer_add(u_int32_t, str +@@ -91,10 +101,9 @@ struct rde_peer *peer_add(u_int32_t, str struct rde_peer *peer_get(u_int32_t); void peer_up(u_int32_t, struct session_up *); void peer_down(u_int32_t); @@ -51,9 +65,19 @@ diff -u -p -r1.1.1.8 -r1.9 +void peer_dump(u_int32_t, u_int8_t); +void peer_send_eor(struct rde_peer *, u_int8_t); - void network_init(struct network_head *); +-void network_init(struct network_head *); void network_add(struct network_config *, int); -@@ -120,11 +125,12 @@ struct rde_dump_ctx { + void network_delete(struct network_config *, int); + void network_dump_upcall(struct rib_entry *, void *); +@@ -108,6 +117,7 @@ time_t reloadtime; + struct rde_peer_head peerlist; + struct rde_peer *peerself; + struct filter_head *rules_l, *newrules; ++struct rdomain_head *rdomains_l, *newdomains; + struct imsgbuf *ibuf_se; + struct imsgbuf *ibuf_se_ctl; + struct imsgbuf *ibuf_main; +@@ -120,11 +130,12 @@ struct rde_dump_ctx { }; struct rde_mrt_ctx { @@ -69,7 +93,7 @@ diff -u -p -r1.1.1.8 -r1.9 u_int rde_mrt_cnt; void -@@ -144,24 +150,17 @@ u_int32_t attrhashsize = 512; +@@ -144,24 +155,18 @@ u_int32_t attrhashsize = 512; u_int32_t nexthophashsize = 64; pid_t @@ -80,6 +104,7 @@ diff -u -p -r1.1.1.8 -r1.9 +rde_main(int pipe_m2r[2], int pipe_s2r[2], int pipe_m2s[2], int pipe_s2rctl[2], + int debug) { ++ struct rlimit rl; pid_t pid; struct passwd *pw; - struct peer *p; @@ -98,7 +123,7 @@ diff -u -p -r1.1.1.8 -r1.9 switch (pid = fork()) { case -1: -@@ -172,8 +171,6 @@ rde_main(struct bgpd_config *config, str +@@ -172,8 +177,6 @@ rde_main(struct bgpd_config *config, str return (pid); } @@ -107,7 +132,20 @@ diff -u -p -r1.1.1.8 -r1.9 if ((pw = getpwnam(BGPD_USER)) == NULL) fatal("getpwnam"); -@@ -194,6 +191,8 @@ rde_main(struct bgpd_config *config, str +@@ -185,6 +188,12 @@ rde_main(struct bgpd_config *config, str + setproctitle("route decision engine"); + bgpd_process = PROC_RDE; + ++ if (getrlimit(RLIMIT_DATA, &rl) == -1) ++ fatal("getrlimit"); ++ rl.rlim_cur = rl.rlim_max; ++ if (setrlimit(RLIMIT_DATA, &rl) == -1) ++ fatal("setrlimit"); ++ + if (setgroups(1, &pw->pw_gid) || + setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || + setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) +@@ -194,6 +203,8 @@ rde_main(struct bgpd_config *config, str signal(SIGINT, rde_sighdlr); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); @@ -116,7 +154,7 @@ diff -u -p -r1.1.1.8 -r1.9 close(pipe_s2r[0]); close(pipe_s2rctl[0]); -@@ -210,50 +209,21 @@ rde_main(struct bgpd_config *config, str +@@ -210,50 +221,25 @@ rde_main(struct bgpd_config *config, str imsg_init(ibuf_se_ctl, pipe_s2rctl[1]); imsg_init(ibuf_main, pipe_m2r[1]); @@ -156,7 +194,11 @@ diff -u -p -r1.1.1.8 -r1.9 + if (rules_l == NULL) + fatal(NULL); + TAILQ_INIT(rules_l); -+ if ((conf = malloc(sizeof(struct bgpd_config))) == NULL) ++ rdomains_l = calloc(1, sizeof(struct rdomain_head)); ++ if (rdomains_l == NULL) ++ fatal(NULL); ++ SIMPLEQ_INIT(rdomains_l); ++ if ((conf = calloc(1, sizeof(struct bgpd_config))) == NULL) + fatal(NULL); log_info("route decision engine ready"); @@ -173,20 +215,29 @@ diff -u -p -r1.1.1.8 -r1.9 while (rde_quit == 0) { if (pfd_elms < PFD_PIPE_COUNT + rde_mrt_cnt) { if ((newp = realloc(pfd, sizeof(struct pollfd) * -@@ -287,9 +257,9 @@ rde_main(struct bgpd_config *config, str +@@ -287,11 +273,18 @@ rde_main(struct bgpd_config *config, str timeout = 0; i = PFD_PIPE_COUNT; - LIST_FOREACH(mrt, &rde_mrts, entry) { - if (mrt->wbuf.queued) { - pfd[i].fd = mrt->wbuf.fd; -+ LIST_FOREACH(mctx, &rde_mrts, entry) { ++ for (mctx = LIST_FIRST(&rde_mrts); mctx != 0; mctx = xmctx) { ++ xmctx = LIST_NEXT(mctx, entry); + if (mctx->mrt.wbuf.queued) { + pfd[i].fd = mctx->mrt.wbuf.fd; pfd[i].events = POLLOUT; i++; ++ } else if (mctx->mrt.state == MRT_STATE_REMOVE) { ++ close(mctx->mrt.wbuf.fd); ++ LIST_REMOVE(&mctx->ribctx, entry); ++ LIST_REMOVE(mctx, entry); ++ free(mctx); ++ rde_mrt_cnt--; } -@@ -325,24 +295,26 @@ rde_main(struct bgpd_config *config, str + } + +@@ -325,24 +318,17 @@ rde_main(struct bgpd_config *config, str if (pfd[PFD_PIPE_SESSION_CTL].revents & POLLIN) rde_dispatch_imsg_session(ibuf_se_ctl); @@ -196,7 +247,6 @@ diff -u -p -r1.1.1.8 -r1.9 - if (pfd[j].fd == mrt->wbuf.fd && + for (j = PFD_PIPE_COUNT, mctx = LIST_FIRST(&rde_mrts); + j < i && mctx != 0; j++) { -+ xmctx = LIST_NEXT(mctx, entry); + if (pfd[j].fd == mctx->mrt.wbuf.fd && pfd[j].revents & POLLOUT) - mrt_write(mrt); @@ -205,17 +255,11 @@ diff -u -p -r1.1.1.8 -r1.9 - close(mrt->wbuf.fd); - LIST_REMOVE(mrt, entry); - free(mrt); -+ mrt_write(&mctx->mrt); -+ if (mctx->mrt.wbuf.queued == 0 && -+ mctx->mrt.state == MRT_STATE_REMOVE) { -+ close(mctx->mrt.wbuf.fd); -+ LIST_REMOVE(&mctx->ribctx, entry); -+ LIST_REMOVE(mctx, entry); -+ free(mctx); - rde_mrt_cnt--; - } +- rde_mrt_cnt--; +- } - mrt = xmrt; -+ mctx = xmctx; ++ mrt_write(&mctx->mrt); ++ mctx = LIST_NEXT(mctx, entry); } rde_update_queue_runner(); @@ -225,7 +269,7 @@ diff -u -p -r1.1.1.8 -r1.9 if (ibuf_se_ctl->w.queued <= 0) rib_dump_runner(); } -@@ -351,11 +323,12 @@ rde_main(struct bgpd_config *config, str +@@ -351,11 +337,12 @@ rde_main(struct bgpd_config *config, str if (debug) rde_shutdown(); @@ -243,7 +287,7 @@ diff -u -p -r1.1.1.8 -r1.9 } msgbuf_clear(&ibuf_se->w); -@@ -378,13 +351,14 @@ rde_dispatch_imsg_session(struct imsgbuf +@@ -378,13 +365,14 @@ rde_dispatch_imsg_session(struct imsgbuf struct imsg imsg; struct peer p; struct peer_config pconf; @@ -260,7 +304,7 @@ diff -u -p -r1.1.1.8 -r1.9 if ((n = imsg_read(ibuf)) == -1) fatal("rde_dispatch_imsg_session: imsg_read error"); -@@ -423,12 +397,14 @@ rde_dispatch_imsg_session(struct imsgbuf +@@ -423,12 +411,14 @@ rde_dispatch_imsg_session(struct imsgbuf peer_down(imsg.hdr.peerid); break; case IMSG_REFRESH: @@ -278,7 +322,7 @@ diff -u -p -r1.1.1.8 -r1.9 break; case IMSG_NETWORK_ADD: if (imsg.hdr.len - IMSG_HEADER_SIZE != -@@ -446,13 +422,13 @@ rde_dispatch_imsg_session(struct imsgbuf +@@ -446,13 +436,13 @@ rde_dispatch_imsg_session(struct imsgbuf break; } session_set = NULL; @@ -295,7 +339,7 @@ diff -u -p -r1.1.1.8 -r1.9 if (netconf_s.prefixlen > 128) goto badnet; network_add(&netconf_s, 0); -@@ -544,6 +520,11 @@ badnet: +@@ -544,6 +534,11 @@ badnet: imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_RIB_MEM, 0, imsg.hdr.pid, -1, &rdemem, sizeof(rdemem)); break; @@ -307,28 +351,153 @@ diff -u -p -r1.1.1.8 -r1.9 default: break; } -@@ -587,7 +568,7 @@ rde_dispatch_imsg_parent(struct imsgbuf - fatal(NULL); - memcpy(nconf, imsg.data, sizeof(struct bgpd_config)); - for (rid = 0; rid < rib_size; rid++) -- ribs[rid].state = RIB_DELETE; -+ ribs[rid].state = RECONF_DELETE; +@@ -554,14 +549,17 @@ badnet: + void + rde_dispatch_imsg_parent(struct imsgbuf *ibuf) + { ++ static struct rdomain *rd; + struct imsg imsg; + struct mrt xmrt; + struct rde_rib rn; + struct rde_peer *peer; ++ struct peer_config *pconf; + struct filter_rule *r; + struct filter_set *s; + struct nexthop *nh; +- int n, fd, reconf_in = 0, reconf_out = 0; ++ int n, fd, reconf_in = 0, reconf_out = 0, ++ reconf_rib = 0; + u_int16_t rid; + + if ((n = imsg_read(ibuf)) == -1) +@@ -576,20 +574,12 @@ rde_dispatch_imsg_parent(struct imsgbuf break; + + switch (imsg.hdr.type) { +- case IMSG_RECONF_CONF: +- reloadtime = time(NULL); +- newrules = calloc(1, sizeof(struct filter_head)); +- if (newrules == NULL) +- fatal(NULL); +- TAILQ_INIT(newrules); +- if ((nconf = malloc(sizeof(struct bgpd_config))) == +- NULL) +- fatal(NULL); +- memcpy(nconf, imsg.data, sizeof(struct bgpd_config)); +- for (rid = 0; rid < rib_size; rid++) +- ribs[rid].state = RIB_DELETE; +- break; case IMSG_NETWORK_ADD: ++ if (imsg.hdr.len - IMSG_HEADER_SIZE != ++ sizeof(struct network_config)) { ++ log_warnx("rde_dispatch: wrong imsg len"); ++ break; ++ } memcpy(&netconf_p, imsg.data, sizeof(netconf_p)); -@@ -615,9 +596,9 @@ rde_dispatch_imsg_parent(struct imsgbuf + TAILQ_INIT(&netconf_p.attrset); + parent_set = &netconf_p.attrset; +@@ -608,6 +598,26 @@ rde_dispatch_imsg_parent(struct imsgbuf + TAILQ_INIT(&netconf_p.attrset); + network_delete(&netconf_p, 1); + break; ++ case IMSG_RECONF_CONF: ++ if (imsg.hdr.len - IMSG_HEADER_SIZE != ++ sizeof(struct bgpd_config)) ++ fatalx("IMSG_RECONF_CONF bad len"); ++ reloadtime = time(NULL); ++ newrules = calloc(1, sizeof(struct filter_head)); ++ if (newrules == NULL) ++ fatal(NULL); ++ TAILQ_INIT(newrules); ++ newdomains = calloc(1, sizeof(struct rdomain_head)); ++ if (newdomains == NULL) ++ fatal(NULL); ++ SIMPLEQ_INIT(newdomains); ++ if ((nconf = malloc(sizeof(struct bgpd_config))) == ++ NULL) ++ fatal(NULL); ++ memcpy(nconf, imsg.data, sizeof(struct bgpd_config)); ++ for (rid = 0; rid < rib_size; rid++) ++ ribs[rid].state = RECONF_DELETE; ++ break; + case IMSG_RECONF_RIB: + if (imsg.hdr.len - IMSG_HEADER_SIZE != + sizeof(struct rde_rib)) +@@ -615,9 +625,26 @@ rde_dispatch_imsg_parent(struct imsgbuf memcpy(&rn, imsg.data, sizeof(rn)); rid = rib_find(rn.name); if (rid == RIB_FAILED) - rib_new(-1, rn.name, rn.flags); -+ rib_new(rn.name, rn.flags); - else +- else - ribs[rid].state = RIB_ACTIVE; ++ rib_new(rn.name, rn.rtableid, rn.flags); ++ else if (ribs[rid].rtableid != rn.rtableid || ++ (ribs[rid].flags & F_RIB_HASNOFIB) != ++ (rn.flags & F_RIB_HASNOFIB)) { ++ /* Big hammer in the F_RIB_NOFIB case but ++ * not often enough used to optimise it more. */ ++ rib_free(&ribs[rid]); ++ rib_new(rn.name, rn.rtableid, rn.flags); ++ } else + ribs[rid].state = RECONF_KEEP; ++ break; ++ case IMSG_RECONF_PEER: ++ if (imsg.hdr.len - IMSG_HEADER_SIZE != ++ sizeof(struct peer_config)) ++ fatalx("IMSG_RECONF_PEER bad len"); ++ if ((peer = peer_get(imsg.hdr.peerid)) == NULL) ++ break; ++ pconf = imsg.data; ++ strlcpy(peer->conf.rib, pconf->rib, ++ sizeof(peer->conf.rib)); break; case IMSG_RECONF_FILTER: if (imsg.hdr.len - IMSG_HEADER_SIZE != -@@ -644,9 +625,17 @@ rde_dispatch_imsg_parent(struct imsgbuf +@@ -631,12 +658,42 @@ rde_dispatch_imsg_parent(struct imsgbuf + parent_set = &r->set; + TAILQ_INSERT_TAIL(newrules, r, entry); + break; ++ case IMSG_RECONF_RDOMAIN: ++ if (imsg.hdr.len - IMSG_HEADER_SIZE != ++ sizeof(struct rdomain)) ++ fatalx("IMSG_RECONF_RDOMAIN bad len"); ++ if ((rd = malloc(sizeof(struct rdomain))) == NULL) ++ fatal(NULL); ++ memcpy(rd, imsg.data, sizeof(struct rdomain)); ++ TAILQ_INIT(&rd->import); ++ TAILQ_INIT(&rd->export); ++ SIMPLEQ_INSERT_TAIL(newdomains, rd, entry); ++ break; ++ case IMSG_RECONF_RDOMAIN_EXPORT: ++ if (rd == NULL) { ++ log_warnx("rde_dispatch_imsg_parent: " ++ "IMSG_RECONF_RDOMAIN_EXPORT unexpected"); ++ break; ++ } ++ parent_set = &rd->export; ++ break; ++ case IMSG_RECONF_RDOMAIN_IMPORT: ++ if (rd == NULL) { ++ log_warnx("rde_dispatch_imsg_parent: " ++ "IMSG_RECONF_RDOMAIN_IMPORT unexpected"); ++ break; ++ } ++ parent_set = &rd->import; ++ break; ++ case IMSG_RECONF_RDOMAIN_DONE: ++ parent_set = NULL; ++ break; + case IMSG_RECONF_DONE: + if (nconf == NULL) + fatalx("got IMSG_RECONF_DONE but no config"); + if ((nconf->flags & BGPD_FLAG_NO_EVALUATE) + != (conf->flags & BGPD_FLAG_NO_EVALUATE)) { +- log_warnx( "change to/from route-collector " ++ log_warnx("change to/from route-collector " + "mode ignored"); + if (conf->flags & BGPD_FLAG_NO_EVALUATE) + nconf->flags |= BGPD_FLAG_NO_EVALUATE; +@@ -644,10 +701,27 @@ rde_dispatch_imsg_parent(struct imsgbuf nconf->flags &= ~BGPD_FLAG_NO_EVALUATE; } memcpy(conf, nconf, sizeof(struct bgpd_config)); @@ -338,19 +507,60 @@ diff -u -p -r1.1.1.8 -r1.9 free(nconf); nconf = NULL; parent_set = NULL; +- prefix_network_clean(peerself, reloadtime, 0); + /* sync peerself with conf */ + peerself->remote_bgpid = ntohl(conf->bgpid); + peerself->conf.local_as = conf->as; + peerself->conf.remote_as = conf->as; + peerself->short_as = conf->short_as; - prefix_network_clean(peerself, reloadtime, 0); ++ ++ /* apply new set of rdomain, sync will be done later */ ++ while ((rd = SIMPLEQ_FIRST(rdomains_l)) != NULL) { ++ SIMPLEQ_REMOVE_HEAD(rdomains_l, entry); ++ filterset_free(&rd->import); ++ filterset_free(&rd->export); ++ free(rd); ++ } ++ free(rdomains_l); ++ rdomains_l = newdomains; /* check if filter changed */ -@@ -668,17 +657,29 @@ rde_dispatch_imsg_parent(struct imsgbuf + LIST_FOREACH(peer, &peerlist, peer_l) { +@@ -655,30 +729,59 @@ rde_dispatch_imsg_parent(struct imsgbuf + continue; + peer->reconf_out = 0; + peer->reconf_in = 0; +- if (peer->conf.softreconfig_out && +- !rde_filter_equal(rules_l, newrules, peer, +- DIR_OUT)) { +- peer->reconf_out = 1; +- reconf_out = 1; +- } ++ peer->reconf_rib = 0; + if (peer->conf.softreconfig_in && + !rde_filter_equal(rules_l, newrules, peer, + DIR_IN)) { + peer->reconf_in = 1; reconf_in = 1; } ++ if (peer->ribid != rib_find(peer->conf.rib)) { ++ rib_dump(&ribs[peer->ribid], ++ rde_softreconfig_unload_peer, peer, ++ AID_UNSPEC); ++ peer->ribid = rib_find(peer->conf.rib); ++ peer->reconf_rib = 1; ++ reconf_rib = 1; ++ continue; ++ } ++ if (peer->conf.softreconfig_out && ++ !rde_filter_equal(rules_l, newrules, peer, ++ DIR_OUT)) { ++ peer->reconf_out = 1; ++ reconf_out = 1; ++ } } - /* XXX this needs rework anyway */ +- /* sync local-RIB first */ + /* bring ribs in sync before softreconfig dance */ + for (rid = 0; rid < rib_size; rid++) { + if (ribs[rid].state == RECONF_DELETE) @@ -360,7 +570,7 @@ diff -u -p -r1.1.1.8 -r1.9 + rde_softreconfig_load, &ribs[rid], + AID_UNSPEC); + } - /* sync local-RIB first */ ++ /* sync local-RIBs first */ if (reconf_in) rib_dump(&ribs[0], rde_softreconfig_in, NULL, - AF_UNSPEC); @@ -377,10 +587,17 @@ diff -u -p -r1.1.1.8 -r1.9 - NULL, AF_UNSPEC); + NULL, AID_UNSPEC); + } ++ } ++ if (reconf_rib) { ++ LIST_FOREACH(peer, &peerlist, peer_l) { ++ rib_dump(&ribs[peer->ribid], ++ rde_softreconfig_load_peer, ++ peer, AID_UNSPEC); ++ } } while ((r = TAILQ_FIRST(rules_l)) != NULL) { -@@ -688,10 +689,6 @@ rde_dispatch_imsg_parent(struct imsgbuf +@@ -688,16 +791,16 @@ rde_dispatch_imsg_parent(struct imsgbuf } free(rules_l); rules_l = newrules; @@ -388,10 +605,20 @@ diff -u -p -r1.1.1.8 -r1.9 - if (ribs[rid].state == RIB_DELETE) - rib_free(&ribs[rid]); - } ++ log_info("RDE reconfigured"); break; case IMSG_NEXTHOP_UPDATE: -@@ -744,6 +741,8 @@ rde_dispatch_imsg_parent(struct imsgbuf + nexthop_update(imsg.data); + break; + case IMSG_FILTER_SET: ++ if (imsg.hdr.len > IMSG_HEADER_SIZE + ++ sizeof(struct filter_set)) ++ fatalx("IMSG_RECONF_CONF bad len"); + if (parent_set == NULL) { + log_warnx("rde_dispatch_imsg_parent: " + "IMSG_FILTER_SET unexpected"); +@@ -744,6 +847,8 @@ rde_dispatch_imsg_parent(struct imsgbuf int rde_update_dispatch(struct imsg *imsg) { @@ -400,7 +627,7 @@ diff -u -p -r1.1.1.8 -r1.9 struct rde_peer *peer; struct rde_aspath *asp = NULL; u_char *p, *mpp = NULL; -@@ -752,9 +751,7 @@ rde_update_dispatch(struct imsg *imsg) +@@ -752,9 +857,8 @@ rde_update_dispatch(struct imsg *imsg) u_int16_t withdrawn_len; u_int16_t attrpath_len; u_int16_t nlri_len; @@ -408,10 +635,11 @@ diff -u -p -r1.1.1.8 -r1.9 - struct bgpd_addr prefix; - struct mpattr mpa; + u_int8_t aid, prefixlen, safi, subtype; ++ u_int32_t fas; peer = peer_get(imsg->hdr.peerid); if (peer == NULL) /* unknown peer, cannot happen */ -@@ -810,14 +807,7 @@ rde_update_dispatch(struct imsg *imsg) +@@ -810,26 +914,21 @@ rde_update_dispatch(struct imsg *imsg) goto done; } @@ -427,7 +655,28 @@ diff -u -p -r1.1.1.8 -r1.9 /* enforce remote AS if requested */ if (asp->flags & F_ATTR_ASPATH && -@@ -860,9 +850,9 @@ rde_update_dispatch(struct imsg *imsg) +- peer->conf.enforce_as == ENFORCE_AS_ON) +- if (peer->conf.remote_as != +- aspath_neighbor(asp->aspath)) { +- log_peer_warnx(&peer->conf, "bad path, " +- "enforce remote-as enabled"); +- rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH, ++ peer->conf.enforce_as == ENFORCE_AS_ON) { ++ fas = aspath_neighbor(asp->aspath); ++ if (peer->conf.remote_as != fas) { ++ log_peer_warnx(&peer->conf, "bad path, " ++ "starting with %s, " ++ "enforce neighbor-as enabled", log_as(fas)); ++ rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH, + NULL, 0); +- goto done; ++ goto done; + } ++ } + + rde_reflector(peer, asp); + } +@@ -860,9 +959,9 @@ rde_update_dispatch(struct imsg *imsg) p += pos; len -= pos; @@ -440,7 +689,7 @@ diff -u -p -r1.1.1.8 -r1.9 rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, NULL, 0); goto done; -@@ -892,15 +882,25 @@ rde_update_dispatch(struct imsg *imsg) +@@ -892,15 +991,25 @@ rde_update_dispatch(struct imsg *imsg) afi = ntohs(afi); safi = *mpp++; mplen--; @@ -475,7 +724,7 @@ diff -u -p -r1.1.1.8 -r1.9 while (mplen > 0) { if ((pos = rde_update_get_prefix6(mpp, mplen, &prefix, &prefixlen)) == -1) { -@@ -926,6 +926,32 @@ rde_update_dispatch(struct imsg *imsg) +@@ -926,6 +1035,32 @@ rde_update_dispatch(struct imsg *imsg) rde_update_withdraw(peer, &prefix, prefixlen); } break; @@ -508,7 +757,7 @@ diff -u -p -r1.1.1.8 -r1.9 default: /* silently ignore unsupported multiprotocol AF */ break; -@@ -963,9 +989,9 @@ rde_update_dispatch(struct imsg *imsg) +@@ -963,9 +1098,9 @@ rde_update_dispatch(struct imsg *imsg) p += pos; nlri_len -= pos; @@ -521,7 +770,7 @@ diff -u -p -r1.1.1.8 -r1.9 rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, NULL, 0); goto done; -@@ -995,6 +1021,22 @@ rde_update_dispatch(struct imsg *imsg) +@@ -995,6 +1130,22 @@ rde_update_dispatch(struct imsg *imsg) safi = *mpp++; mplen--; @@ -544,7 +793,7 @@ diff -u -p -r1.1.1.8 -r1.9 /* * this works because asp is not linked. * But first unlock the previously locked nexthop. -@@ -1004,8 +1046,8 @@ rde_update_dispatch(struct imsg *imsg) +@@ -1004,8 +1155,8 @@ rde_update_dispatch(struct imsg *imsg) (void)nexthop_delete(asp->nexthop); asp->nexthop = NULL; } @@ -555,7 +804,7 @@ diff -u -p -r1.1.1.8 -r1.9 rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, mpa.reach, mpa.reach_len); goto done; -@@ -1013,16 +1055,8 @@ rde_update_dispatch(struct imsg *imsg) +@@ -1013,16 +1164,8 @@ rde_update_dispatch(struct imsg *imsg) mpp += pos; mplen -= pos; @@ -574,7 +823,7 @@ diff -u -p -r1.1.1.8 -r1.9 while (mplen > 0) { if ((pos = rde_update_get_prefix6(mpp, mplen, &prefix, &prefixlen)) == -1) { -@@ -1058,6 +1092,42 @@ rde_update_dispatch(struct imsg *imsg) +@@ -1058,6 +1201,42 @@ rde_update_dispatch(struct imsg *imsg) } break; @@ -617,7 +866,7 @@ diff -u -p -r1.1.1.8 -r1.9 default: /* silently ignore unsupported multiprotocol AF */ break; -@@ -1085,7 +1155,8 @@ rde_update_update(struct rde_peer *peer, +@@ -1085,7 +1264,8 @@ rde_update_update(struct rde_peer *peer, struct bgpd_addr *prefix, u_int8_t prefixlen) { struct rde_aspath *fasp; @@ -627,7 +876,7 @@ diff -u -p -r1.1.1.8 -r1.9 u_int16_t i; peer->prefix_rcvd_update++; -@@ -1095,18 +1166,24 @@ rde_update_update(struct rde_peer *peer, +@@ -1095,18 +1275,24 @@ rde_update_update(struct rde_peer *peer, for (i = 1; i < rib_size; i++) { /* input filter */ @@ -659,7 +908,7 @@ diff -u -p -r1.1.1.8 -r1.9 /* free modified aspath */ if (fasp != asp) path_put(fasp); -@@ -1114,6 +1191,8 @@ done: +@@ -1114,6 +1300,8 @@ done: if (r) peer->prefix_cnt++; @@ -668,7 +917,42 @@ diff -u -p -r1.1.1.8 -r1.9 } void -@@ -1248,7 +1327,7 @@ bad_flags: +@@ -1161,6 +1349,7 @@ rde_attr_parse(u_char *p, u_int16_t len, + struct bgpd_addr nexthop; + u_char *op = p, *npath; + u_int32_t tmp32; ++ int err; + u_int16_t attr_len, nlen; + u_int16_t plen = 0; + u_int8_t flags; +@@ -1195,6 +1384,7 @@ bad_len: + switch (type) { + case ATTR_UNDEF: + /* ignore and drop path attributes with a type code of 0 */ ++ plen += attr_len; + break; + case ATTR_ORIGIN: + if (attr_len != 1) +@@ -1220,7 +1410,17 @@ bad_flags: + case ATTR_ASPATH: + if (!CHECK_FLAGS(flags, ATTR_WELL_KNOWN, 0)) + goto bad_flags; +- if (aspath_verify(p, attr_len, rde_as4byte(peer)) != 0) { ++ err = aspath_verify(p, attr_len, rde_as4byte(peer)); ++ if (err == AS_ERR_SOFT) { ++ /* ++ * soft errors like unexpected segment types are ++ * not considered fatal and the path is just ++ * marked invalid. ++ */ ++ a->flags |= F_ATTR_PARSE_ERR; ++ log_peer_warnx(&peer->conf, "bad ASPATH, " ++ "path invalidated and prefix withdrawn"); ++ } else if (err != 0) { + rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH, + NULL, 0); + return (-1); +@@ -1248,7 +1448,7 @@ bad_flags: a->flags |= F_ATTR_NEXTHOP; bzero(&nexthop, sizeof(nexthop)); @@ -677,7 +961,7 @@ diff -u -p -r1.1.1.8 -r1.9 UPD_READ(&nexthop.v4.s_addr, p, plen, 4); /* * Check if the nexthop is a valid IP address. We consider -@@ -1305,9 +1384,19 @@ bad_flags: +@@ -1305,9 +1505,21 @@ bad_flags: goto optattr; case ATTR_AGGREGATOR: if ((!rde_as4byte(peer) && attr_len != 6) || @@ -692,6 +976,8 @@ diff -u -p -r1.1.1.8 -r1.9 + */ + if ((flags & ATTR_PARTIAL) == 0) + goto bad_len; ++ log_peer_warnx(&peer->conf, "bad AGGREGATOR, " ++ "partial attribute ignored"); + plen += attr_len; + break; + } @@ -700,13 +986,13 @@ diff -u -p -r1.1.1.8 -r1.9 goto bad_flags; if (!rde_as4byte(peer)) { /* need to inflate aggregator AS to 4-byte */ -@@ -1323,8 +1412,33 @@ bad_flags: +@@ -1323,8 +1535,35 @@ bad_flags: /* 4-byte ready server take the default route */ goto optattr; case ATTR_COMMUNITIES: - if ((attr_len & 0x3) != 0) - goto bad_len; -+ if ((attr_len & 0x3) != 0) { ++ if (attr_len % 4 != 0) { + /* + * mark update as bad and withdraw all routes as per + * draft-ietf-idr-optional-transitive-00.txt @@ -714,15 +1000,16 @@ diff -u -p -r1.1.1.8 -r1.9 + */ + if ((flags & ATTR_PARTIAL) == 0) + goto bad_len; -+ else -+ a->flags |= F_ATTR_PARSE_ERR; ++ a->flags |= F_ATTR_PARSE_ERR; ++ log_peer_warnx(&peer->conf, "bad COMMUNITIES, " ++ "path invalidated and prefix withdrawn"); + } + if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, + ATTR_PARTIAL)) + goto bad_flags; + goto optattr; + case ATTR_EXT_COMMUNITIES: -+ if ((attr_len & 0x7) != 0) { ++ if (attr_len % 8 != 0) { + /* + * mark update as bad and withdraw all routes as per + * draft-ietf-idr-optional-transitive-00.txt @@ -730,13 +1017,23 @@ diff -u -p -r1.1.1.8 -r1.9 + */ + if ((flags & ATTR_PARTIAL) == 0) + goto bad_len; -+ else -+ a->flags |= F_ATTR_PARSE_ERR; ++ a->flags |= F_ATTR_PARSE_ERR; ++ log_peer_warnx(&peer->conf, "bad EXT_COMMUNITIES, " ++ "path invalidated and prefix withdrawn"); + } if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, ATTR_PARTIAL)) goto bad_flags; -@@ -1370,8 +1484,14 @@ bad_flags: +@@ -1336,7 +1575,7 @@ bad_flags: + goto bad_flags; + goto optattr; + case ATTR_CLUSTER_LIST: +- if ((attr_len & 0x3) != 0) ++ if (attr_len % 4 != 0) + goto bad_len; + if (!CHECK_FLAGS(flags, ATTR_OPTIONAL, 0)) + goto bad_flags; +@@ -1370,8 +1609,15 @@ bad_flags: plen += attr_len; break; case ATTR_AS4_AGGREGATOR: @@ -746,14 +1043,20 @@ diff -u -p -r1.1.1.8 -r1.9 + /* see ATTR_AGGREGATOR ... */ + if ((flags & ATTR_PARTIAL) == 0) + goto bad_len; -+ /* we should add a warning here */ ++ log_peer_warnx(&peer->conf, "bad AS4_AGGREGATOR, " ++ "partial attribute ignored"); + plen += attr_len; + break; + } if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, ATTR_PARTIAL)) goto bad_flags; -@@ -1385,13 +1505,21 @@ bad_flags: +@@ -1381,17 +1627,28 @@ bad_flags: + if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, + ATTR_PARTIAL)) + goto bad_flags; +- if (aspath_verify(p, attr_len, 1) != 0) { ++ if ((err = aspath_verify(p, attr_len, 1)) != 0) { /* * XXX RFC does not specify how to handle errors. * XXX Instead of dropping the session because of a @@ -767,11 +1070,14 @@ diff -u -p -r1.1.1.8 -r1.9 + * XXX or redistribution. + * XXX We follow draft-ietf-idr-optional-transitive + * XXX by looking at the partial bit. ++ * XXX Consider soft errors similar to a partial attr. */ - a->flags |= F_ATTR_LOOP; - goto optattr; -+ if (flags & ATTR_PARTIAL) { ++ if (flags & ATTR_PARTIAL || err == AS_ERR_SOFT) { + a->flags |= F_ATTR_PARSE_ERR; ++ log_peer_warnx(&peer->conf, "bad AS4_PATH, " ++ "path invalidated and prefix withdrawn"); + goto optattr; + } else { + rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH, @@ -781,7 +1087,7 @@ diff -u -p -r1.1.1.8 -r1.9 } a->flags |= F_ATTR_AS4BYTE_NEW; goto optattr; -@@ -1440,8 +1568,8 @@ rde_attr_missing(struct rde_aspath *a, i +@@ -1440,8 +1697,8 @@ rde_attr_missing(struct rde_aspath *a, i } int @@ -792,7 +1098,7 @@ diff -u -p -r1.1.1.8 -r1.9 { struct bgpd_addr nexthop; u_int8_t totlen, nhlen; -@@ -1457,8 +1585,9 @@ rde_get_mp_nexthop(u_char *data, u_int16 +@@ -1457,8 +1714,9 @@ rde_get_mp_nexthop(u_char *data, u_int16 return (-1); bzero(&nexthop, sizeof(nexthop)); @@ -804,7 +1110,7 @@ diff -u -p -r1.1.1.8 -r1.9 /* * RFC2545 describes that there may be a link-local * address carried in nexthop. Yikes! -@@ -1471,72 +1600,143 @@ rde_get_mp_nexthop(u_char *data, u_int16 +@@ -1471,72 +1729,143 @@ rde_get_mp_nexthop(u_char *data, u_int16 log_warnx("bad multiprotocol nexthop, bad size"); return (-1); } @@ -831,7 +1137,7 @@ diff -u -p -r1.1.1.8 -r1.9 - * cause a use after free error. + * Neither RFC4364 nor RFC3107 specify the format of the + * nexthop in an explicit way. The quality of RFC went down -+ * the toilet the larger the the number got. ++ * the toilet the larger the the number got. + * RFC4364 is very confusing about VPN-IPv4 address and the + * VPN-IPv4 prefix that carries also a MPLS label. + * So the nexthop is a 12-byte address with a 64bit RD and @@ -987,7 +1293,7 @@ diff -u -p -r1.1.1.8 -r1.9 if (len < 1) return (-1); -@@ -1546,18 +1746,43 @@ rde_update_get_prefix6(u_char *p, u_int1 +@@ -1546,25 +1875,50 @@ rde_update_get_prefix6(u_char *p, u_int1 plen = 1; bzero(prefix, sizeof(struct bgpd_addr)); @@ -1041,7 +1347,15 @@ diff -u -p -r1.1.1.8 -r1.9 } void -@@ -1616,6 +1841,14 @@ rde_as4byte_fixup(struct rde_peer *peer, + rde_update_err(struct rde_peer *peer, u_int8_t error, u_int8_t suberr, + void *data, u_int16_t size) + { +- struct buf *wbuf; ++ struct ibuf *wbuf; + + if ((wbuf = imsg_create(ibuf_se, IMSG_UPDATE_ERR, peer->conf.id, 0, + size + sizeof(error) + sizeof(suberr))) == NULL) +@@ -1616,16 +1970,30 @@ rde_as4byte_fixup(struct rde_peer *peer, struct attr *nasp, *naggr, *oaggr; u_int32_t as; @@ -1056,7 +1370,25 @@ diff -u -p -r1.1.1.8 -r1.9 /* first get the attributes */ nasp = attr_optget(a, ATTR_AS4_PATH); naggr = attr_optget(a, ATTR_AS4_AGGREGATOR); -@@ -1669,6 +1902,10 @@ rde_reflector(struct rde_peer *peer, str + + if (rde_as4byte(peer)) { + /* NEW session using 4-byte ASNs */ +- if (nasp) ++ if (nasp) { ++ log_peer_warnx(&peer->conf, "uses 4-byte ASN " ++ "but sent AS4_PATH attribute."); + attr_free(a, nasp); +- if (naggr) ++ } ++ if (naggr) { ++ log_peer_warnx(&peer->conf, "uses 4-byte ASN " ++ "but sent AS4_AGGREGATOR attribute."); + attr_free(a, naggr); ++ } + return; + } + /* OLD session using 2-byte ASNs */ +@@ -1669,6 +2037,10 @@ rde_reflector(struct rde_peer *peer, str u_int16_t len; u_int32_t id; @@ -1067,7 +1399,16 @@ diff -u -p -r1.1.1.8 -r1.9 /* check for originator id if eq router_id drop */ if ((a = attr_optget(asp, ATTR_ORIGINATOR_ID)) != NULL) { if (memcmp(&conf->bgpid, a->data, sizeof(conf->bgpid)) == 0) { -@@ -1748,8 +1985,8 @@ rde_dump_rib_as(struct prefix *p, struct +@@ -1724,7 +2096,7 @@ void + rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags) + { + struct ctl_show_rib rib; +- struct buf *wbuf; ++ struct ibuf *wbuf; + struct attr *a; + void *bp; + u_int8_t l; +@@ -1748,23 +2120,23 @@ rde_dump_rib_as(struct prefix *p, struct /* announced network may have a NULL nexthop */ bzero(&rib.true_nexthop, sizeof(rib.true_nexthop)); bzero(&rib.exit_nexthop, sizeof(rib.exit_nexthop)); @@ -1078,7 +1419,54 @@ diff -u -p -r1.1.1.8 -r1.9 } pt_getaddr(p->prefix, &rib.prefix); rib.prefixlen = p->prefix->prefixlen; -@@ -1836,7 +2073,7 @@ rde_dump_filter(struct prefix *p, struct + rib.origin = asp->origin; + rib.flags = 0; + if (p->rib->active == p) +- rib.flags |= F_RIB_ACTIVE; ++ rib.flags |= F_PREF_ACTIVE; + if (asp->peer->conf.ebgp == 0) +- rib.flags |= F_RIB_INTERNAL; ++ rib.flags |= F_PREF_INTERNAL; + if (asp->flags & F_PREFIX_ANNOUNCED) +- rib.flags |= F_RIB_ANNOUNCE; ++ rib.flags |= F_PREF_ANNOUNCE; + if (asp->nexthop == NULL || asp->nexthop->state == NEXTHOP_REACH) +- rib.flags |= F_RIB_ELIGIBLE; ++ rib.flags |= F_PREF_ELIGIBLE; + if (asp->flags & F_ATTR_LOOP) +- rib.flags &= ~F_RIB_ELIGIBLE; ++ rib.flags &= ~F_PREF_ELIGIBLE; + rib.aspath_len = aspath_length(asp->aspath); + + if ((wbuf = imsg_create(ibuf_se_ctl, IMSG_CTL_SHOW_RIB, 0, pid, +@@ -1784,13 +2156,13 @@ rde_dump_rib_as(struct prefix *p, struct + IMSG_CTL_SHOW_RIB_ATTR, 0, pid, + attr_optlen(a))) == NULL) + return; +- if ((bp = buf_reserve(wbuf, attr_optlen(a))) == NULL) { +- buf_free(wbuf); ++ if ((bp = ibuf_reserve(wbuf, attr_optlen(a))) == NULL) { ++ ibuf_free(wbuf); + return; + } + if (attr_write(bp, attr_optlen(a), a->flags, + a->type, a->data, a->len) == -1) { +- buf_free(wbuf); ++ ibuf_free(wbuf); + return; + } + imsg_close(ibuf_se_ctl, wbuf); +@@ -1828,15 +2200,15 @@ rde_dump_filter(struct prefix *p, struct + { + struct rde_peer *peer; + +- if (req->flags & F_CTL_ADJ_IN || ++ if (req->flags & F_CTL_ADJ_IN || + !(req->flags & (F_CTL_ADJ_IN|F_CTL_ADJ_OUT))) { + if (req->peerid && req->peerid != p->aspath->peer->conf.id) + return; +- if (req->type == IMSG_CTL_SHOW_RIB_AS && ++ if (req->type == IMSG_CTL_SHOW_RIB_AS && !aspath_match(p->aspath->aspath, req->as.type, req->as.as)) return; if (req->type == IMSG_CTL_SHOW_RIB_COMMUNITY && @@ -1087,7 +1475,7 @@ diff -u -p -r1.1.1.8 -r1.9 req->community.type)) return; rde_dump_rib_as(p, p->aspath, req->pid, req->flags); -@@ -1872,7 +2109,7 @@ rde_dump_prefix_upcall(struct rib_entry +@@ -1872,7 +2244,7 @@ rde_dump_prefix_upcall(struct rib_entry pt = re->prefix; pt_getaddr(pt, &addr); @@ -1096,7 +1484,15 @@ diff -u -p -r1.1.1.8 -r1.9 return; if (ctx->req.prefixlen > pt->prefixlen) return; -@@ -1902,6 +2139,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req +@@ -1889,6 +2261,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req + struct rib_entry *re; + u_int error; + u_int16_t id; ++ u_int8_t hostplen = 0; + + if ((ctx = calloc(1, sizeof(*ctx))) == NULL) { + log_warn("rde_dump_ctx_new"); +@@ -1902,6 +2275,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req error = CTL_RES_NOSUCHPEER; imsg_compose(ibuf_se_ctl, IMSG_CTL_RESULT, 0, pid, -1, &error, sizeof(error)); @@ -1104,7 +1500,27 @@ diff -u -p -r1.1.1.8 -r1.9 return; } -@@ -1937,7 +2175,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req +@@ -1924,7 +2298,18 @@ rde_dump_ctx_new(struct ctl_show_rib_req + ctx->ribctx.ctx_upcall = rde_dump_prefix_upcall; + break; + } +- if (req->prefixlen == 32) ++ switch (req->prefix.aid) { ++ case AID_INET: ++ case AID_VPN_IPv4: ++ hostplen = 32; ++ break; ++ case AID_INET6: ++ hostplen = 128; ++ break; ++ default: ++ fatalx("rde_dump_ctx_new: unknown af"); ++ } ++ if (req->prefixlen == hostplen) + re = rib_lookup(&ribs[id], &req->prefix); + else + re = rib_get(&ribs[id], &req->prefix, req->prefixlen); +@@ -1937,7 +2322,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req } ctx->ribctx.ctx_done = rde_dump_done; ctx->ribctx.ctx_arg = ctx; @@ -1113,7 +1529,7 @@ diff -u -p -r1.1.1.8 -r1.9 rib_dump_r(&ctx->ribctx); } -@@ -1974,10 +2212,10 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t +@@ -1974,10 +2359,10 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t ctx->ribctx.ctx_count = RDE_RUNNER_ROUNDS; ctx->ribctx.ctx_rib = &ribs[id]; ctx->ribctx.ctx_upcall = mrt_dump_upcall; @@ -1127,38 +1543,118 @@ diff -u -p -r1.1.1.8 -r1.9 rde_mrt_cnt++; rib_dump_r(&ctx->ribctx); } -@@ -2011,8 +2249,8 @@ rde_send_kroute(struct prefix *new, stru +@@ -1985,13 +2370,25 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t + /* + * kroute specific functions + */ ++int ++rde_rdomain_import(struct rde_aspath *asp, struct rdomain *rd) ++{ ++ struct filter_set *s; ++ ++ TAILQ_FOREACH(s, &rd->import, entry) { ++ if (community_ext_match(asp, &s->action.ext_community, 0)) ++ return (1); ++ } ++ return (0); ++} ++ + void +-rde_send_kroute(struct prefix *new, struct prefix *old) ++rde_send_kroute(struct prefix *new, struct prefix *old, u_int16_t ribid) + { +- struct kroute_label kl; +- struct kroute6_label kl6; ++ struct kroute_full kr; + struct bgpd_addr addr; + struct prefix *p; ++ struct rdomain *rd; + enum imsg_type type; + + /* +@@ -2011,43 +2408,45 @@ rde_send_kroute(struct prefix *new, stru } pt_getaddr(p->prefix, &addr); - switch (addr.af) { - case AF_INET: +- bzero(&kl, sizeof(kl)); +- kl.kr.prefix.s_addr = addr.v4.s_addr; +- kl.kr.prefixlen = p->prefix->prefixlen; +- if (p->aspath->flags & F_NEXTHOP_REJECT) +- kl.kr.flags |= F_REJECT; +- if (p->aspath->flags & F_NEXTHOP_BLACKHOLE) +- kl.kr.flags |= F_BLACKHOLE; +- if (type == IMSG_KROUTE_CHANGE) +- kl.kr.nexthop.s_addr = +- p->aspath->nexthop->true_nexthop.v4.s_addr; +- strlcpy(kl.label, rtlabel_id2name(p->aspath->rtlabelid), +- sizeof(kl.label)); +- if (imsg_compose(ibuf_main, type, 0, 0, -1, &kl, +- sizeof(kl)) == -1) +- fatal("imsg_compose error"); ++ bzero(&kr, sizeof(kr)); ++ memcpy(&kr.prefix, &addr, sizeof(kr.prefix)); ++ kr.prefixlen = p->prefix->prefixlen; ++ if (p->aspath->flags & F_NEXTHOP_REJECT) ++ kr.flags |= F_REJECT; ++ if (p->aspath->flags & F_NEXTHOP_BLACKHOLE) ++ kr.flags |= F_BLACKHOLE; ++ if (type == IMSG_KROUTE_CHANGE) ++ memcpy(&kr.nexthop, &p->aspath->nexthop->true_nexthop, ++ sizeof(kr.nexthop)); ++ strlcpy(kr.label, rtlabel_id2name(p->aspath->rtlabelid), ++ sizeof(kr.label)); ++ + switch (addr.aid) { -+ case AID_INET: - bzero(&kl, sizeof(kl)); - kl.kr.prefix.s_addr = addr.v4.s_addr; - kl.kr.prefixlen = p->prefix->prefixlen; -@@ -2029,7 +2267,7 @@ rde_send_kroute(struct prefix *new, stru - sizeof(kl)) == -1) - fatal("imsg_compose error"); ++ case AID_VPN_IPv4: ++ if (ribid != 1) ++ /* not Loc-RIB, no update for VPNs */ ++ break; ++ ++ SIMPLEQ_FOREACH(rd, rdomains_l, entry) { ++ if (addr.vpn4.rd != rd->rd) ++ continue; ++ if (!rde_rdomain_import(p->aspath, rd)) ++ continue; ++ /* must send exit_nexthop so that correct MPLS tunnel ++ * is chosen ++ */ ++ if (type == IMSG_KROUTE_CHANGE) ++ memcpy(&kr.nexthop, ++ &p->aspath->nexthop->exit_nexthop, ++ sizeof(kr.nexthop)); ++ if (imsg_compose(ibuf_main, type, rd->rtableid, 0, -1, ++ &kr, sizeof(kr)) == -1) ++ fatal("imsg_compose error"); ++ } break; - case AF_INET6: -+ case AID_INET6: - bzero(&kl6, sizeof(kl6)); - memcpy(&kl6.kr.prefix, &addr.v6, sizeof(struct in6_addr)); - kl6.kr.prefixlen = p->prefix->prefixlen; -@@ -2050,6 +2288,10 @@ rde_send_kroute(struct prefix *new, stru - sizeof(kl6)) == -1) +- bzero(&kl6, sizeof(kl6)); +- memcpy(&kl6.kr.prefix, &addr.v6, sizeof(struct in6_addr)); +- kl6.kr.prefixlen = p->prefix->prefixlen; +- if (p->aspath->flags & F_NEXTHOP_REJECT) +- kl6.kr.flags |= F_REJECT; +- if (p->aspath->flags & F_NEXTHOP_BLACKHOLE) +- kl6.kr.flags |= F_BLACKHOLE; +- if (type == IMSG_KROUTE_CHANGE) { +- type = IMSG_KROUTE6_CHANGE; +- memcpy(&kl6.kr.nexthop, +- &p->aspath->nexthop->true_nexthop.v6, +- sizeof(struct in6_addr)); +- } else +- type = IMSG_KROUTE6_DELETE; +- strlcpy(kl6.label, rtlabel_id2name(p->aspath->rtlabelid), +- sizeof(kl6.label)); +- if (imsg_compose(ibuf_main, type, 0, 0, -1, &kl6, +- sizeof(kl6)) == -1) ++ default: ++ if (imsg_compose(ibuf_main, type, ribs[ribid].rtableid, 0, -1, ++ &kr, sizeof(kr)) == -1) fatal("imsg_compose error"); break; -+ case AID_VPN_IPv4: -+ break; -+ default: -+ fatal("rde_send_kroute: unhandled AID"); } - } - -@@ -2098,7 +2340,6 @@ rde_send_pftable_commit(void) +@@ -2098,7 +2497,6 @@ rde_send_pftable_commit(void) void rde_send_nexthop(struct bgpd_addr *next, int valid) { @@ -1166,7 +1662,7 @@ diff -u -p -r1.1.1.8 -r1.9 int type; if (valid) -@@ -2106,8 +2347,6 @@ rde_send_nexthop(struct bgpd_addr *next, +@@ -2106,8 +2504,6 @@ rde_send_nexthop(struct bgpd_addr *next, else type = IMSG_NEXTHOP_REMOVE; @@ -1175,7 +1671,7 @@ diff -u -p -r1.1.1.8 -r1.9 if (imsg_compose(ibuf_main, type, 0, 0, -1, next, sizeof(struct bgpd_addr)) == -1) fatal("imsg_compose error"); -@@ -2201,6 +2440,10 @@ rde_softreconfig_in(struct rib_entry *re +@@ -2201,6 +2597,10 @@ rde_softreconfig_in(struct rib_entry *re continue; for (i = 1; i < rib_size; i++) { @@ -1186,7 +1682,7 @@ diff -u -p -r1.1.1.8 -r1.9 /* check if prefix changed */ oa = rde_filter(i, &oasp, rules_l, peer, asp, &addr, pt->prefixlen, peer, DIR_IN); -@@ -2228,7 +2471,7 @@ rde_softreconfig_in(struct rib_entry *re +@@ -2228,7 +2628,7 @@ rde_softreconfig_in(struct rib_entry *re if (path_compare(nasp, oasp) == 0) goto done; /* send update */ @@ -1195,7 +1691,7 @@ diff -u -p -r1.1.1.8 -r1.9 pt->prefixlen); } -@@ -2241,6 +2484,40 @@ done: +@@ -2241,6 +2641,104 @@ done: } } @@ -1233,10 +1729,92 @@ diff -u -p -r1.1.1.8 -r1.9 + } +} + ++void ++rde_softreconfig_load_peer(struct rib_entry *re, void *ptr) ++{ ++ struct rde_peer *peer = ptr; ++ struct prefix *p = re->active; ++ struct pt_entry *pt; ++ struct rde_aspath *nasp; ++ enum filter_actions na; ++ struct bgpd_addr addr; ++ ++ pt = re->prefix; ++ pt_getaddr(pt, &addr); ++ ++ /* check if prefix was announced */ ++ if (up_test_update(peer, p) != 1) ++ return; ++ ++ na = rde_filter(re->ribid, &nasp, newrules, peer, p->aspath, ++ &addr, pt->prefixlen, p->aspath->peer, DIR_OUT); ++ nasp = nasp != NULL ? nasp : p->aspath; ++ ++ if (na == ACTION_DENY) ++ /* nothing todo */ ++ goto done; ++ ++ /* send update */ ++ up_generate(peer, nasp, &addr, pt->prefixlen); ++done: ++ if (nasp != p->aspath) ++ path_put(nasp); ++} ++ ++void ++rde_softreconfig_unload_peer(struct rib_entry *re, void *ptr) ++{ ++ struct rde_peer *peer = ptr; ++ struct prefix *p = re->active; ++ struct pt_entry *pt; ++ struct rde_aspath *oasp; ++ enum filter_actions oa; ++ struct bgpd_addr addr; ++ ++ pt = re->prefix; ++ pt_getaddr(pt, &addr); ++ ++ /* check if prefix was announced */ ++ if (up_test_update(peer, p) != 1) ++ return; ++ ++ oa = rde_filter(re->ribid, &oasp, rules_l, peer, p->aspath, ++ &addr, pt->prefixlen, p->aspath->peer, DIR_OUT); ++ oasp = oasp != NULL ? oasp : p->aspath; ++ ++ if (oa == ACTION_DENY) ++ /* nothing todo */ ++ goto done; ++ ++ /* send withdraw */ ++ up_generate(peer, NULL, &addr, pt->prefixlen); ++done: ++ if (oasp != p->aspath) ++ path_put(oasp); ++} ++ /* * update specific functions */ -@@ -2286,7 +2563,7 @@ void +@@ -2252,7 +2750,7 @@ rde_up_dump_upcall(struct rib_entry *re, + struct rde_peer *peer = ptr; + + if (re->ribid != peer->ribid) +- fatalx("King Bula: monsterous evil horror."); ++ fatalx("King Bula: monstrous evil horror."); + if (re->active == NULL) + return; + up_generate_updates(rules_l, peer, re->active, NULL); +@@ -2265,7 +2763,7 @@ rde_generate_updates(u_int16_t ribid, st + + /* + * If old is != NULL we know it was active and should be removed. +- * If new is != NULL we know it is reachable and then we should ++ * If new is != NULL we know it is reachable and then we should + * generate an update. + */ + if (old == NULL && new == NULL) +@@ -2286,7 +2784,7 @@ void rde_update_queue_runner(void) { struct rde_peer *peer; @@ -1245,7 +1823,7 @@ diff -u -p -r1.1.1.8 -r1.9 u_int16_t len, wd_len, wpos; len = sizeof(queue_buf) - MSGSIZE_HEADER; -@@ -2300,7 +2577,7 @@ rde_update_queue_runner(void) +@@ -2300,7 +2798,7 @@ rde_update_queue_runner(void) /* first withdraws */ wpos = 2; /* reserve space for the length field */ r = up_dump_prefix(queue_buf + wpos, len - wpos - 2, @@ -1254,7 +1832,7 @@ diff -u -p -r1.1.1.8 -r1.9 wd_len = r; /* write withdraws length filed */ wd_len = htons(wd_len); -@@ -2310,31 +2587,49 @@ rde_update_queue_runner(void) +@@ -2310,31 +2808,49 @@ rde_update_queue_runner(void) /* now bgp path attributes */ r = up_dump_attrnlri(queue_buf + wpos, len - wpos, peer); @@ -1314,7 +1892,7 @@ diff -u -p -r1.1.1.8 -r1.9 u_int16_t len; /* first withdraws ... */ -@@ -2346,7 +2641,7 @@ rde_update6_queue_runner(void) +@@ -2346,7 +2862,7 @@ rde_update6_queue_runner(void) if (peer->state != PEER_UP) continue; len = sizeof(queue_buf) - MSGSIZE_HEADER; @@ -1323,7 +1901,7 @@ diff -u -p -r1.1.1.8 -r1.9 if (b == NULL) continue; -@@ -2369,10 +2664,18 @@ rde_update6_queue_runner(void) +@@ -2369,10 +2885,18 @@ rde_update6_queue_runner(void) if (peer->state != PEER_UP) continue; len = sizeof(queue_buf) - MSGSIZE_HEADER; @@ -1333,19 +1911,19 @@ diff -u -p -r1.1.1.8 -r1.9 + r = up_dump_mp_reach(queue_buf, &len, peer, aid); + switch (r) { + case -2: - continue; ++ continue; + case -1: + peer_send_eor(peer, aid); -+ continue; + continue; + default: + b = queue_buf + r; + break; + } -+ ++ /* finally send message to SE */ if (imsg_compose(ibuf_se, IMSG_UPDATE, peer->conf.id, 0, -1, b, len) == -1) -@@ -2411,7 +2714,7 @@ rde_decisionflags(void) +@@ -2411,7 +2935,7 @@ rde_decisionflags(void) int rde_as4byte(struct rde_peer *peer) { @@ -1354,7 +1932,7 @@ diff -u -p -r1.1.1.8 -r1.9 } /* -@@ -2429,7 +2732,6 @@ void +@@ -2429,7 +2953,6 @@ void peer_init(u_int32_t hashsize) { struct peer_config pc; @@ -1362,7 +1940,7 @@ diff -u -p -r1.1.1.8 -r1.9 u_int32_t hs, i; for (hs = 1; hs < hashsize; hs <<= 1) -@@ -2445,17 +2747,13 @@ peer_init(u_int32_t hashsize) +@@ -2445,17 +2968,13 @@ peer_init(u_int32_t hashsize) peertable.peer_hashmask = hs - 1; bzero(&pc, sizeof(pc)); @@ -1381,7 +1959,7 @@ diff -u -p -r1.1.1.8 -r1.9 } void -@@ -2534,14 +2832,10 @@ peer_localaddrs(struct rde_peer *peer, s +@@ -2534,14 +3053,10 @@ peer_localaddrs(struct rde_peer *peer, s if (ifa->ifa_addr->sa_family == match->ifa_addr->sa_family) ifa = match; @@ -1397,7 +1975,7 @@ diff -u -p -r1.1.1.8 -r1.9 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family == AF_INET6 && strcmp(ifa->ifa_name, match->ifa_name) == 0) { -@@ -2559,13 +2853,7 @@ peer_localaddrs(struct rde_peer *peer, s +@@ -2559,13 +3074,7 @@ peer_localaddrs(struct rde_peer *peer, s &((struct sockaddr_in6 *)ifa-> ifa_addr)->sin6_addr)) continue; @@ -1412,7 +1990,7 @@ diff -u -p -r1.1.1.8 -r1.9 break; } } -@@ -2577,6 +2865,7 @@ void +@@ -2577,6 +3086,7 @@ void peer_up(u_int32_t id, struct session_up *sup) { struct rde_peer *peer; @@ -1420,7 +1998,7 @@ diff -u -p -r1.1.1.8 -r1.9 peer = peer_get(id); if (peer == NULL) { -@@ -2590,10 +2879,7 @@ peer_up(u_int32_t id, struct session_up +@@ -2590,10 +3100,7 @@ peer_up(u_int32_t id, struct session_up peer->short_as = sup->short_as; memcpy(&peer->remote_addr, &sup->remote_addr, sizeof(peer->remote_addr)); @@ -1432,7 +2010,7 @@ diff -u -p -r1.1.1.8 -r1.9 peer_localaddrs(peer, &sup->local_addr); -@@ -2607,7 +2893,10 @@ peer_up(u_int32_t id, struct session_up +@@ -2607,7 +3114,10 @@ peer_up(u_int32_t id, struct session_up */ return; @@ -1444,7 +2022,7 @@ diff -u -p -r1.1.1.8 -r1.9 } void -@@ -2642,42 +2931,32 @@ peer_down(u_int32_t id) +@@ -2642,42 +3152,32 @@ peer_down(u_int32_t id) } void @@ -1501,7 +2079,7 @@ diff -u -p -r1.1.1.8 -r1.9 u_char null[4]; bzero(&null, 4); -@@ -2688,6 +2967,9 @@ peer_send_eor(struct rde_peer *peer, u_i +@@ -2688,6 +3188,9 @@ peer_send_eor(struct rde_peer *peer, u_i u_int16_t i; u_char buf[10]; @@ -1511,50 +2089,178 @@ diff -u -p -r1.1.1.8 -r1.9 i = 0; /* v4 withdrawn len */ bcopy(&i, &buf[0], sizeof(i)); i = htons(6); /* path attr len */ -@@ -2737,7 +3019,7 @@ network_add(struct network_config *nc, i +@@ -2709,25 +3212,43 @@ peer_send_eor(struct rde_peer *peer, u_i + * network announcement stuff + */ + void +-network_init(struct network_head *net_l) +-{ +- struct network *n; +- +- reloadtime = time(NULL); +- +- while ((n = TAILQ_FIRST(net_l)) != NULL) { +- TAILQ_REMOVE(net_l, n, entry); +- network_add(&n->net, 1); +- free(n); +- } +-} +- +-void + network_add(struct network_config *nc, int flagstatic) + { ++ struct rdomain *rd; + struct rde_aspath *asp; ++ struct filter_set_head *vpnset = NULL; ++ in_addr_t prefix4; + u_int16_t i; + ++ if (nc->rtableid) { ++ SIMPLEQ_FOREACH(rd, rdomains_l, entry) { ++ if (rd->rtableid != nc->rtableid) ++ continue; ++ switch (nc->prefix.aid) { ++ case AID_INET: ++ prefix4 = nc->prefix.v4.s_addr; ++ bzero(&nc->prefix, sizeof(nc->prefix)); ++ nc->prefix.aid = AID_VPN_IPv4; ++ nc->prefix.vpn4.rd = rd->rd; ++ nc->prefix.vpn4.addr.s_addr = prefix4; ++ nc->prefix.vpn4.labellen = 3; ++ nc->prefix.vpn4.labelstack[0] = ++ (rd->label >> 12) & 0xff; ++ nc->prefix.vpn4.labelstack[1] = ++ (rd->label >> 4) & 0xff; ++ nc->prefix.vpn4.labelstack[2] = ++ (rd->label << 4) & 0xf0; ++ nc->prefix.vpn4.labelstack[2] |= BGP_MPLS_BOS; ++ vpnset = &rd->export; ++ break; ++ default: ++ log_warnx("unable to VPNize prefix"); ++ filterset_free(&nc->attrset); ++ return; ++ } ++ } ++ } ++ + asp = path_get(); + asp->aspath = aspath_get(NULL, 0); + asp->origin = ORIGIN_IGP; +@@ -2737,7 +3258,9 @@ network_add(struct network_config *nc, i if (!flagstatic) asp->flags |= F_ANN_DYNAMIC; - rde_apply_set(asp, &nc->attrset, nc->prefix.af, peerself, peerself); + rde_apply_set(asp, &nc->attrset, nc->prefix.aid, peerself, peerself); ++ if (vpnset) ++ rde_apply_set(asp, vpnset, nc->prefix.aid, peerself, peerself); for (i = 1; i < rib_size; i++) path_update(&ribs[i], peerself, asp, &nc->prefix, nc->prefixlen); -@@ -2772,9 +3054,10 @@ network_dump_upcall(struct rib_entry *re +@@ -2749,12 +3272,41 @@ network_add(struct network_config *nc, i + void + network_delete(struct network_config *nc, int flagstatic) + { +- u_int32_t flags = F_PREFIX_ANNOUNCED; +- u_int32_t i; ++ struct rdomain *rd; ++ in_addr_t prefix4; ++ u_int32_t flags = F_PREFIX_ANNOUNCED; ++ u_int32_t i; + + if (!flagstatic) + flags |= F_ANN_DYNAMIC; + ++ if (nc->rtableid) { ++ SIMPLEQ_FOREACH(rd, rdomains_l, entry) { ++ if (rd->rtableid != nc->rtableid) ++ continue; ++ switch (nc->prefix.aid) { ++ case AID_INET: ++ prefix4 = nc->prefix.v4.s_addr; ++ bzero(&nc->prefix, sizeof(nc->prefix)); ++ nc->prefix.aid = AID_VPN_IPv4; ++ nc->prefix.vpn4.rd = rd->rd; ++ nc->prefix.vpn4.addr.s_addr = prefix4; ++ nc->prefix.vpn4.labellen = 3; ++ nc->prefix.vpn4.labelstack[0] = ++ (rd->label >> 12) & 0xff; ++ nc->prefix.vpn4.labelstack[1] = ++ (rd->label >> 4) & 0xff; ++ nc->prefix.vpn4.labelstack[2] = ++ (rd->label << 4) & 0xf0; ++ nc->prefix.vpn4.labelstack[2] |= BGP_MPLS_BOS; ++ break; ++ default: ++ log_warnx("unable to VPNize prefix"); ++ return; ++ } ++ } ++ } ++ + for (i = rib_size - 1; i > 0; i--) + prefix_remove(&ribs[i], peerself, &nc->prefix, nc->prefixlen, + flags); +@@ -2764,38 +3316,31 @@ void + network_dump_upcall(struct rib_entry *re, void *ptr) + { + struct prefix *p; +- struct kroute k; +- struct kroute6 k6; ++ struct kroute_full k; + struct bgpd_addr addr; + struct rde_dump_ctx *ctx = ptr; + LIST_FOREACH(p, &re->prefix_h, rib_l) { if (!(p->aspath->flags & F_PREFIX_ANNOUNCED)) continue; - if (p->prefix->af == AF_INET) { -+ pt_getaddr(p->prefix, &addr); -+ switch (addr.aid) { -+ case AID_INET: - bzero(&k, sizeof(k)); +- bzero(&k, sizeof(k)); - pt_getaddr(p->prefix, &addr); - k.prefix.s_addr = addr.v4.s_addr; - k.prefixlen = p->prefix->prefixlen; - if (p->aspath->peer == peerself) -@@ -2783,10 +3066,9 @@ network_dump_upcall(struct rib_entry *re - ctx->req.pid, -1, &k, sizeof(k)) == -1) - log_warnx("network_dump_upcall: " - "imsg_compose error"); +- k.prefix.s_addr = addr.v4.s_addr; +- k.prefixlen = p->prefix->prefixlen; +- if (p->aspath->peer == peerself) +- k.flags = F_KERNEL; +- if (imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NETWORK, 0, +- ctx->req.pid, -1, &k, sizeof(k)) == -1) +- log_warnx("network_dump_upcall: " +- "imsg_compose error"); - } - if (p->prefix->af == AF_INET6) { -+ break; -+ case AID_INET6: - bzero(&k6, sizeof(k6)); +- bzero(&k6, sizeof(k6)); - pt_getaddr(p->prefix, &addr); - memcpy(&k6.prefix, &addr.v6, sizeof(k6.prefix)); - k6.prefixlen = p->prefix->prefixlen; - if (p->aspath->peer == peerself) -@@ -2795,6 +3077,7 @@ network_dump_upcall(struct rib_entry *re - ctx->req.pid, -1, &k6, sizeof(k6)) == -1) - log_warnx("network_dump_upcall: " - "imsg_compose error"); -+ break; - } +- memcpy(&k6.prefix, &addr.v6, sizeof(k6.prefix)); +- k6.prefixlen = p->prefix->prefixlen; +- if (p->aspath->peer == peerself) +- k6.flags = F_KERNEL; +- if (imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NETWORK6, 0, +- ctx->req.pid, -1, &k6, sizeof(k6)) == -1) +- log_warnx("network_dump_upcall: " +- "imsg_compose error"); +- } ++ pt_getaddr(p->prefix, &addr); ++ ++ bzero(&k, sizeof(k)); ++ memcpy(&k.prefix, &addr, sizeof(k.prefix)); ++ if (p->aspath->nexthop == NULL || ++ p->aspath->nexthop->state != NEXTHOP_REACH) ++ k.nexthop.aid = k.prefix.aid; ++ else ++ memcpy(&k.nexthop, &p->aspath->nexthop->true_nexthop, ++ sizeof(k.nexthop)); ++ k.prefixlen = p->prefix->prefixlen; ++ k.flags = F_KERNEL; ++ if ((p->aspath->flags & F_ANN_DYNAMIC) == 0) ++ k.flags = F_STATIC; ++ if (imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NETWORK, 0, ++ ctx->req.pid, -1, &k, sizeof(k)) == -1) ++ log_warnx("network_dump_upcall: " ++ "imsg_compose error"); } } -@@ -2841,10 +3124,10 @@ sa_cmp(struct bgpd_addr *a, struct socka + +@@ -2841,10 +3386,10 @@ sa_cmp(struct bgpd_addr *a, struct socka struct sockaddr_in *in_b; struct sockaddr_in6 *in6_b; diff --git a/net/openbgpd/files/patch-bgpd_rde.h b/net/openbgpd/files/patch-bgpd_rde.h index a19b053cac1d..22b372178ee9 100644 --- a/net/openbgpd/files/patch-bgpd_rde.h +++ b/net/openbgpd/files/patch-bgpd_rde.h @@ -2,13 +2,13 @@ Index: bgpd/rde.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde.h,v retrieving revision 1.1.1.8 -retrieving revision 1.1.1.10 -diff -u -p -r1.1.1.8 -r1.1.1.10 +retrieving revision 1.1.1.11 +diff -u -p -r1.1.1.8 -r1.1.1.11 --- bgpd/rde.h 14 Feb 2010 20:19:57 -0000 1.1.1.8 -+++ bgpd/rde.h 10 Apr 2010 12:13:05 -0000 1.1.1.10 ++++ bgpd/rde.h 12 Jun 2011 10:44:25 -0000 1.1.1.11 @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.120 2009/06/06 01:10:29 claudio Exp $ */ -+/* $OpenBSD: rde.h,v 1.133 2010/03/29 09:24:07 claudio Exp $ */ ++/* $OpenBSD: rde.h,v 1.138 2010/11/18 12:18:31 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and @@ -28,7 +28,21 @@ diff -u -p -r1.1.1.8 -r1.1.1.10 u_int64_t prefix_rcvd_update; u_int64_t prefix_rcvd_withdraw; u_int64_t prefix_sent_update; -@@ -163,6 +160,7 @@ LIST_HEAD(prefix_head, prefix); +@@ -77,10 +74,13 @@ struct rde_peer { + u_int16_t short_as; + u_int8_t reconf_in; /* in filter changed */ + u_int8_t reconf_out; /* out filter changed */ ++ u_int8_t reconf_rib; /* rib changed */ + }; + + #define AS_SET 1 + #define AS_SEQUENCE 2 ++#define AS_CONFED_SEQUENCE 3 ++#define AS_CONFED_SET 4 + #define ASPATH_HEADER_SIZE (sizeof(struct aspath) - sizeof(u_char)) + + LIST_HEAD(aspath_list, aspath); +@@ -163,6 +163,7 @@ LIST_HEAD(prefix_head, prefix); #define F_NEXTHOP_REJECT 0x02000 #define F_NEXTHOP_BLACKHOLE 0x04000 #define F_NEXTHOP_NOMODIFY 0x08000 @@ -36,7 +50,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10 #define F_ATTR_LINKED 0x20000 -@@ -220,14 +218,14 @@ struct nexthop { +@@ -220,14 +221,14 @@ struct nexthop { /* generic entry without address specific part */ struct pt_entry { RB_ENTRY(pt_entry) pt_e; @@ -53,7 +67,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10 u_int8_t prefixlen; u_int16_t refcnt; struct in_addr prefix4; -@@ -235,12 +233,25 @@ struct pt_entry4 { +@@ -235,12 +236,25 @@ struct pt_entry4 { struct pt_entry6 { RB_ENTRY(pt_entry) pt_e; @@ -80,7 +94,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10 struct rib_context { LIST_ENTRY(rib_context) entry; struct rib_entry *ctx_re; -@@ -250,7 +261,7 @@ struct rib_context { +@@ -250,7 +264,7 @@ struct rib_context { void (*ctx_wait)(void *); void *ctx_arg; unsigned int ctx_count; @@ -89,7 +103,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10 }; struct rib_entry { -@@ -262,16 +273,10 @@ struct rib_entry { +@@ -262,23 +276,15 @@ struct rib_entry { u_int16_t flags; }; @@ -103,15 +117,50 @@ diff -u -p -r1.1.1.8 -r1.1.1.10 char name[PEER_DESCR_LEN]; struct rib_tree rib; - enum rib_state state; -+ enum reconf_action state; ++ u_int rtableid; u_int16_t flags; u_int16_t id; ++ enum reconf_action state; }; -@@ -342,21 +347,29 @@ int aspath_loopfree(struct aspath *, u + +-#define F_RIB_ENTRYLOCK 0x0001 +-#define F_RIB_NOEVALUATE 0x0002 +-#define F_RIB_NOFIB 0x0004 + #define RIB_FAILED 0xffff + + struct prefix { +@@ -293,7 +299,7 @@ extern struct rde_memstats rdemem; + + /* prototypes */ + /* rde.c */ +-void rde_send_kroute(struct prefix *, struct prefix *); ++void rde_send_kroute(struct prefix *, struct prefix *, u_int16_t); + void rde_send_nexthop(struct bgpd_addr *, int); + void rde_send_pftable(u_int16_t, struct bgpd_addr *, + u_int8_t, int); +@@ -309,7 +315,7 @@ int rde_as4byte(struct rde_peer *); + /* rde_attr.c */ + int attr_write(void *, u_int16_t, u_int8_t, u_int8_t, void *, + u_int16_t); +-int attr_writebuf(struct buf *, u_int8_t, u_int8_t, void *, ++int attr_writebuf(struct ibuf *, u_int8_t, u_int8_t, void *, + u_int16_t); + void attr_init(u_int32_t); + void attr_shutdown(void); +@@ -327,6 +333,7 @@ int aspath_verify(void *, u_int16_t, i + #define AS_ERR_LEN -1 + #define AS_ERR_TYPE -2 + #define AS_ERR_BAD -3 ++#define AS_ERR_SOFT -4 + void aspath_init(u_int32_t); + void aspath_shutdown(void); + struct aspath *aspath_get(void *, u_int16_t); +@@ -342,21 +349,30 @@ int aspath_loopfree(struct aspath *, u int aspath_compare(struct aspath *, struct aspath *); u_char *aspath_prepend(struct aspath *, u_int32_t, int, u_int16_t *); int aspath_match(struct aspath *, enum as_spec, u_int32_t); -int community_match(void *, u_int16_t, int, int); ++int aspath_lenmatch(struct aspath *, enum aslen_spec, u_int); +int community_match(struct rde_aspath *, int, int); int community_set(struct rde_aspath *, int, int); void community_delete(struct rde_aspath *, int, int); @@ -129,7 +178,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10 extern struct rib *ribs; -u_int16_t rib_new(int, char *, u_int16_t); -+u_int16_t rib_new(char *, u_int16_t); ++u_int16_t rib_new(char *, u_int, u_int16_t); u_int16_t rib_find(char *); void rib_free(struct rib *); struct rib_entry *rib_get(struct rib *, struct bgpd_addr *, int); @@ -140,7 +189,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10 void rib_dump_r(struct rib_context *); void rib_dump_runner(void); int rib_dump_pending(void); -@@ -395,7 +408,7 @@ void prefix_network_clean(struct rde_p +@@ -395,7 +411,7 @@ void prefix_network_clean(struct rde_p void nexthop_init(u_int32_t); void nexthop_shutdown(void); void nexthop_modify(struct rde_aspath *, struct bgpd_addr *, @@ -149,7 +198,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10 void nexthop_link(struct rde_aspath *); void nexthop_unlink(struct rde_aspath *); int nexthop_delete(struct nexthop *); -@@ -415,12 +428,15 @@ int up_generate(struct rde_peer *, str +@@ -415,12 +431,15 @@ int up_generate(struct rde_peer *, str void up_generate_updates(struct filter_head *, struct rde_peer *, struct prefix *, struct prefix *); void up_generate_default(struct filter_head *, struct rde_peer *, @@ -168,7 +217,7 @@ diff -u -p -r1.1.1.8 -r1.1.1.10 /* rde_prefix.c */ #define pt_empty(pt) ((pt)->refcnt == 0) -@@ -452,8 +468,7 @@ enum filter_actions rde_filter(u_int16_t +@@ -452,8 +471,7 @@ enum filter_actions rde_filter(u_int16_t struct rde_aspath *, struct bgpd_addr *, u_int8_t, struct rde_peer *, enum directions); void rde_apply_set(struct rde_aspath *, struct filter_set_head *, diff --git a/net/openbgpd/files/patch-bgpd_rde_attr.c b/net/openbgpd/files/patch-bgpd_rde_attr.c index f62d59f083f0..eccdc1e36c27 100644 --- a/net/openbgpd/files/patch-bgpd_rde_attr.c +++ b/net/openbgpd/files/patch-bgpd_rde_attr.c @@ -2,17 +2,17 @@ Index: bgpd/rde_attr.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_attr.c,v retrieving revision 1.1.1.6 -retrieving revision 1.5 -diff -u -p -r1.1.1.6 -r1.5 +retrieving revision 1.6 +diff -u -p -r1.1.1.6 -r1.6 --- bgpd/rde_attr.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/rde_attr.c 10 Apr 2010 12:16:23 -0000 1.5 ++++ bgpd/rde_attr.c 2 Jul 2011 16:06:38 -0000 1.6 @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_attr.c,v 1.79 2009/03/19 06:52:59 claudio Exp $ */ +/* $OpenBSD: rde_attr.c,v 1.83 2010/03/29 09:24:07 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> -@@ -17,7 +17,11 @@ +@@ -17,14 +17,22 @@ */ #include <sys/types.h> @@ -24,7 +24,8 @@ diff -u -p -r1.1.1.6 -r1.5 #include <sys/queue.h> #include <netinet/in.h> -@@ -25,6 +29,9 @@ + ++#include <limits.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -34,39 +35,143 @@ diff -u -p -r1.1.1.6 -r1.5 #include "bgpd.h" #include "rde.h" -@@ -971,15 +978,26 @@ aspath_match(struct aspath *a, enum as_s +@@ -63,7 +71,7 @@ attr_write(void *p, u_int16_t p_len, u_i + } + + int +-attr_writebuf(struct buf *buf, u_int8_t flags, u_int8_t type, void *data, ++attr_writebuf(struct ibuf *buf, u_int8_t flags, u_int8_t type, void *data, + u_int16_t data_len) + { + u_char hdr[4]; +@@ -80,9 +88,9 @@ attr_writebuf(struct buf *buf, u_int8_t + hdr[0] = flags; + hdr[1] = type; + +- if (buf_add(buf, hdr, flags & ATTR_EXTLEN ? 4 : 3) == -1) ++ if (ibuf_add(buf, hdr, flags & ATTR_EXTLEN ? 4 : 3) == -1) + return (-1); +- if (buf_add(buf, data, data_len) == -1) ++ if (ibuf_add(buf, data, data_len) == -1) + return (-1); return (0); } +@@ -146,8 +154,11 @@ attr_optadd(struct rde_aspath *asp, u_in + for (l = 0; l < asp->others_len; l++) { + if (asp->others[l] == NULL) + break; +- if (type == asp->others[l]->type) ++ if (type == asp->others[l]->type) { ++ if (a->refcnt == 0) ++ attr_put(a); + return (-1); ++ } + } + + /* add attribute to the table but first bump refcnt */ +@@ -405,6 +416,7 @@ aspath_verify(void *data, u_int16_t len, + u_int8_t *seg = data; + u_int16_t seg_size, as_size = 2; + u_int8_t seg_len, seg_type; ++ int err = 0; + if (len & 1) + /* odd length aspath are invalid */ +@@ -419,7 +431,15 @@ aspath_verify(void *data, u_int16_t len, + seg_type = seg[0]; + seg_len = seg[1]; + +- if (seg_type != AS_SET && seg_type != AS_SEQUENCE) ++ /* ++ * BGP confederations should not show up but consider them ++ * as a soft error which invalidates the path but keeps the ++ * bgp session running. ++ */ ++ if (seg_type == AS_CONFED_SEQUENCE || seg_type == AS_CONFED_SET) ++ err = AS_ERR_SOFT; ++ if (seg_type != AS_SET && seg_type != AS_SEQUENCE && ++ seg_type != AS_CONFED_SEQUENCE && seg_type != AS_CONFED_SET) + return (AS_ERR_TYPE); + + seg_size = 2 + as_size * seg_len; +@@ -431,7 +451,7 @@ aspath_verify(void *data, u_int16_t len, + /* empty aspath segments are not allowed */ + return (AS_ERR_BAD); + } +- return (0); /* aspath is valid but probably not loop free */ ++ return (err); /* aspath is valid but probably not loop free */ + } + + void +@@ -972,14 +992,62 @@ aspath_match(struct aspath *a, enum as_s + } + + int +-community_match(void *data, u_int16_t len, int as, int type) ++aspath_lenmatch(struct aspath *a, enum aslen_spec type, u_int aslen) + { +- u_int8_t *p = data; +- u_int16_t eas, etype; ++ u_int8_t *seg; ++ u_int32_t as, lastas = 0; ++ u_int count = 0; ++ u_int16_t len, seg_size; ++ u_int8_t i, seg_type, seg_len; ++ ++ if (type == ASLEN_MAX) { ++ if (aslen < aspath_count(a->data, a->len)) ++ return (1); ++ else ++ return (0); ++ } + +- len >>= 2; /* divide by four */ ++ /* type == ASLEN_SEQ */ ++ seg = a->data; ++ for (len = a->len; len > 0; len -= seg_size, seg += seg_size) { ++ seg_type = seg[0]; ++ seg_len = seg[1]; ++ seg_size = 2 + sizeof(u_int32_t) * seg_len; + +- for (; len > 0; len--) { ++ for (i = 0; i < seg_len; i++) { ++ /* what should we do with AS_SET? */ ++ as = aspath_extract(seg, i); ++ if (as == lastas) { ++ if (aslen < ++count) ++ return (1); ++ } else ++ count = 1; ++ lastas = as; ++ } ++ } ++ return (0); ++} ++ +/* + * Functions handling communities and extended communities. + */ + +int community_ext_matchone(struct filter_extcommunity *, u_int16_t, u_int64_t); + - int --community_match(void *data, u_int16_t len, int as, int type) ++int +community_match(struct rde_aspath *asp, int as, int type) - { -- u_int8_t *p = data; -- u_int16_t eas, etype; ++{ + struct attr *a; + u_int8_t *p; + u_int16_t eas, etype, len; - -- len >>= 2; /* divide by four */ ++ + a = attr_optget(asp, ATTR_COMMUNITIES); + if (a == NULL) + /* no communities, no match */ + return (0); - -- for (; len > 0; len--) { ++ + p = a->data; + for (len = a->len / 4; len > 0; len--) { eas = *p++; eas <<= 8; eas |= *p++; -@@ -1000,7 +1018,6 @@ community_set(struct rde_aspath *asp, in +@@ -1000,7 +1068,6 @@ community_set(struct rde_aspath *asp, in u_int8_t *p = NULL; unsigned int i, ncommunities = 0; u_int8_t f = ATTR_OPTIONAL|ATTR_TRANSITIVE; @@ -74,7 +179,7 @@ diff -u -p -r1.1.1.6 -r1.5 attr = attr_optget(asp, ATTR_COMMUNITIES); if (attr != NULL) { -@@ -1017,7 +1034,7 @@ community_set(struct rde_aspath *asp, in +@@ -1017,7 +1084,7 @@ community_set(struct rde_aspath *asp, in p += 4; } @@ -83,7 +188,7 @@ diff -u -p -r1.1.1.6 -r1.5 /* overflow */ return (0); -@@ -1032,11 +1049,10 @@ community_set(struct rde_aspath *asp, in +@@ -1032,11 +1099,10 @@ community_set(struct rde_aspath *asp, in if (attr != NULL) { memcpy(p + 4, attr->data, attr->len); f = attr->flags; @@ -96,7 +201,7 @@ diff -u -p -r1.1.1.6 -r1.5 free(p); return (1); -@@ -1049,7 +1065,7 @@ community_delete(struct rde_aspath *asp, +@@ -1049,7 +1115,7 @@ community_delete(struct rde_aspath *asp, u_int8_t *p, *n; u_int16_t l, len = 0; u_int16_t eas, etype; @@ -105,7 +210,7 @@ diff -u -p -r1.1.1.6 -r1.5 attr = attr_optget(asp, ATTR_COMMUNITIES); if (attr == NULL) -@@ -1100,10 +1116,250 @@ community_delete(struct rde_aspath *asp, +@@ -1100,10 +1166,250 @@ community_delete(struct rde_aspath *asp, } f = attr->flags; diff --git a/net/openbgpd/files/patch-bgpd_rde_decide.c b/net/openbgpd/files/patch-bgpd_rde_decide.c index 84cafd11beef..3ed963b194dc 100644 --- a/net/openbgpd/files/patch-bgpd_rde_decide.c +++ b/net/openbgpd/files/patch-bgpd_rde_decide.c @@ -2,10 +2,9 @@ Index: bgpd/rde_decide.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_decide.c,v retrieving revision 1.1.1.6 -retrieving revision 1.2 -diff -u -p -r1.1.1.6 -r1.2 +diff -u -p -r1.1.1.6 rde_decide.c --- bgpd/rde_decide.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/rde_decide.c 22 Oct 2009 15:12:21 -0000 1.2 ++++ bgpd/rde_decide.c 3 Jul 2011 04:44:36 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_decide.c,v 1.58 2009/06/29 14:10:13 claudio Exp $ */ +/* $OpenBSD: rde_decide.c,v 1.59 2009/08/06 08:53:11 claudio Exp $ */ @@ -43,3 +42,12 @@ diff -u -p -r1.1.1.6 -r1.2 (xp->aspath->nexthop != NULL && xp->aspath->nexthop->state != NEXTHOP_REACH)) /* xp is ineligible */ +@@ -263,7 +269,7 @@ prefix_evaluate(struct prefix *p, struct + */ + rde_generate_updates(re->ribid, xp, re->active); + if ((re->flags & F_RIB_NOFIB) == 0) +- rde_send_kroute(xp, re->active); ++ rde_send_kroute(xp, re->active, re->ribid); + + re->active = xp; + if (xp != NULL) diff --git a/net/openbgpd/files/patch-bgpd_rde_filter.c b/net/openbgpd/files/patch-bgpd_rde_filter.c index e3cd6712b9f6..b4fe8982b949 100644 --- a/net/openbgpd/files/patch-bgpd_rde_filter.c +++ b/net/openbgpd/files/patch-bgpd_rde_filter.c @@ -2,10 +2,10 @@ Index: bgpd/rde_filter.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_filter.c,v retrieving revision 1.1.1.7 -retrieving revision 1.6 -diff -u -p -r1.1.1.7 -r1.6 +retrieving revision 1.7 +diff -u -p -r1.1.1.7 -r1.7 --- bgpd/rde_filter.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/rde_filter.c 10 Apr 2010 12:16:23 -0000 1.6 ++++ bgpd/rde_filter.c 2 Jul 2011 16:06:38 -0000 1.7 @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_filter.c,v 1.56 2009/06/06 01:10:29 claudio Exp $ */ +/* $OpenBSD: rde_filter.c,v 1.62 2010/03/05 15:25:00 claudio Exp $ */ @@ -18,10 +18,10 @@ diff -u -p -r1.1.1.7 -r1.6 + if (asp->flags & F_ATTR_PARSE_ERR) + /* -+ * don't try to filter bad updates but let them through ++ * don't try to filter bad updates just deny them + * so they act as implicit withdraws + */ -+ return (action); ++ return (ACTION_DENY); + TAILQ_FOREACH(f, rules, entry) { if (dir != f->dir) @@ -71,12 +71,51 @@ diff -u -p -r1.1.1.7 -r1.6 } } } -@@ -281,12 +299,17 @@ rde_filter_match(struct filter_rule *f, +@@ -251,11 +269,21 @@ int + rde_filter_match(struct filter_rule *f, struct rde_aspath *asp, + struct bgpd_addr *prefix, u_int8_t plen, struct rde_peer *peer) + { +- int as, type; ++ u_int32_t pas; ++ int cas, type; + +- if (asp != NULL && f->match.as.type != AS_NONE) +- if (aspath_match(asp->aspath, f->match.as.type, +- f->match.as.as) == 0) ++ if (asp != NULL && f->match.as.type != AS_NONE) { ++ if (f->match.as.flags & AS_FLAG_NEIGHBORAS) ++ pas = peer->conf.remote_as; ++ else ++ pas = f->match.as.as; ++ if (aspath_match(asp->aspath, f->match.as.type, pas) == 0) ++ return (0); ++ } ++ ++ if (asp != NULL && f->match.aslen.type != ASLEN_NONE) ++ if (aspath_lenmatch(asp->aspath, f->match.aslen.type, ++ f->match.aslen.aslen) == 0) + return (0); + + if (asp != NULL && f->match.community.as != COMMUNITY_UNSET) { +@@ -263,10 +291,10 @@ rde_filter_match(struct filter_rule *f, + case COMMUNITY_ERROR: + fatalx("rde_apply_set bad community string"); + case COMMUNITY_NEIGHBOR_AS: +- as = peer->conf.remote_as; ++ cas = peer->conf.remote_as; + break; + default: +- as = f->match.community.as; ++ cas = f->match.community.as; + break; + } + +@@ -281,12 +309,17 @@ rde_filter_match(struct filter_rule *f, break; } - if (rde_filter_community(asp, as, type) == 0) -+ if (community_match(asp, as, type) == 0) ++ if (community_match(asp, cas, type) == 0) return (0); } + if (asp != NULL && @@ -92,7 +131,7 @@ diff -u -p -r1.1.1.7 -r1.6 /* don't use IPv4 rules for IPv6 and vice versa */ return (0); -@@ -322,7 +345,7 @@ rde_filter_match(struct filter_rule *f, +@@ -322,7 +355,7 @@ rde_filter_match(struct filter_rule *f, } else if (f->match.prefixlen.op != OP_NONE) { /* only prefixlen without a prefix */ @@ -101,7 +140,7 @@ diff -u -p -r1.1.1.7 -r1.6 /* don't use IPv4 rules for IPv6 and vice versa */ return (0); -@@ -356,19 +379,6 @@ rde_filter_match(struct filter_rule *f, +@@ -356,19 +389,6 @@ rde_filter_match(struct filter_rule *f, } int @@ -121,7 +160,7 @@ diff -u -p -r1.1.1.7 -r1.6 rde_filter_equal(struct filter_head *a, struct filter_head *b, struct rde_peer *peer, enum directions dir) { -@@ -476,6 +486,12 @@ filterset_cmp(struct filter_set *a, stru +@@ -476,6 +496,12 @@ filterset_cmp(struct filter_set *a, stru return (a->action.community.type - b->action.community.type); } @@ -134,7 +173,7 @@ diff -u -p -r1.1.1.7 -r1.6 if (a->type == ACTION_SET_NEXTHOP && b->type == ACTION_SET_NEXTHOP) { /* * This is the only interesting case, all others are considered -@@ -483,7 +499,7 @@ filterset_cmp(struct filter_set *a, stru +@@ -483,13 +509,29 @@ filterset_cmp(struct filter_set *a, stru * reject it at the same time. Allow one IPv4 and one IPv6 * per filter set or only one of the other nexthop modifiers. */ @@ -143,7 +182,29 @@ diff -u -p -r1.1.1.7 -r1.6 } /* equal */ -@@ -574,6 +590,19 @@ filterset_equal(struct filter_set_head * + return (0); + } + ++void ++filterset_move(struct filter_set_head *source, struct filter_set_head *dest) ++{ ++ struct filter_set *s; ++ ++ TAILQ_INIT(dest); ++ ++ if (source == NULL) ++ return; ++ ++ while ((s = TAILQ_FIRST(source)) != NULL) { ++ TAILQ_REMOVE(source, s, entry); ++ TAILQ_INSERT_TAIL(dest, s, entry); ++ } ++} ++ + int + filterset_equal(struct filter_set_head *ah, struct filter_set_head *bh) + { +@@ -574,6 +616,19 @@ filterset_equal(struct filter_set_head * if (strcmp(as, bs) == 0) continue; break; @@ -163,7 +224,7 @@ diff -u -p -r1.1.1.7 -r1.6 } /* compare failed */ return (0); -@@ -616,7 +645,14 @@ filterset_name(enum action_types type) +@@ -616,7 +671,14 @@ filterset_name(enum action_types type) case ACTION_RTLABEL: case ACTION_RTLABEL_ID: return ("rtlabel"); diff --git a/net/openbgpd/files/patch-bgpd_rde_rib.c b/net/openbgpd/files/patch-bgpd_rde_rib.c index edea241a977e..22d6f0ee0a48 100644 --- a/net/openbgpd/files/patch-bgpd_rde_rib.c +++ b/net/openbgpd/files/patch-bgpd_rde_rib.c @@ -2,10 +2,9 @@ Index: bgpd/rde_rib.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_rib.c,v retrieving revision 1.1.1.7 -retrieving revision 1.6 -diff -u -p -r1.1.1.7 -r1.6 +diff -u -p -r1.1.1.7 rde_rib.c --- bgpd/rde_rib.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/rde_rib.c 10 Apr 2010 12:16:23 -0000 1.6 ++++ bgpd/rde_rib.c 3 Jul 2011 04:45:31 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_rib.c,v 1.116 2009/06/29 14:13:48 claudio Exp $ */ +/* $OpenBSD: rde_rib.c,v 1.125 2010/04/07 09:44:11 claudio Exp $ */ @@ -29,7 +28,7 @@ diff -u -p -r1.1.1.7 -r1.6 /* RIB specific functions */ u_int16_t -rib_new(int id, char *name, u_int16_t flags) -+rib_new(char *name, u_int16_t flags) ++rib_new(char *name, u_int rtableid, u_int16_t flags) { struct rib *xribs; size_t newsize; @@ -46,7 +45,7 @@ diff -u -p -r1.1.1.7 -r1.6 } if (id == RIB_FAILED) -@@ -78,7 +81,7 @@ rib_new(int id, char *name, u_int16_t fl +@@ -78,9 +81,10 @@ rib_new(int id, char *name, u_int16_t fl bzero(&ribs[id], sizeof(struct rib)); strlcpy(ribs[id].name, name, sizeof(ribs[id].name)); RB_INIT(&ribs[id].rib); @@ -54,8 +53,11 @@ diff -u -p -r1.1.1.7 -r1.6 + ribs[id].state = RECONF_REINIT; ribs[id].id = id; ribs[id].flags = flags; ++ ribs[id].rtableid = rtableid; -@@ -173,15 +176,16 @@ rib_lookup(struct rib *rib, struct bgpd_ + return (id); + } +@@ -173,15 +177,16 @@ rib_lookup(struct rib *rib, struct bgpd_ struct rib_entry *re; int i; @@ -75,7 +77,15 @@ diff -u -p -r1.1.1.7 -r1.6 for (i = 128; i >= 0; i--) { re = rib_get(rib, addr, i); if (re != NULL) -@@ -254,7 +258,7 @@ rib_empty(struct rib_entry *re) +@@ -215,6 +220,7 @@ rib_add(struct rib *rib, struct bgpd_add + + if (RB_INSERT(rib_tree, &rib->rib, re) != NULL) { + log_warnx("rib_add: insert failed"); ++ free(re); + return (NULL); + } + +@@ -254,7 +260,7 @@ rib_empty(struct rib_entry *re) void rib_dump(struct rib *rib, void (*upcall)(struct rib_entry *, void *), @@ -84,7 +94,7 @@ diff -u -p -r1.1.1.7 -r1.6 { struct rib_context *ctx; -@@ -263,7 +267,7 @@ rib_dump(struct rib *rib, void (*upcall) +@@ -263,7 +269,7 @@ rib_dump(struct rib *rib, void (*upcall) ctx->ctx_rib = rib; ctx->ctx_upcall = upcall; ctx->ctx_arg = arg; @@ -93,7 +103,7 @@ diff -u -p -r1.1.1.7 -r1.6 rib_dump_r(ctx); } -@@ -280,7 +284,8 @@ rib_dump_r(struct rib_context *ctx) +@@ -280,7 +286,8 @@ rib_dump_r(struct rib_context *ctx) re = rib_restart(ctx); for (i = 0; re != NULL; re = RB_NEXT(rib_tree, unused, re)) { @@ -103,7 +113,7 @@ diff -u -p -r1.1.1.7 -r1.6 continue; if (ctx->ctx_count && i++ >= ctx->ctx_count && (re->flags & F_RIB_ENTRYLOCK) == 0) { -@@ -308,7 +313,7 @@ rib_restart(struct rib_context *ctx) +@@ -308,7 +315,7 @@ rib_restart(struct rib_context *ctx) re->flags &= ~F_RIB_ENTRYLOCK; /* find first non empty element */ @@ -112,7 +122,7 @@ diff -u -p -r1.1.1.7 -r1.6 re = RB_NEXT(rib_tree, unused, re); /* free the previously locked rib element if empty */ -@@ -632,11 +637,11 @@ prefix_compare(const struct bgpd_addr *a +@@ -632,11 +639,11 @@ prefix_compare(const struct bgpd_addr *a int i; u_int8_t m; @@ -128,7 +138,7 @@ diff -u -p -r1.1.1.7 -r1.6 if (prefixlen > 32) fatalx("prefix_cmp: bad IPv4 prefixlen"); mask = htonl(prefixlen2mask(prefixlen)); -@@ -645,7 +650,7 @@ prefix_compare(const struct bgpd_addr *a +@@ -645,7 +652,7 @@ prefix_compare(const struct bgpd_addr *a if (aa != ba) return (aa - ba); return (0); @@ -137,7 +147,7 @@ diff -u -p -r1.1.1.7 -r1.6 if (prefixlen > 128) fatalx("prefix_cmp: bad IPv6 prefixlen"); for (i = 0; i < prefixlen / 8; i++) -@@ -660,6 +665,24 @@ prefix_compare(const struct bgpd_addr *a +@@ -660,6 +667,24 @@ prefix_compare(const struct bgpd_addr *a (b->v6.s6_addr[prefixlen / 8] & m)); } return (0); @@ -162,7 +172,7 @@ diff -u -p -r1.1.1.7 -r1.6 default: fatalx("prefix_cmp: unknown af"); } -@@ -806,16 +829,33 @@ prefix_write(u_char *buf, int len, struc +@@ -806,16 +831,33 @@ prefix_write(u_char *buf, int len, struc { int totlen; @@ -203,7 +213,91 @@ diff -u -p -r1.1.1.7 -r1.6 } /* -@@ -1070,10 +1110,6 @@ nexthop_update(struct kroute_nexthop *ms +@@ -861,7 +903,7 @@ prefix_updateall(struct rde_aspath *asp, + */ + if ((p->rib->flags & F_RIB_NOFIB) == 0 && + p == p->rib->active) +- rde_send_kroute(p, NULL); ++ rde_send_kroute(p, NULL, p->rib->ribid); + continue; + } + +@@ -885,16 +927,12 @@ prefix_updateall(struct rde_aspath *asp, + void + prefix_destroy(struct prefix *p) + { +- struct rib_entry *re; + struct rde_aspath *asp; + +- re = p->rib; + asp = p->aspath; + prefix_unlink(p); + prefix_free(p); + +- if (rib_empty(re)) +- rib_remove(re); + if (path_empty(asp)) + path_destroy(asp); + } +@@ -907,7 +945,6 @@ prefix_network_clean(struct rde_peer *pe + { + struct rde_aspath *asp, *xasp; + struct prefix *p, *xp; +- struct pt_entry *pte; + + for (asp = LIST_FIRST(&peer->path_h); asp != NULL; asp = xasp) { + xasp = LIST_NEXT(asp, peer_l); +@@ -916,12 +953,8 @@ prefix_network_clean(struct rde_peer *pe + for (p = LIST_FIRST(&asp->prefix_h); p != NULL; p = xp) { + xp = LIST_NEXT(p, path_l); + if (reloadtime > p->lastchange) { +- pte = p->prefix; + prefix_unlink(p); + prefix_free(p); +- +- if (pt_empty(pte)) +- pt_remove(pte); + } + } + if (path_empty(asp)) +@@ -954,11 +987,11 @@ prefix_link(struct prefix *pref, struct + static void + prefix_unlink(struct prefix *pref) + { +- if (pref->rib) { +- /* make route decision */ +- LIST_REMOVE(pref, rib_l); +- prefix_evaluate(NULL, pref->rib); +- } ++ struct rib_entry *re = pref->rib; ++ ++ /* make route decision */ ++ LIST_REMOVE(pref, rib_l); ++ prefix_evaluate(NULL, re); + + LIST_REMOVE(pref, path_l); + PREFIX_COUNT(pref->aspath, -1); +@@ -966,6 +999,8 @@ prefix_unlink(struct prefix *pref) + pt_unref(pref->prefix); + if (pt_empty(pref->prefix)) + pt_remove(pref->prefix); ++ if (rib_empty(re)) ++ rib_remove(re); + + /* destroy all references to other objects */ + pref->aspath = NULL; +@@ -973,8 +1008,8 @@ prefix_unlink(struct prefix *pref) + pref->rib = NULL; + + /* +- * It's the caller's duty to remove empty aspath respectively pt_entry +- * structures. Also freeing the unlinked prefix is the caller's duty. ++ * It's the caller's duty to remove empty aspath structures. ++ * Also freeing the unlinked prefix is the caller's duty. + */ + } + +@@ -1070,10 +1105,6 @@ nexthop_update(struct kroute_nexthop *ms return; } @@ -214,7 +308,7 @@ diff -u -p -r1.1.1.7 -r1.6 oldstate = nh->state; if (msg->valid) nh->state = NEXTHOP_REACH; -@@ -1088,21 +1124,13 @@ nexthop_update(struct kroute_nexthop *ms +@@ -1088,21 +1119,13 @@ nexthop_update(struct kroute_nexthop *ms memcpy(&nh->true_nexthop, &msg->gateway, sizeof(nh->true_nexthop)); @@ -243,7 +337,7 @@ diff -u -p -r1.1.1.7 -r1.6 if (rde_noevaluate()) /* -@@ -1118,7 +1146,7 @@ nexthop_update(struct kroute_nexthop *ms +@@ -1118,7 +1141,7 @@ nexthop_update(struct kroute_nexthop *ms void nexthop_modify(struct rde_aspath *asp, struct bgpd_addr *nexthop, @@ -252,7 +346,7 @@ diff -u -p -r1.1.1.7 -r1.6 { struct nexthop *nh; -@@ -1138,7 +1166,7 @@ nexthop_modify(struct rde_aspath *asp, s +@@ -1138,7 +1161,7 @@ nexthop_modify(struct rde_aspath *asp, s asp->flags |= F_NEXTHOP_SELF; return; } @@ -261,7 +355,7 @@ diff -u -p -r1.1.1.7 -r1.6 return; nh = nexthop_get(nexthop); -@@ -1233,17 +1261,17 @@ nexthop_compare(struct nexthop *na, stru +@@ -1233,17 +1256,17 @@ nexthop_compare(struct nexthop *na, stru a = &na->exit_nexthop; b = &nb->exit_nexthop; @@ -284,7 +378,7 @@ diff -u -p -r1.1.1.7 -r1.6 return (memcmp(&a->v6, &b->v6, sizeof(struct in6_addr))); default: fatalx("nexthop_cmp: unknown af"); -@@ -1269,14 +1297,14 @@ nexthop_hash(struct bgpd_addr *nexthop) +@@ -1269,14 +1292,14 @@ nexthop_hash(struct bgpd_addr *nexthop) { u_int32_t h = 0; diff --git a/net/openbgpd/files/patch-bgpd_rde_update.c b/net/openbgpd/files/patch-bgpd_rde_update.c index bbd2c19ce25f..cbffb73387e5 100644 --- a/net/openbgpd/files/patch-bgpd_rde_update.c +++ b/net/openbgpd/files/patch-bgpd_rde_update.c @@ -2,17 +2,16 @@ Index: bgpd/rde_update.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_update.c,v retrieving revision 1.1.1.7 -retrieving revision 1.6 -diff -u -p -r1.1.1.7 -r1.6 +diff -u -p -r1.1.1.7 rde_update.c --- bgpd/rde_update.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/rde_update.c 14 Feb 2010 19:53:36 -0000 1.6 ++++ bgpd/rde_update.c 3 Jul 2011 04:45:50 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_update.c,v 1.68 2009/06/06 01:10:29 claudio Exp $ */ +/* $OpenBSD: rde_update.c,v 1.77 2010/01/13 06:02:37 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> -@@ -17,19 +17,26 @@ +@@ -17,19 +17,27 @@ */ #include <sys/types.h> #include <sys/queue.h> @@ -22,6 +21,7 @@ diff -u -p -r1.1.1.7 -r1.6 #include <sys/hash.h> +#endif /* defined(__FreeBSD__) */ ++#include <limits.h> #include <stdlib.h> #include <string.h> +#if defined(__FreeBSD__) /* limits.h */ @@ -41,7 +41,7 @@ diff -u -p -r1.1.1.7 -r1.6 /* update stuff. */ struct update_prefix { -@@ -65,10 +72,12 @@ RB_GENERATE(uptree_attr, update_attr, en +@@ -65,10 +73,12 @@ RB_GENERATE(uptree_attr, update_attr, en void up_init(struct rde_peer *peer) { @@ -58,7 +58,7 @@ diff -u -p -r1.1.1.7 -r1.6 RB_INIT(&peer->up_prefix); RB_INIT(&peer->up_attrs); peer->up_pcnt = 0; -@@ -103,8 +112,10 @@ up_clear(struct uplist_attr *updates, st +@@ -103,8 +113,10 @@ up_clear(struct uplist_attr *updates, st void up_down(struct rde_peer *peer) { @@ -71,7 +71,7 @@ diff -u -p -r1.1.1.7 -r1.6 RB_INIT(&peer->up_prefix); RB_INIT(&peer->up_attrs); -@@ -120,19 +131,19 @@ up_prefix_cmp(struct update_prefix *a, s +@@ -120,19 +132,19 @@ up_prefix_cmp(struct update_prefix *a, s { int i; @@ -96,7 +96,7 @@ diff -u -p -r1.1.1.7 -r1.6 i = memcmp(&a->prefix.v6, &b->prefix.v6, sizeof(struct in6_addr)); if (i > 0) -@@ -140,6 +151,25 @@ up_prefix_cmp(struct update_prefix *a, s +@@ -140,6 +152,25 @@ up_prefix_cmp(struct update_prefix *a, s if (i < 0) return (-1); break; @@ -122,7 +122,7 @@ diff -u -p -r1.1.1.7 -r1.6 default: fatalx("pt_prefix_cmp: unknown af"); } -@@ -174,18 +204,8 @@ up_add(struct rde_peer *peer, struct upd +@@ -174,18 +205,8 @@ up_add(struct rde_peer *peer, struct upd struct uplist_attr *upl = NULL; struct uplist_prefix *wdl = NULL; @@ -143,7 +143,7 @@ diff -u -p -r1.1.1.7 -r1.6 /* 1. search for attr */ if (a != NULL && (na = RB_FIND(uptree_attr, &peer->up_attrs, a)) == -@@ -270,21 +290,14 @@ up_test_update(struct rde_peer *peer, st +@@ -270,21 +291,14 @@ up_test_update(struct rde_peer *peer, st /* Do not send routes back to sender */ return (0); @@ -169,7 +169,7 @@ diff -u -p -r1.1.1.7 -r1.6 if (p->aspath->peer->conf.ebgp == 0 && peer->conf.ebgp == 0) { /* -@@ -325,13 +338,13 @@ up_test_update(struct rde_peer *peer, st +@@ -325,13 +339,13 @@ up_test_update(struct rde_peer *peer, st } /* well known communities */ @@ -186,7 +186,7 @@ diff -u -p -r1.1.1.7 -r1.6 COMMUNITY_WELLKNOWN, COMMUNITY_NO_EXPSUBCONFED)) return (0); -@@ -362,7 +375,7 @@ up_generate(struct rde_peer *peer, struc +@@ -362,7 +376,7 @@ up_generate(struct rde_peer *peer, struc if (ua == NULL) fatal("up_generate"); @@ -195,7 +195,7 @@ diff -u -p -r1.1.1.7 -r1.6 log_warnx("generation of bgp path attributes failed"); free(ua); return (-1); -@@ -444,18 +457,12 @@ up_generate_updates(struct filter_head * +@@ -444,18 +458,12 @@ up_generate_updates(struct filter_head * /* send a default route to the specified peer */ void up_generate_default(struct filter_head *rules, struct rde_peer *peer, @@ -216,7 +216,7 @@ diff -u -p -r1.1.1.7 -r1.6 return; asp = path_get(); -@@ -471,7 +478,7 @@ up_generate_default(struct filter_head * +@@ -471,7 +479,7 @@ up_generate_default(struct filter_head * /* filter as usual */ bzero(&addr, sizeof(addr)); @@ -225,7 +225,7 @@ diff -u -p -r1.1.1.7 -r1.6 if (rde_filter(peer->ribid, &fasp, rules, peer, asp, &addr, 0, NULL, DIR_OUT) == ACTION_DENY) { -@@ -491,6 +498,43 @@ up_generate_default(struct filter_head * +@@ -491,6 +499,43 @@ up_generate_default(struct filter_head * path_put(asp); } @@ -269,7 +269,7 @@ diff -u -p -r1.1.1.7 -r1.6 u_char up_attr_buf[4096]; /* only for IPv4 */ -@@ -551,28 +595,41 @@ up_get_nexthop(struct rde_peer *peer, st +@@ -551,28 +596,41 @@ up_get_nexthop(struct rde_peer *peer, st int up_generate_mp_reach(struct rde_peer *peer, struct update_attr *upa, @@ -319,7 +319,7 @@ diff -u -p -r1.1.1.7 -r1.6 &peer->remote_addr.v6, sizeof(struct in6_addr)))) memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, sizeof(struct in6_addr)); -@@ -603,6 +660,68 @@ up_generate_mp_reach(struct rde_peer *pe +@@ -603,6 +661,68 @@ up_generate_mp_reach(struct rde_peer *pe memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, sizeof(struct in6_addr)); return (0); @@ -388,7 +388,7 @@ diff -u -p -r1.1.1.7 -r1.6 default: break; } -@@ -611,7 +730,7 @@ up_generate_mp_reach(struct rde_peer *pe +@@ -611,7 +731,7 @@ up_generate_mp_reach(struct rde_peer *pe int up_generate_attr(struct rde_peer *peer, struct update_attr *upa, @@ -397,7 +397,7 @@ diff -u -p -r1.1.1.7 -r1.6 { struct attr *oa, *newaggr = NULL; u_char *pdata; -@@ -643,8 +762,8 @@ up_generate_attr(struct rde_peer *peer, +@@ -643,8 +763,8 @@ up_generate_attr(struct rde_peer *peer, wlen += r; len -= r; free(pdata); @@ -408,7 +408,7 @@ diff -u -p -r1.1.1.7 -r1.6 nexthop = up_get_nexthop(peer, a); if ((r = attr_write(up_attr_buf + wlen, len, ATTR_WELL_KNOWN, ATTR_NEXTHOP, &nexthop, 4)) == -1) -@@ -659,9 +778,11 @@ up_generate_attr(struct rde_peer *peer, +@@ -659,9 +779,11 @@ up_generate_attr(struct rde_peer *peer, /* * The old MED from other peers MUST not be announced to others * unless the MED is originating from us or the peer is an IBGP one. @@ -421,7 +421,7 @@ diff -u -p -r1.1.1.7 -r1.6 tmp32 = htonl(a->med); if ((r = attr_write(up_attr_buf + wlen, len, ATTR_OPTIONAL, ATTR_MED, &tmp32, 4)) == -1) -@@ -791,7 +912,7 @@ up_generate_attr(struct rde_peer *peer, +@@ -791,7 +913,7 @@ up_generate_attr(struct rde_peer *peer, /* write mp attribute to different buffer */ if (ismp) @@ -430,7 +430,7 @@ diff -u -p -r1.1.1.7 -r1.6 return (-1); /* the bgp path attributes are now stored in the global buf */ -@@ -810,6 +931,7 @@ up_dump_prefix(u_char *buf, int len, str +@@ -810,6 +932,7 @@ up_dump_prefix(u_char *buf, int len, str { struct update_prefix *upp; int r, wpos = 0; @@ -438,7 +438,7 @@ diff -u -p -r1.1.1.7 -r1.6 while ((upp = TAILQ_FIRST(prefix_head)) != NULL) { if ((r = prefix_write(buf + wpos, len - wpos, -@@ -820,13 +942,14 @@ up_dump_prefix(u_char *buf, int len, str +@@ -820,13 +943,14 @@ up_dump_prefix(u_char *buf, int len, str log_warnx("dequeuing update failed."); TAILQ_REMOVE(upp->prefix_h, upp, prefix_l); peer->up_pcnt--; @@ -460,7 +460,7 @@ diff -u -p -r1.1.1.7 -r1.6 } free(upp); } -@@ -844,16 +967,21 @@ up_dump_attrnlri(u_char *buf, int len, s +@@ -844,16 +968,21 @@ up_dump_attrnlri(u_char *buf, int len, s * It is possible that a queued path attribute has no nlri prefix. * Ignore and remove those path attributes. */ @@ -484,7 +484,7 @@ diff -u -p -r1.1.1.7 -r1.6 } else break; -@@ -884,7 +1012,7 @@ up_dump_attrnlri(u_char *buf, int len, s +@@ -884,7 +1013,7 @@ up_dump_attrnlri(u_char *buf, int len, s if (TAILQ_EMPTY(&upa->prefix_h)) { if (RB_REMOVE(uptree_attr, &peer->up_attrs, upa) == NULL) log_warnx("dequeuing update failed."); @@ -493,7 +493,7 @@ diff -u -p -r1.1.1.7 -r1.6 free(upa->attr); free(upa->mpattr); free(upa); -@@ -895,12 +1023,13 @@ up_dump_attrnlri(u_char *buf, int len, s +@@ -895,12 +1024,13 @@ up_dump_attrnlri(u_char *buf, int len, s } u_char * @@ -509,7 +509,7 @@ diff -u -p -r1.1.1.7 -r1.6 /* * reserve space for withdraw len, attr len, the attribute header -@@ -912,7 +1041,7 @@ up_dump_mp_unreach(u_char *buf, u_int16_ +@@ -912,7 +1042,7 @@ up_dump_mp_unreach(u_char *buf, u_int16_ return (NULL); datalen = up_dump_prefix(buf + wpos, *len - wpos, @@ -518,7 +518,7 @@ diff -u -p -r1.1.1.7 -r1.6 if (datalen == 0) return (NULL); -@@ -920,9 +1049,11 @@ up_dump_mp_unreach(u_char *buf, u_int16_ +@@ -920,9 +1050,11 @@ up_dump_mp_unreach(u_char *buf, u_int16_ /* prepend header, need to do it reverse */ /* safi & afi */ @@ -532,7 +532,7 @@ diff -u -p -r1.1.1.7 -r1.6 memcpy(buf + wpos, &tmp, sizeof(u_int16_t)); /* attribute length */ -@@ -959,33 +1090,39 @@ up_dump_mp_unreach(u_char *buf, u_int16_ +@@ -959,33 +1091,39 @@ up_dump_mp_unreach(u_char *buf, u_int16_ return (buf + wpos); } @@ -578,7 +578,7 @@ diff -u -p -r1.1.1.7 -r1.6 /* * reserve space for attr len, the attributes, the -@@ -993,12 +1130,12 @@ up_dump_mp_reach(u_char *buf, u_int16_t +@@ -993,12 +1131,12 @@ up_dump_mp_reach(u_char *buf, u_int16_t */ wpos = 2 + 2 + upa->attr_len + 4 + upa->mpattr_len; if (*len < wpos) @@ -593,7 +593,7 @@ diff -u -p -r1.1.1.7 -r1.6 if (upa->mpattr_len == 0 || upa->mpattr == NULL) fatalx("mulitprotocol update without MP attrs"); -@@ -1038,7 +1175,7 @@ up_dump_mp_reach(u_char *buf, u_int16_t +@@ -1038,7 +1176,7 @@ up_dump_mp_reach(u_char *buf, u_int16_t if (TAILQ_EMPTY(&upa->prefix_h)) { if (RB_REMOVE(uptree_attr, &peer->up_attrs, upa) == NULL) log_warnx("dequeuing update failed."); @@ -602,7 +602,7 @@ diff -u -p -r1.1.1.7 -r1.6 free(upa->attr); free(upa->mpattr); free(upa); -@@ -1046,6 +1183,5 @@ up_dump_mp_reach(u_char *buf, u_int16_t +@@ -1046,6 +1184,5 @@ up_dump_mp_reach(u_char *buf, u_int16_t } *len = datalen + 4; diff --git a/net/openbgpd/files/patch-bgpd_session.c b/net/openbgpd/files/patch-bgpd_session.c index b6659f236a79..6b29252645e7 100644 --- a/net/openbgpd/files/patch-bgpd_session.c +++ b/net/openbgpd/files/patch-bgpd_session.c @@ -2,40 +2,52 @@ Index: bgpd/session.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/session.c,v retrieving revision 1.1.1.8 -retrieving revision 1.7 -diff -u -p -r1.1.1.8 -r1.7 +retrieving revision 1.8 +diff -u -p -r1.1.1.8 -r1.8 --- bgpd/session.c 14 Feb 2010 20:19:57 -0000 1.1.1.8 -+++ bgpd/session.c 14 Feb 2010 19:53:36 -0000 1.7 ++++ bgpd/session.c 2 Jul 2011 16:06:38 -0000 1.8 @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.293 2009/06/07 05:56:24 eric Exp $ */ +/* $OpenBSD: session.c,v 1.304 2010/01/05 08:49:57 claudio Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> -@@ -52,6 +52,10 @@ +@@ -21,6 +21,8 @@ + + #include <sys/mman.h> + #include <sys/socket.h> ++#include <sys/time.h> ++#include <sys/resource.h> + #include <sys/un.h> + #include <net/if_types.h> + #include <netinet/in.h> +@@ -50,7 +52,12 @@ + #define PFD_PIPE_ROUTE_CTL 2 + #define PFD_SOCK_CTL 3 #define PFD_SOCK_RCTL 4 - #define PFD_LISTENERS_START 5 - +-#define PFD_LISTENERS_START 5 ++#define PFD_SOCK_PFKEY 5 ++#define PFD_LISTENERS_START 6 ++ +#if defined(__FreeBSD__) /* FreeBSD has no LINK_STATE_IS_UP macro. */ +#define LINK_STATE_IS_UP(_s) ((_s) >= LINK_STATE_UP) +#endif /* defined(__FreeBSD__) */ -+ + void session_sighdlr(int); int setup_listeners(u_int *); - void init_conf(struct bgpd_config *); -@@ -65,9 +69,8 @@ void session_accept(int); +@@ -65,9 +72,8 @@ void session_accept(int); int session_connect(struct peer *); void session_tcp_established(struct peer *); void session_capa_ann_none(struct peer *); -int session_capa_add(struct peer *, struct buf *, u_int8_t, u_int8_t, - u_int8_t *); -int session_capa_add_mp(struct buf *, u_int16_t, u_int8_t); -+int session_capa_add(struct buf *, u_int8_t, u_int8_t); -+int session_capa_add_mp(struct buf *, u_int8_t); ++int session_capa_add(struct ibuf *, u_int8_t, u_int8_t); ++int session_capa_add_mp(struct ibuf *, u_int8_t); struct bgp_msg *session_newmsg(enum msg_type, u_int16_t); int session_sendmsg(struct bgp_msg *, struct peer *); void session_open(struct peer *); -@@ -75,7 +78,7 @@ void session_keepalive(struct peer *); +@@ -75,7 +81,7 @@ void session_keepalive(struct peer *); void session_update(u_int32_t, void *, size_t); void session_notification(struct peer *, u_int8_t, u_int8_t, void *, ssize_t); @@ -44,7 +56,7 @@ diff -u -p -r1.1.1.8 -r1.7 int session_dispatch_msg(struct pollfd *, struct peer *); int parse_header(struct peer *, u_char *, u_int16_t *, u_int8_t *); int parse_open(struct peer *); -@@ -83,22 +86,22 @@ int parse_update(struct peer *); +@@ -83,22 +89,22 @@ int parse_update(struct peer *); int parse_refresh(struct peer *); int parse_notification(struct peer *); int parse_capabilities(struct peer *, u_char *, u_int16_t, u_int32_t *); @@ -76,7 +88,7 @@ diff -u -p -r1.1.1.8 -r1.7 int csock = -1, rcsock = -1; u_int peer_cnt; struct imsgbuf *ibuf_rde; -@@ -175,10 +178,8 @@ setup_listeners(u_int *la_cnt) +@@ -175,12 +181,11 @@ setup_listeners(u_int *la_cnt) } pid_t @@ -84,12 +96,16 @@ diff -u -p -r1.1.1.8 -r1.7 - struct network_head *net_l, struct filter_head *rules, - struct mrt_head *m_l, struct rib_names *rib_l, int pipe_m2s[2], - int pipe_s2r[2], int pipe_m2r[2], int pipe_s2rctl[2]) -+session_main(int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2], -+ int pipe_s2rctl[2], char *cname, char *rcname) ++session_main(int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2], ++ int pipe_s2rctl[2]) { - int nfds, timeout; +- int nfds, timeout; ++ struct rlimit rl; ++ int nfds, timeout, pfkeysock; unsigned int i, j, idx_peers, idx_listeners, idx_mrts; -@@ -189,19 +190,13 @@ session_main(struct bgpd_config *config, + pid_t pid; + u_int pfd_elms = 0, peer_l_elms = 0, mrt_l_elms = 0; +@@ -189,19 +194,13 @@ session_main(struct bgpd_config *config, u_int32_t ctl_queued; struct passwd *pw; struct peer *p, **peer_l = NULL, *last, *next; @@ -110,20 +126,36 @@ diff -u -p -r1.1.1.8 -r1.7 switch (pid = fork()) { case -1: fatal("cannot fork"); -@@ -212,10 +207,9 @@ session_main(struct bgpd_config *config, +@@ -211,13 +210,6 @@ session_main(struct bgpd_config *config, + return (pid); } - /* control socket is outside chroot */ +- /* control socket is outside chroot */ - if ((csock = control_init(0, conf->csock)) == -1) -+ if ((csock = control_init(0, cname)) == -1) - fatalx("control socket setup failed"); +- fatalx("control socket setup failed"); - if (conf->rcsock != NULL && - (rcsock = control_init(1, conf->rcsock)) == -1) -+ if (rcname != NULL && (rcsock = control_init(1, rcname)) == -1) - fatalx("control socket setup failed"); - +- fatalx("control socket setup failed"); +- if ((pw = getpwnam(BGPD_USER)) == NULL) -@@ -237,20 +231,18 @@ session_main(struct bgpd_config *config, + fatal(NULL); + +@@ -229,28 +221,31 @@ session_main(struct bgpd_config *config, + setproctitle("session engine"); + bgpd_process = PROC_SE; + +- if (pfkey_init(&sysdep) == -1) +- fatalx("pfkey setup failed"); ++ if (getrlimit(RLIMIT_NOFILE, &rl) == -1) ++ fatal("getrlimit"); ++ rl.rlim_cur = rl.rlim_max; ++ if (setrlimit(RLIMIT_NOFILE, &rl) == -1) ++ fatal("setrlimit"); ++ ++ pfkeysock = pfkey_init(&sysdep); + + if (setgroups(1, &pw->pw_gid) || + setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("can't drop privileges"); @@ -147,14 +179,14 @@ diff -u -p -r1.1.1.8 -r1.7 if ((ibuf_rde = malloc(sizeof(struct imsgbuf))) == NULL || (ibuf_rde_ctl = malloc(sizeof(struct imsgbuf))) == NULL || (ibuf_main = malloc(sizeof(struct imsgbuf))) == NULL) -@@ -258,37 +250,23 @@ session_main(struct bgpd_config *config, +@@ -258,37 +253,21 @@ session_main(struct bgpd_config *config, imsg_init(ibuf_rde, pipe_s2r[0]); imsg_init(ibuf_rde_ctl, pipe_s2rctl[0]); imsg_init(ibuf_main, pipe_m2s[1]); + TAILQ_INIT(&ctl_conns); - control_listen(csock); - control_listen(rcsock); +- control_listen(csock); +- control_listen(rcsock); LIST_INIT(&mrthead); + listener_cnt = 0; peer_cnt = 0; @@ -173,7 +205,7 @@ diff -u -p -r1.1.1.8 -r1.7 - filterset_free(&net->net.attrset); - free(net); - } -+ if ((conf = malloc(sizeof(struct bgpd_config))) == NULL) ++ if ((conf = calloc(1, sizeof(struct bgpd_config))) == NULL) + fatal(NULL); + if ((conf->listen_addrs = calloc(1, sizeof(struct listen_addrs))) == + NULL) @@ -194,7 +226,7 @@ diff -u -p -r1.1.1.8 -r1.7 while (session_quit == 0) { /* check for peers to be initialized or deleted */ -@@ -308,8 +286,9 @@ session_main(struct bgpd_config *config, +@@ -308,8 +287,9 @@ session_main(struct bgpd_config *config, /* reinit due? */ if (p->conf.reconf_action == RECONF_REINIT) { @@ -206,7 +238,7 @@ diff -u -p -r1.1.1.8 -r1.7 } /* deletion due? */ -@@ -317,7 +296,7 @@ session_main(struct bgpd_config *config, +@@ -317,7 +297,7 @@ session_main(struct bgpd_config *config, if (p->demoted) session_demote(p, -1); p->conf.demote_group[0] = 0; @@ -215,7 +247,7 @@ diff -u -p -r1.1.1.8 -r1.7 log_peer_warnx(&p->conf, "removed"); if (last != NULL) last->next = next; -@@ -346,9 +325,17 @@ session_main(struct bgpd_config *config, +@@ -346,9 +326,17 @@ session_main(struct bgpd_config *config, } mrt_cnt = 0; @@ -234,7 +266,39 @@ diff -u -p -r1.1.1.8 -r1.7 if (mrt_cnt > mrt_l_elms) { if ((newp = realloc(mrt_l, sizeof(struct mrt *) * -@@ -557,7 +544,7 @@ session_main(struct bgpd_config *config, +@@ -394,13 +382,15 @@ session_main(struct bgpd_config *config, + if (ctl_queued < SESSION_CTL_QUEUE_MAX) + /* + * Do not act as unlimited buffer. Don't read in more +- * messages if the ctl sockets are getting full. ++ * messages if the ctl sockets are getting full. + */ + pfd[PFD_PIPE_ROUTE_CTL].events = POLLIN; + pfd[PFD_SOCK_CTL].fd = csock; + pfd[PFD_SOCK_CTL].events = POLLIN; + pfd[PFD_SOCK_RCTL].fd = rcsock; + pfd[PFD_SOCK_RCTL].events = POLLIN; ++ pfd[PFD_SOCK_PFKEY].fd = pfkeysock; ++ pfd[PFD_SOCK_PFKEY].events = POLLIN; + + i = PFD_LISTENERS_START; + TAILQ_FOREACH(la, conf->listen_addrs, entry) { +@@ -534,6 +524,14 @@ session_main(struct bgpd_config *config, + ctl_cnt += control_accept(rcsock, 1); + } + ++ if (nfds > 0 && pfd[PFD_SOCK_PFKEY].revents & POLLIN) { ++ nfds--; ++ if (pfkey_read(pfkeysock, NULL) == -1) { ++ log_warnx("pfkey_read failed, exiting..."); ++ session_quit = 1; ++ } ++ } ++ + for (j = PFD_LISTENERS_START; nfds > 0 && j < idx_listeners; + j++) + if (pfd[j].revents & POLLIN) { +@@ -557,7 +555,7 @@ session_main(struct bgpd_config *config, while ((p = peers) != NULL) { peers = p->next; @@ -243,7 +307,19 @@ diff -u -p -r1.1.1.8 -r1.7 pfkey_remove(p); free(p); } -@@ -746,7 +733,6 @@ bgp_fsm(struct peer *peer, enum session_ +@@ -643,10 +641,9 @@ bgp_fsm(struct peer *peer, enum session_ + timer_stop(peer, Timer_IdleHold); + + /* allocate read buffer */ +- peer->rbuf = calloc(1, sizeof(struct buf_read)); ++ peer->rbuf = calloc(1, sizeof(struct ibuf_read)); + if (peer->rbuf == NULL) + fatal(NULL); +- peer->rbuf->wpos = 0; + + /* init write buffer */ + msgbuf_init(&peer->wbuf); +@@ -746,7 +743,6 @@ bgp_fsm(struct peer *peer, enum session_ /* ignore */ break; case EVNT_STOP: @@ -251,7 +327,17 @@ diff -u -p -r1.1.1.8 -r1.7 change_state(peer, STATE_IDLE, event); break; case EVNT_CON_CLOSED: -@@ -791,7 +777,6 @@ bgp_fsm(struct peer *peer, enum session_ +@@ -780,7 +776,8 @@ bgp_fsm(struct peer *peer, enum session_ + change_state(peer, STATE_IDLE, event); + break; + default: +- session_notification(peer, ERR_FSM, 0, NULL, 0); ++ session_notification(peer, ++ ERR_FSM, ERR_FSM_UNEX_OPENSENT, NULL, 0); + change_state(peer, STATE_IDLE, event); + break; + } +@@ -791,7 +788,6 @@ bgp_fsm(struct peer *peer, enum session_ /* ignore */ break; case EVNT_STOP: @@ -259,7 +345,17 @@ diff -u -p -r1.1.1.8 -r1.7 change_state(peer, STATE_IDLE, event); break; case EVNT_CON_CLOSED: -@@ -826,7 +811,6 @@ bgp_fsm(struct peer *peer, enum session_ +@@ -815,7 +811,8 @@ bgp_fsm(struct peer *peer, enum session_ + change_state(peer, STATE_IDLE, event); + break; + default: +- session_notification(peer, ERR_FSM, 0, NULL, 0); ++ session_notification(peer, ++ ERR_FSM, ERR_FSM_UNEX_OPENCONFIRM, NULL, 0); + change_state(peer, STATE_IDLE, event); + break; + } +@@ -826,7 +823,6 @@ bgp_fsm(struct peer *peer, enum session_ /* ignore */ break; case EVNT_STOP: @@ -267,7 +363,17 @@ diff -u -p -r1.1.1.8 -r1.7 change_state(peer, STATE_IDLE, event); break; case EVNT_CON_CLOSED: -@@ -923,6 +907,7 @@ change_state(struct peer *peer, enum ses +@@ -856,7 +852,8 @@ bgp_fsm(struct peer *peer, enum session_ + change_state(peer, STATE_IDLE, event); + break; + default: +- session_notification(peer, ERR_FSM, 0, NULL, 0); ++ session_notification(peer, ++ ERR_FSM, ERR_FSM_UNEX_ESTABLISHED, NULL, 0); + change_state(peer, STATE_IDLE, event); + break; + } +@@ -923,6 +920,7 @@ change_state(struct peer *peer, enum ses timer_stop(peer, Timer_ConnectRetry); timer_stop(peer, Timer_Keepalive); timer_stop(peer, Timer_Hold); @@ -275,7 +381,7 @@ diff -u -p -r1.1.1.8 -r1.7 timer_stop(peer, Timer_IdleHoldReset); session_close_connection(peer); msgbuf_clear(&peer->wbuf); -@@ -1069,7 +1054,7 @@ session_connect(struct peer *peer) +@@ -1069,7 +1067,7 @@ session_connect(struct peer *peer) if (peer->fd != -1) return (-1); @@ -284,7 +390,7 @@ diff -u -p -r1.1.1.8 -r1.7 IPPROTO_TCP)) == -1) { log_peer_warn(&peer->conf, "session_connect socket"); bgp_fsm(peer, EVNT_CON_OPENFAIL); -@@ -1100,8 +1085,7 @@ session_connect(struct peer *peer) +@@ -1100,8 +1098,7 @@ session_connect(struct peer *peer) peer->wbuf.fd = peer->fd; /* if update source is set we need to bind() */ @@ -294,7 +400,7 @@ diff -u -p -r1.1.1.8 -r1.7 if (bind(peer->fd, sa, sa->sa_len) == -1) { log_peer_warn(&peer->conf, "session_connect bind"); bgp_fsm(peer, EVNT_CON_OPENFAIL); -@@ -1139,42 +1123,50 @@ session_setup_socket(struct peer *p) +@@ -1139,42 +1136,50 @@ session_setup_socket(struct peer *p) int nodelay = 1; int bsize; @@ -375,7 +481,7 @@ diff -u -p -r1.1.1.8 -r1.7 } /* set TCP_NODELAY */ -@@ -1185,14 +1177,6 @@ session_setup_socket(struct peer *p) +@@ -1185,14 +1190,6 @@ session_setup_socket(struct peer *p) return (-1); } @@ -390,7 +496,7 @@ diff -u -p -r1.1.1.8 -r1.7 /* only increase bufsize (and thus window) if md5 or ipsec is in use */ if (p->conf.auth.method != AUTH_NONE) { /* try to increase bufsize. no biggie if it fails */ -@@ -1244,36 +1228,28 @@ session_tcp_established(struct peer *pee +@@ -1244,40 +1241,32 @@ session_tcp_established(struct peer *pee void session_capa_ann_none(struct peer *peer) { @@ -405,7 +511,7 @@ diff -u -p -r1.1.1.8 -r1.7 int -session_capa_add(struct peer *p, struct buf *opb, u_int8_t capa_code, - u_int8_t capa_len, u_int8_t *optparamlen) -+session_capa_add(struct buf *opb, u_int8_t capa_code, u_int8_t capa_len) ++session_capa_add(struct ibuf *opb, u_int8_t capa_code, u_int8_t capa_len) { - u_int8_t op_type, op_len, tot_len, errs = 0; + int errs = 0; @@ -415,15 +521,17 @@ diff -u -p -r1.1.1.8 -r1.7 - tot_len = sizeof(op_type) + sizeof(op_len) + op_len; - errs += buf_add(opb, &op_type, sizeof(op_type)); - errs += buf_add(opb, &op_len, sizeof(op_len)); - errs += buf_add(opb, &capa_code, sizeof(capa_code)); - errs += buf_add(opb, &capa_len, sizeof(capa_len)); +- errs += buf_add(opb, &capa_code, sizeof(capa_code)); +- errs += buf_add(opb, &capa_len, sizeof(capa_len)); - *optparamlen += tot_len; ++ errs += ibuf_add(opb, &capa_code, sizeof(capa_code)); ++ errs += ibuf_add(opb, &capa_len, sizeof(capa_len)); return (errs); } int -session_capa_add_mp(struct buf *buf, u_int16_t afi, u_int8_t safi) -+session_capa_add_mp(struct buf *buf, u_int8_t aid) ++session_capa_add_mp(struct ibuf *buf, u_int8_t aid) { - u_int8_t pad = 0; + u_int8_t safi, pad = 0; @@ -433,19 +541,72 @@ diff -u -p -r1.1.1.8 -r1.7 + if (aid2afi(aid, &afi, &safi) == -1) + fatalx("session_capa_add_mp: bad afi/safi pair"); afi = htons(afi); - errs += buf_add(buf, &afi, sizeof(afi)); - errs += buf_add(buf, &pad, sizeof(pad)); -@@ -1341,36 +1317,34 @@ session_open(struct peer *p) - struct buf *opb; +- errs += buf_add(buf, &afi, sizeof(afi)); +- errs += buf_add(buf, &pad, sizeof(pad)); +- errs += buf_add(buf, &safi, sizeof(safi)); ++ errs += ibuf_add(buf, &afi, sizeof(afi)); ++ errs += ibuf_add(buf, &pad, sizeof(pad)); ++ errs += ibuf_add(buf, &safi, sizeof(safi)); + + return (errs); + } +@@ -1287,23 +1276,22 @@ session_newmsg(enum msg_type msgtype, u_ + { + struct bgp_msg *msg; + struct msg_header hdr; +- struct buf *buf; ++ struct ibuf *buf; + int errs = 0; + + memset(&hdr.marker, 0xff, sizeof(hdr.marker)); + hdr.len = htons(len); + hdr.type = msgtype; + +- if ((buf = buf_open(len)) == NULL) ++ if ((buf = ibuf_open(len)) == NULL) + return (NULL); + +- errs += buf_add(buf, &hdr.marker, sizeof(hdr.marker)); +- errs += buf_add(buf, &hdr.len, sizeof(hdr.len)); +- errs += buf_add(buf, &hdr.type, sizeof(hdr.type)); +- +- if (errs > 0 || +- (msg = calloc(1, sizeof(*msg))) == NULL) { +- buf_free(buf); ++ errs += ibuf_add(buf, &hdr.marker, sizeof(hdr.marker)); ++ errs += ibuf_add(buf, &hdr.len, sizeof(hdr.len)); ++ errs += ibuf_add(buf, &hdr.type, sizeof(hdr.type)); ++ ++ if (errs || (msg = calloc(1, sizeof(*msg))) == NULL) { ++ ibuf_free(buf); + return (NULL); + } + +@@ -1329,7 +1317,7 @@ session_sendmsg(struct bgp_msg *msg, str + mrt_dump_bgp_msg(mrt, msg->buf->buf, msg->len, p); + } + +- buf_close(&p->wbuf, msg->buf); ++ ibuf_close(&p->wbuf, msg->buf); + free(msg); + return (0); + } +@@ -1338,40 +1326,38 @@ void + session_open(struct peer *p) + { + struct bgp_msg *buf; +- struct buf *opb; ++ struct ibuf *opb; struct msg_open msg; u_int16_t len; - u_int8_t optparamlen = 0; +- u_int errs = 0; + u_int8_t i, op_type, optparamlen = 0; - u_int errs = 0; ++ int errs = 0; - if ((opb = buf_dynamic(0, MAX_PKTSIZE - MSGSIZE_OPEN_MIN)) == NULL) { -+ if ((opb = buf_dynamic(0, UCHAR_MAX - sizeof(op_type) - ++ if ((opb = ibuf_dynamic(0, UCHAR_MAX - sizeof(op_type) - + sizeof(optparamlen))) == NULL) { bgp_fsm(p, EVNT_CON_FATAL); return; @@ -478,65 +639,120 @@ diff -u -p -r1.1.1.8 -r1.7 - bzero(&c, 2); c[0] = 0x80; /* we're always restarting */ - errs += session_capa_add(p, opb, CAPA_RESTART, 2, &optparamlen); +- errs += buf_add(opb, &c, 2); + c[1] = 0; + errs += session_capa_add(opb, CAPA_RESTART, 2); - errs += buf_add(opb, &c, 2); ++ errs += ibuf_add(opb, &c, 2); } -@@ -1379,10 +1353,14 @@ session_open(struct peer *p) + /* 4-bytes AS numbers, draft-ietf-idr-as4bytes-13 */ +@@ -1379,13 +1365,17 @@ session_open(struct peer *p) u_int32_t nas; nas = htonl(conf->as); - errs += session_capa_add(p, opb, CAPA_AS4BYTE, 4, &optparamlen); - errs += buf_add(opb, &nas, 4); + errs += session_capa_add(opb, CAPA_AS4BYTE, sizeof(nas)); -+ errs += buf_add(opb, &nas, sizeof(nas)); ++ errs += ibuf_add(opb, &nas, sizeof(nas)); } -+ if (buf_size(opb)) -+ optparamlen = buf_size(opb) + sizeof(op_type) + ++ if (ibuf_size(opb)) ++ optparamlen = ibuf_size(opb) + sizeof(op_type) + + sizeof(optparamlen); + len = MSGSIZE_OPEN_MIN + optparamlen; if (errs || (buf = session_newmsg(OPEN, len)) == NULL) { - buf_free(opb); -@@ -1405,8 +1383,13 @@ session_open(struct peer *p) - errs += buf_add(buf->buf, &msg.bgpid, sizeof(msg.bgpid)); - errs += buf_add(buf->buf, &msg.optparamlen, sizeof(msg.optparamlen)); - +- buf_free(opb); ++ ibuf_free(opb); + bgp_fsm(p, EVNT_CON_FATAL); + return; + } +@@ -1399,19 +1389,24 @@ session_open(struct peer *p) + msg.bgpid = conf->bgpid; /* is already in network byte order */ + msg.optparamlen = optparamlen; + +- errs += buf_add(buf->buf, &msg.version, sizeof(msg.version)); +- errs += buf_add(buf->buf, &msg.myas, sizeof(msg.myas)); +- errs += buf_add(buf->buf, &msg.holdtime, sizeof(msg.holdtime)); +- errs += buf_add(buf->buf, &msg.bgpid, sizeof(msg.bgpid)); +- errs += buf_add(buf->buf, &msg.optparamlen, sizeof(msg.optparamlen)); +- - if (optparamlen) - errs += buf_add(buf->buf, opb->buf, optparamlen); ++ errs += ibuf_add(buf->buf, &msg.version, sizeof(msg.version)); ++ errs += ibuf_add(buf->buf, &msg.myas, sizeof(msg.myas)); ++ errs += ibuf_add(buf->buf, &msg.holdtime, sizeof(msg.holdtime)); ++ errs += ibuf_add(buf->buf, &msg.bgpid, sizeof(msg.bgpid)); ++ errs += ibuf_add(buf->buf, &msg.optparamlen, sizeof(msg.optparamlen)); ++ + if (optparamlen) { + op_type = OPT_PARAM_CAPABILITIES; -+ optparamlen = buf_size(opb); -+ errs += buf_add(buf->buf, &op_type, sizeof(op_type)); -+ errs += buf_add(buf->buf, &optparamlen, sizeof(optparamlen)); -+ errs += buf_add(buf->buf, opb->buf, buf_size(opb)); ++ optparamlen = ibuf_size(opb); ++ errs += ibuf_add(buf->buf, &op_type, sizeof(op_type)); ++ errs += ibuf_add(buf->buf, &optparamlen, sizeof(optparamlen)); ++ errs += ibuf_add(buf->buf, opb->buf, ibuf_size(opb)); + } - buf_free(opb); +- buf_free(opb); ++ ibuf_free(opb); + +- if (errs > 0) { +- buf_free(buf->buf); ++ if (errs) { ++ ibuf_free(buf->buf); + free(buf); + bgp_fsm(p, EVNT_CON_FATAL); + return; +@@ -1459,8 +1454,8 @@ session_update(u_int32_t peerid, void *d + return; + } -@@ -1481,7 +1464,6 @@ session_notification(struct peer *p, u_i +- if (buf_add(buf->buf, data, datalen)) { +- buf_free(buf->buf); ++ if (ibuf_add(buf->buf, data, datalen)) { ++ ibuf_free(buf->buf); + free(buf); + bgp_fsm(p, EVNT_CON_FATAL); + return; +@@ -1480,29 +1475,27 @@ session_notification(struct peer *p, u_i + void *data, ssize_t datalen) { struct bgp_msg *buf; - u_int errs = 0; +- u_int errs = 0; - u_int8_t null8 = 0; ++ int errs = 0; if (p->stats.last_sent_errcode) /* some notification already sent */ return; -@@ -1493,10 +1475,7 @@ session_notification(struct peer *p, u_i + ++ log_notification(p, errcode, subcode, data, datalen, "sending"); ++ + if ((buf = session_newmsg(NOTIFICATION, + MSGSIZE_NOTIFICATION_MIN + datalen)) == NULL) { + bgp_fsm(p, EVNT_CON_FATAL); + return; } - errs += buf_add(buf->buf, &errcode, sizeof(errcode)); +- errs += buf_add(buf->buf, &errcode, sizeof(errcode)); - if (errcode == ERR_CEASE) - errs += buf_add(buf->buf, &null8, sizeof(null8)); - else - errs += buf_add(buf->buf, &subcode, sizeof(subcode)); -+ errs += buf_add(buf->buf, &subcode, sizeof(subcode)); ++ errs += ibuf_add(buf->buf, &errcode, sizeof(errcode)); ++ errs += ibuf_add(buf->buf, &subcode, sizeof(subcode)); if (datalen > 0) - errs += buf_add(buf->buf, data, datalen); -@@ -1521,23 +1500,29 @@ session_notification(struct peer *p, u_i +- errs += buf_add(buf->buf, data, datalen); ++ errs += ibuf_add(buf->buf, data, datalen); + +- if (errs > 0) { +- buf_free(buf->buf); ++ if (errs) { ++ ibuf_free(buf->buf); + free(buf); + bgp_fsm(p, EVNT_CON_FATAL); + return; +@@ -1521,23 +1514,29 @@ session_notification(struct peer *p, u_i int session_neighbor_rrefresh(struct peer *p) { @@ -572,7 +788,25 @@ diff -u -p -r1.1.1.8 -r1.7 if ((buf = session_newmsg(RREFRESH, MSGSIZE_RREFRESH)) == NULL) { bgp_fsm(p, EVNT_CON_FATAL); -@@ -1853,12 +1838,6 @@ parse_open(struct peer *peer) +@@ -1545,12 +1544,12 @@ session_rrefresh(struct peer *p, u_int16 + } + + afi = htons(afi); +- errs += buf_add(buf->buf, &afi, sizeof(afi)); +- errs += buf_add(buf->buf, &null8, sizeof(null8)); +- errs += buf_add(buf->buf, &safi, sizeof(safi)); ++ errs += ibuf_add(buf->buf, &afi, sizeof(afi)); ++ errs += ibuf_add(buf->buf, &null8, sizeof(null8)); ++ errs += ibuf_add(buf->buf, &safi, sizeof(safi)); + +- if (errs > 0) { +- buf_free(buf->buf); ++ if (errs) { ++ ibuf_free(buf->buf); + free(buf); + bgp_fsm(p, EVNT_CON_FATAL); + return; +@@ -1853,12 +1852,6 @@ parse_open(struct peer *peer) p += sizeof(short_as); as = peer->short_as = ntohs(short_as); @@ -585,7 +819,7 @@ diff -u -p -r1.1.1.8 -r1.7 memcpy(&oholdtime, p, sizeof(oholdtime)); p += sizeof(oholdtime); -@@ -1966,6 +1945,15 @@ parse_open(struct peer *peer) +@@ -1966,6 +1959,15 @@ parse_open(struct peer *peer) } } @@ -601,7 +835,7 @@ diff -u -p -r1.1.1.8 -r1.7 if (peer->conf.remote_as != as) { log_peer_warnx(&peer->conf, "peer sent wrong AS %s", log_as(as)); -@@ -1974,6 +1962,14 @@ parse_open(struct peer *peer) +@@ -1974,6 +1976,14 @@ parse_open(struct peer *peer) return (-1); } @@ -616,7 +850,7 @@ diff -u -p -r1.1.1.8 -r1.7 return (0); } -@@ -2008,24 +2004,35 @@ int +@@ -2008,24 +2018,35 @@ int parse_refresh(struct peer *peer) { u_char *p; @@ -658,7 +892,7 @@ diff -u -p -r1.1.1.8 -r1.7 return (-1); return (0); -@@ -2035,11 +2042,12 @@ int +@@ -2035,11 +2056,12 @@ int parse_notification(struct peer *peer) { u_char *p; @@ -672,7 +906,16 @@ diff -u -p -r1.1.1.8 -r1.7 /* just log */ p = peer->rbuf->rptr; -@@ -2094,8 +2102,8 @@ parse_notification(struct peer *peer) +@@ -2059,7 +2081,7 @@ parse_notification(struct peer *peer) + p += sizeof(subcode); + datalen -= sizeof(subcode); + +- log_notification(peer, errcode, subcode, p, datalen); ++ log_notification(peer, errcode, subcode, p, datalen, "received"); + peer->errcnt++; + + if (errcode == ERR_OPEN && subcode == ERR_OPEN_CAPA) { +@@ -2094,8 +2116,8 @@ parse_notification(struct peer *peer) datalen -= capa_len; switch (capa_code) { case CAPA_MP: @@ -683,7 +926,7 @@ diff -u -p -r1.1.1.8 -r1.7 log_peer_warnx(&peer->conf, "disabling multiprotocol capability"); break; -@@ -2139,13 +2147,14 @@ parse_notification(struct peer *peer) +@@ -2139,13 +2161,14 @@ parse_notification(struct peer *peer) int parse_capabilities(struct peer *peer, u_char *d, u_int16_t dlen, u_int32_t *as) { @@ -702,7 +945,7 @@ diff -u -p -r1.1.1.8 -r1.7 len = dlen; while (len > 0) { -@@ -2182,29 +2191,16 @@ parse_capabilities(struct peer *peer, u_ +@@ -2182,29 +2205,16 @@ parse_capabilities(struct peer *peer, u_ "expect len 4, len is %u", capa_len); return (-1); } @@ -740,7 +983,7 @@ diff -u -p -r1.1.1.8 -r1.7 break; case CAPA_REFRESH: peer->capa.peer.refresh = 1; -@@ -2232,6 +2228,37 @@ parse_capabilities(struct peer *peer, u_ +@@ -2232,6 +2242,37 @@ parse_capabilities(struct peer *peer, u_ return (0); } @@ -778,13 +1021,48 @@ diff -u -p -r1.1.1.8 -r1.7 void session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt) { -@@ -2337,10 +2364,16 @@ session_dispatch_imsg(struct imsgbuf *ib +@@ -2244,7 +2285,7 @@ session_dispatch_imsg(struct imsgbuf *ib + struct kif *kif; + u_char *data; + enum reconf_action reconf; +- int n, depend_ok; ++ int n, depend_ok, restricted; + u_int8_t errcode, subcode; + + if ((n = imsg_read(ibuf)) == -1) +@@ -2332,15 +2373,42 @@ session_dispatch_imsg(struct imsgbuf *ib + } + + break; ++ case IMSG_RECONF_CTRL: ++ if (idx != PFD_PIPE_MAIN) ++ fatalx("reconf request not from parent"); ++ if (imsg.hdr.len != IMSG_HEADER_SIZE + ++ sizeof(restricted)) ++ fatalx("IFINFO imsg with wrong len"); ++ memcpy(&restricted, imsg.data, sizeof(restricted)); ++ if (imsg.fd == -1) { ++ log_warnx("expected to receive fd for control " ++ "socket but didn't receive any"); ++ break; ++ } ++ if (restricted) { ++ control_shutdown(rcsock); ++ rcsock = imsg.fd; ++ control_listen(rcsock); ++ } else { ++ control_shutdown(csock); ++ csock = imsg.fd; ++ control_listen(csock); ++ } ++ break; + case IMSG_RECONF_DONE: + if (idx != PFD_PIPE_MAIN) fatalx("reconf request not from parent"); if (nconf == NULL) fatalx("got IMSG_RECONF_DONE but no config"); + conf->flags = nconf->flags; + conf->log = nconf->log; -+ conf->rtableid = nconf->rtableid; + conf->bgpid = nconf->bgpid; + conf->clusterid = nconf->clusterid; conf->as = nconf->as; @@ -796,7 +1074,7 @@ diff -u -p -r1.1.1.8 -r1.7 /* add new peers */ for (p = npeers; p != NULL; p = next) { -@@ -2408,7 +2441,8 @@ session_dispatch_imsg(struct imsgbuf *ib +@@ -2408,7 +2476,8 @@ session_dispatch_imsg(struct imsgbuf *ib bgp_fsm(p, EVNT_START); } else if (!depend_ok && p->depend_ok) { p->depend_ok = depend_ok; @@ -806,7 +1084,27 @@ diff -u -p -r1.1.1.8 -r1.7 } } break; -@@ -2612,29 +2646,23 @@ getpeerbydesc(const char *descr) +@@ -2456,10 +2525,10 @@ session_dispatch_imsg(struct imsgbuf *ib + } + break; + case IMSG_CTL_KROUTE: +- case IMSG_CTL_KROUTE6: + case IMSG_CTL_KROUTE_ADDR: + case IMSG_CTL_SHOW_NEXTHOP: + case IMSG_CTL_SHOW_INTERFACE: ++ case IMSG_CTL_SHOW_FIB_TABLES: + if (idx != PFD_PIPE_MAIN) + fatalx("ctl kroute request not from parent"); + control_imsg_relay(&imsg); +@@ -2469,7 +2538,6 @@ session_dispatch_imsg(struct imsgbuf *ib + case IMSG_CTL_SHOW_RIB_ATTR: + case IMSG_CTL_SHOW_RIB_MEM: + case IMSG_CTL_SHOW_NETWORK: +- case IMSG_CTL_SHOW_NETWORK6: + case IMSG_CTL_SHOW_NEIGHBOR: + if (idx != PFD_PIPE_ROUTE_CTL) + fatalx("ctl rib request not from RDE"); +@@ -2612,29 +2680,23 @@ getpeerbydesc(const char *descr) struct peer * getpeerbyip(struct sockaddr *ip) { @@ -843,7 +1141,7 @@ diff -u -p -r1.1.1.8 -r1.7 if (loose == NULL || loose->conf.remote_masklen < p->conf.remote_masklen) loose = p; -@@ -2653,21 +2681,19 @@ getpeerbyip(struct sockaddr *ip) +@@ -2653,21 +2715,19 @@ getpeerbyip(struct sockaddr *ip) break; } } @@ -872,7 +1170,7 @@ diff -u -p -r1.1.1.8 -r1.7 newpeer->rbuf = NULL; init_peer(newpeer); bgp_fsm(newpeer, EVNT_START); -@@ -2680,40 +2706,24 @@ getpeerbyip(struct sockaddr *ip) +@@ -2680,40 +2740,24 @@ getpeerbyip(struct sockaddr *ip) } int @@ -924,7 +1222,7 @@ diff -u -p -r1.1.1.8 -r1.7 return (0); } -@@ -2733,6 +2743,7 @@ getpeerbyid(u_int32_t peerid) +@@ -2733,6 +2777,7 @@ getpeerbyid(u_int32_t peerid) void session_down(struct peer *peer) { @@ -932,7 +1230,7 @@ diff -u -p -r1.1.1.8 -r1.7 peer->stats.last_updown = time(NULL); if (imsg_compose(ibuf_rde, IMSG_SESSION_DOWN, peer->conf.id, 0, -1, NULL, 0) == -1) -@@ -2748,35 +2759,12 @@ session_up(struct peer *p) +@@ -2748,35 +2793,12 @@ session_up(struct peer *p) &p->conf, sizeof(p->conf)) == -1) fatalx("imsg_compose error"); @@ -971,7 +1269,20 @@ diff -u -p -r1.1.1.8 -r1.7 p->stats.last_updown = time(NULL); if (imsg_compose(ibuf_rde, IMSG_SESSION_UP, p->conf.id, 0, -1, &sup, sizeof(sup)) == -1) -@@ -2795,34 +2783,6 @@ imsg_compose_rde(int type, pid_t pid, vo +@@ -2784,9 +2806,10 @@ session_up(struct peer *p) + } + + int +-imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen) ++imsg_compose_parent(int type, u_int32_t peerid, pid_t pid, void *data, ++ u_int16_t datalen) + { +- return (imsg_compose(ibuf_main, type, 0, pid, -1, data, datalen)); ++ return (imsg_compose(ibuf_main, type, peerid, pid, -1, data, datalen)); + } + + int +@@ -2795,34 +2818,6 @@ imsg_compose_rde(int type, pid_t pid, vo return (imsg_compose(ibuf_rde, type, 0, pid, -1, data, datalen)); } @@ -1006,7 +1317,7 @@ diff -u -p -r1.1.1.8 -r1.7 void session_demote(struct peer *p, int level) { -@@ -2837,3 +2797,19 @@ session_demote(struct peer *p, int level +@@ -2837,3 +2832,19 @@ session_demote(struct peer *p, int level p->demoted += level; } diff --git a/net/openbgpd/files/patch-bgpd_session.h b/net/openbgpd/files/patch-bgpd_session.h index 2d855c2e8b3a..4eb8dbce5f6b 100644 --- a/net/openbgpd/files/patch-bgpd_session.h +++ b/net/openbgpd/files/patch-bgpd_session.h @@ -2,17 +2,40 @@ Index: bgpd/session.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/session.h,v retrieving revision 1.1.1.7 -retrieving revision 1.1.1.8 -diff -u -p -r1.1.1.7 -r1.1.1.8 +retrieving revision 1.1.1.9 +diff -u -p -r1.1.1.7 -r1.1.1.9 --- bgpd/session.h 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/session.h 14 Feb 2010 20:27:06 -0000 1.1.1.8 ++++ bgpd/session.h 12 Jun 2011 10:44:25 -0000 1.1.1.9 @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.101 2009/06/05 20:26:38 claudio Exp $ */ -+/* $OpenBSD: session.h,v 1.104 2009/12/31 15:34:02 claudio Exp $ */ ++/* $OpenBSD: session.h,v 1.111 2010/12/09 13:50:41 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -189,6 +189,7 @@ struct peer { +@@ -94,6 +94,13 @@ enum suberr_open { + ERR_OPEN_CAPA + }; + ++enum suberr_fsm { ++ ERR_FSM_UNSPECIFIC = 0, ++ ERR_FSM_UNEX_OPENSENT, ++ ERR_FSM_UNEX_OPENCONFIRM, ++ ERR_FSM_UNEX_ESTABLISHED ++}; ++ + enum opt_params { + OPT_PARAM_NONE, + OPT_PARAM_AUTH, +@@ -109,7 +116,7 @@ enum capa_codes { + }; + + struct bgp_msg { +- struct buf *buf; ++ struct ibuf *buf; + enum msg_type type; + u_int16_t len; + }; +@@ -189,6 +196,7 @@ struct peer { struct { struct capabilities ann; struct capabilities peer; @@ -20,7 +43,16 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 } capa; struct { struct bgpd_addr local_addr; -@@ -217,7 +218,7 @@ struct peer { +@@ -201,7 +209,7 @@ struct peer { + struct sockaddr_storage sa_remote; + struct peer_timer_head timers; + struct msgbuf wbuf; +- struct buf_read *rbuf; ++ struct ibuf_read *rbuf; + struct peer *next; + int fd; + int lasterr; +@@ -217,7 +225,7 @@ struct peer { u_int8_t passive; }; @@ -29,7 +61,7 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 struct ctl_timer { enum Timer type; -@@ -226,16 +227,14 @@ struct ctl_timer { +@@ -226,38 +234,36 @@ struct ctl_timer { /* session.c */ void session_socket_blockmode(int, enum blockmodes); @@ -37,19 +69,36 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 - struct network_head *, struct filter_head *, - struct mrt_head *, struct rib_names *, - int[2], int[2], int[2], int[2]); -+pid_t session_main(int[2], int[2], int[2], int[2], char *, char *); ++pid_t session_main(int[2], int[2], int[2], int[2]); void bgp_fsm(struct peer *, enum session_events); int session_neighbor_rrefresh(struct peer *p); struct peer *getpeerbyaddr(struct bgpd_addr *); struct peer *getpeerbydesc(const char *); - int imsg_compose_parent(int, pid_t, void *, u_int16_t); +-int imsg_compose_parent(int, pid_t, void *, u_int16_t); ++int imsg_compose_parent(int, u_int32_t, pid_t, void *, u_int16_t); int imsg_compose_rde(int, pid_t, void *, u_int16_t); +void session_stop(struct peer *, u_int8_t); /* log.c */ char *log_fmt_peer(const struct peer_config *); -@@ -255,9 +254,7 @@ int merge_config(struct bgpd_config *, + void log_statechange(struct peer *, enum session_state, + enum session_events); + void log_notification(const struct peer *, u_int8_t, u_int8_t, +- u_char *, u_int16_t); ++ u_char *, u_int16_t, const char *); + void log_conn_attempt(const struct peer *, struct sockaddr *); + + /* parse.y */ + int parse_config(char *, struct bgpd_config *, struct mrt_head *, +- struct peer **, struct network_head *, struct filter_head *); ++ struct peer **, struct network_head *, struct filter_head *, ++ struct rdomain_head *); + + /* config.c */ + int merge_config(struct bgpd_config *, struct bgpd_config *, + struct peer *, struct listen_addrs *); void prepare_listeners(struct bgpd_config *); ++int get_mpe_label(struct rdomain *); /* rde.c */ -pid_t rde_main(struct bgpd_config *, struct peer *, struct network_head *, @@ -59,3 +108,20 @@ diff -u -p -r1.1.1.7 -r1.1.1.8 /* control.c */ int control_init(int, char *); +@@ -267,6 +273,7 @@ int control_dispatch_msg(struct pollfd * + unsigned int control_accept(int, int); + + /* pfkey.c */ ++int pfkey_read(int, struct sadb_msg *); + int pfkey_establish(struct peer *); + int pfkey_remove(struct peer *); + int pfkey_init(struct bgpd_sysdep *); +@@ -274,7 +281,7 @@ int pfkey_init(struct bgpd_sysdep *); + /* printconf.c */ + void print_config(struct bgpd_config *, struct rib_names *, + struct network_head *, struct peer *, struct filter_head *, +- struct mrt_head *); ++ struct mrt_head *, struct rdomain_head *); + + /* carp.c */ + int carp_demote_init(char *, int); diff --git a/net/openbgpd/files/patch-bgpd_timer.c b/net/openbgpd/files/patch-bgpd_timer.c new file mode 100644 index 000000000000..1bace94e1998 --- /dev/null +++ b/net/openbgpd/files/patch-bgpd_timer.c @@ -0,0 +1,23 @@ +Index: bgpd/timer.c +=================================================================== +RCS file: /home/cvs/private/hrs/openbgpd/bgpd/timer.c,v +retrieving revision 1.1.1.2 +retrieving revision 1.1.1.3 +diff -u -p -r1.1.1.2 -r1.1.1.3 +--- bgpd/timer.c 9 Jul 2009 16:49:54 -0000 1.1.1.2 ++++ bgpd/timer.c 12 Jun 2011 10:44:25 -0000 1.1.1.3 +@@ -1,4 +1,4 @@ +-/* $OpenBSD: timer.c,v 1.13 2009/01/21 20:32:53 henning Exp $ */ ++/* $OpenBSD: timer.c,v 1.14 2010/10/24 17:20:08 deraadt Exp $ */ + + /* + * Copyright (c) 2003-2007 Henning Brauer <henning@openbsd.org> +@@ -43,7 +43,7 @@ timer_get(struct peer *p, enum Timer tim + + TAILQ_FOREACH(pt, &p->timers, entry) + if (pt->type == timer) +- break; ++ break; + + return (pt); + } diff --git a/net/openbgpd/files/patch-bgpd_util.c b/net/openbgpd/files/patch-bgpd_util.c index 88c95a8423d8..213c90a2276e 100644 --- a/net/openbgpd/files/patch-bgpd_util.c +++ b/net/openbgpd/files/patch-bgpd_util.c @@ -2,10 +2,10 @@ Index: bgpd/util.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/util.c,v retrieving revision 1.1.1.6 -retrieving revision 1.5 -diff -u -p -r1.1.1.6 -r1.5 +retrieving revision 1.6 +diff -u -p -r1.1.1.6 -r1.6 --- bgpd/util.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/util.c 10 Apr 2010 12:16:23 -0000 1.5 ++++ bgpd/util.c 2 Jul 2011 16:06:38 -0000 1.6 @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.6 2009/06/12 16:42:53 claudio Exp $ */ +/* $OpenBSD: util.c,v 1.11 2010/03/29 09:04:43 claudio Exp $ */ @@ -22,7 +22,13 @@ diff -u -p -r1.1.1.6 -r1.5 #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> -@@ -32,11 +35,24 @@ const char * +@@ -28,15 +31,30 @@ + #include "bgpd.h" + #include "rde.h" + ++const char *aspath_delim(u_int8_t, int); ++ + const char * log_addr(const struct bgpd_addr *addr) { static char buf[48]; @@ -50,7 +56,7 @@ diff -u -p -r1.1.1.6 -r1.5 } const char * -@@ -90,6 +106,64 @@ log_as(u_int32_t as) +@@ -90,6 +108,96 @@ log_as(u_int32_t as) return (buf); } @@ -107,15 +113,81 @@ diff -u -p -r1.1.1.6 -r1.5 + case EXT_COMMUNITY_BGP_COLLECT: + return ("bdc"); /* bgp data collection */ + default: -+ snprintf(etype, sizeof(etype), "[%i]", (int)subtype); ++ snprintf(etype, sizeof(etype), "[%u]", subtype); + return (etype); + } +} + ++const char * ++aspath_delim(u_int8_t seg_type, int closing) ++{ ++ static char db[8]; ++ ++ switch (seg_type) { ++ case AS_SET: ++ if (!closing) ++ return ("{ "); ++ else ++ return (" }"); ++ case AS_SEQUENCE: ++ return (""); ++ case AS_CONFED_SEQUENCE: ++ if (!closing) ++ return ("( "); ++ else ++ return (" )"); ++ case AS_CONFED_SET: ++ if (!closing) ++ return ("[ "); ++ else ++ return (" ]"); ++ default: ++ if (!closing) ++ snprintf(db, sizeof(db), "!%u ", seg_type); ++ else ++ snprintf(db, sizeof(db), " !%u", seg_type); ++ return (db); ++ } ++} ++ int aspath_snprint(char *buf, size_t size, void *data, u_int16_t len) { -@@ -276,3 +350,115 @@ inet6applymask(struct in6_addr *dest, co +@@ -118,16 +226,10 @@ aspath_snprint(char *buf, size_t size, v + seg_len = seg[1]; + seg_size = 2 + sizeof(u_int32_t) * seg_len; + +- if (seg_type == AS_SET) { +- if (total_size != 0) +- r = snprintf(buf, size, " { "); +- else +- r = snprintf(buf, size, "{ "); +- UPDATE(); +- } else if (total_size != 0) { +- r = snprintf(buf, size, " "); +- UPDATE(); +- } ++ r = snprintf(buf, size, "%s%s", ++ total_size != 0 ? " " : "", ++ aspath_delim(seg_type, 0)); ++ UPDATE(); + + for (i = 0; i < seg_len; i++) { + r = snprintf(buf, size, "%s", +@@ -138,10 +240,8 @@ aspath_snprint(char *buf, size_t size, v + UPDATE(); + } + } +- if (seg_type == AS_SET) { +- r = snprintf(buf, size, " }"); +- UPDATE(); +- } ++ r = snprintf(buf, size, "%s", aspath_delim(seg_type, 1)); ++ UPDATE(); + } + /* ensure that we have a valid C-string especially for empty as path */ + if (size > 0) +@@ -276,3 +376,115 @@ inet6applymask(struct in6_addr *dest, co for (i = 0; i < 16; i++) dest->s6_addr[i] = src->s6_addr[i] & mask.s6_addr[i]; } diff --git a/net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c b/net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c new file mode 100644 index 000000000000..7d807d2259d9 --- /dev/null +++ b/net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c @@ -0,0 +1,310 @@ +Index: openbsd-compat/imsg-buffer.c +=================================================================== +RCS file: openbsd-compat/imsg-buffer.c +diff -N openbsd-compat/imsg-buffer.c +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ openbsd-compat/imsg-buffer.c 2 Jul 2011 16:06:38 -0000 1.1 +@@ -0,0 +1,303 @@ ++/* $OpenBSD: imsg-buffer.c,v 1.1 2010/05/26 16:44:32 nicm Exp $ */ ++ ++/* ++ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include <sys/param.h> ++#include <sys/queue.h> ++#include <sys/socket.h> ++#include <sys/uio.h> ++ ++#include <errno.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++ ++#include "imsg.h" ++ ++int ibuf_realloc(struct ibuf *, size_t); ++void ibuf_enqueue(struct msgbuf *, struct ibuf *); ++void ibuf_dequeue(struct msgbuf *, struct ibuf *); ++ ++struct ibuf * ++ibuf_open(size_t len) ++{ ++ struct ibuf *buf; ++ ++ if ((buf = calloc(1, sizeof(struct ibuf))) == NULL) ++ return (NULL); ++ if ((buf->buf = malloc(len)) == NULL) { ++ free(buf); ++ return (NULL); ++ } ++ buf->size = buf->max = len; ++ buf->fd = -1; ++ ++ return (buf); ++} ++ ++struct ibuf * ++ibuf_dynamic(size_t len, size_t max) ++{ ++ struct ibuf *buf; ++ ++ if (max < len) ++ return (NULL); ++ ++ if ((buf = ibuf_open(len)) == NULL) ++ return (NULL); ++ ++ if (max > 0) ++ buf->max = max; ++ ++ return (buf); ++} ++ ++int ++ibuf_realloc(struct ibuf *buf, size_t len) ++{ ++ u_char *b; ++ ++ /* on static buffers max is eq size and so the following fails */ ++ if (buf->wpos + len > buf->max) { ++ errno = ENOMEM; ++ return (-1); ++ } ++ ++ b = realloc(buf->buf, buf->wpos + len); ++ if (b == NULL) ++ return (-1); ++ buf->buf = b; ++ buf->size = buf->wpos + len; ++ ++ return (0); ++} ++ ++int ++ibuf_add(struct ibuf *buf, const void *data, size_t len) ++{ ++ if (buf->wpos + len > buf->size) ++ if (ibuf_realloc(buf, len) == -1) ++ return (-1); ++ ++ memcpy(buf->buf + buf->wpos, data, len); ++ buf->wpos += len; ++ return (0); ++} ++ ++void * ++ibuf_reserve(struct ibuf *buf, size_t len) ++{ ++ void *b; ++ ++ if (buf->wpos + len > buf->size) ++ if (ibuf_realloc(buf, len) == -1) ++ return (NULL); ++ ++ b = buf->buf + buf->wpos; ++ buf->wpos += len; ++ return (b); ++} ++ ++void * ++ibuf_seek(struct ibuf *buf, size_t pos, size_t len) ++{ ++ /* only allowed to seek in already written parts */ ++ if (pos + len > buf->wpos) ++ return (NULL); ++ ++ return (buf->buf + pos); ++} ++ ++size_t ++ibuf_size(struct ibuf *buf) ++{ ++ return (buf->wpos); ++} ++ ++size_t ++ibuf_left(struct ibuf *buf) ++{ ++ return (buf->max - buf->wpos); ++} ++ ++void ++ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf) ++{ ++ ibuf_enqueue(msgbuf, buf); ++} ++ ++int ++ibuf_write(struct msgbuf *msgbuf) ++{ ++ struct iovec iov[IOV_MAX]; ++ struct ibuf *buf; ++ unsigned int i = 0; ++ ssize_t n; ++ ++ bzero(&iov, sizeof(iov)); ++ TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { ++ if (i >= IOV_MAX) ++ break; ++ iov[i].iov_base = buf->buf + buf->rpos; ++ iov[i].iov_len = buf->wpos - buf->rpos; ++ i++; ++ } ++ ++ if ((n = writev(msgbuf->fd, iov, i)) == -1) { ++ if (errno == EAGAIN || errno == ENOBUFS || ++ errno == EINTR) /* try later */ ++ return (0); ++ else ++ return (-1); ++ } ++ ++ if (n == 0) { /* connection closed */ ++ errno = 0; ++ return (-2); ++ } ++ ++ msgbuf_drain(msgbuf, n); ++ ++ return (0); ++} ++ ++void ++ibuf_free(struct ibuf *buf) ++{ ++ free(buf->buf); ++ free(buf); ++} ++ ++void ++msgbuf_init(struct msgbuf *msgbuf) ++{ ++ msgbuf->queued = 0; ++ msgbuf->fd = -1; ++ TAILQ_INIT(&msgbuf->bufs); ++} ++ ++void ++msgbuf_drain(struct msgbuf *msgbuf, size_t n) ++{ ++ struct ibuf *buf, *next; ++ ++ for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; ++ buf = next) { ++ next = TAILQ_NEXT(buf, entry); ++ if (buf->rpos + n >= buf->wpos) { ++ n -= buf->wpos - buf->rpos; ++ ibuf_dequeue(msgbuf, buf); ++ } else { ++ buf->rpos += n; ++ n = 0; ++ } ++ } ++} ++ ++void ++msgbuf_clear(struct msgbuf *msgbuf) ++{ ++ struct ibuf *buf; ++ ++ while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL) ++ ibuf_dequeue(msgbuf, buf); ++} ++ ++int ++msgbuf_write(struct msgbuf *msgbuf) ++{ ++ struct iovec iov[IOV_MAX]; ++ struct ibuf *buf; ++ unsigned int i = 0; ++ ssize_t n; ++ struct msghdr msg; ++ struct cmsghdr *cmsg; ++ union { ++ struct cmsghdr hdr; ++ char buf[CMSG_SPACE(sizeof(int))]; ++ } cmsgbuf; ++ ++ bzero(&iov, sizeof(iov)); ++ bzero(&msg, sizeof(msg)); ++ TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { ++ if (i >= IOV_MAX) ++ break; ++ iov[i].iov_base = buf->buf + buf->rpos; ++ iov[i].iov_len = buf->wpos - buf->rpos; ++ i++; ++ if (buf->fd != -1) ++ break; ++ } ++ ++ msg.msg_iov = iov; ++ msg.msg_iovlen = i; ++ ++ if (buf != NULL && buf->fd != -1) { ++ msg.msg_control = (caddr_t)&cmsgbuf.buf; ++ msg.msg_controllen = sizeof(cmsgbuf.buf); ++ cmsg = CMSG_FIRSTHDR(&msg); ++ cmsg->cmsg_len = CMSG_LEN(sizeof(int)); ++ cmsg->cmsg_level = SOL_SOCKET; ++ cmsg->cmsg_type = SCM_RIGHTS; ++ *(int *)CMSG_DATA(cmsg) = buf->fd; ++ } ++ ++ if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) { ++ if (errno == EAGAIN || errno == ENOBUFS || ++ errno == EINTR) /* try later */ ++ return (0); ++ else ++ return (-1); ++ } ++ ++ if (n == 0) { /* connection closed */ ++ errno = 0; ++ return (-2); ++ } ++ ++ /* ++ * assumption: fd got sent if sendmsg sent anything ++ * this works because fds are passed one at a time ++ */ ++ if (buf != NULL && buf->fd != -1) { ++ close(buf->fd); ++ buf->fd = -1; ++ } ++ ++ msgbuf_drain(msgbuf, n); ++ ++ return (0); ++} ++ ++void ++ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf) ++{ ++ TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry); ++ msgbuf->queued++; ++} ++ ++void ++ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf) ++{ ++ TAILQ_REMOVE(&msgbuf->bufs, buf, entry); ++ ++ if (buf->fd != -1) ++ close(buf->fd); ++ ++ msgbuf->queued--; ++ ibuf_free(buf); ++} diff --git a/net/openbgpd/files/patch-openbsd-compat_imsg.c b/net/openbgpd/files/patch-openbsd-compat_imsg.c new file mode 100644 index 000000000000..183a46ba6697 --- /dev/null +++ b/net/openbgpd/files/patch-openbsd-compat_imsg.c @@ -0,0 +1,278 @@ +Index: openbsd-compat/imsg.c +=================================================================== +RCS file: openbsd-compat/imsg.c +diff -N openbsd-compat/imsg.c +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ openbsd-compat/imsg.c 2 Jul 2011 16:06:38 -0000 1.1 +@@ -0,0 +1,271 @@ ++/* $OpenBSD: imsg.c,v 1.1 2010/05/26 16:44:32 nicm Exp $ */ ++ ++/* ++ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include <sys/param.h> ++#include <sys/queue.h> ++#include <sys/socket.h> ++#include <sys/uio.h> ++ ++#include <errno.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++ ++#include "imsg.h" ++ ++int imsg_get_fd(struct imsgbuf *); ++ ++void ++imsg_init(struct imsgbuf *ibuf, int fd) ++{ ++ msgbuf_init(&ibuf->w); ++ bzero(&ibuf->r, sizeof(ibuf->r)); ++ ibuf->fd = fd; ++ ibuf->w.fd = fd; ++ ibuf->pid = getpid(); ++ TAILQ_INIT(&ibuf->fds); ++} ++ ++ssize_t ++imsg_read(struct imsgbuf *ibuf) ++{ ++ struct msghdr msg; ++ struct cmsghdr *cmsg; ++ union { ++ struct cmsghdr hdr; ++ char buf[CMSG_SPACE(sizeof(int) * 16)]; ++ } cmsgbuf; ++ struct iovec iov; ++ ssize_t n; ++ int fd; ++ struct imsg_fd *ifd; ++ ++ bzero(&msg, sizeof(msg)); ++ ++ iov.iov_base = ibuf->r.buf + ibuf->r.wpos; ++ iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos; ++ msg.msg_iov = &iov; ++ msg.msg_iovlen = 1; ++ msg.msg_control = &cmsgbuf.buf; ++ msg.msg_controllen = sizeof(cmsgbuf.buf); ++ ++ if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) { ++ if (errno != EINTR && errno != EAGAIN) { ++ return (-1); ++ } ++ return (-2); ++ } ++ ++ ibuf->r.wpos += n; ++ ++ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; ++ cmsg = CMSG_NXTHDR(&msg, cmsg)) { ++ if (cmsg->cmsg_level == SOL_SOCKET && ++ cmsg->cmsg_type == SCM_RIGHTS) { ++ fd = (*(int *)CMSG_DATA(cmsg)); ++ if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) { ++ close(fd); ++ return (-1); ++ } ++ ifd->fd = fd; ++ TAILQ_INSERT_TAIL(&ibuf->fds, ifd, entry); ++ } ++ /* we do not handle other ctl data level */ ++ } ++ ++ return (n); ++} ++ ++ssize_t ++imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) ++{ ++ size_t av, left, datalen; ++ ++ av = ibuf->r.wpos; ++ ++ if (IMSG_HEADER_SIZE > av) ++ return (0); ++ ++ memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr)); ++ if (imsg->hdr.len < IMSG_HEADER_SIZE || ++ imsg->hdr.len > MAX_IMSGSIZE) { ++ errno = ERANGE; ++ return (-1); ++ } ++ if (imsg->hdr.len > av) ++ return (0); ++ datalen = imsg->hdr.len - IMSG_HEADER_SIZE; ++ ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE; ++ if ((imsg->data = malloc(datalen)) == NULL) ++ return (-1); ++ ++ if (imsg->hdr.flags & IMSGF_HASFD) ++ imsg->fd = imsg_get_fd(ibuf); ++ else ++ imsg->fd = -1; ++ ++ memcpy(imsg->data, ibuf->r.rptr, datalen); ++ ++ if (imsg->hdr.len < av) { ++ left = av - imsg->hdr.len; ++ memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left); ++ ibuf->r.wpos = left; ++ } else ++ ibuf->r.wpos = 0; ++ ++ return (datalen + IMSG_HEADER_SIZE); ++} ++ ++int ++imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, ++ pid_t pid, int fd, void *data, u_int16_t datalen) ++{ ++ struct ibuf *wbuf; ++ ++ if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) ++ return (-1); ++ ++ if (imsg_add(wbuf, data, datalen) == -1) ++ return (-1); ++ ++ wbuf->fd = fd; ++ ++ imsg_close(ibuf, wbuf); ++ ++ return (1); ++} ++ ++int ++imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, ++ pid_t pid, int fd, const struct iovec *iov, int iovcnt) ++{ ++ struct ibuf *wbuf; ++ int i, datalen = 0; ++ ++ for (i = 0; i < iovcnt; i++) ++ datalen += iov[i].iov_len; ++ ++ if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) ++ return (-1); ++ ++ for (i = 0; i < iovcnt; i++) ++ if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1) ++ return (-1); ++ ++ wbuf->fd = fd; ++ ++ imsg_close(ibuf, wbuf); ++ ++ return (1); ++} ++ ++/* ARGSUSED */ ++struct ibuf * ++imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, ++ pid_t pid, u_int16_t datalen) ++{ ++ struct ibuf *wbuf; ++ struct imsg_hdr hdr; ++ ++ datalen += IMSG_HEADER_SIZE; ++ if (datalen > MAX_IMSGSIZE) { ++ errno = ERANGE; ++ return (NULL); ++ } ++ ++ hdr.type = type; ++ hdr.flags = 0; ++ hdr.peerid = peerid; ++ if ((hdr.pid = pid) == 0) ++ hdr.pid = ibuf->pid; ++ if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) { ++ return (NULL); ++ } ++ if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1) ++ return (NULL); ++ ++ return (wbuf); ++} ++ ++int ++imsg_add(struct ibuf *msg, void *data, u_int16_t datalen) ++{ ++ if (datalen) ++ if (ibuf_add(msg, data, datalen) == -1) { ++ ibuf_free(msg); ++ return (-1); ++ } ++ return (datalen); ++} ++ ++void ++imsg_close(struct imsgbuf *ibuf, struct ibuf *msg) ++{ ++ struct imsg_hdr *hdr; ++ ++ hdr = (struct imsg_hdr *)msg->buf; ++ ++ hdr->flags &= ~IMSGF_HASFD; ++ if (msg->fd != -1) ++ hdr->flags |= IMSGF_HASFD; ++ ++ hdr->len = (u_int16_t)msg->wpos; ++ ++ ibuf_close(&ibuf->w, msg); ++} ++ ++void ++imsg_free(struct imsg *imsg) ++{ ++ free(imsg->data); ++} ++ ++int ++imsg_get_fd(struct imsgbuf *ibuf) ++{ ++ int fd; ++ struct imsg_fd *ifd; ++ ++ if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL) ++ return (-1); ++ ++ fd = ifd->fd; ++ TAILQ_REMOVE(&ibuf->fds, ifd, entry); ++ free(ifd); ++ ++ return (fd); ++} ++ ++int ++imsg_flush(struct imsgbuf *ibuf) ++{ ++ while (ibuf->w.queued) ++ if (msgbuf_write(&ibuf->w) < 0) ++ return (-1); ++ return (0); ++} ++ ++void ++imsg_clear(struct imsgbuf *ibuf) ++{ ++ int fd; ++ ++ msgbuf_clear(&ibuf->w); ++ while ((fd = imsg_get_fd(ibuf)) != -1) ++ close(fd); ++} diff --git a/net/openbgpd/files/patch-openbsd-compat_imsg.h b/net/openbgpd/files/patch-openbsd-compat_imsg.h new file mode 100644 index 000000000000..80ce85487aef --- /dev/null +++ b/net/openbgpd/files/patch-openbsd-compat_imsg.h @@ -0,0 +1,119 @@ +Index: openbsd-compat/imsg.h +=================================================================== +RCS file: openbsd-compat/imsg.h +diff -N openbsd-compat/imsg.h +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ openbsd-compat/imsg.h 2 Jul 2011 16:06:38 -0000 1.1 +@@ -0,0 +1,112 @@ ++/* $OpenBSD: imsg.h,v 1.2 2010/06/23 07:53:55 nicm Exp $ */ ++ ++/* ++ * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org> ++ * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org> ++ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _IMSG_H_ ++#define _IMSG_H_ ++ ++#define IBUF_READ_SIZE 65535 ++#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr) ++#define MAX_IMSGSIZE 16384 ++ ++struct ibuf { ++ TAILQ_ENTRY(ibuf) entry; ++ u_char *buf; ++ size_t size; ++ size_t max; ++ size_t wpos; ++ size_t rpos; ++ int fd; ++}; ++ ++struct msgbuf { ++ TAILQ_HEAD(, ibuf) bufs; ++ u_int32_t queued; ++ int fd; ++}; ++ ++struct ibuf_read { ++ u_char buf[IBUF_READ_SIZE]; ++ u_char *rptr; ++ size_t wpos; ++}; ++ ++struct imsg_fd { ++ TAILQ_ENTRY(imsg_fd) entry; ++ int fd; ++}; ++ ++struct imsgbuf { ++ TAILQ_HEAD(, imsg_fd) fds; ++ struct ibuf_read r; ++ struct msgbuf w; ++ int fd; ++ pid_t pid; ++}; ++ ++#define IMSGF_HASFD 1 ++ ++struct imsg_hdr { ++ u_int32_t type; ++ u_int16_t len; ++ u_int16_t flags; ++ u_int32_t peerid; ++ u_int32_t pid; ++}; ++ ++struct imsg { ++ struct imsg_hdr hdr; ++ int fd; ++ void *data; ++}; ++ ++ ++/* buffer.c */ ++struct ibuf *ibuf_open(size_t); ++struct ibuf *ibuf_dynamic(size_t, size_t); ++int ibuf_add(struct ibuf *, const void *, size_t); ++void *ibuf_reserve(struct ibuf *, size_t); ++void *ibuf_seek(struct ibuf *, size_t, size_t); ++size_t ibuf_size(struct ibuf *); ++size_t ibuf_left(struct ibuf *); ++void ibuf_close(struct msgbuf *, struct ibuf *); ++int ibuf_write(struct msgbuf *); ++void ibuf_free(struct ibuf *); ++void msgbuf_init(struct msgbuf *); ++void msgbuf_clear(struct msgbuf *); ++int msgbuf_write(struct msgbuf *); ++void msgbuf_drain(struct msgbuf *, size_t); ++ ++/* imsg.c */ ++void imsg_init(struct imsgbuf *, int); ++ssize_t imsg_read(struct imsgbuf *); ++ssize_t imsg_get(struct imsgbuf *, struct imsg *); ++int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, ++ int, void *, u_int16_t); ++int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, ++ int, const struct iovec *, int); ++struct ibuf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, ++ u_int16_t); ++int imsg_add(struct ibuf *, void *, u_int16_t); ++void imsg_close(struct imsgbuf *, struct ibuf *); ++void imsg_free(struct imsg *); ++int imsg_flush(struct imsgbuf *); ++void imsg_clear(struct imsgbuf *); ++ ++#endif diff --git a/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h b/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h index 1339f1f1a772..312906fefe60 100644 --- a/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h +++ b/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h @@ -3,10 +3,10 @@ Index: openbsd-compat/openbsd-compat.h RCS file: openbsd-compat/openbsd-compat.h diff -N openbsd-compat/openbsd-compat.h --- /dev/null 1 Jan 1970 00:00:00 -0000 -+++ openbsd-compat/openbsd-compat.h 4 Feb 2010 16:22:51 -0000 1.4 ++++ openbsd-compat/openbsd-compat.h 3 Jul 2011 04:46:38 -0000 1.6 @@ -0,0 +1,87 @@ +/* -+ * $hrs: openbgpd/openbsd-compat/openbsd-compat.h,v 1.4 2010/02/04 16:22:51 hrs Exp $ ++ * $hrs: openbgpd/openbsd-compat/openbsd-compat.h,v 1.6 2011/07/03 04:46:38 hrs Exp $ + */ + +#ifndef _OPENBSD_COMPAT_H diff --git a/net/openbgpd/files/patch-openbsd-compat_pfkey_compat.c b/net/openbgpd/files/patch-openbsd-compat_pfkey_compat.c index d7754e350646..6e2a53f6d341 100644 --- a/net/openbgpd/files/patch-openbsd-compat_pfkey_compat.c +++ b/net/openbgpd/files/patch-openbsd-compat_pfkey_compat.c @@ -3,8 +3,8 @@ Index: openbsd-compat/pfkey_compat.c RCS file: openbsd-compat/pfkey_compat.c diff -N openbsd-compat/pfkey_compat.c --- /dev/null 1 Jan 1970 00:00:00 -0000 -+++ openbsd-compat/pfkey_compat.c 30 Jun 2009 06:40:07 -0000 1.1 -@@ -0,0 +1,27 @@ ++++ openbsd-compat/pfkey_compat.c 2 Jul 2011 16:06:38 -0000 1.2 +@@ -0,0 +1,32 @@ +#include "bgpd.h" +#include "session.h" + @@ -32,3 +32,8 @@ diff -N openbsd-compat/pfkey_compat.c + return (0); +} + ++int ++pfkey_read(int sd, struct sadb_msg *h) ++{ ++ return (1); ++} diff --git a/net/openbgpd/pkg-install b/net/openbgpd/pkg-install deleted file mode 100644 index f5996af787be..000000000000 --- a/net/openbgpd/pkg-install +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -case $2 in -POST-INSTALL) - USER=_bgpd - GROUP=${USER} - UID=130 - GID=${UID} - PW=/usr/sbin/pw - - if ${PW} group show "${GROUP}" 2>/dev/null; then - echo "You already have a group \"${GROUP}\", so I will use it." - else - if ${PW} groupadd ${GROUP} -g ${GID}; then - echo "Added group \"${GROUP}\"." - else - echo "Adding group \"${GROUP}\" failed..." - exit 1 - fi - fi - - if ${PW} user show "${USER}" 2>/dev/null; then - echo "You already have a user \"${USER}\", so I will use it." - else - if ${PW} useradd ${USER} -u ${UID} -g ${GROUP} -h - \ - -d "/var/empty" -s /sbin/nologin -c "BGP Daemon" - then - echo "Added user \"${USER}\"." - else - echo "Adding user \"${USER}\" failed..." - exit 1 - fi - fi - exit 0 - ;; -esac |