diff options
author | hrs <hrs@FreeBSD.org> | 2010-02-17 03:27:03 +0800 |
---|---|---|
committer | hrs <hrs@FreeBSD.org> | 2010-02-17 03:27:03 +0800 |
commit | f224ddaace2eaacf1892db702cc436b93f7a1daa (patch) | |
tree | 576b460ac6fc99065dbc59b2a6a05cbd5180fea5 /net | |
parent | 1a8b352996af161adf5b34c6a6b7defb2892ff32 (diff) | |
download | freebsd-ports-gnome-f224ddaace2eaacf1892db702cc436b93f7a1daa.tar.gz freebsd-ports-gnome-f224ddaace2eaacf1892db702cc436b93f7a1daa.tar.zst freebsd-ports-gnome-f224ddaace2eaacf1892db702cc436b93f7a1daa.zip |
Update to 4.6.20100215.
Feature safe: yes
Diffstat (limited to 'net')
51 files changed, 6735 insertions, 8013 deletions
diff --git a/net/openbgpd/Makefile b/net/openbgpd/Makefile index 059bd6b3868c..320017370218 100644 --- a/net/openbgpd/Makefile +++ b/net/openbgpd/Makefile @@ -6,11 +6,11 @@ # PORTNAME= openbgpd -PORTVERSION= 4.5.20091022 +PORTVERSION= 4.6.20100215 CATEGORIES= net MASTER_SITES= ${MASTER_SITE_OPENBSD} MASTER_SITE_SUBDIR= OpenBGPD -DISTNAME= ${PORTNAME}-4.4.1 +DISTNAME= ${PORTNAME}-4.6 EXTRACT_SUFX= .tgz DIST_SUBDIR= ${PORTNAME} diff --git a/net/openbgpd/distinfo b/net/openbgpd/distinfo index e6ddbe50d38c..bede0f581a7e 100644 --- a/net/openbgpd/distinfo +++ b/net/openbgpd/distinfo @@ -1,12 +1,3 @@ -MD5 (openbgpd/openbgpd-4.4.1.tgz) = 5ac036b2ca2905a7efe2e0364aef00e7 -SHA256 (openbgpd/openbgpd-4.4.1.tgz) = 284406daa359bf1e9386e5055a1803453d04fd9c9ef5479ac324c8d1eebc33a4 -SIZE (openbgpd/openbgpd-4.4.1.tgz) = 163070 -MD5 (openbgpd/if_media.h) = 4ff9297f5c133425dafe3ca565c0f811 -SHA256 (openbgpd/if_media.h) = 58225d0ed363c2beb23426f0f8254089d4541c3334776f3750ba434d4491a1d1 -SIZE (openbgpd/if_media.h) = 23762 -MD5 (openbgpd/hash.h) = 0c397692b9b152f1bca968b6248bc09c -SHA256 (openbgpd/hash.h) = 0c5561c6765325f49d82d5c5fd9471dbfadf21f44e554758eb112a23f7c317b1 -SIZE (openbgpd/hash.h) = 3488 -MD5 (openbgpd/strtonum.c) = da3ba14723ae645c13b8ea96d3f78f20 -SHA256 (openbgpd/strtonum.c) = eabeece529ed7678b5d79774813818ed1d46b7c7a934c98e474c8f62c56abaec -SIZE (openbgpd/strtonum.c) = 1769 +MD5 (openbgpd/openbgpd-4.6.tgz) = 846feb4de328e7d47526a83087000863 +SHA256 (openbgpd/openbgpd-4.6.tgz) = d9a0a3542e5ec744889ca12871f01aa1d86f12844e093010f37d0601796e15cf +SIZE (openbgpd/openbgpd-4.6.tgz) = 168197 diff --git a/net/openbgpd/files/patch-bgpctl-compat-openbsd.h b/net/openbgpd/files/patch-bgpctl-compat-openbsd.h deleted file mode 100644 index bbec3833bac7..000000000000 --- a/net/openbgpd/files/patch-bgpctl-compat-openbsd.h +++ /dev/null @@ -1,6 +0,0 @@ ---- /dev/null 2009-06-24 01:22:00.000000000 +0900 -+++ bgpctl/compat-openbsd.h 2009-06-24 01:24:55.000000000 +0900 -@@ -0,0 +1,3 @@ -+#include <sys/endian.h> -+ -+#define betoh64(x) (be64toh(x)) diff --git a/net/openbgpd/files/patch-bgpctl_bgpctl.8 b/net/openbgpd/files/patch-bgpctl_bgpctl.8 index 0b329535d398..33875d1056c2 100644 --- a/net/openbgpd/files/patch-bgpctl_bgpctl.8 +++ b/net/openbgpd/files/patch-bgpctl_bgpctl.8 @@ -1,14 +1,14 @@ Index: bgpctl/bgpctl.8 =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/bgpctl.8,v -retrieving revision 1.1.1.1 -retrieving revision 1.3 -diff -u -p -r1.1.1.1 -r1.3 ---- bgpctl/bgpctl.8 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpctl/bgpctl.8 9 Jul 2009 17:22:12 -0000 1.3 +retrieving revision 1.1.1.6 +retrieving revision 1.4 +diff -u -p -r1.1.1.6 -r1.4 +--- 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 @@ -1,4 +1,4 @@ --.\" $OpenBSD: bgpctl.8,v 1.47 2008/06/07 18:14:41 henning Exp $ -+.\" $OpenBSD: bgpctl.8,v 1.49 2009/06/06 06:11:17 claudio Exp $ +-.\" $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 $ .\" .\" Copyright (c) 2003 Henning Brauer <henning@openbsd.org> .\" @@ -16,30 +16,28 @@ diff -u -p -r1.1.1.1 -r1.3 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" --.Dd $Mdocdate: June 7 2008 $ -+.Dd $Mdocdate: December 6 2008 $ +-.Dd $Mdocdate: June 6 2009 $ ++.Dd $Mdocdate: November 2 2009 $ .Dt BGPCTL 8 .Os .Sh NAME -@@ -25,7 +25,7 @@ - .Op Fl n - .Op Fl s Ar socket - .Ar command --.Op Ar arguments ... -+.Op Ar argument ... - .Sh DESCRIPTION - The - .Nm -@@ -202,6 +202,8 @@ Show all entries with community - .Ar community . - .It Cm neighbor Ar peer - Show only entries from the specified peer. -+.It Cm table Ar rib -+Show only entries from the specified RIB table. - .It Cm summary - This is the same as the - .Ic show summary -@@ -244,7 +246,7 @@ in a terse format. +@@ -79,7 +79,15 @@ The options are as follows: + Use + .Ar directory + to write the filter files to. ++.It Fl 4 ++Fetch only IPv4 prefixes from the registry. ++.It Fl 6 ++Fetch only IPv6 prefixes from the registry. + .El ++.It Cm log brief ++Disable verbose debug logging. ++.It Cm log verbose ++Enable verbose debug logging. + .It Cm neighbor Ar peer Cm up + Take the BGP session to the specified neighbor up. + .Ar peer +@@ -246,7 +254,7 @@ in a terse format. .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 be4f91b3defe..96f7769b8144 100644 --- a/net/openbgpd/files/patch-bgpctl_bgpctl.c +++ b/net/openbgpd/files/patch-bgpctl_bgpctl.c @@ -1,14 +1,14 @@ Index: bgpctl/bgpctl.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/bgpctl.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.4 -diff -u -p -r1.1.1.1 -r1.4 ---- bgpctl/bgpctl.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpctl/bgpctl.c 10 Aug 2009 21:20:02 -0000 1.4 +retrieving revision 1.1.1.7 +retrieving revision 1.6 +diff -u -p -r1.1.1.7 -r1.6 +--- bgpctl/bgpctl.c 14 Feb 2010 20:20:14 -0000 1.1.1.7 ++++ bgpctl/bgpctl.c 14 Feb 2010 19:55:02 -0000 1.6 @@ -1,4 +1,4 @@ --/* $OpenBSD: bgpctl.c,v 1.134 2008/06/07 20:23:15 henning Exp $ */ -+/* $OpenBSD: bgpctl.c,v 1.145 2009/07/23 14:55:25 claudio Exp $ */ +-/* $OpenBSD: bgpctl.c,v 1.142 2009/06/06 06:33:15 eric Exp $ */ ++/* $OpenBSD: bgpctl.c,v 1.155 2010/01/10 00:16:23 claudio Exp $ */ /* * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> @@ -55,6 +55,15 @@ diff -u -p -r1.1.1.1 -r1.4 enum neighbor_views { NV_DEFAULT, NV_TIMERS +@@ -50,7 +66,7 @@ int show_summary_msg(struct imsg *, in + int show_summary_terse_msg(struct imsg *, int); + int show_neighbor_terse(struct imsg *); + int show_neighbor_msg(struct imsg *, enum neighbor_views); +-void print_neighbor_capa_mp_safi(u_int8_t); ++void print_neighbor_capa_mp(struct peer *); + void print_neighbor_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); int ift2ifm(int); const char * get_media_descr(int); @@ -64,58 +73,217 @@ diff -u -p -r1.1.1.1 -r1.4 int show_interface_msg(struct imsg *); void show_rib_summary_head(void); void print_prefix(struct bgpd_addr *, u_int8_t, u_int8_t); -@@ -89,8 +105,8 @@ usage(void) +@@ -74,7 +90,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); +-const char *get_ext_subtype(u_int8_t); + void show_ext_community(u_char *, u_int16_t); + char *fmt_mem(int64_t); + int show_rib_memory_msg(struct imsg *); +@@ -98,7 +113,7 @@ int + main(int argc, char *argv[]) { - extern char *__progname; - -- fprintf(stderr, "usage: %s [-n] [-s socket] " -- "command [arguments ...]\n", __progname); -+ fprintf(stderr, "usage: %s [-n] [-s socket] command [argument ...]\n", -+ __progname); - exit(1); - } + struct sockaddr_un sun; +- int fd, n, done, ch, nodescr = 0; ++ int fd, n, done, ch, nodescr = 0, verbose = 0; + struct imsg imsg; + struct network_config net; + struct parse_result *res; +@@ -164,15 +179,17 @@ 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) { ++ if (!res->addr.aid) { + struct buf *msg; ++ sa_family_t af; -@@ -174,8 +190,7 @@ main(int argc, char *argv[]) ++ 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) + errx(1, "imsg_create failure"); + if (imsg_add(msg, &res->flags, sizeof(res->flags)) == -1 || - imsg_add(msg, &res->af, sizeof(res->af)) == -1) +- imsg_add(msg, &res->af, sizeof(res->af)) == -1) ++ imsg_add(msg, &af, sizeof(af)) == -1) errx(1, "imsg_add failure"); -- if (imsg_close(ibuf, msg) < 0) -- errx(1, "imsg_close error"); -+ imsg_close(ibuf, msg); + imsg_close(ibuf, msg); } else - imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1, - &res->addr, sizeof(res->addr)); -@@ -220,6 +235,7 @@ main(int argc, char *argv[]) +@@ -192,7 +209,7 @@ main(int argc, char *argv[]) + case SHOW_NEIGHBOR_TIMERS: + case SHOW_NEIGHBOR_TERSE: + neighbor.show_timers = (res->action == SHOW_NEIGHBOR_TIMERS); +- if (res->peeraddr.af || res->peerdesc[0]) ++ if (res->peeraddr.aid || res->peerdesc[0]) + imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1, + &neighbor, sizeof(neighbor)); + else +@@ -206,7 +223,7 @@ main(int argc, char *argv[]) + memcpy(&ribreq.as, &res->as, sizeof(res->as)); + type = IMSG_CTL_SHOW_RIB_AS; } +- if (res->addr.af) { ++ if (res->addr.aid) { + memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr)); + ribreq.prefixlen = res->prefixlen; + type = IMSG_CTL_SHOW_RIB_PREFIX; +@@ -220,7 +237,7 @@ main(int argc, char *argv[]) memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor)); -+ strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib)); - ribreq.af = res->af; + strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib)); +- ribreq.af = res->af; ++ ribreq.aid = res->aid; ribreq.flags = res->flags; imsg_compose(ibuf, type, 0, 0, -1, &ribreq, sizeof(ribreq)); -@@ -289,8 +305,11 @@ main(int argc, char *argv[]) - done = 1; + if (!(res->flags & F_CTL_DETAIL)) +@@ -290,12 +307,21 @@ main(int argc, char *argv[]) break; case NETWORK_SHOW: -+ bzero(&ribreq, sizeof(ribreq)); -+ ribreq.af = res->af; -+ strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib)); + bzero(&ribreq, sizeof(ribreq)); +- ribreq.af = res->af; ++ ribreq.aid = res->aid; + strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib)); imsg_compose(ibuf, IMSG_CTL_SHOW_NETWORK, 0, 0, -1, -- &res->af, sizeof(res->af)); -+ &ribreq, sizeof(ribreq)); + &ribreq, sizeof(ribreq)); show_network_head(); break; ++ case LOG_VERBOSE: ++ verbose = 1; ++ /* FALLTHROUGH */ ++ case LOG_BRIEF: ++ imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1, ++ &verbose, sizeof(verbose)); ++ printf("logging request sent.\n"); ++ done = 1; ++ break; + } + + while (ibuf->w.queued) +@@ -304,13 +330,13 @@ main(int argc, char *argv[]) + + while (!done) { + if ((n = imsg_read(ibuf)) == -1) +- errx(1, "imsg_read error"); ++ err(1, "imsg_read error"); + if (n == 0) + errx(1, "pipe closed"); + + while (!done) { + if ((n = imsg_get(ibuf, &imsg)) == -1) +- errx(1, "imsg_get error"); ++ err(1, "imsg_get error"); + if (n == 0) + break; + +@@ -373,6 +399,8 @@ main(int argc, char *argv[]) + case NETWORK_REMOVE: + case NETWORK_FLUSH: + case IRRFILTER: ++ case LOG_VERBOSE: ++ case LOG_BRIEF: + break; + } + imsg_free(&imsg); +@@ -398,8 +426,8 @@ fmt_peer(const char *descr, const struct } -@@ -410,7 +429,7 @@ fmt_peer(const char *descr, const struct + + ip = log_addr(remote_addr); +- if (masklen != -1 && ((remote_addr->af == AF_INET && masklen != 32) || +- (remote_addr->af == AF_INET6 && masklen != 128))) { ++ if (masklen != -1 && ((remote_addr->aid == AID_INET && masklen != 32) || ++ (remote_addr->aid == AID_INET6 && masklen != 128))) { + if (asprintf(&p, "%s/%u", ip, masklen) == -1) + err(1, NULL); + } else { +@@ -521,13 +549,15 @@ show_neighbor_msg(struct imsg *imsg, enu + struct ctl_timer *t; + struct in_addr ina; + char buf[NI_MAXHOST], pbuf[NI_MAXSERV], *s; ++ int hascapamp = 0; ++ u_int8_t i; + + switch (imsg->hdr.type) { + case IMSG_CTL_SHOW_NEIGHBOR: + p = imsg->data; +- if ((p->conf.remote_addr.af == AF_INET && ++ if ((p->conf.remote_addr.aid == AID_INET && + p->conf.remote_masklen != 32) || +- (p->conf.remote_addr.af == AF_INET6 && ++ (p->conf.remote_addr.aid == AID_INET6 && + p->conf.remote_masklen != 128)) { + if (asprintf(&s, "%s/%u", + log_addr(&p->conf.remote_addr), +@@ -549,6 +579,10 @@ show_neighbor_msg(struct imsg *imsg, enu + printf(", Template"); + if (p->conf.cloned) + printf(", Cloned"); ++ if (p->conf.passive) ++ printf(", Passive"); ++ if (p->conf.ebgp && p->conf.distance > 1) ++ printf(", Multihop (%u)", (int)p->conf.distance); + printf("\n"); + if (p->conf.descr[0]) + printf(" Description: %s\n", p->conf.descr); +@@ -563,17 +597,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); +- if (p->capa.peer.mp_v4 || p->capa.peer.mp_v6 || +- p->capa.peer.refresh || p->capa.peer.restart || +- p->capa.peer.as4byte) { ++ for (i = 0; i < AID_MAX; i++) ++ if (p->capa.peer.mp[i]) ++ hascapamp = 1; ++ if (hascapamp || p->capa.peer.refresh || ++ p->capa.peer.restart || p->capa.peer.as4byte) { + printf(" Neighbor capabilities:\n"); +- if (p->capa.peer.mp_v4) { +- printf(" Multiprotocol extensions: IPv4"); +- print_neighbor_capa_mp_safi(p->capa.peer.mp_v4); +- } +- if (p->capa.peer.mp_v6) { +- printf(" Multiprotocol extensions: IPv6"); +- print_neighbor_capa_mp_safi(p->capa.peer.mp_v6); ++ if (hascapamp) { ++ printf(" Multiprotocol extensions: "); ++ print_neighbor_capa_mp(p); ++ printf("\n"); + } + if (p->capa.peer.refresh) + printf(" Route Refresh\n"); +@@ -633,20 +666,16 @@ show_neighbor_msg(struct imsg *imsg, enu + } + void - show_summary_head(void) +-print_neighbor_capa_mp_safi(u_int8_t safi) ++print_neighbor_capa_mp(struct peer *p) { -- printf("%-20s %-8s %-10s %-10s %-5s %-8s %s\n", "Neighbor", "AS", -+ printf("%-20s %8s %10s %10s %5s %-8s %s\n", "Neighbor", "AS", - "MsgRcvd", "MsgSent", "OutQ", "Up/Down", "State/PrfRcvd"); +- switch (safi) { +- case SAFI_UNICAST: +- printf(" Unicast"); +- break; +- case SAFI_MULTICAST: +- printf(" Multicast"); +- break; +- default: +- printf(" unknown (%u)", safi); +- break; +- } +- printf("\n"); ++ int comma; ++ u_int8_t i; ++ ++ for (i = 0, comma = 0; i < AID_MAX; i++) ++ if (p->capa.peer.mp[i]) { ++ printf("%s%s", comma ? ", " : "", aid2str(i)); ++ comma = 1; ++ } } -@@ -677,7 +696,7 @@ print_neighbor_msgstats(struct peer *p) + void +@@ -680,7 +709,7 @@ print_neighbor_msgstats(struct peer *p) } void @@ -124,34 +292,7 @@ diff -u -p -r1.1.1.1 -r1.4 { printf(" %-20s ", name); -@@ -738,7 +757,7 @@ show_fib_head(void) - printf("flags: * = valid, B = BGP, C = Connected, S = Static\n"); - printf(" N = BGP Nexthop reachable via this route\n"); - printf(" r = reject route, b = blackhole route\n\n"); -- printf("flags destination gateway\n"); -+ printf("flags prio destination gateway\n"); - } - - void -@@ -801,7 +820,7 @@ show_fib_msg(struct imsg *imsg) - if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), k->prefixlen) == - -1) - err(1, NULL); -- printf("%-20s ", p); -+ printf("%4i %-20s ", k->priority, p); - free(p); - - if (k->nexthop.s_addr) -@@ -822,7 +841,7 @@ show_fib_msg(struct imsg *imsg) - if (asprintf(&p, "%s/%u", log_in6addr(&k6->prefix), - k6->prefixlen) == -1) - err(1, NULL); -- printf("%-20s ", p); -+ printf("%4i %-20s ", k6->priority, p); - free(p); - - if (!IN6_IS_ADDR_UNSPECIFIED(&k6->nexthop)) -@@ -845,35 +864,77 @@ show_fib_msg(struct imsg *imsg) +@@ -848,35 +877,70 @@ show_fib_msg(struct imsg *imsg) void show_nexthop_head(void) { @@ -165,10 +306,10 @@ diff -u -p -r1.1.1.1 -r1.4 show_nexthop_msg(struct imsg *imsg) { struct ctl_show_nexthop *p; +- int ifms_type; + struct kroute *k; + struct kroute6 *k6; + char *s; - int ifms_type; switch (imsg->hdr.type) { case IMSG_CTL_SHOW_NEXTHOP: @@ -180,8 +321,8 @@ diff -u -p -r1.1.1.1 -r1.4 + printf("\n"); + return (0); + } -+ switch (p->addr.af) { -+ case AF_INET: ++ switch (p->addr.aid) { ++ case AID_INET: + k = &p->kr.kr4; + if (asprintf(&s, "%s/%u", inet_ntoa(k->prefix), + k->prefixlen) == -1) @@ -192,7 +333,7 @@ diff -u -p -r1.1.1.1 -r1.4 + k->flags & F_CONNECTED ? "connected" : + inet_ntoa(k->nexthop)); + break; -+ case AF_INET6: ++ case AID_INET6: + k6 = &p->kr.kr6; + if (asprintf(&s, "%s/%u", log_in6addr(&k6->prefix), + k6->prefixlen) == -1) @@ -204,7 +345,7 @@ diff -u -p -r1.1.1.1 -r1.4 + log_in6addr(&k6->nexthop)); + break; + default: -+ printf("unknown address familiy %d\n", p->addr.af); ++ printf("unknown address family\n"); + return (0); + } if (p->kif.ifname[0]) { @@ -217,24 +358,19 @@ diff -u -p -r1.1.1.1 -r1.4 - get_media_descr(ifms_type), - get_linkstate(ifms_type, - p->kif.link_state)); -+ char *s1; -+ ifms_type = ift2ifm(p->kif.media_type); -+ if (LINK_STATE_IS_UP(p->kif.link_state)) { - if (p->kif.baudrate) { +- if (p->kif.baudrate) { - printf(", "); - print_baudrate(p->kif.baudrate); - } - } -+ if (asprintf(&s1, ", %s", -+ get_baudrate(p->kif.baudrate, -+ "bps")) == -1) -+ err(1, NULL); -+ } else if (asprintf(&s1, ", %s", get_linkstate( -+ ifms_type, p->kif.link_state)) == -1) -+ err(1, NULL); -+ } else if (ifms_type) -+ if (asprintf(&s1, ", %s", get_linkstate( -+ ifms_type, p->kif.link_state)) == -1) ++ char *s1; ++ if (p->kif.baudrate) { ++ if (asprintf(&s1, ", %s", ++ get_baudrate(p->kif.baudrate, ++ "bps")) == -1) ++ err(1, NULL); ++ } else if (asprintf(&s1, ", %s", get_linkstate( ++ p->kif.media_type, p->kif.link_state)) == -1) + err(1, NULL); + if (asprintf(&s, "%s (%s%s)", p->kif.ifname, + p->kif.flags & IFF_UP ? "UP" : "DOWN", s1) == -1) @@ -245,8 +381,47 @@ diff -u -p -r1.1.1.1 -r1.4 } printf("\n"); break; -@@ -952,17 +1013,25 @@ get_linkstate(int media_type, int link_s - return ("unknown link state"); +@@ -898,9 +962,8 @@ show_interface_head(void) + "Link state"); + } + +-const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST; +-const struct ifmedia_status_description +- ifm_status_descriptions[] = IFM_STATUS_DESCRIPTIONS; ++const struct if_status_description ++ if_status_descriptions[] = LINK_STATE_DESCRIPTIONS; + const struct ifmedia_description + ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; + +@@ -936,36 +999,36 @@ get_media_descr(int media_type) + const char * + get_linkstate(int media_type, int link_state) + { +- const struct ifmedia_status_description *p; +- int i; ++ const struct if_status_description *p; ++ static char buf[8]; + +- if (link_state == LINK_STATE_UNKNOWN) +- return ("unknown"); +- +- for (i = 0; ifm_status_valid_list[i] != 0; i++) +- for (p = ifm_status_descriptions; p->ifms_valid != 0; p++) { +- if (p->ifms_type != media_type || +- p->ifms_valid != ifm_status_valid_list[i]) +- continue; +- if (LINK_STATE_IS_UP(link_state)) +- return (p->ifms_string[1]); +- return (p->ifms_string[0]); +- } +- +- return ("unknown link state"); ++ for (p = if_status_descriptions; p->ifs_string != NULL; p++) { ++ if (LINK_STATE_DESC_MATCH(p, media_type, link_state)) ++ return (p->ifs_string); ++ } ++ snprintf(buf, sizeof(buf), "[#%d]", link_state); ++ return (buf); } -void @@ -277,42 +452,162 @@ diff -u -p -r1.1.1.1 -r1.4 } int -@@ -987,8 +1056,7 @@ show_interface_msg(struct imsg *imsg) - printf("link state %u", k->link_state); +@@ -982,17 +1045,12 @@ show_interface_msg(struct imsg *imsg) + printf("%-15s", k->flags & IFF_UP ? "UP" : ""); - if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) { + if ((ifms_type = ift2ifm(k->media_type)) != 0) +- printf("%s, %s", get_media_descr(ifms_type), +- get_linkstate(ifms_type, k->link_state)); +- else if (k->link_state == LINK_STATE_UNKNOWN) +- printf("unknown"); +- else +- printf("link state %u", k->link_state); ++ printf("%s, ", get_media_descr(ifms_type)); + +- if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) { - printf(", "); - print_baudrate(k->baudrate); +- } ++ printf("%s", get_linkstate(k->media_type, k->link_state)); ++ ++ if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) + printf(", %s", get_baudrate(k->baudrate, "Bit/s")); - } printf("\n"); break; -@@ -1186,8 +1254,8 @@ show_rib_detail_msg(struct imsg *imsg, i - case ATTR_AGGREGATOR: + case IMSG_CTL_END: +@@ -1011,7 +1069,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"); +- printf("%-5s %-20s%-15s %5s %5s %s\n", "flags", "destination", ++ printf("%-5s %-20s %-15s %5s %5s %s\n", "flags", "destination", + "gateway", "lpref", "med", "aspath origin"); + } + +@@ -1085,7 +1143,7 @@ show_rib_summary_msg(struct imsg *imsg) + memcpy(&rib, imsg->data, sizeof(rib)); + + print_prefix(&rib.prefix, rib.prefixlen, rib.flags); +- printf("%-15s ", log_addr(&rib.exit_nexthop)); ++ printf(" %-15s ", log_addr(&rib.exit_nexthop)); + + printf(" %5u %5u ", rib.local_pref, rib.med); + +@@ -1190,7 +1248,7 @@ show_rib_detail_msg(struct imsg *imsg, i memcpy(&as, data, sizeof(as)); memcpy(&id, data + sizeof(as), sizeof(id)); -- printf(" Aggregator: %s [%s]\n", log_as(as), -- inet_ntoa(id)); -+ printf(" Aggregator: %s [%s]\n", -+ log_as(htonl(as)), inet_ntoa(id)); + printf(" Aggregator: %s [%s]\n", +- log_as(htonl(as)), inet_ntoa(id)); ++ log_as(ntohl(as)), inet_ntoa(id)); break; case ATTR_ORIGINATOR_ID: memcpy(&id, data, sizeof(id)); -@@ -1249,6 +1317,9 @@ show_rib_memory_msg(struct imsg *imsg) - printf("%10lld IPv6 network entries using " - "%s of memory\n", (long long)stats.pt6_cnt, - fmt_mem(stats.pt6_cnt * sizeof(struct pt_entry6))); -+ printf("%10lld rib entries using %s of memory\n", -+ (long long)stats.rib_cnt, fmt_mem(stats.rib_cnt * -+ sizeof(struct rib_entry))); - printf("%10lld prefix entries using %s of memory\n", - (long long)stats.prefix_cnt, fmt_mem(stats.prefix_cnt * - sizeof(struct prefix))); -@@ -1270,6 +1341,7 @@ show_rib_memory_msg(struct imsg *imsg) - stats.pt4_cnt * sizeof(struct pt_entry4) + - stats.pt6_cnt * sizeof(struct pt_entry6) + +@@ -1236,22 +1294,27 @@ fmt_mem(int64_t num) + return (buf); + } + ++size_t pt_sizes[AID_MAX] = AID_PTSIZE; ++ + int + show_rib_memory_msg(struct imsg *imsg) + { + struct rde_memstats stats; ++ size_t pts = 0; ++ int i; + + switch (imsg->hdr.type) { + case IMSG_CTL_SHOW_RIB_MEM: + memcpy(&stats, imsg->data, sizeof(stats)); + printf("RDE memory statistics\n"); +- printf("%10lld IPv4 network entries using %s of memory\n", +- (long long)stats.pt4_cnt, fmt_mem(stats.pt4_cnt * +- sizeof(struct pt_entry4))); +- if (stats.pt6_cnt != 0) +- printf("%10lld IPv6 network entries using " +- "%s of memory\n", (long long)stats.pt6_cnt, +- fmt_mem(stats.pt6_cnt * sizeof(struct pt_entry6))); ++ for (i = 0; i < AID_MAX; i++) { ++ if (stats.pt_cnt[i] == 0) ++ continue; ++ pts += stats.pt_cnt[i] * pt_sizes[i]; ++ printf("%10lld %s network entries using %s of memory\n", ++ (long long)stats.pt_cnt[i], aid_vals[i].name, ++ fmt_mem(stats.pt_cnt[i] * pt_sizes[i])); ++ } + printf("%10lld rib entries using %s of memory\n", + (long long)stats.rib_cnt, fmt_mem(stats.rib_cnt * + sizeof(struct rib_entry))); +@@ -1272,9 +1335,7 @@ show_rib_memory_msg(struct imsg *imsg) + (long long)stats.attr_refs); + printf("%10lld BGP attributes using %s of memory\n", + (long long)stats.attr_dcnt, fmt_mem(stats.attr_data)); +- printf("RIB using %s of memory\n", fmt_mem( +- stats.pt4_cnt * sizeof(struct pt_entry4) + +- stats.pt6_cnt * sizeof(struct pt_entry6) + ++ printf("RIB using %s of memory\n", fmt_mem(pts + stats.prefix_cnt * sizeof(struct prefix) + -+ stats.rib_cnt * sizeof(struct rib_entry) + + stats.rib_cnt * sizeof(struct rib_entry) + stats.path_cnt * sizeof(struct rde_aspath) + - stats.aspath_size + stats.attr_cnt * sizeof(struct attr) + - stats.attr_data)); +@@ -1328,30 +1389,6 @@ show_community(u_char *data, u_int16_t l + } + } + +-const char * +-get_ext_subtype(u_int8_t type) +-{ +- static char etype[6]; +- +- switch (type) { +- case EXT_COMMUNITY_ROUTE_TGT: +- return "rt"; /* route target */ +- case EXT_CUMMUNITY_ROUTE_ORIG: +- return "soo"; /* source of origin */ +- case EXT_COMMUNITY_OSPF_DOM_ID: +- return "odi"; /* ospf domain id */ +- case EXT_COMMUNITY_OSPF_RTR_TYPE: +- return "ort"; /* ospf route type */ +- case EXT_COMMUNITY_OSPF_RTR_ID: +- return "ori"; /* ospf router id */ +- case EXT_COMMUNITY_BGP_COLLECT: +- return "bdc"; /* bgp data collection */ +- default: +- snprintf(etype, sizeof(etype), "[%i]", (int)type); +- return etype; +- } +-} +- + void + show_ext_community(u_char *data, u_int16_t len) + { +@@ -1372,24 +1409,25 @@ show_ext_community(u_char *data, u_int16 + case EXT_COMMUNITY_TWO_AS: + memcpy(&as2, data + i + 2, sizeof(as2)); + memcpy(&u32, data + i + 4, sizeof(u32)); +- printf("%s %hu:%u", get_ext_subtype(subtype), as2, u32); ++ printf("%s %s:%u", log_ext_subtype(subtype), ++ log_as(ntohs(as2)), ntohl(u32)); + break; + case EXT_COMMUNITY_IPV4: + memcpy(&ip, data + i + 2, sizeof(ip)); + memcpy(&u16, data + i + 6, sizeof(u16)); +- printf("%s %s:%hu", get_ext_subtype(subtype), +- inet_ntoa(ip), u16); ++ printf("%s %s:%hu", log_ext_subtype(subtype), ++ inet_ntoa(ip), ntohs(u16)); + break; + case EXT_COMMUNITY_FOUR_AS: + memcpy(&as4, data + i + 2, sizeof(as4)); + memcpy(&u16, data + i + 6, sizeof(u16)); +- printf("%s %s:%hu", get_ext_subtype(subtype), +- log_as(as4), u16); ++ printf("%s %s:%hu", log_ext_subtype(subtype), ++ log_as(ntohl(as4)), ntohs(u16)); + break; + case EXT_COMMUNITY_OPAQUE: + memcpy(&ext, data + i, sizeof(ext)); + ext = betoh64(ext) & 0xffffffffffffLL; +- printf("%s 0x%llx", get_ext_subtype(subtype), ext); ++ printf("%s 0x%llx", log_ext_subtype(subtype), ext); + break; + default: + memcpy(&ext, data + i, sizeof(ext)); diff --git a/net/openbgpd/files/patch-bgpctl_fmt_scaled.c b/net/openbgpd/files/patch-bgpctl_fmt_scaled.c deleted file mode 100644 index 66e5b90ef4c9..000000000000 --- a/net/openbgpd/files/patch-bgpctl_fmt_scaled.c +++ /dev/null @@ -1,271 +0,0 @@ ---- /dev/null 1 Jan 1970 00:00:00 -0000 -+++ bgpctl/fmt_scaled.c 2008-03-18 13:27:29.000000000 +0100 -@@ -0,0 +1,268 @@ -+/* $OpenBSD: fmt_scaled.c,v 1.9 2007/03/20 03:42:52 tedu Exp $ */ -+ -+/* -+ * Copyright (c) 2001, 2002, 2003 Ian F. Darwin. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The name of the author may not be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/* -+ * fmt_scaled: Format numbers scaled for human comprehension -+ * scan_scaled: Scan numbers in this format. -+ * -+ * "Human-readable" output uses 4 digits max, and puts a unit suffix at -+ * the end. Makes output compact and easy-to-read esp. on huge disks. -+ * Formatting code was originally in OpenBSD "df", converted to library routine. -+ * Scanning code written for OpenBSD libutil. -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <errno.h> -+#include <string.h> -+#include <ctype.h> -+#include <limits.h> -+ -+#include "util.h" -+ -+typedef enum { -+ NONE = 0, KILO = 1, MEGA = 2, GIGA = 3, TERA = 4, PETA = 5, EXA = 6 -+} unit_type; -+ -+/* These three arrays MUST be in sync! XXX make a struct */ -+static unit_type units[] = { NONE, KILO, MEGA, GIGA, TERA, PETA, EXA }; -+static char scale_chars[] = "BKMGTPE"; -+static long long scale_factors[] = { -+ 1LL, -+ 1024LL, -+ 1024LL*1024, -+ 1024LL*1024*1024, -+ 1024LL*1024*1024*1024, -+ 1024LL*1024*1024*1024*1024, -+ 1024LL*1024*1024*1024*1024*1024, -+}; -+#define SCALE_LENGTH (sizeof(units)/sizeof(units[0])) -+ -+#define MAX_DIGITS (SCALE_LENGTH * 3) /* XXX strlen(sprintf("%lld", -1)? */ -+ -+/** Convert the given input string "scaled" into numeric in "result". -+ * Return 0 on success, -1 and errno set on error. -+ */ -+int -+scan_scaled(char *scaled, long long *result) -+{ -+ char *p = scaled; -+ int sign = 0; -+ unsigned int i, ndigits = 0, fract_digits = 0; -+ long long scale_fact = 1, whole = 0, fpart = 0; -+ -+ /* Skip leading whitespace */ -+ while (isascii(*p) && isspace(*p)) -+ ++p; -+ -+ /* Then at most one leading + or - */ -+ while (*p == '-' || *p == '+') { -+ if (*p == '-') { -+ if (sign) { -+ errno = EINVAL; -+ return -1; -+ } -+ sign = -1; -+ ++p; -+ } else if (*p == '+') { -+ if (sign) { -+ errno = EINVAL; -+ return -1; -+ } -+ sign = +1; -+ ++p; -+ } -+ } -+ -+ /* Main loop: Scan digits, find decimal point, if present. -+ * We don't allow exponentials, so no scientific notation -+ * (but note that E for Exa might look like e to some!). -+ * Advance 'p' to end, to get scale factor. -+ */ -+ for (; isascii(*p) && (isdigit(*p) || *p=='.'); ++p) { -+ if (*p == '.') { -+ if (fract_digits > 0) { /* oops, more than one '.' */ -+ errno = EINVAL; -+ return -1; -+ } -+ fract_digits = 1; -+ continue; -+ } -+ -+ i = (*p) - '0'; /* whew! finally a digit we can use */ -+ if (fract_digits > 0) { -+ if (fract_digits >= MAX_DIGITS-1) -+ /* ignore extra fractional digits */ -+ continue; -+ fract_digits++; /* for later scaling */ -+ fpart *= 10; -+ fpart += i; -+ } else { /* normal digit */ -+ if (++ndigits >= MAX_DIGITS) { -+ errno = ERANGE; -+ return -1; -+ } -+ whole *= 10; -+ whole += i; -+ } -+ } -+ -+ if (sign) { -+ whole *= sign; -+ fpart *= sign; -+ } -+ -+ /* If no scale factor given, we're done. fraction is discarded. */ -+ if (!*p) { -+ *result = whole; -+ return 0; -+ } -+ -+ /* Validate scale factor, and scale whole and fraction by it. */ -+ for (i = 0; i < SCALE_LENGTH; i++) { -+ -+ /** Are we there yet? */ -+ if (*p == scale_chars[i] || -+ *p == tolower(scale_chars[i])) { -+ -+ /* If it ends with alphanumerics after the scale char, bad. */ -+ if (isalnum(*(p+1))) { -+ errno = EINVAL; -+ return -1; -+ } -+ scale_fact = scale_factors[i]; -+ -+ /* scale whole part */ -+ whole *= scale_fact; -+ -+ /* truncate fpart so it does't overflow. -+ * then scale fractional part. -+ */ -+ while (fpart >= LLONG_MAX / scale_fact) { -+ fpart /= 10; -+ fract_digits--; -+ } -+ fpart *= scale_fact; -+ if (fract_digits > 0) { -+ for (i = 0; i < fract_digits -1; i++) -+ fpart /= 10; -+ } -+ whole += fpart; -+ *result = whole; -+ return 0; -+ } -+ } -+ errno = ERANGE; -+ return -1; -+} -+ -+/* Format the given "number" into human-readable form in "result". -+ * Result must point to an allocated buffer of length FMT_SCALED_STRSIZE. -+ * Return 0 on success, -1 and errno set if error. -+ */ -+int -+fmt_scaled(long long number, char *result) -+{ -+ long long abval, fract = 0; -+ unsigned int i; -+ unit_type unit = NONE; -+ -+ abval = (number < 0LL) ? -number : number; /* no long long_abs yet */ -+ -+ /* Not every negative long long has a positive representation. -+ * Also check for numbers that are just too darned big to format -+ */ -+ if (abval < 0 || abval / 1024 >= scale_factors[SCALE_LENGTH-1]) { -+ errno = ERANGE; -+ return -1; -+ } -+ -+ /* scale whole part; get unscaled fraction */ -+ for (i = 0; i < SCALE_LENGTH; i++) { -+ if (abval/1024 < scale_factors[i]) { -+ unit = units[i]; -+ fract = (i == 0) ? 0 : abval % scale_factors[i]; -+ number /= scale_factors[i]; -+ if (i > 0) -+ fract /= scale_factors[i - 1]; -+ break; -+ } -+ } -+ -+ fract = (10 * fract + 512) / 1024; -+ /* if the result would be >= 10, round main number */ -+ if (fract == 10) { -+ if (number >= 0) -+ number++; -+ else -+ number--; -+ fract = 0; -+ } -+ -+ if (number == 0) -+ strlcpy(result, "0B", FMT_SCALED_STRSIZE); -+ else if (unit == NONE || number >= 100 || number <= -100) { -+ if (fract >= 5) { -+ if (number >= 0) -+ number++; -+ else -+ number--; -+ } -+ (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld%c", -+ number, scale_chars[unit]); -+ } else -+ (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld.%1lld%c", -+ number, fract, scale_chars[unit]); -+ -+ return 0; -+} -+ -+#ifdef MAIN -+/* -+ * This is the original version of the program in the man page. -+ * Copy-and-paste whatever you need from it. -+ */ -+int -+main(int argc, char **argv) -+{ -+ char *cinput = "1.5K", buf[FMT_SCALED_STRSIZE]; -+ long long ninput = 10483892, result; -+ -+ if (scan_scaled(cinput, &result) == 0) -+ printf("\"%s\" -> %lld\n", cinput, result); -+ else -+ perror(cinput); -+ -+ if (fmt_scaled(ninput, buf) == 0) -+ printf("%lld -> \"%s\"\n", ninput, buf); -+ else -+ fprintf(stderr, "%lld invalid (%s)\n", ninput, strerror(errno)); -+ -+ return 0; -+} -+#endif diff --git a/net/openbgpd/files/patch-bgpctl_irr_asset.c b/net/openbgpd/files/patch-bgpctl_irr_asset.c deleted file mode 100644 index 4ced146617df..000000000000 --- a/net/openbgpd/files/patch-bgpctl_irr_asset.c +++ /dev/null @@ -1,23 +0,0 @@ -Index: bgpctl/irr_asset.c -=================================================================== -RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_asset.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.1.1.2 -diff -u -p -r1.1.1.1 -r1.1.1.2 ---- bgpctl/irr_asset.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpctl/irr_asset.c 9 Jul 2009 16:49:55 -0000 1.1.1.2 -@@ -1,4 +1,4 @@ --/* $OpenBSD: irr_asset.c,v 1.7 2007/03/31 12:46:55 henning Exp $ */ -+/* $OpenBSD: irr_asset.c,v 1.8 2009/04/14 21:10:54 jj Exp $ */ - - /* - * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> -@@ -105,7 +105,7 @@ asset_get(char *name) - break; - case T_AUTNUM: - /* -- * make a dummy as-set with the the AS both as name -+ * make a dummy as-set with the AS both as name - * and its only member - */ - asset_add_as(ass, name); diff --git a/net/openbgpd/files/patch-bgpctl_irr_parser.c b/net/openbgpd/files/patch-bgpctl_irr_parser.c index a24d580b0c13..af140f8b0f82 100644 --- a/net/openbgpd/files/patch-bgpctl_irr_parser.c +++ b/net/openbgpd/files/patch-bgpctl_irr_parser.c @@ -1,16 +1,41 @@ Index: bgpctl/irr_parser.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_parser.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.2 -diff -u -p -r1.1.1.1 -r1.2 ---- bgpctl/irr_parser.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpctl/irr_parser.c 30 Jun 2009 06:40:06 -0000 1.2 -@@ -18,6 +18,7 @@ +retrieving revision 1.1.1.5 +retrieving revision 1.4 +diff -u -p -r1.1.1.5 -r1.4 +--- bgpctl/irr_parser.c 14 Feb 2010 20:20:14 -0000 1.1.1.5 ++++ bgpctl/irr_parser.c 4 Feb 2010 16:22:26 -0000 1.4 +@@ -1,4 +1,4 @@ +-/* $OpenBSD: irr_parser.c,v 1.8 2007/03/05 22:34:08 henning Exp $ */ ++/* $OpenBSD: irr_parser.c,v 1.9 2009/09/08 15:40:25 claudio Exp $ */ - #include <sys/types.h> - #include <sys/param.h> -+ - #include <ctype.h> - #include <err.h> - #include <stdio.h> + /* + * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> +@@ -81,6 +81,7 @@ parse_response(FILE *f, enum qtype qtype + return (-1); + break; + case QTYPE_ROUTE: ++ case QTYPE_ROUTE6: + if ((n = parse_route(key, val)) == -1) + return (-1); + break; +@@ -281,7 +282,7 @@ parse_policy(char *key, char *val) + !isdigit(tok[2])) + errx(1, "peering spec \"%s\": format " + "error, AS expected", tok); +- pi->peer_as = strtonum(tok + 2, 1, USHRT_MAX, ++ pi->peer_as = strtonum(tok + 2, 1, UINT_MAX, + &errstr); + if (errstr) + errx(1, "peering spec \"%s\": format " +@@ -407,7 +408,8 @@ parse_asset(char *key, char *val) + int + parse_route(char *key, char *val) + { +- if (strcmp(key, "route")) /* ignore everything else */ ++ if (strcmp(key, "route") && strcmp(key, "route6")) ++ /* ignore everything else */ + return (0); + + /* route is single-value, but seen trailing , in the wild */ diff --git a/net/openbgpd/files/patch-bgpctl_irr_prefix.c b/net/openbgpd/files/patch-bgpctl_irr_prefix.c new file mode 100644 index 000000000000..2d1d5217c4cc --- /dev/null +++ b/net/openbgpd/files/patch-bgpctl_irr_prefix.c @@ -0,0 +1,156 @@ +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 +--- 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 +@@ -1,4 +1,4 @@ +-/* $OpenBSD: irr_prefix.c,v 1.15 2007/05/27 18:54:25 henning Exp $ */ ++/* $OpenBSD: irr_prefix.c,v 1.17 2009/09/08 16:11:36 sthen Exp $ */ + + /* + * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> +@@ -29,6 +29,7 @@ + #include <arpa/inet.h> + + #include "irrfilter.h" ++#include "bgpd.h" + + void prefixset_aggregate(struct prefix_set *); + int prefix_aggregate(struct irr_prefix *, const struct irr_prefix *); +@@ -63,7 +64,11 @@ prefixset_get(char *as) + fflush(stdout); + } + curpfxs = pfxs; +- if (whois(as, QTYPE_ROUTE) == -1) ++ if ((irrflags & F_IPV4) && whois(as, QTYPE_ROUTE) == -1) ++ errx(1, "whois error, prefixset_get %s", as); ++ if ((irrflags & F_IPV6) && whois(as, QTYPE_ROUTE6) == -1) ++ errx(1, "whois error, prefixset_get %s", as); ++ if (whois(as, QTYPE_ROUTE6) == -1) + errx(1, "whois error, prefixset_get %s", as); + curpfxs = NULL; + if (irrverbose >= 3) +@@ -80,9 +85,11 @@ prefixset_addmember(char *s) + void *p; + u_int i; + struct irr_prefix *pfx; +- int len; ++ int len, ret; ++ char *slash; ++ const char *errstr; + +- if (strchr(s, '/') == NULL) { ++ if ((slash = strchr(s, '/')) == NULL) { + fprintf(stderr, "%s: prefix %s does not have the len " + "specified, ignoring\n", curpfxs->as, s); + return (0); +@@ -92,17 +99,26 @@ prefixset_addmember(char *s) + err(1, "prefixset_addmember calloc"); + + if ((len = inet_net_pton(AF_INET, s, &pfx->addr.in, +- sizeof(pfx->addr.in))) == -1) { +- if (errno == ENOENT) { +- fprintf(stderr, "%s: prefix \"%s\": parse error\n", ++ sizeof(pfx->addr.in))) != -1) { ++ pfx->af = AF_INET; ++ } else { ++ len = strtonum(slash + 1, 0, 128, &errstr); ++ if (errstr) ++ errx(1, "prefixset_addmember %s prefix %s: prefixlen " ++ "is %s", curpfxs->as, s, errstr); ++ *slash = '\0'; ++ ++ if ((ret = inet_pton(AF_INET6, s, &pfx->addr.in6)) == -1) ++ err(1, "prefixset_addmember %s prefix \"%s\"", + curpfxs->as, s); ++ else if (ret == 0) { ++ fprintf(stderr, "prefixset_addmember %s prefix \"%s\": " ++ "No matching address family found", curpfxs->as, s); ++ free(pfx); + return (0); +- } else +- err(1, "prefixset_addmember %s inet_net_pton \"%s\"", +- curpfxs->as, s); ++ } ++ pfx->af = AF_INET6; + } +- +- pfx->af = AF_INET; + pfx->len = pfx->maxlen = len; + + /* yes, there are dupes... e. g. from multiple sources */ +@@ -175,24 +191,47 @@ prefixset_aggregate(struct prefix_set *p + int + prefix_aggregate(struct irr_prefix *a, const struct irr_prefix *b) + { +- in_addr_t mask; ++ in_addr_t mask; ++ struct in6_addr ma; ++ struct in6_addr mb; + + if (a->len == 0) + return (1); + +- mask = htonl(0xffffffff << (32 - a->len)); ++ if (a->af != b->af) ++ /* We cannot aggregate addresses of different families. */ ++ return (0); + +- if ((a->addr.in.s_addr & mask) == (b->addr.in.s_addr & mask)) +- return (1); ++ if (a->af == AF_INET) { ++ mask = htonl(prefixlen2mask(a->len)); ++ if ((a->addr.in.s_addr & mask) == (b->addr.in.s_addr & mask)) ++ return (1); ++ } else if (a->af == AF_INET6) { ++ inet6applymask(&ma, &a->addr.in6, a->len); ++ inet6applymask(&mb, &b->addr.in6, a->len); ++ if (IN6_ARE_ADDR_EQUAL(&ma, &mb)) ++ return (1); ++ } + + /* see wether we can fold them in one */ + if (a->len == b->len && a->len > 1) { +- mask = htonl(0xffffffff << (32 - (a->len - 1))); +- if ((a->addr.in.s_addr & mask) == +- (b->addr.in.s_addr & mask)) { +- a->len--; +- a->addr.in.s_addr &= mask; +- return (1); ++ if (a->af == AF_INET) { ++ mask = htonl(prefixlen2mask(a->len - 1)); ++ if ((a->addr.in.s_addr & mask) == ++ (b->addr.in.s_addr & mask)) { ++ a->len--; ++ a->addr.in.s_addr &= mask; ++ return (1); ++ } ++ } else if (a->af == AF_INET6) { ++ inet6applymask(&ma, &a->addr.in6, a->len - 1); ++ inet6applymask(&mb, &b->addr.in6, a->len - 1); ++ ++ if (IN6_ARE_ADDR_EQUAL(&ma, &mb)) { ++ a->len--; ++ memcpy(&a->addr.in6, &ma, sizeof(ma)); ++ return (1); ++ } + } + } + +@@ -219,6 +258,13 @@ irr_prefix_cmp(const void *a, const void + if (ntohl(pa->addr.in.s_addr) > + ntohl(pb->addr.in.s_addr)) + return (1); ++ } else if (pa->af == AF_INET6) { ++ for (r = 0; r < 16; r++) { ++ if (pa->addr.in6.s6_addr[r] < pb->addr.in6.s6_addr[r]) ++ return (-1); ++ if (pa->addr.in6.s6_addr[r] > pb->addr.in6.s6_addr[r]) ++ return (1); ++ } + } else + errx(1, "irr_prefix_cmp unknown af %u", pa->af); + diff --git a/net/openbgpd/files/patch-bgpctl_irrfilter.h b/net/openbgpd/files/patch-bgpctl_irrfilter.h index bffc8bd24629..cc9b1df0799a 100644 --- a/net/openbgpd/files/patch-bgpctl_irrfilter.h +++ b/net/openbgpd/files/patch-bgpctl_irrfilter.h @@ -1,12 +1,18 @@ Index: bgpctl/irrfilter.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irrfilter.h,v -retrieving revision 1.1.1.1 -retrieving revision 1.2 -diff -u -p -r1.1.1.1 -r1.2 ---- bgpctl/irrfilter.h 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpctl/irrfilter.h 30 Jun 2009 06:40:06 -0000 1.2 -@@ -16,6 +16,10 @@ +retrieving revision 1.1.1.5 +retrieving revision 1.3 +diff -u -p -r1.1.1.5 -r1.3 +--- bgpctl/irrfilter.h 14 Feb 2010 20:20:14 -0000 1.1.1.5 ++++ bgpctl/irrfilter.h 4 Feb 2010 16:22:26 -0000 1.3 +@@ -1,4 +1,4 @@ +-/* $OpenBSD: irrfilter.h,v 1.7 2007/03/06 16:45:34 henning Exp $ */ ++/* $OpenBSD: irrfilter.h,v 1.9 2009/09/08 16:11:36 sthen Exp $ */ + + /* + * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> +@@ -16,11 +16,17 @@ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ @@ -17,3 +23,37 @@ diff -u -p -r1.1.1.1 -r1.2 #include <sys/queue.h> #include <sys/tree.h> #include <netinet/in.h> + + #define F_IMPORTONLY 0x01 /* skip export: items */ ++#define F_IPV4 0x02 /* use IPv4 items */ ++#define F_IPV6 0x04 /* use IPv6 items */ + + int irrflags; + int irrverbose; +@@ -37,7 +43,7 @@ struct policy_item { + char *action; + char *filter; + enum pdir dir; +- u_int16_t peer_as; ++ u_int32_t peer_as; + }; + + TAILQ_HEAD(policy_head, policy_item); +@@ -55,7 +61,8 @@ enum qtype { + QTYPE_NONE, + QTYPE_OWNAS, + QTYPE_ASSET, +- QTYPE_ROUTE ++ QTYPE_ROUTE, ++ QTYPE_ROUTE6 + }; + + struct as_set { +@@ -72,6 +79,7 @@ struct as_set { + struct irr_prefix { + union { + struct in_addr in; ++ struct in6_addr in6; + } addr; + sa_family_t af; + u_int8_t len; diff --git a/net/openbgpd/files/patch-bgpctl_parser.c b/net/openbgpd/files/patch-bgpctl_parser.c index bb3e6ef03a57..dd0ae874e3df 100644 --- a/net/openbgpd/files/patch-bgpctl_parser.c +++ b/net/openbgpd/files/patch-bgpctl_parser.c @@ -1,14 +1,14 @@ Index: bgpctl/parser.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/parser.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.3 -diff -u -p -r1.1.1.1 -r1.3 ---- bgpctl/parser.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpctl/parser.c 9 Jul 2009 17:22:12 -0000 1.3 +retrieving revision 1.1.1.6 +retrieving revision 1.4 +diff -u -p -r1.1.1.6 -r1.4 +--- bgpctl/parser.c 14 Feb 2010 20:20:14 -0000 1.1.1.6 ++++ bgpctl/parser.c 4 Feb 2010 16:22:26 -0000 1.4 @@ -1,4 +1,4 @@ --/* $OpenBSD: parser.c,v 1.50 2008/06/15 09:58:43 claudio Exp $ */ -+/* $OpenBSD: parser.c,v 1.54 2009/06/12 16:44:02 claudio Exp $ */ +-/* $OpenBSD: parser.c,v 1.54 2009/06/12 16:44:02 claudio Exp $ */ ++/* $OpenBSD: parser.c,v 1.60 2010/01/13 06:04:00 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -23,126 +23,144 @@ diff -u -p -r1.1.1.1 -r1.3 #include <sys/types.h> #include <sys/socket.h> -@@ -42,6 +46,7 @@ enum token_type { - ASTYPE, - PREFIX, - PEERDESC, -+ RIBNAME, - COMMUNITY, - LOCALPREF, - MED, -@@ -72,6 +77,7 @@ static const struct token t_show_summary - static const struct token t_show_fib[]; - static const struct token t_show_rib[]; - static const struct token t_show_rib_neigh[]; -+static const struct token t_show_rib_rib[]; - static const struct token t_show_neighbor[]; - static const struct token t_show_neighbor_modifiers[]; - static const struct token t_fib[]; -@@ -148,6 +154,7 @@ static const struct token t_show_rib[] = - { FLAG, "in", F_CTL_ADJ_IN, t_show_rib}, - { FLAG, "out", F_CTL_ADJ_OUT, t_show_rib}, - { KEYWORD, "neighbor", NONE, t_show_rib_neigh}, -+ { KEYWORD, "table", NONE, t_show_rib_rib}, - { KEYWORD, "summary", SHOW_SUMMARY, t_show_summary}, - { KEYWORD, "memory", SHOW_RIB_MEM, NULL}, - { FAMILY, "", NONE, t_show_rib}, -@@ -161,6 +168,11 @@ static const struct token t_show_rib_nei - { ENDTOKEN, "", NONE, NULL} +@@ -97,6 +101,7 @@ 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_main[] = { + { KEYWORD, "reload", RELOAD, NULL}, +@@ -105,6 +110,7 @@ static const struct token t_main[] = { + { KEYWORD, "neighbor", NEIGHBOR, t_neighbor}, + { KEYWORD, "network", NONE, t_network}, + { KEYWORD, "irrfilter", IRRFILTER, t_irrfilter}, ++ { KEYWORD, "log", NONE, t_log}, + { ENDTOKEN, "", NONE, NULL} + }; + +@@ -311,6 +317,12 @@ static const struct token t_irrfilter_op + { ENDTOKEN, "", NONE, NULL} }; -+static const struct token t_show_rib_rib[] = { -+ { RIBNAME, "", NONE, t_show_rib}, -+ { ENDTOKEN, "", NONE, NULL} ++static const struct token t_log[] = { ++ { KEYWORD, "verbose", LOG_VERBOSE, NULL}, ++ { KEYWORD, "brief", LOG_BRIEF, NULL}, ++ { ENDTOKEN, "", NONE, NULL} +}; + - static const struct token t_show_neighbor[] = { - { NOTOKEN, "", NONE, NULL}, - { PEERADDRESS, "", NONE, t_show_neighbor_modifiers}, -@@ -456,6 +468,15 @@ match_token(int *argc, char **argv[], co - t = &table[i]; - } - break; -+ case RIBNAME: -+ if (!match && word != NULL && strlen(word) > 0) { -+ if (strlcpy(res.rib, word, sizeof(res.rib)) >= -+ sizeof(res.rib)) -+ errx(1, "rib name too long"); + static struct parse_result res; + + const struct token *match_token(int *argc, char **argv[], +@@ -336,6 +348,7 @@ parse(int argc, char *argv[]) + bzero(&res, sizeof(res)); + res.community.as = COMMUNITY_UNSET; + res.community.type = COMMUNITY_UNSET; ++ res.flags = (F_IPV4 | F_IPV6); + TAILQ_INIT(&res.set); + if ((res.irr_outdir = getcwd(NULL, 0)) == NULL) { + fprintf(stderr, "getcwd failed: %s", strerror(errno)); +@@ -404,15 +417,22 @@ match_token(int *argc, char **argv[], co + case FAMILY: + if (word == NULL) + break; +- if (!strcmp(word, "inet") || !strcmp(word, "IPv4")) { ++ if (!strcmp(word, "inet") || ++ !strcasecmp(word, "IPv4")) { + match++; + t = &table[i]; ++ res.aid = AID_INET; + } -+ break; - case COMMUNITY: - if (word != NULL && strlen(word) > 0 && - parse_community(word, &res)) { -@@ -547,6 +568,9 @@ show_valid_args(const struct token table - case PEERDESC: - fprintf(stderr, " <neighbor description>\n"); ++ if (!strcmp(word, "inet6") || ++ !strcasecmp(word, "IPv6")) { + match++; + t = &table[i]; +- res.af = AF_INET; ++ res.aid = AID_INET6; + } +- if (!strcmp(word, "inet6") || !strcmp(word, "IPv6")) { ++ if (!strcasecmp(word, "VPNv4")) { + match++; + t = &table[i]; +- res.af = AF_INET6; ++ res.aid = AID_VPN_IPv4; + } break; -+ case RIBNAME: -+ fprintf(stderr, " <rib name>\n"); -+ break; - case COMMUNITY: - fprintf(stderr, " <community>\n"); + case ADDRESS: +@@ -584,7 +604,7 @@ show_valid_args(const struct token table + fprintf(stderr, " <pftable>\n"); + break; + case FAMILY: +- fprintf(stderr, " [ inet | inet6 | IPv4 | IPv6 ]\n"); ++ fprintf(stderr, " [ inet | inet6 | IPv4 | IPv6 | VPNv4 ]\n"); break; -@@ -686,7 +710,7 @@ parse_asnum(const char *word, u_int32_t + case GETOPT: + fprintf(stderr, " <options>\n"); +@@ -608,7 +628,7 @@ parse_addr(const char *word, struct bgpd + bzero(&ina, sizeof(ina)); + + if (inet_net_pton(AF_INET, word, &ina, sizeof(ina)) != -1) { +- addr->af = AF_INET; ++ addr->aid = AID_INET; + addr->v4 = ina; + return (1); + } +@@ -618,13 +638,7 @@ parse_addr(const char *word, struct bgpd + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_flags = AI_NUMERICHOST; + if (getaddrinfo(word, "0", &hints, &r) == 0) { +- addr->af = AF_INET6; +- memcpy(&addr->v6, +- &((struct sockaddr_in6 *)r->ai_addr)->sin6_addr, +- sizeof(addr->v6)); +- addr->scope_id = +- ((struct sockaddr_in6 *)r->ai_addr)->sin6_scope_id; +- ++ sa2addr(r->ai_addr, addr); + freeaddrinfo(r); + return (1); + } +@@ -663,15 +677,15 @@ parse_prefix(const char *word, struct bg + if (parse_addr(word, addr) == 0) + return (0); + +- switch (addr->af) { +- case AF_INET: ++ switch (addr->aid) { ++ case AID_INET: + if (mask == -1) + mask = 32; + if (mask > 32) + errx(1, "invalid netmask: too large"); + addr->v4.s_addr = addr->v4.s_addr & htonl(prefixlen2mask(mask)); + break; +- case AF_INET6: ++ case AID_INET6: + if (mask == -1) + mask = 128; + inet6applymask(&addr->v6, &addr->v6, mask); +@@ -706,7 +720,7 @@ parse_asnum(const char *word, u_int32_t if (errstr) errx(1, "AS number is %s: %s", errstr, word); } else { -- uval = strtonum(word, 0, USHRT_MAX - 1, &errstr); -+ uval = strtonum(word, 0, ASNUM_MAX - 1, &errstr); +- uval = strtonum(word, 0, ASNUM_MAX - 1, &errstr); ++ uval = strtonum(word, 0, UINT_MAX, &errstr); if (errstr) errx(1, "AS number is %s: %s", errstr, word); } -@@ -801,7 +825,7 @@ parse_community(const char *word, struct - type = getcommunity(p); +@@ -882,8 +896,14 @@ bgpctl_getopt(int *argc, char **argv[], + int ch; - done: -- if (as == 0 || as == USHRT_MAX) { -+ if (as == 0) { - fprintf(stderr, "Invalid community\n"); - return (0); - } -@@ -814,7 +838,7 @@ done: + optind = optreset = 1; +- while ((ch = getopt((*argc) + 1, (*argv) - 1, "o:")) != -1) { ++ while ((ch = getopt((*argc) + 1, (*argv) - 1, "46o:")) != -1) { + switch (ch) { ++ case '4': ++ res.flags = (res.flags | F_IPV4) & ~F_IPV6; ++ break; ++ case '6': ++ res.flags = (res.flags | F_IPV6) & ~F_IPV4; ++ break; + case 'o': + res.irr_outdir = optarg; break; - default: - /* unknown */ -- fprintf(stderr, "Invalid well-known community\n"); -+ fprintf(stderr, "Unknown well-known community\n"); - return (0); - } - -@@ -856,33 +880,6 @@ parse_nexthop(const char *word, struct p - return (1); - } - --/* XXX local copies from kroute.c, should go to a shared file */ --in_addr_t --prefixlen2mask(u_int8_t prefixlen) --{ -- if (prefixlen == 0) -- return (0); -- -- return (0xffffffff << (32 - prefixlen)); --} -- --void --inet6applymask(struct in6_addr *dest, const struct in6_addr *src, int prefixlen) --{ -- struct in6_addr mask; -- int i; -- -- bzero(&mask, sizeof(mask)); -- for (i = 0; i < prefixlen / 8; i++) -- mask.s6_addr[i] = 0xff; -- i = prefixlen % 8; -- if (i) -- mask.s6_addr[prefixlen / 8] = 0xff00 >> i; -- -- for (i = 0; i < 16; i++) -- dest->s6_addr[i] = src->s6_addr[i] & mask.s6_addr[i]; --} -- - int - bgpctl_getopt(int *argc, char **argv[], int type) - { diff --git a/net/openbgpd/files/patch-bgpctl_parser.h b/net/openbgpd/files/patch-bgpctl_parser.h index a5ffc4417d54..a3bb1fede7af 100644 --- a/net/openbgpd/files/patch-bgpctl_parser.h +++ b/net/openbgpd/files/patch-bgpctl_parser.h @@ -1,22 +1,32 @@ Index: bgpctl/parser.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/parser.h,v -retrieving revision 1.1.1.1 -retrieving revision 1.1.1.2 -diff -u -p -r1.1.1.1 -r1.1.1.2 ---- bgpctl/parser.h 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpctl/parser.h 9 Jul 2009 16:49:55 -0000 1.1.1.2 +retrieving revision 1.1.1.6 +retrieving revision 1.1.1.7 +diff -u -p -r1.1.1.6 -r1.1.1.7 +--- 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 @@ -1,4 +1,4 @@ --/* $OpenBSD: parser.h,v 1.18 2008/06/07 18:14:41 henning Exp $ */ -+/* $OpenBSD: parser.h,v 1.19 2009/06/06 06:05:41 claudio Exp $ */ +-/* $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 $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -56,6 +56,7 @@ struct parse_result { - struct filter_set_head set; - struct filter_community community; - char peerdesc[PEER_DESCR_LEN]; -+ char rib[PEER_DESCR_LEN]; - char *irr_outdir; +@@ -37,6 +37,8 @@ enum actions { + FIB, + FIB_COUPLE, + FIB_DECOUPLE, ++ LOG_VERBOSE, ++ LOG_BRIEF, + NEIGHBOR, + NEIGHBOR_UP, + NEIGHBOR_DOWN, +@@ -61,7 +63,7 @@ struct parse_result { int flags; enum actions action; + u_int8_t prefixlen; +- sa_family_t af; ++ u_int8_t aid; + }; + + __dead void usage(void); diff --git a/net/openbgpd/files/patch-bgpctl_util.h b/net/openbgpd/files/patch-bgpctl_util.h deleted file mode 100644 index 47ad44a5d6ac..000000000000 --- a/net/openbgpd/files/patch-bgpctl_util.h +++ /dev/null @@ -1,122 +0,0 @@ ---- /dev/null 1970-01-01 01:00:00.000000000 +0100 -+++ bgpctl/util.h 2008-03-18 13:27:29.000000000 +0100 -@@ -0,0 +1,119 @@ -+/* $OpenBSD: util.h,v 1.27 2006/06/14 02:14:25 krw Exp $ */ -+/* $NetBSD: util.h,v 1.2 1996/05/16 07:00:22 thorpej Exp $ */ -+ -+/*- -+ * Copyright (c) 1995 -+ * The Regents of the University of California. All rights reserved. -+ * Portions Copyright (c) 1996, Jason Downs. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ */ -+ -+#ifndef _UTIL_H_ -+#define _UTIL_H_ -+ -+#include <sys/cdefs.h> -+#include <sys/types.h> -+ -+/* -+ * fparseln() specific operation flags. -+ */ -+#define FPARSELN_UNESCESC 0x01 -+#define FPARSELN_UNESCCONT 0x02 -+#define FPARSELN_UNESCCOMM 0x04 -+#define FPARSELN_UNESCREST 0x08 -+#define FPARSELN_UNESCALL 0x0f -+ -+/* -+ * opendev() specific operation flags. -+ */ -+#define OPENDEV_PART 0x01 /* Try to open the raw partition. */ -+#define OPENDEV_BLCK 0x04 /* Open block, not character device. */ -+ -+/* -+ * uucplock(3) specific flags. -+ */ -+#define UU_LOCK_INUSE (1) -+#define UU_LOCK_OK (0) -+#define UU_LOCK_OPEN_ERR (-1) -+#define UU_LOCK_READ_ERR (-2) -+#define UU_LOCK_CREAT_ERR (-3) -+#define UU_LOCK_WRITE_ERR (-4) -+#define UU_LOCK_LINK_ERR (-5) -+#define UU_LOCK_TRY_ERR (-6) -+#define UU_LOCK_OWNER_ERR (-7) -+ -+/* -+ * fmt_scaled(3) specific flags. -+ */ -+#define FMT_SCALED_STRSIZE 7 /* minus sign, 4 digits, suffix, null byte */ -+ -+/* -+ * stub struct definitions. -+ */ -+struct __sFILE; -+struct login_cap; -+struct passwd; -+struct termios; -+struct utmp; -+struct winsize; -+ -+__BEGIN_DECLS -+char *fparseln(struct __sFILE *, size_t *, size_t *, const char[3], int); -+void login(struct utmp *); -+int login_tty(int); -+int logout(const char *); -+void logwtmp(const char *, const char *, const char *); -+int opendev(char *, int, int, char **); -+int pidfile(const char *); -+void pw_setdir(const char *); -+char *pw_file(const char *); -+int pw_lock(int retries); -+int pw_mkdb(char *, int); -+int pw_abort(void); -+void pw_init(void); -+void pw_edit(int, const char *); -+void pw_prompt(void); -+void pw_copy(int, int, const struct passwd *, const struct passwd *); -+int pw_scan(char *, struct passwd *, int *); -+void pw_error(const char *, int, int); -+int openpty(int *, int *, char *, struct termios *, struct winsize *); -+int opendisk(const char *path, int flags, char *buf, size_t buflen, -+ int iscooked); -+pid_t forkpty(int *, char *, struct termios *, struct winsize *); -+int getmaxpartitions(void); -+int getrawpartition(void); -+void login_fbtab(const char *, uid_t, gid_t); -+int login_check_expire(struct __sFILE *, struct passwd *, char *, int); -+char *readlabelfs(char *, int); -+const char *uu_lockerr(int _uu_lockresult); -+int uu_lock(const char *_ttyname); -+int uu_lock_txfr(const char *_ttyname, pid_t _pid); -+int uu_unlock(const char *_ttyname); -+int fmt_scaled(long long number, char *result); -+int scan_scaled(char *scaled, long long *result); -+__END_DECLS -+ -+#endif /* !_UTIL_H_ */ diff --git a/net/openbgpd/files/patch-bgpctl_whois.c b/net/openbgpd/files/patch-bgpctl_whois.c new file mode 100644 index 000000000000..3ae7685e7cc1 --- /dev/null +++ b/net/openbgpd/files/patch-bgpctl_whois.c @@ -0,0 +1,24 @@ +Index: bgpctl/whois.c +=================================================================== +RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/whois.c,v +retrieving revision 1.1.1.5 +retrieving revision 1.1.1.6 +diff -u -p -r1.1.1.5 -r1.1.1.6 +--- bgpctl/whois.c 14 Feb 2010 20:20:14 -0000 1.1.1.5 ++++ bgpctl/whois.c 14 Feb 2010 20:27:21 -0000 1.1.1.6 +@@ -1,4 +1,4 @@ +-/* $OpenBSD: whois.c,v 1.3 2007/03/05 16:43:24 henning Exp $ */ ++/* $OpenBSD: whois.c,v 1.4 2009/09/08 15:40:25 claudio Exp $ */ + + /* + * Copyright (c) 2007 Henning Brauer <henning@openbsd.org> +@@ -68,7 +68,8 @@ char *qtype_opts[] = { + "", + "-T aut-num", + "-K -T as-set", +- "-K -T route -i origin" ++ "-K -T route -i origin", ++ "-K -T route6 -i origin" + }; + + char *server = "whois.radb.net"; diff --git a/net/openbgpd/files/patch-bgpd_Makefile b/net/openbgpd/files/patch-bgpd_Makefile index 4c73aee2ade6..a7289abf0dc4 100644 --- a/net/openbgpd/files/patch-bgpd_Makefile +++ b/net/openbgpd/files/patch-bgpd_Makefile @@ -1,20 +1,18 @@ Index: bgpd/Makefile =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/Makefile,v -retrieving revision 1.1.1.1 +retrieving revision 1.1.1.2 retrieving revision 1.6 -diff -u -p -r1.1.1.1 -r1.6 ---- bgpd/Makefile 30 Jun 2009 05:46:15 -0000 1.1.1.1 +diff -u -p -r1.1.1.2 -r1.6 +--- 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,17 +1,23 @@ --# $OpenBSD: Makefile,v 1.27 2007/12/20 17:08:47 henning Exp $ -+# $OpenBSD: Makefile,v 1.28 2009/06/25 14:14:54 deraadt Exp $ +@@ -1,15 +1,23 @@ + # $OpenBSD: Makefile,v 1.28 2009/06/25 14:14:54 deraadt Exp $ --.PATH: ${.CURDIR}/.. +.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 \ rde.c rde_rib.c rde_decide.c rde_prefix.c mrt.c kroute.c \ diff --git a/net/openbgpd/files/patch-bgpd_bgpd.8 b/net/openbgpd/files/patch-bgpd_bgpd.8 index e7b5adbb402c..e90c32eabfd7 100644 --- a/net/openbgpd/files/patch-bgpd_bgpd.8 +++ b/net/openbgpd/files/patch-bgpd_bgpd.8 @@ -1,14 +1,14 @@ Index: bgpd/bgpd.8 =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.8,v -retrieving revision 1.1.1.1 -retrieving revision 1.6 -diff -u -p -r1.1.1.1 -r1.6 ---- bgpd/bgpd.8 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/bgpd.8 22 Oct 2009 15:10:02 -0000 1.6 +retrieving revision 1.1.1.8 +retrieving revision 1.7 +diff -u -p -r1.1.1.8 -r1.7 +--- bgpd/bgpd.8 14 Feb 2010 20:19:57 -0000 1.1.1.8 ++++ bgpd/bgpd.8 4 Feb 2010 16:22:23 -0000 1.7 @@ -1,4 +1,4 @@ --.\" $OpenBSD: bgpd.8,v 1.27 2007/05/31 19:20:22 jmc Exp $ -+.\" $OpenBSD: bgpd.8,v 1.29 2009/08/06 08:53:11 claudio Exp $ +-.\" $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 $ .\" .\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> .\" @@ -16,8 +16,8 @@ diff -u -p -r1.1.1.1 -r1.6 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" --.Dd $Mdocdate: May 31 2007 $ -+.Dd $Mdocdate: September 2 2009 $ +-.Dd $Mdocdate: January 13 2009 $ ++.Dd $Mdocdate: October 26 2009 $ .Dt BGPD 8 .Os .Sh NAME @@ -51,7 +51,19 @@ diff -u -p -r1.1.1.1 -r1.6 default .Nm configuration file -@@ -175,11 +175,6 @@ control socket +@@ -165,6 +165,11 @@ control socket + .%D August 1998 + .Re + .Rs ++.%R RFC 2545 ++.%T "Use of BGP-4 Multiprotocol Extensions for IPv6 Inter-Domain Routing" ++.%D March 1999 ++.Re ++.Rs + .%R RFC 2796 + .%T "BGP Route Reflection - An Alternative to Full Mesh IBGP" + .%D April 2000 +@@ -175,11 +180,6 @@ control socket .%D September 2000 .Re .Rs @@ -63,10 +75,15 @@ diff -u -p -r1.1.1.1 -r1.6 .%R RFC 3682 .%T "The Generalized TTL Security Mechanism (GTSM)" .%D February 2004 -@@ -190,14 +185,29 @@ control socket +@@ -190,6 +190,16 @@ control socket .%D April 2004 .Re .Rs ++.%R RFC 4360 ++.%T "BGP Extended Communities Attribute" ++.%D February 2006 ++.Re ++.Rs +.%R RFC 4486 +.%T "BGP Cease Notification Message Subcodes" +.%D April 2006 @@ -75,14 +92,10 @@ diff -u -p -r1.1.1.1 -r1.6 .%R RFC 4760 .%T "Multiprotocol Extensions for BGP-4" .%D January 2007 - .Re - .Rs --.%R draft-ietf-idr-as4bytes-13 -+.%R RFC 4893 +@@ -199,6 +209,16 @@ control socket .%T "BGP Support for Four-octet AS Number Space" --.%D February 2007 -+.%D May 2007 -+.Re + .%D May 2007 + .Re +.Rs +.%R RFC 5492 +.%T "Capabilities Advertisement with BGP-4" @@ -92,6 +105,7 @@ diff -u -p -r1.1.1.1 -r1.6 +.%R draft-ietf-idr-optional-transitive-00 +.%T "Error Handling for Optional Transitive BGP Attributes" +.%D April 2009 - .Re ++.Re .Sh HISTORY The + .Nm diff --git a/net/openbgpd/files/patch-bgpd_bgpd.c b/net/openbgpd/files/patch-bgpd_bgpd.c index bdea87117a19..520f82348b10 100644 --- a/net/openbgpd/files/patch-bgpd_bgpd.c +++ b/net/openbgpd/files/patch-bgpd_bgpd.c @@ -1,72 +1,145 @@ Index: bgpd/bgpd.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.1.1.3 -diff -u -p -r1.1.1.1 -r1.1.1.3 ---- bgpd/bgpd.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/bgpd.c 10 Aug 2009 21:09:57 -0000 1.1.1.3 +retrieving revision 1.1.1.7 +retrieving revision 1.1.1.8 +diff -u -p -r1.1.1.7 -r1.1.1.8 +--- bgpd/bgpd.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 ++++ bgpd/bgpd.c 14 Feb 2010 20:27:06 -0000 1.1.1.8 @@ -1,4 +1,4 @@ --/* $OpenBSD: bgpd.c,v 1.145 2008/05/12 19:15:02 pyr Exp $ */ -+/* $OpenBSD: bgpd.c,v 1.149 2009/07/20 15:00:13 claudio Exp $ */ +-/* $OpenBSD: bgpd.c,v 1.148 2009/06/07 00:30:23 claudio Exp $ */ ++/* $OpenBSD: bgpd.c,v 1.154 2010/02/11 14:40:06 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -58,6 +58,7 @@ volatile sig_atomic_t reconfig = 0; - pid_t reconfpid = 0; - struct imsgbuf *ibuf_se; - struct imsgbuf *ibuf_rde; -+struct rib_names ribnames = SIMPLEQ_HEAD_INITIALIZER(ribnames); - - void - sighdlr(int sig) -@@ -108,6 +109,7 @@ main(int argc, char *argv[]) - struct filter_rule *r; +@@ -101,15 +101,11 @@ int + main(int argc, char *argv[]) + { + struct bgpd_config conf; +- struct peer *peer_l, *p; + struct mrt_head mrt_l; +- struct network_head net_l; ++ struct peer *peer_l, *p; + struct filter_head *rules_l; +- struct network *net; +- struct filter_rule *r; struct mrt *m; struct listen_addr *la; -+ struct rde_rib *rr; +- struct rde_rib *rr; struct pollfd pfd[POLL_MAX]; pid_t io_pid = 0, rde_pid = 0, pid; char *conffile; -@@ -181,7 +183,8 @@ main(int argc, char *argv[]) +@@ -129,9 +125,8 @@ main(int argc, char *argv[]) + err(1, NULL); + + bzero(&conf, sizeof(conf)); +- LIST_INIT(&mrt_l); +- TAILQ_INIT(&net_l); + TAILQ_INIT(rules_l); ++ LIST_INIT(&mrt_l); + peer_l = NULL; + conf.csock = SOCKET_NAME; +@@ -158,6 +153,7 @@ main(int argc, char *argv[]) + if (conf.opts & BGPD_OPT_VERBOSE) + conf.opts |= BGPD_OPT_VERBOSE2; + conf.opts |= BGPD_OPT_VERBOSE; ++ log_verbose(1); + break; + case 'r': + conf.rcsock = optarg; +@@ -176,12 +172,15 @@ main(int argc, char *argv[]) + if (argc > 0) + usage(); + +- if (parse_config(conffile, &conf, &mrt_l, &peer_l, &net_l, rules_l)) { +- free(rules_l); +- exit(1); +- } +- if (conf.opts & BGPD_OPT_NOACTION) { ++ struct network_head net_l; ++ TAILQ_INIT(&net_l); ++ if (parse_config(conffile, &conf, &mrt_l, &peer_l, &net_l, ++ rules_l)) { ++ free(rules_l); ++ exit(1); ++ } ++ if (conf.opts & BGPD_OPT_VERBOSE) -- print_config(&conf, &net_l, peer_l, rules_l, &mrt_l); -+ print_config(&conf, &ribnames, &net_l, peer_l, rules_l, -+ &mrt_l); - else - fprintf(stderr, "configuration OK\n"); - exit(0); -@@ -225,9 +228,9 @@ main(int argc, char *argv[]) - prepare_listeners(&conf); + print_config(&conf, &ribnames, &net_l, peer_l, rules_l, + &mrt_l); +@@ -225,13 +224,10 @@ main(int argc, char *argv[]) + session_socket_blockmode(pipe_s2r_c[0], BM_NONBLOCK); + session_socket_blockmode(pipe_s2r_c[1], BM_NONBLOCK); +- prepare_listeners(&conf); +- /* fork children */ -- rde_pid = rde_main(&conf, peer_l, &net_l, rules_l, &mrt_l, -+ rde_pid = rde_main(&conf, peer_l, &net_l, rules_l, &mrt_l, &ribnames, - pipe_m2r, pipe_s2r, pipe_m2s, pipe_s2r_c, debug); -- io_pid = session_main(&conf, peer_l, &net_l, rules_l, &mrt_l, -+ 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(&conf, peer_l, &net_l, rules_l, &mrt_l, &ribnames, +- pipe_m2r, pipe_s2r, pipe_m2s, pipe_s2r_c, debug); +- io_pid = session_main(&conf, peer_l, &net_l, rules_l, &mrt_l, &ribnames, +- pipe_m2s, pipe_s2r, pipe_m2r, pipe_s2r_c); ++ rde_pid = rde_main(pipe_m2r, pipe_s2r, pipe_m2s, pipe_s2r_c, debug); ++ io_pid = session_main(pipe_m2s, pipe_s2r, pipe_m2r, pipe_s2r_c, ++ conf.csock, conf.rcsock); setproctitle("parent"); -@@ -271,6 +274,10 @@ main(int argc, char *argv[]) - close(la->fd); - la->fd = -1; - } -+ while ((rr = SIMPLEQ_FIRST(&ribnames))) { -+ SIMPLEQ_REMOVE_HEAD(&ribnames, entry); -+ free(rr); -+ } - mrt_reconfigure(&mrt_l); +@@ -254,33 +250,13 @@ 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, rules_l); + if ((rfd = kr_init(!(conf.flags & BGPD_FLAG_NO_FIB_UPDATE), + conf.rtableid)) == -1) + quit = 1; + if (pftable_clear_all() != 0) + quit = 1; -@@ -452,10 +459,15 @@ reconfigure(char *conffile, struct bgpd_ - struct peer *p; - struct filter_rule *r; - struct listen_addr *la; -+ struct rde_rib *rr; +- while ((net = TAILQ_FIRST(&net_l)) != NULL) { +- TAILQ_REMOVE(&net_l, net, entry); +- filterset_free(&net->net.attrset); +- free(net); +- } +- +- while ((r = TAILQ_FIRST(rules_l)) != NULL) { +- TAILQ_REMOVE(rules_l, r, entry); +- free(r); +- } +- TAILQ_FOREACH(la, conf.listen_addrs, entry) { +- close(la->fd); +- la->fd = -1; +- } +- while ((rr = SIMPLEQ_FIRST(&ribnames))) { +- SIMPLEQ_REMOVE_HEAD(&ribnames, entry); +- free(rr); +- } +- +- mrt_reconfigure(&mrt_l); +- + while (quit == 0) { + bzero(pfd, sizeof(pfd)); + pfd[PFD_PIPE_SESSION].fd = ibuf_se->fd; +@@ -389,11 +365,12 @@ main(int argc, char *argv[]) + LIST_REMOVE(m, entry); + free(m); + } +- while ((la = TAILQ_FIRST(conf.listen_addrs)) != NULL) { +- TAILQ_REMOVE(conf.listen_addrs, la, entry); +- close(la->fd); +- free(la); +- } ++ if (conf.listen_addrs) ++ while ((la = TAILQ_FIRST(conf.listen_addrs)) != NULL) { ++ TAILQ_REMOVE(conf.listen_addrs, la, entry); ++ close(la->fd); ++ free(la); ++ } + free(rules_l); + control_cleanup(conf.csock); +@@ -464,6 +441,10 @@ reconfigure(char *conffile, struct bgpd_ if (parse_config(conffile, conf, mrt_l, peer_l, &net_l, rules_l)) { log_warnx("config file %s has errors, not reloading", conffile); @@ -77,19 +150,59 @@ diff -u -p -r1.1.1.1 -r1.1.1.3 return (1); } -@@ -488,6 +500,15 @@ reconfigure(char *conffile, struct bgpd_ - la->fd = -1; - } +@@ -550,8 +531,8 @@ int + dispatch_imsg(struct imsgbuf *ibuf, int idx) + { + struct imsg imsg; +- int n; +- int rv; ++ ssize_t n; ++ int rv, verbose; -+ /* RIBs for the RDE */ -+ while ((rr = SIMPLEQ_FIRST(&ribnames))) { -+ SIMPLEQ_REMOVE_HEAD(&ribnames, entry); -+ 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, + if ((n = imsg_read(ibuf)) == -1) + return (-1); +@@ -692,6 +673,11 @@ dispatch_imsg(struct imsgbuf *ibuf, int + carp_demote_set(msg->demote_group, msg->level); + } + break; ++ case IMSG_CTL_LOG_VERBOSE: ++ /* already checked by SE */ ++ memcpy(&verbose, imsg.data, sizeof(verbose)); ++ log_verbose(verbose); ++ break; + default: + break; + } +@@ -707,7 +693,7 @@ send_nexthop_update(struct kroute_nextho + { + char *gw = NULL; + +- if (msg->gateway.af) ++ if (msg->gateway.aid) + if (asprintf(&gw, ": via %s", + log_addr(&msg->gateway)) == -1) { + log_warn("send_nexthop_update"); +@@ -717,7 +703,7 @@ send_nexthop_update(struct kroute_nextho + log_info("nexthop %s now %s%s%s", log_addr(&msg->nexthop), + msg->valid ? "valid" : "invalid", + msg->connected ? ": directly connected" : "", +- msg->gateway.af ? gw : ""); ++ msg->gateway.aid ? gw : ""); + + free(gw); + +@@ -758,12 +744,12 @@ bgpd_redistribute(int type, struct krout + 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.af = AF_INET6; ++ net.prefix.aid = AID_INET6; + memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr)); + net.prefixlen = kr6->prefixlen; + } diff --git a/net/openbgpd/files/patch-bgpd_bgpd.conf.5 b/net/openbgpd/files/patch-bgpd_bgpd.conf.5 index bee730547c3b..b1ccbec4a8f2 100644 --- a/net/openbgpd/files/patch-bgpd_bgpd.conf.5 +++ b/net/openbgpd/files/patch-bgpd_bgpd.conf.5 @@ -1,14 +1,14 @@ Index: bgpd/bgpd.conf.5 =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.conf.5,v -retrieving revision 1.1.1.1 -retrieving revision 1.5 -diff -u -p -r1.1.1.1 -r1.5 ---- bgpd/bgpd.conf.5 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/bgpd.conf.5 22 Oct 2009 15:10:02 -0000 1.5 +retrieving revision 1.1.1.7 +retrieving revision 1.6 +diff -u -p -r1.1.1.7 -r1.6 +--- bgpd/bgpd.conf.5 14 Feb 2010 20:19:57 -0000 1.1.1.7 ++++ bgpd/bgpd.conf.5 4 Feb 2010 16:22:23 -0000 1.6 @@ -1,4 +1,4 @@ --.\" $OpenBSD: bgpd.conf.5,v 1.88 2008/03/22 08:38:38 claudio Exp $ -+.\" $OpenBSD: bgpd.conf.5,v 1.94 2009/06/07 00:31:22 claudio Exp $ +-.\" $OpenBSD: bgpd.conf.5,v 1.94 2009/06/07 00:31:22 claudio Exp $ ++.\" $OpenBSD: bgpd.conf.5,v 1.103 2009/12/16 15:40:55 claudio Exp $ .\" .\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> .\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -16,73 +16,39 @@ diff -u -p -r1.1.1.1 -r1.5 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" --.Dd $Mdocdate: March 22 2008 $ -+.Dd $Mdocdate: October 6 2009 $ +-.Dd $Mdocdate: June 7 2009 $ ++.Dd $Mdocdate: November 26 2009 $ .Dt BGPD.CONF 5 .Os .Sh NAME -@@ -123,14 +123,26 @@ sets the local AS to 65001. - The AS numbers 64512 \(en 65534 are designated for private use. - The AS number 23456 is a specially designated Autonomous System Number and - should not be used. --4-byte AS numbers are specified as two numbers separated by a dot. --For example: -+4-byte AS numbers are specified as two numbers separated by a dot -+(ASDOT format), -+for example: - .Bd -literal -offset indent - AS 3.10 - .Ed - .Pp -+or as a large number (ASPLAIN format), for example: -+.Bd -literal -offset indent -+AS 196618 -+.Ed -+.Pp -+.It Ic connect-retry Ar seconds -+Set the number of seconds before retrying to open a connection. -+This timer should be sufficiently large in EBGP configurations. -+The default is 120 seconds. -+.Pp - .It Xo - .Ic dump -+.Op Ic rib Ar name - .Pq Ic table Ns \&| Ns Ic table-mp - .Ar file Op Ar timeout +@@ -93,7 +93,7 @@ Set the local + .Em autonomous system + number to + .Ar as-number . +-If the first AS number is a 4-byte AS it is possible to specifiy a secondary ++If the first AS number is a 4-byte AS it is possible to specify a secondary + 2-byte AS number which is used for neighbors which do not support 4-byte AS + numbers. + The default for the secondary AS is 23456. +@@ -313,7 +313,7 @@ is only compared between peers belonging + .Ic rib Ar name + .Op Ic no Ic evaluate .Xc -@@ -145,7 +157,8 @@ Dump the RIB, a.k.a. the - and all BGP messages in Multi-threaded Routing Toolkit (MRT) format. - Dumping the RIB is normally an expensive operation, - but it should not influence the session handling. --Excessive dumping may result in delayed update processing. -+It is possible to dump alternate RIB with the use of -+.Ar name . - .Pp - For example, the following will dump the entire table to the - .Xr strftime 3 Ns -expanded -@@ -297,6 +310,21 @@ is only compared between peers belonging +-Creat an additional RIB named ++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. + .Ic Adj-RIB-In + and + .Ic Loc-RIB +-are created automaticaly and used as default. ++are created automatically and used as default. .Pp .It Xo .Ic rde -+.Ic rib Ar name -+.Op Ic no Ic evaluate -+.Xc -+Create an additional RIB named -+.Ar name . -+It is possible to disable the decision process per RIB with the -+.Ic no Ic evaluate -+flag. -+.Ic Adj-RIB-In -+and -+.Ic Loc-RIB -+are created automaticaly and used as default. -+.Pp -+.It Xo -+.Ic rde - .Ic route-age - .Pq Ic ignore Ns \&| Ns Ic evaluate - .Xc -@@ -455,6 +483,17 @@ Only routes for that address family and +@@ -483,6 +483,17 @@ Only routes for that address family and announced and processed. .Pp .It Xo @@ -100,7 +66,7 @@ diff -u -p -r1.1.1.1 -r1.5 .Ic announce capabilities .Pq Ic yes Ns \&| Ns Ic no .Xc -@@ -465,6 +504,29 @@ This can be helpful to connect to old or +@@ -493,6 +504,29 @@ This can be helpful to connect to old or The default is .Ic yes . .Pp @@ -130,7 +96,16 @@ diff -u -p -r1.1.1.1 -r1.5 .It Ic demote Ar group Increase the .Xr carp 4 -@@ -561,6 +623,12 @@ Inherited from the global configuration +@@ -504,7 +538,7 @@ The demotion counter will be increased a + .Xr bgpd 8 + starts and decreased + 60 seconds after the session went to state +-.Em ESTABLISHED. ++.Em ESTABLISHED . + For neighbors added at runtime, the demotion counter is only increased after + the session has been + .Em ESTABLISHED +@@ -589,6 +623,12 @@ Inherited from the global configuration Set the minimal acceptable holdtime. Inherited from the global configuration if not given. .Pp @@ -143,11 +118,11 @@ diff -u -p -r1.1.1.1 -r1.5 .It Xo .Ic ipsec .Pq Ic ah Ns \&| Ns Ic esp -@@ -611,11 +679,11 @@ is responsible for managing the session +@@ -639,11 +679,11 @@ is responsible for managing the session With .Xr isakmpd 8 , it is sufficient to copy the peer's public key, found in --.Pa /etc/isakmpd/private/local.pub , +-.Pa /etc/isakmpd/local.pub , +.Pa %%PREFIX%%/etc/isakmpd/private/local.pub , to the local machine. It must be stored in a file @@ -157,44 +132,99 @@ diff -u -p -r1.1.1.1 -r1.5 The local public key must be copied to the peer in the same way. As .Xr bgpd 8 -@@ -670,6 +738,9 @@ Do not attempt to actively open a TCP co +@@ -698,7 +738,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 +-.It rib .Ar name +.It Ic rib Ar name -+Bind the neighbor to the specified RIB. -+.Pp + Bind the neighbor to the specified RIB. + .Pp .It Ic route-reflector Op Ar address - Act as an RFC 2796 - .Em route-reflector -@@ -728,6 +799,18 @@ tcp md5sig key deadbeef - .Ed +@@ -1028,6 +1068,12 @@ matches a rule which has the + option set, this rule is considered the last matching rule, and evaluation + of subsequent rules is skipped. .Pp - .It Xo -+.Ic transparent-as -+.Pq Ic yes Ns \&| Ns Ic no -+.Xc -+If set to -+.Ic yes , -+.Em AS paths -+to EBGP neighbors are not prepended with their own AS. -+The default is inherited from the global -+.Ic transparent-as -+setting. ++.It Ic rib Ar name ++Apply rule only to the specified RIB. ++This only applies for received updates, so not for rules using the ++.Ar to peer ++parameter. +.Pp + .It Ic set Ar attribute ... + All matching rules can set the + .Em AS path attributes +@@ -1079,6 +1125,48 @@ Alternately, well-known communities may + or + .Ic NO_PEER . + .Pp +.It Xo - .Ic ttl-security - .Pq Ic yes Ns \&| Ns Ic no - .Xc -@@ -1048,6 +1131,7 @@ will be adjusted by adding or subtractin - .Ar number ; - otherwise it will be set to ++.Ic ext-community Op Ar delete ++.Ar subtype Ar as-number Ns Li : Ns Ar local ++.Xc ++.It Xo ++.Ic ext-community Op Ar delete ++.Ar subtype Ar IP Ns Li : Ns Ar local ++.Xc ++.It Xo ++.Ic ext-community Op Ar delete ++.Ar subtype Ar numvalue ++.Xc ++Set or delete the ++.Em Extended Community ++AS path attribute. ++Extended Communities are specified by a ++.Ar subtype ++and normally two values, a globally unique part (e.g. the AS number) and a ++local part. ++The type is selected depending on the encoding of the global part. ++Two-octet AS Specific Extended Communities and Four-octet AS Specific Extended ++Communities are encoded as ++.Ar as-number Ns Li : Ns Ar local . ++Four-octet encoding is used if the ++.Ar as-number ++is bigger then 65535 or if the AS_DOT encoding is used. ++IPv4 Address Specific Extended Communities are encoded as ++.Ar IP Ns Li : Ns Ar local . ++Opaque Extended Communities are encoded with a single numeric value. ++Currently the following subtypes are supported: ++.Bd -literal -offset indent ++rt Route Target ++soo Source of Origin ++odi OSPF Domain Identifier ++ort OSPF Route Type ++ori OSPF Router ID ++bdc BGP Data Collection ++.Ed ++.Pp ++Not all type and subtype value pairs are allowed by IANA and the parser ++will ensure that no invalid combination is created. ++.Pp + .It Ic localpref Ar number + Set the + .Em LOCAL_PREF +@@ -1108,6 +1196,20 @@ otherwise it will be set to .Ar number . -+The default is 100. .Pp - .It Ic med Ar number - .It Ic metric Ar number -@@ -1137,8 +1221,8 @@ For prefixes with equally long paths, th + .It Xo ++.Ic origin ++.Sm off ++.Po Ic igp \*(Ba ++.Ic egp \*(Ba ++.Ic incomplete Pc ++.Sm on ++.Xc ++Set the ++.Em ORIGIN ++AS path attribute to mark the source of this ++route as being injected from an igp protocol, an egp protocol ++or being an aggregated route. ++.Pp ++.It Xo + .Ic nexthop + .Sm off + .Po Ar address \*(Ba +@@ -1181,8 +1283,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 74ff65d5d6b1..89f2e5115d14 100644 --- a/net/openbgpd/files/patch-bgpd_bgpd.h +++ b/net/openbgpd/files/patch-bgpd_bgpd.h @@ -1,26 +1,27 @@ Index: bgpd/bgpd.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.h,v -retrieving revision 1.1.1.1 -retrieving revision 1.8 -diff -u -p -r1.1.1.1 -r1.8 ---- bgpd/bgpd.h 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/bgpd.h 22 Oct 2009 15:53:39 -0000 1.8 +retrieving revision 1.1.1.8 +retrieving revision 1.10 +diff -u -p -r1.1.1.8 -r1.10 +--- bgpd/bgpd.h 14 Feb 2010 20:19:57 -0000 1.1.1.8 ++++ bgpd/bgpd.h 14 Feb 2010 19:53:36 -0000 1.10 @@ -1,4 +1,4 @@ --/* $OpenBSD: bgpd.h,v 1.222 2008/01/23 08:11:32 claudio Exp $ */ -+/* $OpenBSD: bgpd.h,v 1.243 2009/07/23 14:53:18 claudio Exp $ */ +-/* $OpenBSD: bgpd.h,v 1.241 2009/06/12 16:42:53 claudio Exp $ */ ++/* $OpenBSD: bgpd.h,v 1.252 2010/01/13 06:02:37 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -30,9 +30,16 @@ +@@ -30,11 +30,16 @@ #include <poll.h> #include <stdarg.h> +-#include <imsg.h> +#if defined(__FreeBSD__) /* compat */ +#include "openbsd-compat.h" +#endif /* defined(__FreeBSD__) */ +#include "imsg.h" -+ + #define BGP_VERSION 4 #define BGP_PORT 179 +#ifndef CONFFILE @@ -29,223 +30,137 @@ diff -u -p -r1.1.1.1 -r1.8 #define BGPD_USER "_bgpd" #define PEER_DESCR_LEN 32 #define PFTABLE_LEN 16 -@@ -40,6 +47,8 @@ +@@ -42,8 +47,6 @@ #define IPSEC_ENC_KEY_LEN 32 #define IPSEC_AUTH_KEY_LEN 20 -+#define ASNUM_MAX 0xffffffff -+ +-#define ASNUM_MAX 0xffffffff +- #define MAX_PKTSIZE 4096 #define MIN_HOLDTIME 3 #define READ_BUF_SIZE 65535 -@@ -85,8 +94,8 @@ - - /* - * Limit the number of control messages generated by the RDE and queued in -- * session enigine. The RDE limit defines how many imsg are generated in -- * on poll round. The if the SE limit is hit the RDE control socket will no -+ * session engine. The RDE limit defines how many imsg are generated in -+ * one poll round. Then if the SE limit is hit the RDE control socket will no - * longer be polled. - */ - #define RDE_RUNNER_ROUNDS 100 -@@ -105,21 +114,6 @@ enum reconf_action { +@@ -109,18 +112,74 @@ enum reconf_action { RECONF_DELETE }; --struct buf { -- TAILQ_ENTRY(buf) entry; -- u_char *buf; -- size_t size; -- size_t wpos; -- size_t rpos; -- int fd; --}; -- --struct msgbuf { -- TAILQ_HEAD(, buf) bufs; -- u_int32_t queued; -- int fd; --}; -- ++/* Address Family Numbers as per RFC 1700 */ ++#define AFI_UNSPEC 0 ++#define AFI_IPv4 1 ++#define AFI_IPv6 2 ++ ++/* Subsequent Address Family Identifier as per RFC 4760 */ ++#define SAFI_NONE 0 ++#define SAFI_UNICAST 1 ++#define SAFI_MULTICAST 2 ++#define SAFI_MPLS 4 ++#define SAFI_MPLSVPN 128 ++ ++struct aid { ++ u_int16_t afi; ++ sa_family_t af; ++ u_int8_t safi; ++ char *name; ++}; ++ ++extern const struct aid aid_vals[]; ++ ++#define AID_UNSPEC 0 ++#define AID_INET 1 ++#define AID_INET6 2 ++#define AID_VPN_IPv4 3 ++#define AID_MAX 4 ++ ++#define AID_VALS { \ ++ /* afi, af, safii, name */ \ ++ { AFI_UNSPEC, AF_UNSPEC, SAFI_NONE, "unspec"}, \ ++ { AFI_IPv4, AF_INET, SAFI_UNICAST, "IPv4 unicast" }, \ ++ { AFI_IPv6, AF_INET6, SAFI_UNICAST, "IPv6 unicast" }, \ ++ { AFI_IPv4, AF_INET, SAFI_MPLSVPN, "IPv4 vpn" } \ ++} ++ ++#define AID_PTSIZE { \ ++ 0, \ ++ sizeof(struct pt_entry4), \ ++ sizeof(struct pt_entry6), \ ++ sizeof(struct pt_entry_vpn4) \ ++} ++ ++struct vpn4_addr { ++ u_int64_t rd; ++ struct in_addr addr; ++ u_int8_t labelstack[21]; /* max that makes sense */ ++ u_int8_t labellen; ++ u_int8_t pad1; ++ u_int8_t pad2; ++}; ++ ++#define BGP_MPLS_BOS 0x01 ++ struct bgpd_addr { - sa_family_t af; +- sa_family_t af; union { -@@ -169,12 +163,7 @@ struct bgpd_config { - u_int16_t short_as; - u_int16_t holdtime; - u_int16_t min_holdtime; --}; -- --struct buf_read { -- u_char buf[READ_BUF_SIZE]; -- u_char *rptr; -- size_t wpos; -+ u_int16_t connectretry; + struct in_addr v4; + struct in6_addr v6; +- u_int8_t addr8[16]; +- u_int16_t addr16[8]; +- u_int32_t addr32[4]; ++ struct vpn4_addr vpn4; ++ /* maximum size for a prefix is 256 bits */ ++ u_int8_t addr8[32]; ++ u_int16_t addr16[16]; ++ u_int32_t addr32[8]; + } ba; /* 128-bit address */ + u_int32_t scope_id; /* iface scope id for v6 */ ++ u_int8_t aid; + #define v4 ba.v4 + #define v6 ba.v6 ++#define vpn4 ba.vpn4 + #define addr8 ba.addr8 + #define addr16 ba.addr16 + #define addr32 ba.addr32 +@@ -205,11 +264,10 @@ struct peer_auth { }; - enum announce_type { -@@ -235,11 +224,13 @@ struct peer_config { - struct capabilities capabilities; - char group[PEER_DESCR_LEN]; - char descr[PEER_DESCR_LEN]; -+ char rib[PEER_DESCR_LEN]; - char if_depend[IFNAMSIZ]; - char demote_group[IFNAMSIZ]; - u_int32_t id; - u_int32_t groupid; - u_int32_t remote_as; -+ u_int32_t local_as; - u_int32_t max_prefix; - enum announce_type announce_type; - enum enforce_as enforce_as; -@@ -247,6 +238,7 @@ struct peer_config { - u_int16_t max_prefix_restart; - u_int16_t holdtime; - u_int16_t min_holdtime; -+ u_int16_t local_short_as; - u_int8_t template; - u_int8_t remote_masklen; - u_int8_t cloned; -@@ -259,8 +251,13 @@ struct peer_config { - u_int8_t softreconfig_in; - u_int8_t softreconfig_out; - u_int8_t ttlsec; /* TTL security hack */ -+ u_int8_t flags; -+ u_int8_t pad[3]; -+ char lliface[IFNAMSIZ]; + struct capabilities { +- u_int8_t mp_v4; /* multiprotocol extensions, RFC 4760 */ +- u_int8_t mp_v6; +- u_int8_t refresh; /* route refresh, RFC 2918 */ +- u_int8_t restart; /* graceful restart, RFC 4724 */ +- u_int8_t as4byte; /* draft-ietf-idr-as4bytes-13 */ ++ int8_t mp[AID_MAX]; /* multiprotocol extensions, RFC 4760 */ ++ int8_t refresh; /* route refresh, RFC 2918 */ ++ int8_t restart; /* graceful restart, RFC 4724 */ ++ int8_t as4byte; /* draft-ietf-idr-as4bytes-13 */ }; -+#define PEERFLAG_TRANS_AS 0x01 -+ - struct network_config { - struct bgpd_addr prefix; - struct filter_set_head attrset; -@@ -274,54 +271,8 @@ struct network { - TAILQ_ENTRY(network) entry; + struct peer_config { +@@ -248,6 +306,7 @@ struct peer_config { + u_int8_t ttlsec; /* TTL security hack */ + u_int8_t flags; + u_int8_t pad[3]; ++ char lliface[IFNAMSIZ]; }; --/* ipc messages */ -- --#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr) --#define MAX_IMSGSIZE 8192 -- --struct imsg_fd { -- TAILQ_ENTRY(imsg_fd) entry; -- int fd; --}; -- --struct imsgbuf { -- TAILQ_HEAD(fds, imsg_fd) fds; -- struct buf_read r; -- struct msgbuf w; -- int fd; -- pid_t pid; --}; -- - enum imsg_type { - IMSG_NONE, -- IMSG_RECONF_CONF, -- IMSG_RECONF_PEER, -- IMSG_RECONF_FILTER, -- IMSG_RECONF_LISTENER, -- IMSG_RECONF_DONE, -- IMSG_UPDATE, -- IMSG_UPDATE_ERR, -- IMSG_SESSION_ADD, -- IMSG_SESSION_UP, -- IMSG_SESSION_DOWN, -- IMSG_MRT_OPEN, -- IMSG_MRT_REOPEN, -- IMSG_MRT_CLOSE, -- IMSG_KROUTE_CHANGE, -- IMSG_KROUTE_DELETE, -- IMSG_KROUTE6_CHANGE, -- IMSG_KROUTE6_DELETE, -- IMSG_NEXTHOP_ADD, -- IMSG_NEXTHOP_REMOVE, -- IMSG_NEXTHOP_UPDATE, -- IMSG_PFTABLE_ADD, -- IMSG_PFTABLE_REMOVE, -- IMSG_PFTABLE_COMMIT, -- IMSG_NETWORK_ADD, -- IMSG_NETWORK_REMOVE, -- IMSG_NETWORK_FLUSH, -- IMSG_NETWORK_DONE, -- IMSG_FILTER_SET, - IMSG_CTL_END, - IMSG_CTL_RELOAD, - IMSG_CTL_FIB_COUPLE, -@@ -347,23 +298,40 @@ enum imsg_type { + #define PEERFLAG_TRANS_AS 0x01 +@@ -292,6 +351,7 @@ enum imsg_type { IMSG_CTL_SHOW_RIB_MEM, IMSG_CTL_SHOW_TERSE, IMSG_CTL_SHOW_TIMER, -+ IMSG_NETWORK_ADD, -+ IMSG_NETWORK_REMOVE, -+ IMSG_NETWORK_FLUSH, -+ IMSG_NETWORK_DONE, -+ IMSG_FILTER_SET, -+ IMSG_RECONF_CONF, -+ IMSG_RECONF_RIB, -+ IMSG_RECONF_PEER, -+ IMSG_RECONF_FILTER, -+ IMSG_RECONF_LISTENER, -+ IMSG_RECONF_DONE, -+ IMSG_UPDATE, -+ IMSG_UPDATE_ERR, -+ IMSG_SESSION_ADD, -+ IMSG_SESSION_UP, -+ IMSG_SESSION_DOWN, -+ IMSG_MRT_OPEN, -+ IMSG_MRT_REOPEN, -+ IMSG_MRT_CLOSE, -+ IMSG_KROUTE_CHANGE, -+ IMSG_KROUTE_DELETE, -+ IMSG_KROUTE6_CHANGE, -+ IMSG_KROUTE6_DELETE, -+ IMSG_NEXTHOP_ADD, -+ IMSG_NEXTHOP_REMOVE, -+ IMSG_NEXTHOP_UPDATE, -+ IMSG_PFTABLE_ADD, -+ IMSG_PFTABLE_REMOVE, -+ IMSG_PFTABLE_COMMIT, - IMSG_REFRESH, - IMSG_IFINFO, - IMSG_DEMOTE - }; - --struct imsg_hdr { -- u_int32_t peerid; -- pid_t pid; -- enum imsg_type type; -- u_int16_t len; --}; -- --struct imsg { -- struct imsg_hdr hdr; -- void *data; --}; -- - struct demote_msg { - char demote_group[IFNAMSIZ]; - int level; -@@ -424,6 +392,7 @@ struct kroute { - u_int16_t labelid; - u_short ifindex; - u_int8_t prefixlen; -+ u_int8_t priority; - }; - - struct kroute6 { -@@ -433,6 +402,7 @@ struct kroute6 { - u_int16_t labelid; - u_short ifindex; - u_int8_t prefixlen; -+ u_int8_t priority; ++ IMSG_CTL_LOG_VERBOSE, + IMSG_NETWORK_ADD, + IMSG_NETWORK_REMOVE, + IMSG_NETWORK_FLUSH, +@@ -423,8 +483,7 @@ struct kif { + struct session_up { + struct bgpd_addr local_addr; + struct bgpd_addr remote_addr; +- struct capabilities capa_announced; +- struct capabilities capa_received; ++ struct capabilities capa; + u_int32_t remote_bgpid; + u_int16_t short_as; }; - - struct kroute_nexthop { -@@ -473,8 +443,13 @@ struct pftable_msg { +@@ -437,8 +496,13 @@ struct pftable_msg { struct ctl_show_nexthop { struct bgpd_addr addr; @@ -260,73 +175,159 @@ diff -u -p -r1.1.1.1 -r1.8 }; struct ctl_neighbor { -@@ -510,7 +485,7 @@ struct ctl_show_rib { - u_int32_t med; - u_int32_t prefix_cnt; - u_int32_t active_cnt; -- u_int32_t adjrib_cnt; -+ u_int32_t rib_cnt; - u_int16_t aspath_len; - u_int16_t flags; - u_int8_t prefixlen; -@@ -545,6 +520,7 @@ struct filter_community { +@@ -508,6 +572,27 @@ struct filter_community { + int type; }; ++struct filter_extcommunity { ++ u_int8_t type; ++ u_int8_t subtype; /* if extended type */ ++ union { ++ struct ext_as { ++ u_int16_t as; ++ u_int32_t val; ++ } ext_as; ++ struct ext_as4 { ++ u_int32_t as4; ++ u_int16_t val; ++ } ext_as4; ++ struct ext_ip { ++ struct in_addr addr; ++ u_int16_t val; ++ } ext_ip; ++ u_int64_t ext_opaq; /* only 48 bits */ ++ } data; ++}; ++ ++ struct ctl_show_rib_request { -+ char rib[PEER_DESCR_LEN]; + char rib[PEER_DESCR_LEN]; struct ctl_neighbor neighbor; - struct bgpd_addr prefix; - struct filter_as as; -@@ -590,6 +566,7 @@ enum comp_ops { - struct filter_peers { - u_int32_t peerid; - u_int32_t groupid; -+ u_int16_t ribid; +@@ -518,8 +603,8 @@ struct ctl_show_rib_request { + pid_t pid; + u_int16_t flags; + enum imsg_type type; +- sa_family_t af; + u_int8_t prefixlen; ++ u_int8_t aid; }; - /* special community type */ -@@ -644,6 +621,7 @@ TAILQ_HEAD(filter_head, filter_rule); + enum filter_actions { +@@ -585,6 +670,27 @@ struct filter_peers { + #define EXT_COMMUNITY_OSPF_RTR_TYPE 6 /* RFC 4577 */ + #define EXT_COMMUNITY_OSPF_RTR_ID 7 /* RFC 4577 */ + #define EXT_COMMUNITY_BGP_COLLECT 8 /* RFC 4384 */ ++/* other handy defines */ ++#define EXT_COMMUNITY_OPAQUE_MAX 0xffffffffffffULL ++ ++struct ext_comm_pairs { ++ u_int8_t type; ++ u_int8_t subtype; ++ u_int8_t transitive; /* transitive bit needs to be set */ ++}; ++ ++#define IANA_EXT_COMMUNITIES { \ ++ { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_ROUTE_TGT, 0 }, \ ++ { EXT_COMMUNITY_TWO_AS, EXT_CUMMUNITY_ROUTE_ORIG, 0 }, \ ++ { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_OSPF_DOM_ID, 0 }, \ ++ { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_BGP_COLLECT, 0 }, \ ++ { EXT_COMMUNITY_FOUR_AS, EXT_COMMUNITY_ROUTE_TGT, 0 }, \ ++ { EXT_COMMUNITY_FOUR_AS, EXT_CUMMUNITY_ROUTE_ORIG, 0 }, \ ++ { EXT_COMMUNITY_IPV4, EXT_COMMUNITY_ROUTE_TGT, 0 }, \ ++ { EXT_COMMUNITY_IPV4, EXT_CUMMUNITY_ROUTE_ORIG, 0 }, \ ++ { EXT_COMMUNITY_IPV4, EXT_COMMUNITY_OSPF_RTR_ID, 0 }, \ ++ { EXT_COMMUNITY_OPAQUE, EXT_COMMUNITY_OSPF_RTR_TYPE, 0 } \ ++} - struct filter_rule { - TAILQ_ENTRY(filter_rule) entry; -+ char rib[PEER_DESCR_LEN]; - struct filter_peers peer; - struct filter_match match; - struct filter_set_head set; -@@ -697,6 +675,7 @@ struct rrefresh { - struct rde_memstats { - int64_t path_cnt; - int64_t prefix_cnt; -+ int64_t rib_cnt; - int64_t pt4_cnt; - int64_t pt6_cnt; - int64_t nexthop_cnt; -@@ -709,6 +688,15 @@ struct rde_memstats { - int64_t attr_dcnt; + + struct filter_prefix { +@@ -594,7 +700,7 @@ struct filter_prefix { + + struct filter_prefixlen { + enum comp_ops op; +- sa_family_t af; ++ u_int8_t aid; + u_int8_t len_min; + u_int8_t len_max; + }; +@@ -635,10 +741,13 @@ enum action_types { + ACTION_SET_NEXTHOP_SELF, + ACTION_SET_COMMUNITY, + ACTION_DEL_COMMUNITY, ++ ACTION_SET_EXT_COMMUNITY, ++ ACTION_DEL_EXT_COMMUNITY, + ACTION_PFTABLE, + ACTION_PFTABLE_ID, + ACTION_RTLABEL, +- ACTION_RTLABEL_ID ++ ACTION_RTLABEL_ID, ++ ACTION_SET_ORIGIN }; + struct filter_set { +@@ -650,23 +759,31 @@ struct filter_set { + int32_t relative; + struct bgpd_addr nexthop; + struct filter_community community; ++ struct filter_extcommunity ext_community; + char pftable[PFTABLE_LEN]; + char rtlabel[RTLABEL_LEN]; ++ u_int8_t origin; + } action; + enum action_types type; + }; + +-struct rrefresh { +- u_int16_t afi; +- u_int8_t safi; +struct rde_rib { + SIMPLEQ_ENTRY(rde_rib) entry; + char name[PEER_DESCR_LEN]; + u_int16_t id; + u_int16_t flags; -+}; + }; +SIMPLEQ_HEAD(rib_names, rde_rib); +extern struct rib_names ribnames; + - /* Address Family Numbers as per RFC 1700 */ - #define AFI_IPv4 1 - #define AFI_IPv6 2 -@@ -718,11 +706,24 @@ struct rde_memstats { - #define SAFI_NONE 0x00 - #define SAFI_UNICAST 0x01 - #define SAFI_MULTICAST 0x02 -+#define SAFI_MPLS 0x04 - #define SAFI_ALL 0xff ++/* 4-byte magic AS number */ ++#define AS_TRANS 23456 - /* 4-byte magic AS number */ - #define AS_TRANS 23456 + struct rde_memstats { + int64_t path_cnt; + int64_t prefix_cnt; + int64_t rib_cnt; +- int64_t pt4_cnt; +- int64_t pt6_cnt; ++ int64_t pt_cnt[AID_MAX]; + int64_t nexthop_cnt; + int64_t aspath_cnt; + int64_t aspath_size; +@@ -677,28 +794,17 @@ struct rde_memstats { + int64_t attr_dcnt; + }; +-struct rde_rib { +- SIMPLEQ_ENTRY(rde_rib) entry; +- char name[PEER_DESCR_LEN]; +- u_int16_t id; +- u_int16_t flags; +-}; +-SIMPLEQ_HEAD(rib_names, rde_rib); +-extern struct rib_names ribnames; +- +-/* Address Family Numbers as per RFC 1700 */ +-#define AFI_IPv4 1 +-#define AFI_IPv6 2 +-#define AFI_ALL 0xffff +- +-/* Subsequent Address Family Identifier as per RFC 4760 */ +-#define SAFI_NONE 0x00 +-#define SAFI_UNICAST 0x01 +-#define SAFI_MULTICAST 0x02 +-#define SAFI_ALL 0xff +- +-/* 4-byte magic AS number */ +-#define AS_TRANS 23456 +/* macros for IPv6 link-local address */ +#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER) +#define IN6_LINKLOCAL_IFINDEX(addr) \ @@ -338,77 +339,34 @@ diff -u -p -r1.1.1.1 -r1.8 + (addr).s6_addr[3] = (index) & 0xff; \ + } while (0) +#endif -+ + /* prototypes */ /* bgpd.c */ - void send_nexthop_update(struct kroute_nexthop *); -@@ -730,18 +731,6 @@ void send_imsg_session(int, pid_t, voi - int bgpd_redistribute(int, struct kroute *, struct kroute6 *); - int bgpd_filternexthop(struct kroute *, struct kroute6 *); +@@ -709,6 +815,7 @@ int bgpd_filternexthop(struct kroute * --/* buffer.c */ --struct buf *buf_open(size_t); --struct buf *buf_grow(struct buf *, size_t); --int buf_add(struct buf *, const void *, size_t); --void *buf_reserve(struct buf *, size_t); --int buf_close(struct msgbuf *, struct buf *); --int buf_write(int, struct buf *); --void buf_free(struct buf *); --void msgbuf_init(struct msgbuf *); --void msgbuf_clear(struct msgbuf *); --int msgbuf_write(struct msgbuf *); -- /* log.c */ void log_init(int); ++void log_verbose(int); void vlog(int, const char *, va_list); -@@ -760,19 +749,6 @@ int cmdline_symset(char *); - /* config.c */ - int host(const char *, struct bgpd_addr *, u_int8_t *); - --/* imsg.c */ --void imsg_init(struct imsgbuf *, int); --int imsg_read(struct imsgbuf *); --int imsg_get(struct imsgbuf *, struct imsg *); --int imsg_compose(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t, int, -- const void *, u_int16_t); --struct buf *imsg_create(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t, -- u_int16_t); --int imsg_add(struct buf *, const void *, u_int16_t); --int imsg_close(struct imsgbuf *, struct buf *); --void imsg_free(struct imsg *); --int imsg_get_fd(struct imsgbuf *); -- - /* kroute.c */ - int kr_init(int, u_int); - int kr_change(struct kroute_label *); -@@ -788,10 +764,7 @@ void kr_nexthop_delete(struct bgpd_add - void kr_show_route(struct imsg *); - void kr_ifinfo(char *); - int kr_reload(void); --in_addr_t prefixlen2mask(u_int8_t); - struct in6_addr *prefixlen2mask6(u_int8_t prefixlen); --void inet6applymask(struct in6_addr *, const struct in6_addr *, -- int); - - /* control.c */ - void control_cleanup(const char *); -@@ -806,6 +779,10 @@ int pftable_addr_remove(struct pftable_m - int pftable_commit(void); - - /* name2id.c */ -+u_int16_t rib_name2id(const char *); -+const char *rib_id2name(u_int16_t); -+void rib_unref(u_int16_t); -+void rib_ref(u_int16_t); - u_int16_t rtlabel_name2id(const char *); - const char *rtlabel_id2name(u_int16_t); - void rtlabel_unref(u_int16_t); -@@ -829,5 +806,8 @@ const char *log_as(u_int32_t); + void log_peer_warn(const struct peer_config *, const char *, ...); + void log_peer_warnx(const struct peer_config *, const char *, ...); +@@ -779,11 +886,19 @@ const char *log_addr(const struct bgpd_a + const char *log_in6addr(const struct in6_addr *); + const char *log_sockaddr(struct sockaddr *); + const char *log_as(u_int32_t); ++const char *log_ext_subtype(u_int8_t); int aspath_snprint(char *, size_t, void *, u_int16_t); int aspath_asprint(char **, void *, u_int16_t); size_t aspath_strlen(void *, u_int16_t); -+in_addr_t prefixlen2mask(u_int8_t); -+void inet6applymask(struct in6_addr *, const struct in6_addr *, -+ int); + in_addr_t prefixlen2mask(u_int8_t); + void inet6applymask(struct in6_addr *, const struct in6_addr *, + int); ++const char *aid2str(u_int8_t); ++int aid2afi(u_int8_t, u_int16_t *, u_int8_t *); ++int afi2aid(u_int16_t, u_int8_t, u_int8_t *); ++sa_family_t aid2af(u_int8_t); ++int af2aid(sa_family_t, u_int8_t, u_int8_t *); ++struct sockaddr *addr2sa(struct bgpd_addr *, u_int16_t); ++void sa2addr(struct sockaddr *, struct bgpd_addr *); #endif /* __BGPD_H__ */ diff --git a/net/openbgpd/files/patch-bgpd_buffer.c b/net/openbgpd/files/patch-bgpd_buffer.c index ccb9dc1d71bd..875b789f68b3 100644 --- a/net/openbgpd/files/patch-bgpd_buffer.c +++ b/net/openbgpd/files/patch-bgpd_buffer.c @@ -1,191 +1,55 @@ Index: bgpd/buffer.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/buffer.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.1.1.4 -diff -u -p -r1.1.1.1 -r1.1.1.4 ---- bgpd/buffer.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/buffer.c 22 Oct 2009 14:24:02 -0000 1.1.1.4 +retrieving revision 1.1.1.7 +retrieving revision 1.1.1.8 +diff -u -p -r1.1.1.7 -r1.1.1.8 +--- 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 @@ --/* $OpenBSD: buffer.c,v 1.39 2008/03/24 16:11:02 deraadt Exp $ */ +-/* $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> -@@ -16,18 +16,19 @@ - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - --#include <sys/types.h> -+#include <sys/param.h> -+#include <sys/queue.h> -+#include <sys/socket.h> - #include <sys/uio.h> - - #include <errno.h> --#include <limits.h> --#include <stdio.h> - #include <stdlib.h> - #include <string.h> - #include <unistd.h> - --#include "bgpd.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 *); - -@@ -42,35 +43,55 @@ buf_open(size_t len) - free(buf); - return (NULL); - } -- buf->size = len; -+ buf->size = buf->max = len; - buf->fd = -1; - - return (buf); - } - - struct buf * --buf_grow(struct buf *buf, size_t len) -+buf_dynamic(size_t len, size_t max) - { -- void *p; -+ struct buf *buf; - -- if ((p = realloc(buf->buf, buf->size + len)) == NULL) { -- free(buf->buf); -- buf->buf = NULL; -- buf->size = 0; -+ if (max < len) - return (NULL); -- } - -- buf->buf = p; -- buf->size += len; -+ 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) -- return (-1); -+ if (buf_realloc(buf, len) == -1) -+ return (-1); - - memcpy(buf->buf + buf->wpos, data, len); - buf->wpos += len; -@@ -83,27 +104,60 @@ buf_reserve(struct buf *buf, size_t len) - void *b; - - if (buf->wpos + len > buf->size) -- return (NULL); -+ if (buf_realloc(buf, len) == -1) -+ return (NULL); - - b = buf->buf + buf->wpos; - buf->wpos += len; - return (b); - } - --int -+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); -- return (1); - } - - int --buf_write(int sock, struct buf *buf) -+buf_write(struct msgbuf *msgbuf) +@@ -144,7 +144,7 @@ int + buf_write(struct msgbuf *msgbuf) { -+ struct iovec iov[IOV_MAX]; + struct iovec iov[IOV_MAX]; +- struct buf *buf, *next; + struct buf *buf; -+ unsigned int i = 0; + unsigned int i = 0; ssize_t n; -- if ((n = write(sock, buf->buf + buf->rpos, -- buf->size - buf->rpos)) == -1) { -+ bzero(&iov, sizeof(iov)); -+ TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { -+ if (i >= IOV_MAX) -+ break; -+ iov[i].iov_base = buf->buf + buf->rpos; +@@ -153,7 +153,7 @@ buf_write(struct msgbuf *msgbuf) + if (i >= IOV_MAX) + break; + iov[i].iov_base = buf->buf + buf->rpos; +- iov[i].iov_len = buf->size - buf->rpos; + iov[i].iov_len = buf->wpos - buf->rpos; -+ i++; -+ } -+ -+ if ((n = writev(msgbuf->fd, iov, i)) == -1) { - if (errno == EAGAIN || errno == ENOBUFS || - errno == EINTR) /* try later */ - return (0); -@@ -116,11 +170,9 @@ buf_write(int sock, struct buf *buf) + i++; + } + +@@ -170,17 +170,7 @@ buf_write(struct msgbuf *msgbuf) return (-2); } -- if (buf->rpos + n < buf->size) { /* not all data written yet */ -- buf->rpos += n; -- return (0); -- } else -- return (1); +- for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; +- buf = next) { +- next = TAILQ_NEXT(buf, entry); +- if (buf->rpos + n >= buf->size) { +- n -= buf->size - buf->rpos; +- buf_dequeue(msgbuf, buf); +- } else { +- buf->rpos += n; +- n = 0; +- } +- } + msgbuf_drain(msgbuf, n); -+ -+ return (0); - } - void -@@ -139,6 +191,24 @@ msgbuf_init(struct msgbuf *msgbuf) + return (0); + } +@@ -201,6 +191,24 @@ msgbuf_init(struct msgbuf *msgbuf) } void @@ -210,43 +74,24 @@ diff -u -p -r1.1.1.1 -r1.1.1.4 msgbuf_clear(struct msgbuf *msgbuf) { struct buf *buf; -@@ -151,14 +221,14 @@ int +@@ -213,7 +221,7 @@ int msgbuf_write(struct msgbuf *msgbuf) { struct iovec iov[IOV_MAX]; - struct buf *buf, *next; -- int i = 0; + struct buf *buf; -+ unsigned int i = 0; + unsigned int i = 0; ssize_t n; struct msghdr msg; - struct cmsghdr *cmsg; - union { -- struct cmsghdr hdr; -- char buf[CMSG_SPACE(sizeof(int))]; -+ struct cmsghdr hdr; -+ char buf[CMSG_SPACE(sizeof(int))]; - } cmsgbuf; - - bzero(&iov, sizeof(iov)); -@@ -167,7 +237,7 @@ msgbuf_write(struct msgbuf *msgbuf) - if (i >= IOV_MAX) - break; - iov[i].iov_base = buf->buf + buf->rpos; -- iov[i].iov_len = buf->size - buf->rpos; -+ iov[i].iov_len = buf->wpos - buf->rpos; - i++; - if (buf->fd != -1) - break; -@@ -208,17 +278,7 @@ msgbuf_write(struct msgbuf *msgbuf) +@@ -270,17 +278,7 @@ msgbuf_write(struct msgbuf *msgbuf) buf->fd = -1; } - for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; - buf = next) { - next = TAILQ_NEXT(buf, entry); -- if (buf->rpos + n >= buf->size) { -- n -= buf->size - buf->rpos; +- if (buf->rpos + n >= buf->wpos) { +- n -= buf->wpos - buf->rpos; - buf_dequeue(msgbuf, buf); - } else { - buf->rpos += n; diff --git a/net/openbgpd/files/patch-bgpd_carp.c b/net/openbgpd/files/patch-bgpd_carp.c index f8fdaf66b53f..7ed50075cd5c 100644 --- a/net/openbgpd/files/patch-bgpd_carp.c +++ b/net/openbgpd/files/patch-bgpd_carp.c @@ -1,31 +1,12 @@ Index: bgpd/carp.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/carp.c,v -retrieving revision 1.1.1.1 +retrieving revision 1.1.1.6 retrieving revision 1.4 -diff -u -p -r1.1.1.1 -r1.4 ---- bgpd/carp.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 +diff -u -p -r1.1.1.6 -r1.4 +--- bgpd/carp.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 +++ bgpd/carp.c 22 Oct 2009 15:10:02 -0000 1.4 -@@ -1,4 +1,4 @@ --/* $OpenBSD: carp.c,v 1.5 2007/04/23 14:52:28 claudio Exp $ */ -+/* $OpenBSD: carp.c,v 1.6 2008/09/10 15:00:01 tobias Exp $ */ - - /* - * Copyright (c) 2006 Henning Brauer <henning@openbsd.org> -@@ -72,8 +72,11 @@ carp_demote_init(char *group, int force) - } - - /* only demote if this group already is demoted */ -- if ((level = carp_demote_get(group)) == -1) -+ if ((level = carp_demote_get(group)) == -1) { -+ free(c->group); -+ free(c); - return (-1); -+ } - if (level > 0 || force) - c->do_demote = 1; - -@@ -90,9 +93,8 @@ carp_demote_shutdown(void) +@@ -93,9 +93,8 @@ carp_demote_shutdown(void) while ((c = TAILQ_FIRST(&carpgroups)) != NULL) { TAILQ_REMOVE(&carpgroups, c, entry); @@ -37,7 +18,7 @@ diff -u -p -r1.1.1.1 -r1.4 free(c->group); free(c); -@@ -102,6 +104,9 @@ carp_demote_shutdown(void) +@@ -105,6 +104,9 @@ carp_demote_shutdown(void) int carp_demote_get(char *group) { @@ -47,7 +28,7 @@ diff -u -p -r1.1.1.1 -r1.4 int s; struct ifgroupreq ifgr; -@@ -124,6 +129,7 @@ carp_demote_get(char *group) +@@ -127,6 +129,7 @@ carp_demote_get(char *group) close(s); return ((int)ifgr.ifgr_attrib.ifg_carp_demoted); @@ -55,7 +36,7 @@ diff -u -p -r1.1.1.1 -r1.4 } int -@@ -156,6 +162,9 @@ carp_demote_set(char *group, int demote) +@@ -159,6 +162,9 @@ carp_demote_set(char *group, int demote) int carp_demote_ioctl(char *group, int demote) { @@ -65,7 +46,7 @@ diff -u -p -r1.1.1.1 -r1.4 int s, res; struct ifgroupreq ifgr; -@@ -178,4 +187,5 @@ carp_demote_ioctl(char *group, int demot +@@ -181,4 +187,5 @@ carp_demote_ioctl(char *group, int demot close(s); return (res); diff --git a/net/openbgpd/files/patch-bgpd_config.c b/net/openbgpd/files/patch-bgpd_config.c index c0a43a16d5ad..77598e255fa6 100644 --- a/net/openbgpd/files/patch-bgpd_config.c +++ b/net/openbgpd/files/patch-bgpd_config.c @@ -1,23 +1,38 @@ Index: bgpd/config.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/config.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.1.1.2 -diff -u -p -r1.1.1.1 -r1.1.1.2 ---- bgpd/config.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/config.c 9 Jul 2009 16:49:54 -0000 1.1.1.2 +retrieving revision 1.1.1.6 +retrieving revision 1.1.1.7 +diff -u -p -r1.1.1.6 -r1.1.1.7 +--- 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 @@ -1,4 +1,4 @@ --/* $OpenBSD: config.c,v 1.50 2007/10/13 16:35:20 deraadt Exp $ */ -+/* $OpenBSD: config.c,v 1.51 2009/01/26 23:10:02 claudio Exp $ */ +-/* $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 $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> -@@ -145,7 +145,7 @@ get_bgpid(void) - cur = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; - if ((cur & localnet) == localnet) /* skip 127/8 */ - continue; -- if (cur > ip) -+ if (ntohl(cur) > ntohl(ip)) - ip = cur; +@@ -208,7 +208,7 @@ host_v4(const char *s, struct bgpd_addr + return (0); + } + +- h->af = AF_INET; ++ h->aid = AID_INET; + h->v4.s_addr = ina.s_addr; + *len = bits; + +@@ -225,13 +225,7 @@ host_v6(const char *s, struct bgpd_addr + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_flags = AI_NUMERICHOST; + if (getaddrinfo(s, "0", &hints, &res) == 0) { +- h->af = AF_INET6; +- memcpy(&h->v6, +- &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, +- sizeof(h->v6)); +- h->scope_id = +- ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; +- ++ sa2addr(res->ai_addr, h); + freeaddrinfo(res); + return (1); } - freeifaddrs(ifap); diff --git a/net/openbgpd/files/patch-bgpd_control.c b/net/openbgpd/files/patch-bgpd_control.c index 9402b5961f4b..70b1dfd9393a 100644 --- a/net/openbgpd/files/patch-bgpd_control.c +++ b/net/openbgpd/files/patch-bgpd_control.c @@ -1,18 +1,54 @@ Index: bgpd/control.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/control.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.1.1.3 -diff -u -p -r1.1.1.1 -r1.1.1.3 ---- bgpd/control.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/control.c 22 Oct 2009 14:24:02 -0000 1.1.1.3 +retrieving revision 1.1.1.7 +retrieving revision 1.1.1.8 +diff -u -p -r1.1.1.7 -r1.1.1.8 +--- 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 @@ -1,4 +1,4 @@ --/* $OpenBSD: control.c,v 1.60 2008/05/11 01:08:05 henning Exp $ */ -+/* $OpenBSD: control.c,v 1.61 2009/05/05 20:09:19 sthen Exp $ */ +-/* $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 $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -328,11 +328,11 @@ control_dispatch_msg(struct pollfd *pfd, +@@ -53,7 +53,7 @@ control_init(int restricted, char *path) + + if (unlink(path) == -1) + if (errno != ENOENT) { +- log_warn("unlink %s", path); ++ log_warn("control_init: unlink %s", path); + close(fd); + return (-1); + } +@@ -123,14 +123,14 @@ control_accept(int listenfd, int restric + if ((connfd = accept(listenfd, + (struct sockaddr *)&sun, &len)) == -1) { + if (errno != EWOULDBLOCK && errno != EINTR) +- log_warn("session_control_accept"); ++ log_warn("control_accept: accept"); + return (0); + } + + session_socket_blockmode(connfd, BM_NONBLOCK); + + if ((ctl_conn = malloc(sizeof(struct ctl_conn))) == NULL) { +- log_warn("session_control_accept"); ++ log_warn("control_accept"); + close(connfd); + return (0); + } +@@ -191,7 +191,8 @@ control_dispatch_msg(struct pollfd *pfd, + { + struct imsg imsg; + struct ctl_conn *c; +- int n; ++ ssize_t n; ++ int verbose; + struct peer *p; + struct ctl_neighbor *neighbor; + struct ctl_show_rib_request *ribreq; +@@ -328,13 +329,19 @@ control_dispatch_msg(struct pollfd *pfd, control_result(c, CTL_RES_OK); break; case IMSG_CTL_NEIGHBOR_DOWN: @@ -22,21 +58,57 @@ diff -u -p -r1.1.1.1 -r1.1.1.3 break; case IMSG_CTL_NEIGHBOR_CLEAR: - bgp_fsm(p, EVNT_STOP); -+ session_stop(p, ERR_CEASE_ADMIN_RESET); - timer_set(p, Timer_IdleHold, - SESSION_CLEAR_DELAY); +- timer_set(p, Timer_IdleHold, +- SESSION_CLEAR_DELAY); ++ if (!p->conf.down) { ++ session_stop(p, ++ ERR_CEASE_ADMIN_RESET); ++ timer_set(p, Timer_IdleHold, ++ SESSION_CLEAR_DELAY); ++ } else { ++ session_stop(p, ++ ERR_CEASE_ADMIN_DOWN); ++ } control_result(c, CTL_RES_OK); -@@ -396,6 +396,13 @@ control_dispatch_msg(struct pollfd *pfd, - control_result(c, CTL_RES_NOCAP); + break; + case IMSG_CTL_NEIGHBOR_RREFRESH: +@@ -370,7 +377,7 @@ control_dispatch_msg(struct pollfd *pfd, + neighbor->descr[PEER_DESCR_LEN - 1] = 0; + ribreq->peerid = 0; + p = NULL; +- if (neighbor->addr.af) { ++ if (neighbor->addr.aid) { + p = getpeerbyaddr(&neighbor->addr); + if (p == NULL) { + control_result(c, +@@ -397,8 +404,7 @@ control_dispatch_msg(struct pollfd *pfd, break; } -+ if ((imsg.hdr.type == IMSG_CTL_SHOW_RIB_PREFIX) -+ && (ribreq->prefix.af != AF_INET) -+ && (ribreq->prefix.af != AF_INET6)) { -+ /* malformed request, must specify af */ -+ control_result(c, CTL_RES_PARSE_ERROR); -+ break; -+ } - c->ibuf.pid = imsg.hdr.pid; - imsg_compose_rde(imsg.hdr.type, imsg.hdr.pid, - imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); + if ((imsg.hdr.type == IMSG_CTL_SHOW_RIB_PREFIX) +- && (ribreq->prefix.af != AF_INET) +- && (ribreq->prefix.af != AF_INET6)) { ++ && (ribreq->prefix.aid == AID_UNSPEC)) { + /* malformed request, must specify af */ + control_result(c, CTL_RES_PARSE_ERROR); + break; +@@ -425,6 +431,20 @@ control_dispatch_msg(struct pollfd *pfd, + imsg_compose_rde(imsg.hdr.type, 0, + imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); + break; ++ case IMSG_CTL_LOG_VERBOSE: ++ if (imsg.hdr.len != IMSG_HEADER_SIZE + ++ sizeof(verbose)) ++ break; ++ ++ /* forward to other processes */ ++ imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid, ++ imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); ++ imsg_compose_rde(imsg.hdr.type, 0, ++ imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); ++ ++ memcpy(&verbose, imsg.data, sizeof(verbose)); ++ log_verbose(verbose); ++ break; + default: + break; + } diff --git a/net/openbgpd/files/patch-bgpd_imsg.c b/net/openbgpd/files/patch-bgpd_imsg.c index 242a9aa8ca65..3bc2bb9a90b0 100644 --- a/net/openbgpd/files/patch-bgpd_imsg.c +++ b/net/openbgpd/files/patch-bgpd_imsg.c @@ -1,267 +1,26 @@ Index: bgpd/imsg.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/imsg.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.1.1.3 -diff -u -p -r1.1.1.1 -r1.1.1.3 ---- bgpd/imsg.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/imsg.c 10 Aug 2009 21:09:57 -0000 1.1.1.3 +retrieving revision 1.1.1.6 +retrieving revision 1.1.1.7 +diff -u -p -r1.1.1.6 -r1.1.1.7 +--- bgpd/imsg.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 ++++ bgpd/imsg.c 14 Feb 2010 20:27:06 -0000 1.1.1.7 @@ -1,4 +1,4 @@ --/* $OpenBSD: imsg.c,v 1.42 2008/03/24 16:11:02 deraadt Exp $ */ +-/* $OpenBSD: imsg.c,v 1.47 2009/06/08 08:30:06 dlg Exp $ */ +/* $OpenBSD: imsg.c,v 1.48 2009/08/08 18:33:40 nicm Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -16,7 +16,9 @@ - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - --#include <sys/types.h> -+#include <sys/param.h> -+#include <sys/queue.h> -+#include <sys/socket.h> - #include <sys/uio.h> - - #include <errno.h> -@@ -24,7 +26,9 @@ - #include <string.h> - #include <unistd.h> - --#include "bgpd.h" -+#include "imsg.h" -+ -+int imsg_get_fd(struct imsgbuf *); - +@@ -263,6 +263,9 @@ imsg_flush(struct imsgbuf *ibuf) void - imsg_init(struct imsgbuf *ibuf, int fd) -@@ -37,14 +41,14 @@ imsg_init(struct imsgbuf *ibuf, int fd) - TAILQ_INIT(&ibuf->fds); - } - --int -+ssize_t - imsg_read(struct imsgbuf *ibuf) - { - struct msghdr msg; - struct cmsghdr *cmsg; - union { - struct cmsghdr hdr; -- char buf[CMSG_SPACE(sizeof(int) * 16)]; -+ char buf[CMSG_SPACE(sizeof(int) * 16)]; - } cmsgbuf; - struct iovec iov; - ssize_t n; -@@ -52,6 +56,7 @@ imsg_read(struct imsgbuf *ibuf) - 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; -@@ -61,7 +66,6 @@ imsg_read(struct imsgbuf *ibuf) - - if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) { - if (errno != EINTR && errno != EAGAIN) { -- log_warn("imsg_read: pipe read error"); - return (-1); - } - return (-2); -@@ -74,19 +78,20 @@ imsg_read(struct imsgbuf *ibuf) - 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) -- fatal("imsg_read calloc"); -+ if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) { -+ /* XXX: this return can leak */ -+ return (-1); -+ } - ifd->fd = fd; - TAILQ_INSERT_TAIL(&ibuf->fds, ifd, entry); -- } else -- log_warn("imsg_read: got unexpected ctl data level %d " -- "type %d", cmsg->cmsg_level, cmsg->cmsg_type); -+ } -+ /* we do not handle other ctl data level */ - } - - return (n); - } - --int -+ssize_t - imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) - { - size_t av, left, datalen; -@@ -99,18 +104,21 @@ imsg_get(struct imsgbuf *ibuf, struct im - memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr)); - if (imsg->hdr.len < IMSG_HEADER_SIZE || - imsg->hdr.len > MAX_IMSGSIZE) { -- log_warnx("imsg_get: imsg hdr len %u out of bounds, type=%u", -- imsg->hdr.len, imsg->hdr.type); -+ 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) { -- log_warn("imsg_get"); -+ 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) { -@@ -124,11 +132,10 @@ imsg_get(struct imsgbuf *ibuf, struct im - } - - int --imsg_compose(struct imsgbuf *ibuf, enum imsg_type type, u_int32_t peerid, -- pid_t pid, int fd, const void *data, u_int16_t datalen) -+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; -- int n; - - if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) - return (-1); -@@ -138,33 +145,55 @@ imsg_compose(struct imsgbuf *ibuf, enum - - wbuf->fd = fd; - -- if ((n = imsg_close(ibuf, wbuf)) < 0) -+ 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); - -- return (n); -+ 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, enum imsg_type type, u_int32_t peerid, -+imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, - pid_t pid, u_int16_t datalen) + imsg_clear(struct imsgbuf *ibuf) { - struct buf *wbuf; - struct imsg_hdr hdr; - -- if (datalen > MAX_IMSGSIZE - IMSG_HEADER_SIZE) { -- log_warnx("imsg_create: len %u > MAX_IMSGSIZE; " -- "type %u peerid %lu", datalen + IMSG_HEADER_SIZE, -- type, peerid); -+ datalen += IMSG_HEADER_SIZE; -+ if (datalen > MAX_IMSGSIZE) { -+ errno = ERANGE; - return (NULL); - } - -- hdr.len = datalen + IMSG_HEADER_SIZE; - hdr.type = type; -+ hdr.flags = 0; - hdr.peerid = peerid; - if ((hdr.pid = pid) == 0) - hdr.pid = ibuf->pid; -- if ((wbuf = buf_open(hdr.len)) == NULL) { -- log_warn("imsg_create: buf_open"); -+ if ((wbuf = buf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) { - return (NULL); - } - if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1) -@@ -174,28 +203,30 @@ imsg_create(struct imsgbuf *ibuf, enum i - } - - int --imsg_add(struct buf *msg, const void *data, u_int16_t datalen) -+imsg_add(struct buf *msg, void *data, u_int16_t datalen) - { - if (datalen) - if (buf_add(msg, data, datalen) == -1) { -- log_warnx("imsg_add: buf_add error"); - buf_free(msg); - return (-1); - } - return (datalen); - } - --int -+void - imsg_close(struct imsgbuf *ibuf, struct buf *msg) - { -- int n; -+ struct imsg_hdr *hdr; - -- if ((n = buf_close(&ibuf->w, msg)) < 0) { -- log_warnx("imsg_close: buf_close error"); -- buf_free(msg); -- return (-1); -- } -- return (n); -+ 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 -@@ -219,3 +250,22 @@ imsg_get_fd(struct imsgbuf *ibuf) - - 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 d0efb9046949..a7b0c120c556 100644 --- a/net/openbgpd/files/patch-bgpd_imsg.h +++ b/net/openbgpd/files/patch-bgpd_imsg.h @@ -1,116 +1,16 @@ Index: bgpd/imsg.h =================================================================== -RCS file: bgpd/imsg.h -diff -N bgpd/imsg.h ---- /dev/null 1 Jan 1970 00:00:00 -0000 -+++ bgpd/imsg.h 22 Oct 2009 14:24:02 -0000 1.1.1.2 -@@ -0,0 +1,109 @@ -+/* $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 *); +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 +--- 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); -+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 *); + + /* imsg.c */ + void imsg_init(struct imsgbuf *, int); diff --git a/net/openbgpd/files/patch-bgpd_kroute.c b/net/openbgpd/files/patch-bgpd_kroute.c index f66f1819c955..ccfc5d14c7e5 100644 --- a/net/openbgpd/files/patch-bgpd_kroute.c +++ b/net/openbgpd/files/patch-bgpd_kroute.c @@ -1,187 +1,69 @@ Index: bgpd/kroute.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/kroute.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.5 -diff -u -p -r1.1.1.1 -r1.5 ---- bgpd/kroute.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/kroute.c 10 Aug 2009 21:20:05 -0000 1.5 +retrieving revision 1.1.1.7 +retrieving revision 1.6 +diff -u -p -r1.1.1.7 -r1.6 +--- bgpd/kroute.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 ++++ bgpd/kroute.c 4 Feb 2010 16:22:23 -0000 1.6 @@ -1,4 +1,4 @@ --/* $OpenBSD: kroute.c,v 1.160 2008/05/09 12:45:25 henning Exp $ */ -+/* $OpenBSD: kroute.c,v 1.172 2009/07/23 14:53:20 claudio Exp $ */ +-/* $OpenBSD: kroute.c,v 1.169 2009/06/25 15:54:22 claudio Exp $ */ ++/* $OpenBSD: kroute.c,v 1.173 2009/12/01 14:28:05 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -48,11 +48,13 @@ struct { - struct kroute_node { - RB_ENTRY(kroute_node) entry; - struct kroute r; -+ struct kroute_node *next; - }; - - struct kroute6_node { - RB_ENTRY(kroute6_node) entry; - struct kroute6 r; -+ struct kroute6_node *next; - }; - - struct knexthop_node { -@@ -88,12 +90,17 @@ int kroute6_compare(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); -+struct kroute_node *kroute_find(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); - --struct kroute6_node *kroute6_find(const struct in6_addr *, u_int8_t); -+struct kroute6_node *kroute6_find(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); -@@ -118,6 +125,7 @@ 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 *); -@@ -164,8 +172,8 @@ kr_init(int fs, u_int rtableid) - int opt = 0, rcvbuf, default_rcvbuf; - socklen_t optlen; - -- kr_state.fib_sync = fs; - 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"); -@@ -219,13 +227,9 @@ kr_change(struct kroute_label *kl) - struct kroute_node *kr; - int action = RTM_ADD; - -- if ((kr = kroute_find(kl->kr.prefix.s_addr, kl->kr.prefixlen)) != -- NULL) { -- if (kr->r.flags & F_BGPD_INSERTED) -- action = RTM_CHANGE; -- else /* a non-bgp route already exists. not a problem */ -- return (0); -- } -+ if ((kr = kroute_find(kl->kr.prefix.s_addr, kl->kr.prefixlen, RTP_BGP)) -+ != NULL) -+ action = RTM_CHANGE; - - /* nexthop within 127/8 -> ignore silently */ - if ((kl->kr.nexthop.s_addr & htonl(IN_CLASSA_NET)) == -@@ -252,6 +256,7 @@ kr_change(struct kroute_label *kl) - 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.priority = RTP_BGP; - kr->r.labelid = kl->kr.labelid; - - if (kroute_insert(kr) == -1) -@@ -277,8 +282,8 @@ kr_delete(struct kroute_label *kl) - { - struct kroute_node *kr; - -- if ((kr = kroute_find(kl->kr.prefix.s_addr, kl->kr.prefixlen)) == -- NULL) -+ if ((kr = kroute_find(kl->kr.prefix.s_addr, kl->kr.prefixlen, RTP_BGP)) -+ == NULL) - return (0); - - if (!(kr->r.flags & F_BGPD_INSERTED)) -@@ -307,12 +312,9 @@ kr6_change(struct kroute6_label *kl) - int action = RTM_ADD; - struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; - -- if ((kr6 = kroute6_find(&kl->kr.prefix, kl->kr.prefixlen)) != NULL) { -- if (kr6->r.flags & F_BGPD_INSERTED) -- action = RTM_CHANGE; -- else /* a non-bgp route already exists. not a problem */ -- return (0); -- } -+ if ((kr6 = kroute6_find(&kl->kr.prefix, kl->kr.prefixlen, RTP_BGP)) -+ != NULL) -+ action = RTM_CHANGE; - - /* nexthop to loopback -> ignore silently */ - if (IN6_IS_ADDR_LOOPBACK(&kl->kr.nexthop)) -@@ -340,6 +342,7 @@ kr6_change(struct kroute6_label *kl) - 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; - - if (kroute6_insert(kr6) == -1) -@@ -366,7 +369,8 @@ kr6_delete(struct kroute6_label *kl) - { - struct kroute6_node *kr6; - -- if ((kr6 = kroute6_find(&kl->kr.prefix, kl->kr.prefixlen)) == NULL) -+ if ((kr6 = kroute6_find(&kl->kr.prefix, kl->kr.prefixlen, RTP_BGP)) -+ == NULL) - return (0); - - if (!(kr6->r.flags & F_BGPD_INSERTED)) -@@ -509,8 +513,8 @@ kr_nexthop_delete(struct bgpd_addr *addr - void - kr_show_route(struct imsg *imsg) - { -- struct kroute_node *kr; -- struct kroute6_node *kr6; -+ struct kroute_node *kr, *kn; -+ struct kroute6_node *kr6, *kn6; - struct bgpd_addr *addr; - int flags; - sa_family_t af; -@@ -530,16 +534,26 @@ kr_show_route(struct imsg *imsg) - 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) -- send_imsg_session(IMSG_CTL_KROUTE, -- imsg->hdr.pid, &kr->r, -- sizeof(kr->r)); -+ 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); -+ } - if (!af || af == AF_INET6) - RB_FOREACH(kr6, kroute6_tree, &krt6) -- if (!flags || kr6->r.flags & flags) -- send_imsg_session(IMSG_CTL_KROUTE6, -- imsg->hdr.pid, &kr6->r, -- sizeof(kr6->r)); -+ 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); -+ } - break; - case IMSG_CTL_KROUTE_ADDR: - if (imsg->hdr.len != IMSG_HEADER_SIZE + -@@ -573,11 +587,17 @@ kr_show_route(struct imsg *imsg) - case AF_INET: +@@ -463,21 +463,21 @@ kr_nexthop_add(struct bgpd_addr *addr) + bzero(&nh, sizeof(nh)); + memcpy(&nh.nexthop, addr, sizeof(nh.nexthop)); + nh.valid = 1; +- if (h->kroute != NULL && addr->af == AF_INET) { ++ if (h->kroute != NULL && addr->aid == AID_INET) { + k = h->kroute; + nh.connected = k->r.flags & F_CONNECTED; + if (k->r.nexthop.s_addr != 0) { +- nh.gateway.af = AF_INET; ++ nh.gateway.aid = AID_INET; + nh.gateway.v4.s_addr = + k->r.nexthop.s_addr; + } + memcpy(&nh.kr.kr4, &k->r, sizeof(nh.kr.kr4)); +- } else if (h->kroute != NULL && addr->af == AF_INET6) { ++ } else if (h->kroute != NULL && addr->aid == AID_INET6) { + k6 = h->kroute; + nh.connected = k6->r.flags & F_CONNECTED; + if (memcmp(&k6->r.nexthop, &in6addr_any, + sizeof(struct in6_addr)) != 0) { +- nh.gateway.af = AF_INET6; ++ nh.gateway.aid = AID_INET6; + memcpy(&nh.gateway.v6, &k6->r.nexthop, + sizeof(struct in6_addr)); + } +@@ -563,14 +563,14 @@ kr_show_route(struct imsg *imsg) + } + addr = imsg->data; + kr = NULL; +- switch (addr->af) { +- case AF_INET: ++ switch (addr->aid) { ++ case AID_INET: + kr = kroute_match(addr->v4.s_addr, 1); + if (kr != NULL) + send_imsg_session(IMSG_CTL_KROUTE, + imsg->hdr.pid, &kr->r, sizeof(kr->r)); + break; +- case AF_INET6: ++ case AID_INET6: + kr6 = kroute6_match(&addr->v6, 1); + if (kr6 != NULL) + send_imsg_session(IMSG_CTL_KROUTE6, +@@ -583,15 +583,21 @@ kr_show_route(struct imsg *imsg) + bzero(&snh, sizeof(snh)); + memcpy(&snh.addr, &h->nexthop, sizeof(snh.addr)); + if (h->kroute != NULL) { +- switch (h->nexthop.af) { +- case AF_INET: ++ switch (h->nexthop.aid) { ++ case AID_INET: kr = h->kroute; snh.valid = kroute_validate(&kr->r); + snh.krvalid = 1; @@ -189,7 +71,8 @@ diff -u -p -r1.1.1.1 -r1.5 + sizeof(snh.kr.kr4)); ifindex = kr->r.ifindex; break; - case AF_INET6: +- case AF_INET6: ++ case AID_INET6: kr6 = h->kroute; snh.valid = kroute6_validate(&kr6->r); + snh.krvalid = 1; @@ -198,55 +81,30 @@ diff -u -p -r1.1.1.1 -r1.5 ifindex = kr6->r.ifindex; break; } -@@ -791,6 +811,14 @@ kroute_compare(struct kroute_node *a, st - return (-1); - if (a->r.prefixlen > b->r.prefixlen) - return (1); -+ -+ /* if the priority is RTP_ANY finish on the first address hit */ -+ if (a->r.priority == RTP_ANY || b->r.priority == RTP_ANY) -+ return (0); -+ if (a->r.priority < b->r.priority) -+ return (-1); -+ if (a->r.priority > b->r.priority) -+ return (1); - return (0); - } - -@@ -810,32 +838,42 @@ kroute6_compare(struct kroute6_node *a, - return (-1); - if (a->r.prefixlen > b->r.prefixlen) - return (1); -+ -+ /* if the priority is RTP_ANY finish on the first address hit */ -+ if (a->r.priority == RTP_ANY || b->r.priority == RTP_ANY) -+ return (0); -+ if (a->r.priority < b->r.priority) -+ return (-1); -+ if (a->r.priority > b->r.priority) -+ return (1); - return (0); - } - +@@ -846,26 +852,28 @@ kroute6_compare(struct kroute6_node *a, int knexthop_compare(struct knexthop_node *a, struct knexthop_node *b) { - u_int32_t r; + int i; - if (a->nexthop.af != b->nexthop.af) - return (b->nexthop.af - a->nexthop.af); +- if (a->nexthop.af != b->nexthop.af) +- return (b->nexthop.af - a->nexthop.af); ++ if (a->nexthop.aid != b->nexthop.aid) ++ return (b->nexthop.aid - a->nexthop.aid); - switch (a->nexthop.af) { - case AF_INET: +- switch (a->nexthop.af) { +- case AF_INET: - if ((r = b->nexthop.addr32[0] - a->nexthop.addr32[0]) != 0) - return (r); ++ switch (a->nexthop.aid) { ++ case AID_INET: + if (ntohl(a->nexthop.v4.s_addr) < ntohl(b->nexthop.v4.s_addr)) + return (-1); + if (ntohl(a->nexthop.v4.s_addr) > ntohl(b->nexthop.v4.s_addr)) + return (1); break; - case AF_INET6: +- case AF_INET6: - if ((r = b->nexthop.addr32[3] - a->nexthop.addr32[3]) != 0) - return (r); - if ((r = b->nexthop.addr32[2] - a->nexthop.addr32[2]) != 0) @@ -255,6 +113,7 @@ diff -u -p -r1.1.1.1 -r1.5 - return (r); - if ((r = b->nexthop.addr32[0] - a->nexthop.addr32[0]) != 0) - return (r); ++ case AID_INET6: + for (i = 0; i < 16; i++) { + if (a->nexthop.v6.s6_addr[i] < b->nexthop.v6.s6_addr[i]) + return (-1); @@ -267,279 +126,34 @@ diff -u -p -r1.1.1.1 -r1.5 } return (0); -@@ -853,27 +891,62 @@ kif_compare(struct kif_node *a, struct k - */ - - struct kroute_node * --kroute_find(in_addr_t prefix, u_int8_t prefixlen) -+kroute_find(in_addr_t prefix, u_int8_t prefixlen, u_int8_t prio) - { - struct kroute_node s; -+ struct kroute_node *kn, *tmp; - - s.r.prefix.s_addr = prefix; - s.r.prefixlen = prefixlen; -+ s.r.priority = prio; - -- return (RB_FIND(kroute_tree, &krt, &s)); -+ kn = RB_FIND(kroute_tree, &krt, &s); -+ if (kn && prio == RTP_ANY) { -+ tmp = RB_PREV(kroute_tree, &krt, kn); -+ while (tmp) { -+ if (kroute_compare(&s, tmp) == 0) -+ kn = tmp; -+ else -+ break; -+ tmp = RB_PREV(kroute_tree, &krt, kn); -+ } -+ } -+ return (kn); -+} -+ -+struct kroute_node * -+kroute_matchgw(struct kroute_node *kr, struct sockaddr_in *sa_in) -+{ -+ in_addr_t nexthop; -+ -+ if (sa_in == NULL) { -+ log_warnx("kroute_matchgw: no nexthop defined"); -+ return (NULL); -+ } -+ nexthop = sa_in->sin_addr.s_addr; -+ -+ while (kr) { -+ if (kr->r.nexthop.s_addr == nexthop) -+ return (kr); -+ kr = kr->next; -+ } -+ -+ return (NULL); - } - - int - kroute_insert(struct kroute_node *kr) - { -+ struct kroute_node *krm; - struct knexthop_node *h; - in_addr_t mask, ina; - -- if (RB_INSERT(kroute_tree, &krt, kr) != NULL) { -- log_warnx("kroute_tree insert failed for %s/%u", -- inet_ntoa(kr->r.prefix), kr->r.prefixlen); -- free(kr); -- return (-1); -+ if ((krm = RB_INSERT(kroute_tree, &krt, kr)) != NULL) { -+ /* multipath route, add at end of list */ -+ while (krm->next != NULL) -+ krm = krm->next; -+ krm->next = kr; -+ kr->next = NULL; /* to be sure */ - } - - if (kr->r.flags & F_KERNEL) { -@@ -888,29 +961,61 @@ kroute_insert(struct kroute_node *kr) - if (kif_kr_insert(kr) == -1) - return (-1); - -- kr_redistribute(IMSG_NETWORK_ADD, &kr->r); -+ if (krm == NULL) -+ /* redistribute multipath routes only once */ -+ kr_redistribute(IMSG_NETWORK_ADD, &kr->r); - } - return (0); - } - -+ - int - kroute_remove(struct kroute_node *kr) - { -+ struct kroute_node *krm; - struct knexthop_node *s; - -- if (RB_REMOVE(kroute_tree, &krt, kr) == NULL) { -- log_warnx("kroute_remove failed for %s/%u", -+ if ((krm = RB_FIND(kroute_tree, &krt, kr)) == NULL) { -+ log_warnx("kroute_remove failed to find %s/%u", - inet_ntoa(kr->r.prefix), kr->r.prefixlen); - return (-1); - } - -+ if (krm == kr) { -+ /* head element */ -+ if (RB_REMOVE(kroute_tree, &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) { -+ log_warnx("kroute_remove failed to add %s/%u", -+ inet_ntoa(kr->r.prefix), kr->r.prefixlen); -+ return (-1); -+ } -+ } -+ } else { -+ /* somewhere in the list */ -+ while (krm->next != kr && krm->next != NULL) -+ krm = krm->next; -+ if (krm->next == NULL) { -+ log_warnx("kroute_remove multipath list corrupted " -+ "for %s/%u", inet_ntoa(kr->r.prefix), -+ kr->r.prefixlen); -+ return (-1); -+ } -+ krm->next = kr->next; -+ } -+ - /* check whether a nexthop depends on this kroute */ - if ((kr->r.flags & F_KERNEL) && (kr->r.flags & F_NEXTHOP)) - RB_FOREACH(s, knexthop_tree, &knt) - if (s->kroute == kr) - knexthop_validate(s); - -- if (kr->r.flags & F_KERNEL) -+ if (kr->r.flags & F_KERNEL && kr == krm && kr->next == NULL) -+ /* again remove only once */ - kr_redistribute(IMSG_NETWORK_REMOVE, &kr->r); - - if (kr->r.flags & F_CONNECTED) -@@ -933,27 +1038,62 @@ kroute_clear(void) - } - - struct kroute6_node * --kroute6_find(const struct in6_addr *prefix, u_int8_t prefixlen) -+kroute6_find(const struct in6_addr *prefix, u_int8_t prefixlen, u_int8_t prio) - { - struct kroute6_node s; -+ struct kroute6_node *kn6, *tmp; - - memcpy(&s.r.prefix, prefix, sizeof(struct in6_addr)); - s.r.prefixlen = prefixlen; -+ s.r.priority = prio; - -- return (RB_FIND(kroute6_tree, &krt6, &s)); -+ kn6 = RB_FIND(kroute6_tree, &krt6, &s); -+ if (kn6 && prio == RTP_ANY) { -+ tmp = RB_PREV(kroute6_tree, &krt6, kn6); -+ while (tmp) { -+ if (kroute6_compare(&s, tmp) == 0) -+ kn6 = tmp; -+ else -+ break; -+ tmp = RB_PREV(kroute6_tree, &krt6, kn6); -+ } -+ } -+ return (kn6); -+} -+ -+struct kroute6_node * -+kroute6_matchgw(struct kroute6_node *kr, struct sockaddr_in6 *sa_in6) -+{ -+ struct in6_addr nexthop; -+ -+ if (sa_in6 == NULL) { -+ log_warnx("kroute6_matchgw: no nexthop defined"); -+ return (NULL); -+ } -+ memcpy(&nexthop, &sa_in6->sin6_addr, sizeof(nexthop)); -+ -+ while (kr) { +@@ -945,7 +953,7 @@ kroute_insert(struct kroute_node *kr) + mask = prefixlen2mask(kr->r.prefixlen); + ina = ntohl(kr->r.prefix.s_addr); + RB_FOREACH(h, knexthop_tree, &knt) +- if (h->nexthop.af == AF_INET && ++ if (h->nexthop.aid == AID_INET && + (ntohl(h->nexthop.v4.s_addr) & mask) == ina) + knexthop_validate(h); + +@@ -1065,7 +1073,7 @@ kroute6_matchgw(struct kroute6_node *kr, + memcpy(&nexthop, &sa_in6->sin6_addr, sizeof(nexthop)); + + while (kr) { +- if (memcmp(&kr->r.nexthop, &nexthop, sizeof(nexthop)) == NULL) + if (memcmp(&kr->r.nexthop, &nexthop, sizeof(nexthop)) == 0) -+ return (kr); -+ kr = kr->next; -+ } -+ -+ return (NULL); - } - - int - kroute6_insert(struct kroute6_node *kr) - { -+ struct kroute6_node *krm; - struct knexthop_node *h; - struct in6_addr ina, inb; - -- if (RB_INSERT(kroute6_tree, &krt6, kr) != NULL) { -- log_warnx("kroute_tree insert failed for %s/%u", -- log_in6addr(&kr->r.prefix), kr->r.prefixlen); -- free(kr); -- return (-1); -+ if ((krm = RB_INSERT(kroute6_tree, &krt6, kr)) != NULL) { -+ /* multipath route, add at end of list */ -+ while (krm->next != NULL) -+ krm = krm->next; -+ krm->next = kr; -+ kr->next = NULL; /* to be sure */ + return (kr); + kr = kr->next; } - +@@ -1091,7 +1099,7 @@ kroute6_insert(struct kroute6_node *kr) if (kr->r.flags & F_KERNEL) { -@@ -970,7 +1110,9 @@ kroute6_insert(struct kroute6_node *kr) - if (kif_kr6_insert(kr) == -1) - return (-1); - -- kr_redistribute6(IMSG_NETWORK_ADD, &kr->r); -+ if (krm == NULL) -+ /* redistribute multipath routes only once */ -+ kr_redistribute6(IMSG_NETWORK_ADD, &kr->r); - } - - return (0); -@@ -979,21 +1121,51 @@ kroute6_insert(struct kroute6_node *kr) - int - kroute6_remove(struct kroute6_node *kr) - { -+ struct kroute6_node *krm; - struct knexthop_node *s; - -- if (RB_REMOVE(kroute6_tree, &krt6, kr) == NULL) { -- log_warnx("kroute_remove failed for %s/%u", -+ if ((krm = RB_FIND(kroute6_tree, &krt6, kr)) == NULL) { -+ log_warnx("kroute6_remove failed for %s/%u", - log_in6addr(&kr->r.prefix), kr->r.prefixlen); - return (-1); - } - -+ if (krm == kr) { -+ /* head element */ -+ if (RB_REMOVE(kroute6_tree, &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) { -+ log_warnx("kroute6_remove failed to add %s/%u", -+ log_in6addr(&kr->r.prefix), -+ kr->r.prefixlen); -+ return (-1); -+ } -+ } -+ } else { -+ /* somewhere in the list */ -+ while (krm->next != kr && krm->next != NULL) -+ krm = krm->next; -+ if (krm->next == NULL) { -+ log_warnx("kroute6_remove multipath list corrupted " -+ "for %s/%u", log_in6addr(&kr->r.prefix), -+ kr->r.prefixlen); -+ return (-1); -+ } -+ krm->next = kr->next; -+ } -+ - /* check whether a nexthop depends on this kroute */ - if ((kr->r.flags & F_KERNEL) && (kr->r.flags & F_NEXTHOP)) - RB_FOREACH(s, knexthop_tree, &knt) - if (s->kroute == kr) - knexthop_validate(s); - -- if (kr->r.flags & F_KERNEL) -+ if (kr->r.flags & F_KERNEL && kr == krm && kr->next == NULL) -+ /* again remove only once */ - kr_redistribute6(IMSG_NETWORK_REMOVE, &kr->r); - - if (kr->r.flags & F_CONNECTED) -@@ -1020,6 +1192,7 @@ knexthop_find(struct bgpd_addr *addr) + inet6applymask(&ina, &kr->r.prefix, kr->r.prefixlen); + RB_FOREACH(h, knexthop_tree, &knt) +- if (h->nexthop.af == AF_INET6) { ++ if (h->nexthop.aid == AID_INET6) { + inet6applymask(&inb, &h->nexthop.v6, + kr->r.prefixlen); + if (memcmp(&ina, &inb, sizeof(ina)) == 0) +@@ -1184,6 +1192,7 @@ knexthop_find(struct bgpd_addr *addr) { struct knexthop_node s; @@ -547,148 +161,119 @@ diff -u -p -r1.1.1.1 -r1.5 memcpy(&s.nexthop, addr, sizeof(s.nexthop)); return (RB_FIND(knexthop_tree, &knt, &s)); -@@ -1374,6 +1547,46 @@ knexthop_validate(struct knexthop_node * - } - } - -+void -+knexthop_track(void *krn) -+{ -+ 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) { -+ bzero(&n, sizeof(n)); -+ memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop)); -+ -+ switch (kn->nexthop.af) { -+ case AF_INET: -+ kr = krn; -+ n.valid = 1; -+ n.connected = kr->r.flags & F_CONNECTED; -+ if ((n.gateway.v4.s_addr = -+ kr->r.nexthop.s_addr) != 0) -+ n.gateway.af = AF_INET; -+ memcpy(&n.kr.kr4, &kr->r, sizeof(n.kr.kr4)); -+ break; -+ case AF_INET6: -+ kr6 = krn; -+ n.valid = 1; -+ n.connected = kr6->r.flags & F_CONNECTED; -+ if (memcmp(&kr6->r.nexthop, &in6addr_any, -+ sizeof(struct in6_addr)) != 0) { -+ n.gateway.af = AF_INET6; -+ memcpy(&n.gateway.v6, &kr6->r.nexthop, -+ sizeof(struct in6_addr)); -+ } -+ memcpy(&n.kr.kr6, &kr6->r, sizeof(n.kr.kr6)); -+ break; -+ } -+ send_nexthop_update(&n); -+ } -+} -+ - struct kroute_node * - kroute_match(in_addr_t key, int matchall) - { -@@ -1385,13 +1598,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)) != NULL) -+ if ((kr = kroute_find(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)) != NULL) -+ if ((kr = kroute_find(0, 0, RTP_ANY)) != NULL) - if (matchall || bgpd_filternexthop(&kr->r, NULL) == 0) - return (kr); - -@@ -1408,13 +1621,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)) != NULL) -+ if ((kr6 = kroute6_find(&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)) != NULL) -+ if ((kr6 = kroute6_find(&in6addr_any, 0, RTP_ANY)) != NULL) - if (matchall || bgpd_filternexthop(NULL, &kr6->r) == 0) - return (kr6); - -@@ -1456,7 +1669,6 @@ kroute_detach_nexthop(struct knexthop_no - kn->kroute = NULL; - } - -- - /* - * misc helpers - */ -@@ -1568,15 +1780,6 @@ mask2prefixlen6(struct sockaddr_in6 *sa_ - return (l); - } - --in_addr_t --prefixlen2mask(u_int8_t prefixlen) --{ -- if (prefixlen == 0) -- return (0); -- -- return (0xffffffff << (32 - prefixlen)); --} -- - struct in6_addr * - prefixlen2mask6(u_int8_t prefixlen) - { -@@ -1593,25 +1796,8 @@ prefixlen2mask6(u_int8_t prefixlen) - return (&mask); - } - --void --inet6applymask(struct in6_addr *dest, const struct in6_addr *src, int prefixlen) --{ -- struct in6_addr mask; -- int i; -- -- bzero(&mask, sizeof(mask)); -- for (i = 0; i < prefixlen / 8; i++) -- mask.s6_addr[i] = 0xff; -- i = prefixlen % 8; -- if (i) -- mask.s6_addr[prefixlen / 8] = 0xff00 >> i; -- -- for (i = 0; i < 16; i++) -- dest->s6_addr[i] = src->s6_addr[i] & mask.s6_addr[i]; --} -- --#define ROUNDUP(a, size) \ -- (((a) & ((size) - 1)) ? (1 + ((a) | ((size) - 1))) : (a)) -+#define ROUNDUP(a) \ -+ (((a) & ((sizeof(long)) - 1)) ? (1 + ((a) | ((sizeof(long)) - 1))) : (a)) - - void - get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) -@@ -1622,7 +1808,7 @@ get_rtaddrs(int addrs, struct sockaddr * - if (addrs & (1 << i)) { - rti_info[i] = sa; - sa = (struct sockaddr *)((char *)(sa) + -- ROUNDUP(sa->sa_len, sizeof(long))); -+ ROUNDUP(sa->sa_len)); - } else - rti_info[i] = NULL; - } -@@ -1747,7 +1933,9 @@ send_rtmsg(int fd, int action, struct kr +@@ -1480,17 +1489,17 @@ knexthop_validate(struct knexthop_node * + struct kroute_nexthop n; + int was_valid = 0; + +- if (kn->nexthop.af == AF_INET && (kr = kn->kroute) != NULL) ++ if (kn->nexthop.aid == AID_INET && (kr = kn->kroute) != NULL) + was_valid = kroute_validate(&kr->r); +- if (kn->nexthop.af == AF_INET6 && (kr6 = kn->kroute) != NULL) ++ if (kn->nexthop.aid == AID_INET6 && (kr6 = kn->kroute) != NULL) + was_valid = kroute6_validate(&kr6->r); + + bzero(&n, sizeof(n)); + memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop)); + kroute_detach_nexthop(kn); + +- switch (kn->nexthop.af) { +- case AF_INET: ++ switch (kn->nexthop.aid) { ++ case AID_INET: + if ((kr = kroute_match(kn->nexthop.v4.s_addr, 0)) == NULL) { + if (was_valid) + send_nexthop_update(&n); +@@ -1500,7 +1509,7 @@ knexthop_validate(struct knexthop_node * + n.connected = kr->r.flags & F_CONNECTED; + if ((n.gateway.v4.s_addr = + kr->r.nexthop.s_addr) != 0) +- n.gateway.af = AF_INET; ++ n.gateway.aid = AID_INET; + memcpy(&n.kr.kr4, &kr->r, sizeof(n.kr.kr4)); + send_nexthop_update(&n); + } else /* down */ +@@ -1511,7 +1520,7 @@ knexthop_validate(struct knexthop_node * + kr->r.flags |= F_NEXTHOP; + } + break; +- case AF_INET6: ++ case AID_INET6: + if ((kr6 = kroute6_match(&kn->nexthop.v6, 0)) == NULL) { + if (was_valid) + send_nexthop_update(&n); +@@ -1521,7 +1530,7 @@ knexthop_validate(struct knexthop_node * + n.connected = kr6->r.flags & F_CONNECTED; + if (memcmp(&kr6->r.nexthop, &in6addr_any, + sizeof(struct in6_addr)) != 0) { +- n.gateway.af = AF_INET6; ++ n.gateway.aid = AID_INET6; + memcpy(&n.gateway.v6, &kr6->r.nexthop, + sizeof(struct in6_addr)); + } +@@ -1551,23 +1560,23 @@ knexthop_track(void *krn) + bzero(&n, sizeof(n)); + memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop)); + +- switch (kn->nexthop.af) { +- case AF_INET: ++ switch (kn->nexthop.aid) { ++ case AID_INET: + kr = krn; + n.valid = 1; + n.connected = kr->r.flags & F_CONNECTED; + if ((n.gateway.v4.s_addr = + kr->r.nexthop.s_addr) != 0) +- n.gateway.af = AF_INET; ++ n.gateway.aid = AID_INET; + memcpy(&n.kr.kr4, &kr->r, sizeof(n.kr.kr4)); + break; +- case AF_INET6: ++ case AID_INET6: + kr6 = krn; + n.valid = 1; + n.connected = kr6->r.flags & F_CONNECTED; + if (memcmp(&kr6->r.nexthop, &in6addr_any, + sizeof(struct in6_addr)) != 0) { +- n.gateway.af = AF_INET6; ++ n.gateway.aid = AID_INET6; + memcpy(&n.gateway.v6, &kr6->r.nexthop, + sizeof(struct in6_addr)); + } +@@ -1645,12 +1654,12 @@ kroute_detach_nexthop(struct knexthop_no + ; /* nothing */ + + if (s == NULL) { +- switch (kn->nexthop.af) { +- case AF_INET: ++ switch (kn->nexthop.aid) { ++ case AID_INET: + k = kn->kroute; + k->r.flags &= ~F_NEXTHOP; + break; +- case AF_INET6: ++ case AID_INET6: + k6 = kn->kroute; + k6->r.flags &= ~F_NEXTHOP; + break; +@@ -1849,7 +1858,7 @@ if_change(u_short ifindex, int flags, st + nh.connected = 1; + if ((nh.gateway.v4.s_addr = + kkr->kr->r.nexthop.s_addr) != 0) +- nh.gateway.af = AF_INET; ++ nh.gateway.aid = AID_INET; + } + memcpy(&nh.kr.kr4, &kkr->kr->r, + sizeof(nh.kr.kr4)); +@@ -1873,7 +1882,7 @@ if_change(u_short ifindex, int flags, st + if (memcmp(&kkr6->kr->r.nexthop, + &in6addr_any, sizeof(struct + in6_addr))) { +- nh.gateway.af = AF_INET6; ++ nh.gateway.aid = AID_INET6; + memcpy(&nh.gateway.v6, + &kkr6->kr->r.nexthop, + sizeof(struct in6_addr)); +@@ -1924,7 +1933,9 @@ send_rtmsg(int fd, int action, struct kr struct sockaddr_in prefix; struct sockaddr_in nexthop; struct sockaddr_in mask; @@ -698,21 +283,21 @@ diff -u -p -r1.1.1.1 -r1.5 int iovcnt = 0; if (kr_state.fib_sync == 0) -@@ -1757,9 +1945,13 @@ send_rtmsg(int fd, int action, struct kr +@@ -1934,8 +1945,13 @@ send_rtmsg(int fd, int action, struct kr 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__) */ - hdr.rtm_flags = RTF_PROTO1; ++ hdr.rtm_flags = RTF_PROTO1; +#if !defined(__FreeBSD__) /* XXX: FreeBSD has no rtm_priority */ hdr.rtm_priority = RTP_BGP; +#endif /* !defined(__FreeBSD__) */ if (kroute->flags & F_BLACKHOLE) hdr.rtm_flags |= RTF_BLACKHOLE; if (kroute->flags & F_REJECT) -@@ -1808,6 +2000,7 @@ send_rtmsg(int fd, int action, struct kr +@@ -1984,6 +2000,7 @@ send_rtmsg(int fd, int action, struct kr iov[iovcnt].iov_base = &mask; iov[iovcnt++].iov_len = sizeof(mask); @@ -720,7 +305,7 @@ diff -u -p -r1.1.1.1 -r1.5 if (kroute->labelid) { bzero(&label, sizeof(label)); label.sr_len = sizeof(label); -@@ -1820,6 +2013,7 @@ send_rtmsg(int fd, int action, struct kr +@@ -1996,6 +2013,7 @@ send_rtmsg(int fd, int action, struct kr iov[iovcnt].iov_base = &label; iov[iovcnt++].iov_len = sizeof(label); } @@ -728,96 +313,36 @@ diff -u -p -r1.1.1.1 -r1.5 retry: if (writev(fd, iov, iovcnt) == -1) { -@@ -1857,10 +2051,13 @@ send_rt6msg(int fd, int action, struct k - { - struct iovec iov[5]; - struct rt_msghdr hdr; -- struct sockaddr_in6 prefix; -- struct sockaddr_in6 nexthop; -- struct sockaddr_in6 mask; -+ struct pad { -+ struct sockaddr_in6 addr; -+ char pad[sizeof(long)]; -+ } prefix, nexthop, mask; +@@ -2037,7 +2055,9 @@ send_rt6msg(int fd, int action, struct k + struct sockaddr_in6 addr; + char pad[sizeof(long)]; + } prefix, nexthop, mask; +#if !defined(__FreeBSD__) /* FreeBSD has no route labeling. */ struct sockaddr_rtlabel label; +#endif /* !defined(__FreeBSD__) */ int iovcnt = 0; if (kr_state.fib_sync == 0) -@@ -1870,7 +2067,9 @@ send_rt6msg(int fd, int action, struct k +@@ -2047,7 +2067,10 @@ send_rt6msg(int fd, int action, struct k 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__) */ - hdr.rtm_flags = RTF_PROTO1; ++ hdr.rtm_flags = RTF_PROTO1; if (kroute->flags & F_BLACKHOLE) hdr.rtm_flags |= RTF_BLACKHOLE; -@@ -1885,44 +2084,46 @@ send_rt6msg(int fd, int action, struct k - iov[iovcnt++].iov_len = sizeof(hdr); - - bzero(&prefix, sizeof(prefix)); -- prefix.sin6_len = sizeof(prefix); -- prefix.sin6_family = AF_INET6; -- memcpy(&prefix.sin6_addr, &kroute->prefix, sizeof(struct in6_addr)); -+ prefix.addr.sin6_len = sizeof(struct sockaddr_in6); -+ prefix.addr.sin6_family = AF_INET6; -+ memcpy(&prefix.addr.sin6_addr, &kroute->prefix, -+ sizeof(struct in6_addr)); - /* XXX scope does not matter or? */ - /* adjust header */ - hdr.rtm_addrs |= RTA_DST; -- hdr.rtm_msglen += sizeof(prefix); -+ hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6)); - /* adjust iovec */ - iov[iovcnt].iov_base = &prefix; -- iov[iovcnt++].iov_len = sizeof(prefix); -+ iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6)); - - if (memcmp(&kroute->nexthop, &in6addr_any, sizeof(struct in6_addr))) { - bzero(&nexthop, sizeof(nexthop)); -- nexthop.sin6_len = sizeof(nexthop); -- nexthop.sin6_family = AF_INET6; -- memcpy(&nexthop.sin6_addr, &kroute->nexthop, -+ nexthop.addr.sin6_len = sizeof(struct sockaddr_in6); -+ nexthop.addr.sin6_family = AF_INET6; -+ memcpy(&nexthop.addr.sin6_addr, &kroute->nexthop, - sizeof(struct in6_addr)); - /* adjust header */ - hdr.rtm_flags |= RTF_GATEWAY; - hdr.rtm_addrs |= RTA_GATEWAY; -- hdr.rtm_msglen += sizeof(nexthop); -+ hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6)); - /* adjust iovec */ - iov[iovcnt].iov_base = &nexthop; -- iov[iovcnt++].iov_len = sizeof(nexthop); -+ iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6)); - } - - bzero(&mask, sizeof(mask)); -- mask.sin6_len = sizeof(mask); -- mask.sin6_family = AF_INET6; -- memcpy(&mask.sin6_addr, prefixlen2mask6(kroute->prefixlen), -+ mask.addr.sin6_len = sizeof(struct sockaddr_in6); -+ mask.addr.sin6_family = AF_INET6; -+ memcpy(&mask.addr.sin6_addr, prefixlen2mask6(kroute->prefixlen), - sizeof(struct in6_addr)); - /* adjust header */ - hdr.rtm_addrs |= RTA_NETMASK; -- hdr.rtm_msglen += sizeof(mask); -+ hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6)); - /* adjust iovec */ + if (kroute->flags & F_REJECT) +@@ -2100,6 +2123,7 @@ send_rt6msg(int fd, int action, struct k iov[iovcnt].iov_base = &mask; -- iov[iovcnt++].iov_len = sizeof(mask); -+ iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6)); + iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6)); +#if !defined(__FreeBSD__) /* FreeBSD has no route labeling. */ if (kroute->labelid) { bzero(&label, sizeof(label)); label.sr_len = sizeof(label); -@@ -1935,6 +2136,7 @@ send_rt6msg(int fd, int action, struct k +@@ -2112,6 +2136,7 @@ send_rt6msg(int fd, int action, struct k iov[iovcnt].iov_base = &label; iov[iovcnt++].iov_len = sizeof(label); } @@ -825,25 +350,7 @@ diff -u -p -r1.1.1.1 -r1.5 retry: if (writev(fd, iov, iovcnt) == -1) { -@@ -1949,7 +2151,7 @@ retry: - kroute->prefixlen); - return (0); - } else { -- log_warnx("send_rtmsg: action %u, " -+ log_warnx("send_rt6msg: action %u, " - "prefix %s/%u: %s", hdr.rtm_type, - log_in6addr(&kroute->prefix), - kroute->prefixlen, strerror(errno)); -@@ -1957,7 +2159,7 @@ retry: - } - break; - default: -- log_warnx("send_rtmsg: action %u, prefix %s/%u: %s", -+ log_warnx("send_rt6msg: action %u, prefix %s/%u: %s", - hdr.rtm_type, log_in6addr(&kroute->prefix), - kroute->prefixlen, strerror(errno)); - return (0); -@@ -1970,8 +2172,8 @@ retry: +@@ -2147,8 +2172,8 @@ retry: int fetchtable(u_int rtableid, int connected_only) { @@ -854,7 +361,7 @@ diff -u -p -r1.1.1.1 -r1.5 char *buf, *next, *lim; struct rt_msghdr *rtm; struct sockaddr *sa, *gw, *rti_info[RTAX_MAX]; -@@ -1986,9 +2188,8 @@ fetchtable(u_int rtableid, int connected +@@ -2163,9 +2188,8 @@ fetchtable(u_int rtableid, int connected mib[3] = 0; mib[4] = NET_RT_DUMP; mib[5] = 0; @@ -865,7 +372,7 @@ diff -u -p -r1.1.1.1 -r1.5 if (rtableid != 0 && errno == EINVAL) /* table nonexistent */ return (0); log_warn("sysctl"); -@@ -1998,7 +2199,7 @@ fetchtable(u_int rtableid, int connected +@@ -2175,7 +2199,7 @@ fetchtable(u_int rtableid, int connected log_warn("fetchtable"); return (-1); } @@ -874,63 +381,48 @@ diff -u -p -r1.1.1.1 -r1.5 log_warn("sysctl"); free(buf); return (-1); -@@ -2007,7 +2208,13 @@ fetchtable(u_int rtableid, int connected - lim = buf + len; - for (next = buf; next < lim; next += rtm->rtm_msglen) { +@@ -2186,7 +2210,11 @@ fetchtable(u_int rtableid, int connected rtm = (struct rt_msghdr *)next; -- sa = (struct sockaddr *)(rtm + 1); -+ if (rtm->rtm_version != RTM_VERSION) -+ continue; + if (rtm->rtm_version != RTM_VERSION) + continue; +#if !defined(__FreeBSD__) /* no rtm_hdrlen on FreeBSD */ -+ sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); + sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); +#else + sa = (struct sockaddr *)(next + sizeof(struct rt_msghdr)); +#endif get_rtaddrs(rtm->rtm_addrs, sa, rti_info); if ((sa = rti_info[RTAX_DST]) == NULL) -@@ -2016,10 +2223,6 @@ fetchtable(u_int rtableid, int connected - if (rtm->rtm_flags & RTF_LLINFO) /* arp cache */ - continue; - --#ifdef RTF_MPATH -- if (rtm->rtm_flags & RTF_MPATH) /* multipath */ -- continue; --#endif - switch (sa->sa_family) { - case AF_INET: - if ((kr = calloc(1, sizeof(struct kroute_node))) == -@@ -2030,6 +2233,11 @@ fetchtable(u_int rtableid, int connected +@@ -2205,7 +2233,11 @@ fetchtable(u_int rtableid, int connected } kr->r.flags = F_KERNEL; +#if defined(__FreeBSD__) /* no rtm_priority on FreeBSD */ + kr->r.priority = RTP_BGP; +#else -+ kr->r.priority = rtm->rtm_priority; + kr->r.priority = rtm->rtm_priority; +#endif kr->r.ifindex = rtm->rtm_index; kr->r.prefix.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; -@@ -2062,6 +2270,11 @@ fetchtable(u_int rtableid, int connected +@@ -2238,7 +2270,11 @@ fetchtable(u_int rtableid, int connected } kr6->r.flags = F_KERNEL; +#if defined(__FreeBSD__) /* no rtm_priority on FreeBSD */ + kr6->r.priority = RTP_BGP; +#else -+ kr6->r.priority = rtm->rtm_priority; + kr6->r.priority = rtm->rtm_priority; +#endif kr6->r.ifindex = rtm->rtm_index; memcpy(&kr6->r.prefix, &((struct sockaddr_in6 *)sa)->sin6_addr, -@@ -2113,7 +2326,12 @@ fetchtable(u_int rtableid, int connected +@@ -2290,7 +2326,12 @@ fetchtable(u_int rtableid, int connected } if (sa->sa_family == AF_INET) { -- if (rtm->rtm_flags & RTF_PROTO1) { +#if !defined(__FreeBSD__) /* no rtm_priority on FreeBSD */ -+ if (rtm->rtm_priority == RTP_BGP) { + if (rtm->rtm_priority == RTP_BGP) { +#else + /* never delete route */ + if (0) { @@ -938,13 +430,12 @@ diff -u -p -r1.1.1.1 -r1.5 send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r); free(kr); } else if (connected_only && -@@ -2122,7 +2340,12 @@ fetchtable(u_int rtableid, int connected +@@ -2299,7 +2340,12 @@ fetchtable(u_int rtableid, int connected else kroute_insert(kr); } else if (sa->sa_family == AF_INET6) { -- if (rtm->rtm_flags & RTF_PROTO1) { +#if !defined(__FreeBSD__) /* no rtm_priority on FreeBSD */ -+ if (rtm->rtm_priority == RTP_BGP) { + if (rtm->rtm_priority == RTP_BGP) { +#else + /* never delete route */ + if (0) { @@ -952,27 +443,19 @@ diff -u -p -r1.1.1.1 -r1.5 send_rt6msg(kr_state.fd, RTM_DELETE, &kr6->r); free(kr6); } else if (connected_only && -@@ -2234,12 +2457,18 @@ dispatch_rtmsg(void) - lim = buf + n; - for (next = buf; next < lim; next += rtm->rtm_msglen) { - rtm = (struct rt_msghdr *)next; -+ if (rtm->rtm_version != RTM_VERSION) -+ continue; - - switch (rtm->rtm_type) { +@@ -2418,7 +2464,11 @@ dispatch_rtmsg(void) case RTM_ADD: case RTM_CHANGE: case RTM_DELETE: -- sa = (struct sockaddr *)(rtm + 1); +#if !defined(__FreeBSD__) /* no rtm_hdrlen on FreeBSD */ -+ sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); + sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); +#else + sa = (struct sockaddr *)(next + sizeof(struct rt_msghdr)); +#endif get_rtaddrs(rtm->rtm_addrs, sa, rti_info); if (rtm->rtm_pid == kr_state.pid) /* cause by us */ -@@ -2252,12 +2481,14 @@ dispatch_rtmsg(void) +@@ -2431,12 +2481,14 @@ dispatch_rtmsg(void) continue; connected_only = 0; @@ -987,192 +470,68 @@ diff -u -p -r1.1.1.1 -r1.5 if (dispatch_rtmsg_addr(rtm, rti_info, connected_only) == -1) -@@ -2289,9 +2520,10 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt - struct kroute_node *kr; - struct kroute6_node *kr6; - struct bgpd_addr prefix; -- int flags, oflags; -+ int flags, oflags, mpath = 0; - u_int16_t ifindex; - u_int8_t prefixlen; -+ u_int8_t prio; - - flags = F_KERNEL; - ifindex = 0; -@@ -2309,7 +2541,16 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt - flags |= F_REJECT; - if (rtm->rtm_flags & RTF_DYNAMIC) - flags |= F_DYNAMIC; -+#ifdef RTF_MPATH -+ if (rtm->rtm_flags & RTF_MPATH) -+ mpath = 1; -+#endif +@@ -2494,10 +2546,14 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt + mpath = 1; + #endif +#if !defined(__FreeBSD__) /* no rtm_priority on FreeBSD */ -+ prio = rtm->rtm_priority; + prio = rtm->rtm_priority; +- prefix.af = sa->sa_family; +- switch (prefix.af) { +#else + prio = RTP_BGP; +#endif - prefix.af = sa->sa_family; - switch (prefix.af) { ++ switch (sa->sa_family) { case AF_INET: -@@ -2341,22 +2582,54 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt - return (0); - } ++ prefix.aid = AID_INET; + prefix.v4.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; + sa_in = (struct sockaddr_in *)rti_info[RTAX_NETMASK]; + if (sa_in != NULL) { +@@ -2511,6 +2567,7 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt + prefixlen_classful(prefix.v4.s_addr); + break; + case AF_INET6: ++ prefix.aid = AID_INET6; + memcpy(&prefix.v6, &((struct sockaddr_in6 *)sa)->sin6_addr, + sizeof(struct in6_addr)); + sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK]; +@@ -2537,8 +2594,8 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt + } -+ if ((sa = rti_info[RTAX_GATEWAY]) != NULL) -+ switch (sa->sa_family) { -+ case AF_LINK: -+ flags |= F_CONNECTED; -+ ifindex = rtm->rtm_index; -+ sa = NULL; -+ mpath = 0; /* link local stuff can't be mpath */ -+ break; -+ } -+ if (rtm->rtm_type == RTM_DELETE) { - switch (prefix.af) { - case AF_INET: -+ sa_in = (struct sockaddr_in *)sa; +- switch (prefix.af) { +- case AF_INET: ++ switch (prefix.aid) { ++ case AID_INET: + sa_in = (struct sockaddr_in *)sa; if ((kr = kroute_find(prefix.v4.s_addr, -- prefixlen)) == NULL) -+ prefixlen, prio)) == NULL) - return (0); - if (!(kr->r.flags & F_KERNEL)) - return (0); -+ -+ if (mpath) -+ /* get the correct route */ -+ if ((kr = kroute_matchgw(kr, sa_in)) == NULL) { -+ log_warnx("dispatch_rtmsg[delete] " -+ "mpath route not found"); -+ return (0); -+ } -+ + prefixlen, prio)) == NULL) +@@ -2557,7 +2614,7 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt if (kroute_remove(kr) == -1) return (-1); break; - case AF_INET6: -- if ((kr6 = kroute6_find(&prefix.v6, prefixlen)) == NULL) -+ sa_in6 = (struct sockaddr_in6 *)sa; -+ if ((kr6 = kroute6_find(&prefix.v6, prefixlen, -+ prio)) == NULL) - return (0); - if (!(kr6->r.flags & F_KERNEL)) - return (0); -+ -+ if (mpath) -+ /* get the correct route */ -+ if ((kr6 = kroute6_matchgw(kr6, sa_in6)) == -+ NULL) { -+ log_warnx("dispatch_rtmsg[delete] " -+ "IPv6 mpath route not found"); -+ return (0); -+ } -+ - if (kroute6_remove(kr6) == -1) - return (-1); - break; -@@ -2364,15 +2637,6 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt +- case AF_INET6: ++ case AID_INET6: + sa_in6 = (struct sockaddr_in6 *)sa; + if ((kr6 = kroute6_find(&prefix.v6, prefixlen, + prio)) == NULL) +@@ -2590,8 +2647,8 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt return (0); } -- if ((sa = rti_info[RTAX_GATEWAY]) != NULL) -- switch (sa->sa_family) { -- case AF_LINK: -- flags |= F_CONNECTED; -- ifindex = rtm->rtm_index; -- sa = NULL; -- break; -- } -- - if (connected_only && !(flags & F_CONNECTED)) - return (0); - -@@ -2385,8 +2649,18 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt - switch (prefix.af) { - case AF_INET: +- switch (prefix.af) { +- case AF_INET: ++ switch (prefix.aid) { ++ case AID_INET: sa_in = (struct sockaddr_in *)sa; -- if ((kr = kroute_find(prefix.v4.s_addr, prefixlen)) != NULL) { -+ if ((kr = kroute_find(prefix.v4.s_addr, prefixlen, -+ prio)) != NULL) { - if (kr->r.flags & F_KERNEL) { -+ /* get the correct route */ -+ if (mpath && rtm->rtm_type == RTM_CHANGE && -+ (kr = kroute_matchgw(kr, sa_in)) == NULL) { -+ log_warnx("dispatch_rtmsg[change] " -+ "mpath route not found"); -+ return (-1); -+ } else if (mpath && rtm->rtm_type == RTM_ADD) -+ goto add4; -+ - if (sa_in != NULL) - kr->r.nexthop.s_addr = - sa_in->sin_addr.s_addr; -@@ -2409,12 +2683,15 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt - kr_redistribute(IMSG_NETWORK_ADD, - &kr->r); - } -+ if (kr->r.flags & F_NEXTHOP) -+ knexthop_track(kr); - } - } else if (rtm->rtm_type == RTM_CHANGE) { - log_warnx("change req for %s/%u: not in table", - log_addr(&prefix), prefixlen); - return (0); - } else { -+add4: - if ((kr = calloc(1, - sizeof(struct kroute_node))) == NULL) { - log_warn("dispatch_rtmsg"); -@@ -2428,14 +2705,25 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt - kr->r.nexthop.s_addr = 0; - kr->r.flags = flags; - kr->r.ifindex = ifindex; -+ kr->r.priority = prio; - + if ((kr = kroute_find(prefix.v4.s_addr, prefixlen, + prio)) != NULL) { +@@ -2654,7 +2711,7 @@ add4: kroute_insert(kr); } break; - case AF_INET6: +- case AF_INET6: ++ case AID_INET6: sa_in6 = (struct sockaddr_in6 *)sa; -- if ((kr6 = kroute6_find(&prefix.v6, prefixlen)) != NULL) { -+ if ((kr6 = kroute6_find(&prefix.v6, prefixlen, prio)) != NULL) { + if ((kr6 = kroute6_find(&prefix.v6, prefixlen, prio)) != NULL) { if (kr6->r.flags & F_KERNEL) { -+ /* get the correct route */ -+ if (mpath && rtm->rtm_type == RTM_CHANGE && -+ (kr6 = kroute6_matchgw(kr6, sa_in6)) == -+ NULL) { -+ log_warnx("dispatch_rtmsg[change] " -+ "mpath route not found"); -+ return (-1); -+ } else if (mpath && rtm->rtm_type == RTM_ADD) -+ goto add6; -+ - if (sa_in6 != NULL) - memcpy(&kr6->r.nexthop, - &sa_in6->sin6_addr, -@@ -2461,12 +2749,15 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt - kr_redistribute6(IMSG_NETWORK_ADD, - &kr6->r); - } -+ if (kr6->r.flags & F_NEXTHOP) -+ knexthop_track(kr6); - } - } else if (rtm->rtm_type == RTM_CHANGE) { - log_warnx("change req for %s/%u: not in table", - log_addr(&prefix), prefixlen); - return (0); - } else { -+add6: - if ((kr6 = calloc(1, - sizeof(struct kroute6_node))) == NULL) { - log_warn("dispatch_rtmsg"); -@@ -2483,6 +2774,7 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt - sizeof(struct in6_addr)); - kr6->r.flags = flags; - kr6->r.ifindex = ifindex; -+ kr6->r.priority = prio; - - kroute6_insert(kr6); - } diff --git a/net/openbgpd/files/patch-bgpd_log.c b/net/openbgpd/files/patch-bgpd_log.c new file mode 100644 index 000000000000..603711ce1158 --- /dev/null +++ b/net/openbgpd/files/patch-bgpd_log.c @@ -0,0 +1,74 @@ +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 +--- 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 +@@ -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 $ */ + + /* + * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> +@@ -32,6 +32,7 @@ + #include "log.h" + + int debug; ++int verbose; + + void logit(int, const char *, ...); + +@@ -42,8 +43,9 @@ log_fmt_peer(const struct peer_config *p + char *pfmt, *p; + + ip = log_addr(&peer->remote_addr); +- if ((peer->remote_addr.af == AF_INET && peer->remote_masklen != 32) || +- (peer->remote_addr.af == AF_INET6 && peer->remote_masklen != 128)) { ++ if ((peer->remote_addr.aid == AID_INET && peer->remote_masklen != 32) || ++ (peer->remote_addr.aid == AID_INET6 && ++ peer->remote_masklen != 128)) { + if (asprintf(&p, "%s/%u", ip, peer->remote_masklen) == -1) + fatal(NULL); + } else { +@@ -69,6 +71,7 @@ log_init(int n_debug) + extern char *__progname; + + debug = n_debug; ++ verbose = n_debug; + + if (!debug) + openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); +@@ -77,6 +80,12 @@ log_init(int n_debug) + } + + void ++log_verbose(int v) ++{ ++ verbose = v; ++} ++ ++void + logit(int pri, const char *fmt, ...) + { + va_list ap; +@@ -193,7 +202,7 @@ log_debug(const char *emsg, ...) + { + va_list ap; + +- if (debug) { ++ if (verbose) { + va_start(ap, emsg); + vlog(LOG_DEBUG, emsg, ap); + va_end(ap); +@@ -318,6 +327,9 @@ log_conn_attempt(const struct peer *peer + b = log_sockaddr(sa); + logit(LOG_INFO, "connection from non-peer %s refused", b); + } else { ++ /* only log if there is a chance that the session may come up */ ++ if (peer->conf.down && peer->state == STATE_IDLE) ++ return; + p = log_fmt_peer(&peer->conf); + logit(LOG_INFO, "Connection attempt from %s while session is " + "in state %s", p, statenames[peer->state]); diff --git a/net/openbgpd/files/patch-bgpd_log.h b/net/openbgpd/files/patch-bgpd_log.h deleted file mode 100644 index 18c6457cfd90..000000000000 --- a/net/openbgpd/files/patch-bgpd_log.h +++ /dev/null @@ -1,21 +0,0 @@ -Index: bgpd/log.h -=================================================================== -RCS file: /home/cvs/private/hrs/openbgpd/bgpd/log.h,v -retrieving revision 1.1.1.1 -retrieving revision 1.1.1.2 -diff -u -p -r1.1.1.1 -r1.1.1.2 ---- bgpd/log.h 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/log.h 9 Jul 2009 16:49:54 -0000 1.1.1.2 -@@ -1,4 +1,4 @@ --/* $OpenBSD: log.h,v 1.10 2007/12/23 18:26:13 henning Exp $ */ -+/* $OpenBSD: log.h,v 1.11 2008/09/11 14:49:58 henning Exp $ */ - - /* - * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -119,5 +119,6 @@ static const char * const timernames[] = - "HoldTimer", - "IdleHoldTimer", - "IdleHoldResetTimer", -+ "CarpUndemoteTimer", - "" - }; diff --git a/net/openbgpd/files/patch-bgpd_mrt.c b/net/openbgpd/files/patch-bgpd_mrt.c index e7cad7121912..c35359ac5f39 100644 --- a/net/openbgpd/files/patch-bgpd_mrt.c +++ b/net/openbgpd/files/patch-bgpd_mrt.c @@ -1,1002 +1,122 @@ Index: bgpd/mrt.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/mrt.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.1.1.3 -diff -u -p -r1.1.1.1 -r1.1.1.3 ---- bgpd/mrt.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/mrt.c 10 Aug 2009 21:09:57 -0000 1.1.1.3 +retrieving revision 1.1.1.7 +retrieving revision 1.1.1.8 +diff -u -p -r1.1.1.7 -r1.1.1.8 +--- 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 @@ -1,4 +1,4 @@ --/* $OpenBSD: mrt.c,v 1.53 2007/04/23 13:04:24 claudio Exp $ */ -+/* $OpenBSD: mrt.c,v 1.64 2009/07/12 15:36:41 jsg Exp $ */ +-/* $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 $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> -@@ -32,24 +32,21 @@ - - #include "mrt.h" - --static u_int16_t mrt_attr_length(struct rde_aspath *, int); --static int mrt_attr_dump(void *, u_int16_t, struct rde_aspath *, -- struct bgpd_addr *); --static int mrt_dump_entry_mp(struct mrt *, struct prefix *, -- u_int16_t, struct rde_peer*); --static int mrt_dump_entry(struct mrt *, struct prefix *, -- u_int16_t, struct rde_peer*); --static int mrt_dump_header(struct buf *, u_int16_t, u_int16_t, -- u_int32_t); --static int mrt_open(struct mrt *, time_t); -+int mrt_attr_dump(struct buf *, 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, -+ u_int32_t, int); -+int mrt_dump_hdr_rde(struct buf **, 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"); \ -- buf_free((x)); \ -- return (-1); \ -+ goto fail; \ - } \ - } while (0) - -@@ -59,8 +56,7 @@ static int mrt_open(struct mrt *, time_ - t = htons((s)); \ - if (buf_add((x), &t, sizeof(t)) == -1) { \ - log_warnx("mrt_dump2: buf_add error"); \ -- buf_free((x)); \ -- return (-1); \ -+ goto fail; \ - } \ - } while (0) - -@@ -70,8 +66,7 @@ static int mrt_open(struct mrt *, time_ - t = htonl((l)); \ - if (buf_add((x), &t, sizeof(t)) == -1) { \ - log_warnx("mrt_dump3: buf_add error"); \ -- buf_free((x)); \ -- return (-1); \ -+ goto fail; \ - } \ - } while (0) - -@@ -80,327 +75,175 @@ static int mrt_open(struct mrt *, time_ - u_int32_t t = (l); \ - if (buf_add((x), &t, sizeof(t)) == -1) { \ - log_warnx("mrt_dump4: buf_add error"); \ -- buf_free((x)); \ -- return (-1); \ -+ goto fail; \ - } \ - } while (0) - --int -+void - mrt_dump_bgp_msg(struct mrt *mrt, void *pkg, u_int16_t pkglen, -- struct peer *peer, struct bgpd_config *bgp) -+ struct peer *peer) - { - struct buf *buf; -- u_int16_t len; - int incoming = 0; - -- switch (peer->sa_local.ss_family) { -- case AF_INET: -- len = pkglen + MRT_BGP4MP_IPv4_HEADER_SIZE; -- break; -- case AF_INET6: -- len = pkglen + MRT_BGP4MP_IPv6_HEADER_SIZE; -- break; -- default: -- return (-1); -- } -- - /* 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 ((buf = buf_open(len + MRT_HEADER_SIZE)) == NULL) { -- log_warnx("mrt_dump_bgp_msg: buf_open error"); -- return (-1); -- } -- -- if (mrt_dump_header(buf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE, -- len) == -1) { -- log_warnx("mrt_dump_bgp_msg: buf_add error"); -- return (-1); -- } -- -- if (!incoming) -- DUMP_SHORT(buf, bgp->short_as); -- DUMP_SHORT(buf, peer->short_as); -- if (incoming) -- DUMP_SHORT(buf, bgp->short_as); -- DUMP_SHORT(buf, /* ifindex */ 0); -- switch (peer->sa_local.ss_family) { -- case AF_INET: -- DUMP_SHORT(buf, AFI_IPv4); -- if (!incoming) -- DUMP_NLONG(buf, ((struct sockaddr_in *) -- &peer->sa_local)->sin_addr.s_addr); -- DUMP_NLONG(buf, -- ((struct sockaddr_in *)&peer->sa_remote)->sin_addr.s_addr); -- if (incoming) -- DUMP_NLONG(buf, ((struct sockaddr_in *) -- &peer->sa_local)->sin_addr.s_addr); -- break; -- case AF_INET6: -- DUMP_SHORT(buf, AFI_IPv6); -- if (!incoming) -- if (buf_add(buf, &((struct sockaddr_in6 *) -- &peer->sa_local)->sin6_addr, -- sizeof(struct in6_addr)) == -1) { -- log_warnx("mrt_dump_bgp_msg: buf_add error"); -- buf_free(buf); -- return (-1); -- } -- if (buf_add(buf, -- &((struct sockaddr_in6 *)&peer->sa_remote)->sin6_addr, -- sizeof(struct in6_addr)) == -1) { -- log_warnx("mrt_dump_bgp_msg: buf_add error"); -- buf_free(buf); -- return (-1); -- } -- if (incoming) -- if (buf_add(buf, &((struct sockaddr_in6 *) -- &peer->sa_local)->sin6_addr, -- sizeof(struct in6_addr)) == -1) { -- log_warnx("mrt_dump_bgp_msg: buf_add error"); -- buf_free(buf); -- return (-1); -- } -- break; -- } -+ if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE, -+ pkglen, incoming) == -1) -+ return; - - if (buf_add(buf, pkg, pkglen) == -1) { - log_warnx("mrt_dump_bgp_msg: buf_add error"); - buf_free(buf); -- return (-1); -+ return; - } - -- TAILQ_INSERT_TAIL(&mrt->bufs, buf, entry); -- mrt->queued++; -- -- return (len + MRT_HEADER_SIZE); -+ buf_close(&mrt->wbuf, buf); - } - --int -+void - mrt_dump_state(struct mrt *mrt, u_int16_t old_state, u_int16_t new_state, -- struct peer *peer, struct bgpd_config *bgp) -+ struct peer *peer) - { - struct buf *buf; -- u_int16_t len; -- -- switch (peer->sa_local.ss_family) { -- case AF_INET: -- len = 4 + MRT_BGP4MP_IPv4_HEADER_SIZE; -- break; -- case AF_INET6: -- len = 4 + MRT_BGP4MP_IPv6_HEADER_SIZE; -- break; -- default: -- return (-1); -- } -- -- if ((buf = buf_open(len + MRT_HEADER_SIZE)) == NULL) { -- log_warnx("mrt_dump_bgp_state: buf_open error"); -- return (-1); -- } - -- if (mrt_dump_header(buf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE, -- len) == -1) { -- log_warnx("mrt_dump_bgp_state: buf_add error"); -- return (-1); -- } -- -- DUMP_SHORT(buf, bgp->short_as); -- DUMP_SHORT(buf, peer->short_as); -- DUMP_SHORT(buf, /* ifindex */ 0); -- switch (peer->sa_local.ss_family) { -- case AF_INET: -- DUMP_SHORT(buf, AFI_IPv4); -- DUMP_NLONG(buf, -- ((struct sockaddr_in *)&peer->sa_local)->sin_addr.s_addr); -- DUMP_NLONG(buf, -- ((struct sockaddr_in *)&peer->sa_remote)->sin_addr.s_addr); -- break; -- case AF_INET6: -- DUMP_SHORT(buf, AFI_IPv6); -- if (buf_add(buf, -- &((struct sockaddr_in6 *)&peer->sa_local)->sin6_addr, -- sizeof(struct in6_addr)) == -1 || -- buf_add(buf, -- &((struct sockaddr_in6 *)&peer->sa_remote)->sin6_addr, -- sizeof(struct in6_addr)) == -1) { -- log_warnx("mrt_dump_bgp_msg: buf_add error"); -- buf_free(buf); -- return (-1); -- } -- break; -- } -+ if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE, -+ 2 * sizeof(short), 0) == -1) -+ return; - - DUMP_SHORT(buf, old_state); - DUMP_SHORT(buf, new_state); - -- TAILQ_INSERT_TAIL(&mrt->bufs, buf, entry); -- mrt->queued++; -- -- return (len + MRT_HEADER_SIZE); --} -- --static u_int16_t --mrt_attr_length(struct rde_aspath *a, int oldform) --{ -- u_int16_t alen, plen; -- u_int8_t l; -+ buf_close(&mrt->wbuf, buf); -+ return; - -- alen = 4 /* origin */ + 7 /* lpref */; -- if (oldform) -- alen += 7 /* nexthop */; -- plen = aspath_length(a->aspath); -- alen += 2 + plen + (plen > 255 ? 2 : 1); -- if (a->med != 0) -- alen += 7; -- -- for (l = 0; l < a->others_len; l++) -- if (a->others[l] != NULL) -- alen += 2 + a->others[l]->len + -- (a->others[l]->len > 255 ? 2 : 1); -- else -- break; -- -- return alen; -+fail: -+ buf_free(buf); - } - --static int --mrt_attr_dump(void *p, u_int16_t len, struct rde_aspath *a, -- struct bgpd_addr *nexthop) -+int -+mrt_attr_dump(struct buf *buf, struct rde_aspath *a, struct bgpd_addr *nexthop) - { - struct attr *oa; -- u_char *buf = p; -- u_int32_t tmp32; -- int r; -- u_int16_t aslen, wlen = 0; -+ u_char *pdata; -+ u_int32_t tmp; -+ int neednewpath = 0; -+ u_int16_t plen; - u_int8_t l; - - /* origin */ -- if ((r = attr_write(buf + wlen, len, ATTR_WELL_KNOWN, ATTR_ORIGIN, -- &a->origin, 1)) == -1) -+ if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ORIGIN, -+ &a->origin, 1) == -1) - return (-1); -- wlen += r; len -= r; - - /* aspath */ -- aslen = aspath_length(a->aspath); -- if ((r = attr_write(buf + wlen, len, ATTR_WELL_KNOWN, ATTR_ASPATH, -- aspath_dump(a->aspath), aslen)) == -1) -+ 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) - return (-1); -- wlen += r; len -= r; -+ free(pdata); - - if (nexthop) { - /* nexthop, already network byte order */ -- if ((r = attr_write(buf + wlen, len, ATTR_WELL_KNOWN, -- ATTR_NEXTHOP, &nexthop->v4.s_addr, 4)) == -1) -+ if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_NEXTHOP, -+ &nexthop->v4.s_addr, 4) == -1) - return (-1); -- wlen += r; len -= r; - } - - /* MED, non transitive */ - if (a->med != 0) { -- tmp32 = htonl(a->med); -- if ((r = attr_write(buf + wlen, len, ATTR_OPTIONAL, ATTR_MED, -- &tmp32, 4)) == -1) -+ tmp = htonl(a->med); -+ if (attr_writebuf(buf, ATTR_OPTIONAL, ATTR_MED, &tmp, 4) == -1) - return (-1); -- wlen += r; len -= r; - } - - /* local preference, only valid for ibgp */ -- tmp32 = htonl(a->lpref); -- if ((r = attr_write(buf + wlen, len, ATTR_WELL_KNOWN, ATTR_LOCALPREF, -- &tmp32, 4)) == -1) -+ tmp = htonl(a->lpref); -+ if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_LOCALPREF, &tmp, 4) == -1) - return (-1); -- wlen += r; len -= r; - - /* dump all other path attributes without modification */ - for (l = 0; l < a->others_len; l++) { - if ((oa = a->others[l]) == NULL) - break; -- if ((r = attr_write(buf + wlen, len, oa->flags, oa->type, -- oa->data, oa->len)) == -1) -+ if (attr_writebuf(buf, oa->flags, oa->type, -+ oa->data, oa->len) == -1) - return (-1); -- wlen += r; len -= r; - } - -- return (wlen); -+ 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) -+ return (-1); -+ free(pdata); -+ } -+ -+ return (0); - } - --static int -+int - mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum, - struct rde_peer *peer) - { -- struct buf *buf; -+ struct buf *buf, *hbuf = NULL, *h2buf = NULL; - void *bptr; +@@ -194,7 +194,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struc struct bgpd_addr addr, nexthop, *nh; -- u_int16_t len, attr_len; -+ u_int16_t len; + u_int16_t len; u_int8_t p_len; - sa_family_t af; +- sa_family_t af; ++ u_int8_t aid; -- attr_len = mrt_attr_length(p->aspath, 0); -- p_len = PREFIX_SIZE(p->prefix->prefixlen); -- pt_getaddr(p->prefix, &addr); -- -- af = peer->remote_addr.af == 0 ? addr.af : peer->remote_addr.af; + if ((buf = buf_dynamic(0, MAX_PKTSIZE)) == NULL) { + log_warn("mrt_dump_entry_mp: buf_dynamic"); +@@ -219,14 +219,15 @@ mrt_dump_entry_mp(struct mrt *mrt, struc + DUMP_SHORT(h2buf, /* ifindex */ 0); + + /* XXX is this for peer self? */ +- af = peer->remote_addr.af == 0 ? p->prefix->af : peer->remote_addr.af; - switch (af) { - case AF_INET: -- len = MRT_BGP4MP_IPv4_HEADER_SIZE; -- break; -- case AF_INET6: -- len = MRT_BGP4MP_IPv6_HEADER_SIZE; -- break; -- default: -- return (-1); -- } -- -- switch (addr.af) { -- case AF_INET: -- len += MRT_BGP4MP_IPv4_ENTRY_SIZE + p_len + attr_len; -- break; -- case AF_INET6: -- len += MRT_BGP4MP_IPv4_ENTRY_SIZE + p_len + attr_len; -- break; -- default: -+ if ((buf = buf_dynamic(0, MAX_PKTSIZE)) == NULL) { -+ log_warn("mrt_dump_entry_mp: buf_dynamic"); - return (-1); - } - -- if ((buf = buf_open(len + MRT_HEADER_SIZE)) == NULL) { -- log_warnx("mrt_dump_entry_mp: buf_open error"); -- return (-1); -+ if (mrt_attr_dump(buf, p->aspath, NULL) == -1) { -+ log_warnx("mrt_dump_entry_mp: mrt_attr_dump error"); -+ goto fail; - } -+ len = buf_size(buf); - -- if (mrt_dump_header(buf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY, -- len) == -1) { -- log_warnx("mrt_dump_entry_mp: buf_add error"); -- return (-1); -+ if ((h2buf = buf_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"); -+ goto fail; - } - -- DUMP_SHORT(buf, rde_local_as()); -- DUMP_SHORT(buf, peer->short_as); -- DUMP_SHORT(buf, /* ifindex */ 0); -+ DUMP_SHORT(h2buf, rde_local_as()); -+ DUMP_SHORT(h2buf, peer->short_as); -+ DUMP_SHORT(h2buf, /* ifindex */ 0); - -+ /* XXX is this for peer self? */ -+ af = peer->remote_addr.af == 0 ? p->prefix->af : peer->remote_addr.af; - switch (af) { - case AF_INET: -- DUMP_SHORT(buf, AFI_IPv4); -- DUMP_NLONG(buf, peer->local_v4_addr.v4.s_addr); -- DUMP_NLONG(buf, peer->remote_addr.v4.s_addr); -+ DUMP_SHORT(h2buf, AFI_IPv4); -+ DUMP_NLONG(h2buf, peer->local_v4_addr.v4.s_addr); -+ DUMP_NLONG(h2buf, peer->remote_addr.v4.s_addr); ++ aid = peer->remote_addr.aid == AID_UNSPEC ? p->prefix->aid : ++ peer->remote_addr.aid; ++ switch (aid) { ++ case AID_INET: + DUMP_SHORT(h2buf, AFI_IPv4); + DUMP_NLONG(h2buf, peer->local_v4_addr.v4.s_addr); + DUMP_NLONG(h2buf, peer->remote_addr.v4.s_addr); break; - case AF_INET6: -- DUMP_SHORT(buf, AFI_IPv6); -- if (buf_add(buf, &peer->local_v6_addr.v6, -+ DUMP_SHORT(h2buf, AFI_IPv6); -+ if (buf_add(h2buf, &peer->local_v6_addr.v6, +- case AF_INET6: ++ case AID_INET6: + DUMP_SHORT(h2buf, AFI_IPv6); + if (buf_add(h2buf, &peer->local_v6_addr.v6, sizeof(struct in6_addr)) == -1 || -- buf_add(buf, &peer->remote_addr.v6, -+ buf_add(h2buf, &peer->remote_addr.v6, - sizeof(struct in6_addr)) == -1) { - log_warnx("mrt_dump_entry_mp: buf_add error"); -- buf_free(buf); -- return (-1); -+ goto fail; +@@ -237,7 +238,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struc } break; -+ default: -+ log_warnx("king bula found new AF %d in mrt_dump_entry_mp", af); -+ goto fail; + default: +- log_warnx("king bula found new AF %d in mrt_dump_entry_mp", af); ++ log_warnx("king bula found new AF in mrt_dump_entry_mp"); + goto fail; } -- DUMP_SHORT(buf, 0); /* view */ -- DUMP_SHORT(buf, 1); /* status */ -- DUMP_LONG(buf, p->lastchange); /* originated */ -+ DUMP_SHORT(h2buf, 0); /* view */ -+ DUMP_SHORT(h2buf, 1); /* status */ -+ DUMP_LONG(h2buf, p->lastchange); /* originated */ +@@ -247,20 +248,20 @@ mrt_dump_entry_mp(struct mrt *mrt, struc if (p->aspath->nexthop == NULL) { bzero(&nexthop, sizeof(struct bgpd_addr)); -@@ -409,95 +252,74 @@ mrt_dump_entry_mp(struct mrt *mrt, struc +- nexthop.af = addr.af; ++ nexthop.aid = addr.aid; + nh = &nexthop; } else nh = &p->aspath->nexthop->exit_nexthop; -+ pt_getaddr(p->prefix, &addr); - switch (addr.af) { - case AF_INET: -- DUMP_SHORT(buf, AFI_IPv4); /* afi */ -- DUMP_BYTE(buf, SAFI_UNICAST); /* safi */ -- DUMP_BYTE(buf, 4); /* nhlen */ -- DUMP_NLONG(buf, nh->v4.s_addr); /* nexthop */ -+ DUMP_SHORT(h2buf, AFI_IPv4); /* afi */ -+ DUMP_BYTE(h2buf, SAFI_UNICAST); /* safi */ -+ DUMP_BYTE(h2buf, 4); /* nhlen */ -+ DUMP_NLONG(h2buf, nh->v4.s_addr); /* nexthop */ - break; - case AF_INET6: -- DUMP_SHORT(buf, AFI_IPv6); /* afi */ -- DUMP_BYTE(buf, SAFI_UNICAST); /* safi */ -- DUMP_BYTE(buf, 16); /* nhlen */ -- if (buf_add(buf, &nh->v6, sizeof(struct in6_addr)) == -1) { -+ DUMP_SHORT(h2buf, AFI_IPv6); /* afi */ -+ DUMP_BYTE(h2buf, SAFI_UNICAST); /* safi */ -+ DUMP_BYTE(h2buf, 16); /* nhlen */ -+ if (buf_add(h2buf, &nh->v6, sizeof(struct in6_addr)) == -1) { - log_warnx("mrt_dump_entry_mp: buf_add error"); -- buf_free(buf); -- return (-1); -+ goto fail; - } + pt_getaddr(p->prefix, &addr); +- switch (addr.af) { +- case AF_INET: ++ switch (addr.aid) { ++ case AID_INET: + DUMP_SHORT(h2buf, AFI_IPv4); /* afi */ + DUMP_BYTE(h2buf, SAFI_UNICAST); /* safi */ + DUMP_BYTE(h2buf, 4); /* nhlen */ + DUMP_NLONG(h2buf, nh->v4.s_addr); /* nexthop */ break; -+ default: -+ log_warnx("king bula found new AF in mrt_dump_entry_mp"); -+ goto fail; - } - -- if ((bptr = buf_reserve(buf, p_len)) == NULL) { -+ p_len = PREFIX_SIZE(p->prefix->prefixlen); -+ if ((bptr = buf_reserve(h2buf, p_len)) == NULL) { - log_warnx("mrt_dump_entry_mp: buf_reserve error"); -- buf_free(buf); -- return (-1); -+ goto fail; - } - if (prefix_write(bptr, p_len, &addr, p->prefix->prefixlen) == -1) { - log_warnx("mrt_dump_entry_mp: prefix_write error"); -- buf_free(buf); -- return (-1); -+ goto fail; - } - -- DUMP_SHORT(buf, attr_len); -- if ((bptr = buf_reserve(buf, attr_len)) == NULL) { -- log_warnx("mrt_dump_entry_mp: buf_reserve error"); -- buf_free(buf); -- return (-1); -- } -+ DUMP_SHORT(h2buf, len); -+ len += buf_size(h2buf); - -- if (mrt_attr_dump(bptr, attr_len, p->aspath, NULL) == -1) { -- log_warnx("mrt_dump_entry_mp: mrt_attr_dump error"); -- buf_free(buf); -- return (-1); -- } -+ if (mrt_dump_hdr_rde(&hbuf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY, -+ len) == -1) -+ goto fail; - -- TAILQ_INSERT_TAIL(&mrt->bufs, buf, entry); -- mrt->queued++; -+ buf_close(&mrt->wbuf, hbuf); -+ buf_close(&mrt->wbuf, h2buf); -+ buf_close(&mrt->wbuf, buf); - - return (len + MRT_HEADER_SIZE); -+ -+fail: -+ if (hbuf) -+ buf_free(hbuf); +- case AF_INET6: ++ case AID_INET6: + 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 + fail: + if (hbuf) + buf_free(hbuf); +- if (h2buf); + if (h2buf) -+ buf_free(h2buf); -+ buf_free(buf); -+ return (-1); - } - --static int -+int - mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum, - struct rde_peer *peer) - { -- struct buf *buf; -- void *bptr; -+ struct buf *buf, *hbuf; + buf_free(h2buf); + buf_free(buf); + return (-1); +@@ -314,7 +315,8 @@ mrt_dump_entry(struct mrt *mrt, struct p struct bgpd_addr addr, *nh; -- u_int16_t len, attr_len; -+ size_t len; + size_t len; - if (p->prefix->af != AF_INET && peer->remote_addr.af == AF_INET) -- /* only for true IPv4 */ -+ /* only able to dump IPv4 */ +- 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 */ return (0); -- attr_len = mrt_attr_length(p->aspath, 1); -- len = MRT_DUMP_HEADER_SIZE + attr_len; -- pt_getaddr(p->prefix, &addr); -- -- if ((buf = buf_open(len + MRT_HEADER_SIZE)) == NULL) { -- log_warnx("mrt_dump_entry: buf_open error"); -- return (-1); -- } -- -- if (mrt_dump_header(buf, MSG_TABLE_DUMP, AFI_IPv4, len) == -1) { -- log_warnx("mrt_dump_entry: buf_add error"); -- return (-1); -- } -- -- DUMP_SHORT(buf, 0); -- DUMP_SHORT(buf, snum); -- DUMP_NLONG(buf, addr.v4.s_addr); -- DUMP_BYTE(buf, p->prefix->prefixlen); -- DUMP_BYTE(buf, 1); /* state */ -- DUMP_LONG(buf, p->lastchange); /* originated */ -- DUMP_NLONG(buf, peer->remote_addr.v4.s_addr); -- DUMP_SHORT(buf, peer->short_as); -- -- DUMP_SHORT(buf, attr_len); -- if ((bptr = buf_reserve(buf, attr_len)) == NULL) { -- log_warnx("mrt_dump_entry: buf_reserve error"); -- buf_free(buf); -+ if ((buf = buf_dynamic(0, MAX_PKTSIZE)) == NULL) { -+ log_warnx("mrt_dump_entry: buf_dynamic"); - return (-1); - } +@@ -325,7 +327,7 @@ mrt_dump_entry(struct mrt *mrt, struct p -@@ -507,28 +329,44 @@ mrt_dump_entry(struct mrt *mrt, struct p + if (p->aspath->nexthop == NULL) { + bzero(&addr, sizeof(struct bgpd_addr)); +- addr.af = AF_INET; ++ addr.aid = AID_INET; nh = &addr; } else nh = &p->aspath->nexthop->exit_nexthop; -- if (mrt_attr_dump(bptr, attr_len, p->aspath, nh) == -1) { -+ if (mrt_attr_dump(buf, p->aspath, nh) == -1) { - log_warnx("mrt_dump_entry: mrt_attr_dump error"); - buf_free(buf); - return (-1); - } -+ len = buf_size(buf); - -- TAILQ_INSERT_TAIL(&mrt->bufs, buf, entry); -- mrt->queued++; -+ if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP, AFI_IPv4, len) == -1) { -+ buf_free(buf); -+ return (-1); -+ } - -- return (len + MRT_HEADER_SIZE); --} -+ DUMP_SHORT(hbuf, 0); -+ DUMP_SHORT(hbuf, snum); - --static u_int16_t sequencenum = 0; -+ pt_getaddr(p->prefix, &addr); -+ DUMP_NLONG(hbuf, addr.v4.s_addr); -+ DUMP_BYTE(hbuf, p->prefix->prefixlen); - --void --mrt_clear_seq(void) --{ -- sequencenum = 0; -+ DUMP_BYTE(hbuf, 1); /* state */ -+ DUMP_LONG(hbuf, p->lastchange); /* originated */ -+ DUMP_NLONG(hbuf, peer->remote_addr.v4.s_addr); -+ DUMP_SHORT(hbuf, peer->short_as); -+ DUMP_SHORT(hbuf, len); -+ -+ buf_close(&mrt->wbuf, hbuf); -+ buf_close(&mrt->wbuf, buf); -+ -+ return (len + MRT_HEADER_SIZE); -+ -+fail: -+ buf_free(hbuf); -+ buf_free(buf); -+ return (-1); +@@ -387,7 +389,7 @@ mrt_dump_upcall(struct rib_entry *re, vo } void --mrt_dump_upcall(struct pt_entry *pt, void *ptr) -+mrt_dump_upcall(struct rib_entry *re, void *ptr) +-mrt_dump_done(void *ptr) ++mrt_done(void *ptr) { struct mrt *mrtbuf = ptr; - struct prefix *p; -@@ -538,53 +376,172 @@ mrt_dump_upcall(struct pt_entry *pt, voi - * dumps the table so we do the same. If only the active route should - * be dumped p should be set to p = pt->active. - */ -- LIST_FOREACH(p, &pt->prefix_h, prefix_l) { -- /* for now dump only stuff from the local-RIB */ -- if (!(p->flags & F_LOCAL)) -- continue; -+ LIST_FOREACH(p, &re->prefix_h, rib_l) { - if (mrtbuf->type == MRT_TABLE_DUMP) -- mrt_dump_entry(mrtbuf, p, sequencenum++, -+ mrt_dump_entry(mrtbuf, p, mrtbuf->seqnum++, - p->aspath->peer); - else -- mrt_dump_entry_mp(mrtbuf, p, sequencenum++, -+ mrt_dump_entry_mp(mrtbuf, p, mrtbuf->seqnum++, - p->aspath->peer); - } - } - --static int --mrt_dump_header(struct buf *buf, u_int16_t type, u_int16_t subtype, -- u_int32_t len) -+void -+mrt_dump_done(void *ptr) -+{ -+ struct mrt *mrtbuf = ptr; -+ -+ mrtbuf->state = MRT_STATE_REMOVE; -+} -+ -+int -+mrt_dump_hdr_se(struct buf ** bp, struct peer *peer, u_int16_t type, -+ u_int16_t subtype, u_int32_t len, int swap) - { -- time_t now; -+ time_t now; -+ -+ if ((*bp = buf_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); -+ } - - now = time(NULL); -- DUMP_LONG(buf, now); -- DUMP_SHORT(buf, type); -- DUMP_SHORT(buf, subtype); -- DUMP_LONG(buf, len); -+ DUMP_LONG(*bp, now); -+ DUMP_SHORT(*bp, type); -+ DUMP_SHORT(*bp, subtype); -+ -+ switch (peer->sa_local.ss_family) { -+ case AF_INET: -+ if (subtype == BGP4MP_STATE_CHANGE_AS4 || -+ subtype == BGP4MP_MESSAGE_AS4) -+ len += MRT_BGP4MP_AS4_IPv4_HEADER_SIZE; -+ else -+ len += MRT_BGP4MP_IPv4_HEADER_SIZE; -+ break; -+ case AF_INET6: -+ if (subtype == BGP4MP_STATE_CHANGE_AS4 || -+ subtype == BGP4MP_MESSAGE_AS4) -+ len += MRT_BGP4MP_AS4_IPv6_HEADER_SIZE; -+ else -+ len += MRT_BGP4MP_IPv6_HEADER_SIZE; -+ break; -+ case 0: -+ goto fail; -+ default: -+ log_warnx("king bula found new AF in mrt_dump_hdr_se"); -+ goto fail; -+ } -+ -+ DUMP_LONG(*bp, len); -+ -+ if (subtype == BGP4MP_STATE_CHANGE_AS4 || -+ subtype == BGP4MP_MESSAGE_AS4) { -+ if (!swap) -+ DUMP_LONG(*bp, peer->conf.local_as); -+ DUMP_LONG(*bp, peer->conf.remote_as); -+ if (swap) -+ DUMP_LONG(*bp, peer->conf.local_as); -+ } else { -+ if (!swap) -+ DUMP_SHORT(*bp, peer->conf.local_short_as); -+ DUMP_SHORT(*bp, peer->short_as); -+ if (swap) -+ DUMP_SHORT(*bp, peer->conf.local_short_as); -+ } -+ -+ DUMP_SHORT(*bp, /* ifindex */ 0); -+ -+ switch (peer->sa_local.ss_family) { -+ case AF_INET: -+ DUMP_SHORT(*bp, AFI_IPv4); -+ if (!swap) -+ DUMP_NLONG(*bp, ((struct sockaddr_in *) -+ &peer->sa_local)->sin_addr.s_addr); -+ DUMP_NLONG(*bp, -+ ((struct sockaddr_in *)&peer->sa_remote)->sin_addr.s_addr); -+ if (swap) -+ DUMP_NLONG(*bp, ((struct sockaddr_in *) -+ &peer->sa_local)->sin_addr.s_addr); -+ break; -+ case AF_INET6: -+ DUMP_SHORT(*bp, AFI_IPv6); -+ if (!swap) -+ if (buf_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, -+ &((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 *) -+ &peer->sa_local)->sin6_addr, -+ sizeof(struct in6_addr)) == -1) { -+ log_warnx("mrt_dump_hdr_se: buf_add error"); -+ goto fail; -+ } -+ break; -+ } - - return (0); -+ -+fail: -+ buf_free(*bp); -+ return (-1); - } - - int --mrt_write(struct mrt *mrt) -+mrt_dump_hdr_rde(struct buf **bp, u_int16_t type, u_int16_t subtype, -+ u_int32_t len) - { -- struct buf *b; -- int r = 0; -+ time_t now; - -- while ((b = TAILQ_FIRST(&mrt->bufs)) && -- (r = buf_write(mrt->fd, b)) == 1) { -- TAILQ_REMOVE(&mrt->bufs, b, entry); -- mrt->queued--; -- buf_free(b); -- } -- if (r <= -1) { -- log_warn("mrt dump write"); -- mrt_clean(mrt); -+ if ((*bp = buf_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"); - return (-1); +@@ -541,6 +543,7 @@ mrt_write(struct mrt *mrt) + if ((r = buf_write(&mrt->wbuf)) < 0) { + log_warn("mrt dump aborted, mrt_write"); + mrt_clean(mrt); ++ mrt_done(mrt); } -+ -+ now = time(NULL); -+ DUMP_LONG(*bp, now); -+ DUMP_SHORT(*bp, type); -+ DUMP_SHORT(*bp, subtype); -+ -+ switch (type) { -+ case MSG_TABLE_DUMP: -+ DUMP_LONG(*bp, MRT_DUMP_HEADER_SIZE + len); -+ break; -+ case MSG_PROTOCOL_BGP4MP: -+ DUMP_LONG(*bp, len); -+ break; -+ default: -+ log_warnx("mrt_dump_hdr_rde: unsupported type"); -+ goto fail; -+ } - return (0); -+ -+fail: -+ buf_free(*bp); -+ return (-1); -+} -+ -+void -+mrt_write(struct mrt *mrt) -+{ -+ int r; -+ -+ if ((r = buf_write(&mrt->wbuf)) < 0) { -+ log_warn("mrt dump aborted, mrt_write"); -+ mrt_clean(mrt); -+ } } - void -@@ -592,12 +549,12 @@ mrt_clean(struct mrt *mrt) - { - struct buf *b; - -- close(mrt->fd); -- while ((b = TAILQ_FIRST(&mrt->bufs))) { -- TAILQ_REMOVE(&mrt->bufs, b, entry); -+ close(mrt->wbuf.fd); -+ while ((b = TAILQ_FIRST(&mrt->wbuf.bufs))) { -+ TAILQ_REMOVE(&mrt->wbuf.bufs, b, entry); - buf_free(b); - } -- mrt->queued = 0; -+ mrt->wbuf.queued = 0; - } - - static struct imsgbuf *mrt_imsgbuf[2]; -@@ -613,30 +570,30 @@ int - mrt_open(struct mrt *mrt, time_t now) - { - enum imsg_type type; -- int i; -+ int i = 1, fd; - - if (strftime(MRT2MC(mrt)->file, sizeof(MRT2MC(mrt)->file), - MRT2MC(mrt)->name, localtime(&now)) == 0) { - log_warnx("mrt_open: strftime conversion failed"); -- mrt->fd = -1; - return (-1); - } - -- mrt->fd = open(MRT2MC(mrt)->file, -+ fd = open(MRT2MC(mrt)->file, - O_WRONLY|O_NONBLOCK|O_CREAT|O_TRUNC, 0644); -- if (mrt->fd == -1) { -+ if (fd == -1) { - log_warn("mrt_open %s", MRT2MC(mrt)->file); - return (1); - } - -- if (MRT2MC(mrt)->state == MRT_STATE_OPEN) -+ if (mrt->state == MRT_STATE_OPEN) - type = IMSG_MRT_OPEN; - else - type = IMSG_MRT_REOPEN; - -- i = mrt->type == MRT_TABLE_DUMP ? 0 : 1; -+ if (mrt->type == MRT_TABLE_DUMP || mrt->type == MRT_TABLE_DUMP_MP) -+ i = 0; - -- if (imsg_compose(mrt_imsgbuf[i], type, 0, 0, mrt->fd, -+ if (imsg_compose(mrt_imsgbuf[i], type, 0, 0, fd, - mrt, sizeof(struct mrt)) == -1) - log_warn("mrt_open"); - -@@ -652,7 +609,7 @@ mrt_timeout(struct mrt_head *mrt) - - now = time(NULL); - LIST_FOREACH(m, mrt, entry) { -- if (MRT2MC(m)->state == MRT_STATE_RUNNING && -+ if (m->state == MRT_STATE_RUNNING && - MRT2MC(m)->ReopenTimerInterval != 0) { - if (MRT2MC(m)->ReopenTimer <= now) { - mrt_open(m, now); -@@ -675,16 +632,16 @@ mrt_reconfigure(struct mrt_head *mrt) - now = time(NULL); - for (m = LIST_FIRST(mrt); m != NULL; m = xm) { - xm = LIST_NEXT(m, entry); -- if (MRT2MC(m)->state == MRT_STATE_OPEN || -- MRT2MC(m)->state == MRT_STATE_REOPEN) { -+ if (m->state == MRT_STATE_OPEN || -+ m->state == MRT_STATE_REOPEN) { - if (mrt_open(m, now) == -1) - continue; - if (MRT2MC(m)->ReopenTimerInterval != 0) - MRT2MC(m)->ReopenTimer = - now + MRT2MC(m)->ReopenTimerInterval; -- MRT2MC(m)->state = MRT_STATE_RUNNING; -+ m->state = MRT_STATE_RUNNING; - } -- if (MRT2MC(m)->state == MRT_STATE_REMOVE) { -+ if (m->state == MRT_STATE_REMOVE) { - LIST_REMOVE(m, entry); - free(m); - continue; -@@ -700,7 +657,7 @@ mrt_handler(struct mrt_head *mrt) - - now = time(NULL); - LIST_FOREACH(m, mrt, entry) { -- if (MRT2MC(m)->state == MRT_STATE_RUNNING && -+ if (m->state == MRT_STATE_RUNNING && - (MRT2MC(m)->ReopenTimerInterval != 0 || - m->type == MRT_TABLE_DUMP)) { - if (mrt_open(m, now) == -1) -@@ -719,8 +676,8 @@ mrt_get(struct mrt_head *c, struct mrt * - LIST_FOREACH(t, c, entry) { - if (t->type != m->type) - continue; -- if (t->type == MRT_TABLE_DUMP) -- return (t); -+ if (strcmp(t->rib, m->rib)) -+ continue; - if (t->peer_id == m->peer_id && - t->group_id == m->group_id) - return (t); -@@ -739,8 +696,7 @@ mrt_mergeconfig(struct mrt_head *xconf, - if ((xm = calloc(1, sizeof(struct mrt_config))) == NULL) - fatal("mrt_mergeconfig"); - memcpy(xm, m, sizeof(struct mrt_config)); -- xm->fd = -1; -- MRT2MC(xm)->state = MRT_STATE_OPEN; -+ xm->state = MRT_STATE_OPEN; - LIST_INSERT_HEAD(xconf, xm, entry); - } else { - /* MERGE */ -@@ -750,14 +706,14 @@ mrt_mergeconfig(struct mrt_head *xconf, - fatalx("mrt_mergeconfig: strlcpy"); - MRT2MC(xm)->ReopenTimerInterval = - MRT2MC(m)->ReopenTimerInterval; -- MRT2MC(xm)->state = MRT_STATE_REOPEN; -+ xm->state = MRT_STATE_REOPEN; - } - } - - LIST_FOREACH(xm, xconf, entry) - if (mrt_get(nconf, xm) == NULL) - /* REMOVE */ -- MRT2MC(xm)->state = MRT_STATE_REMOVE; -+ xm->state = MRT_STATE_REMOVE; - - /* free config */ - while ((m = LIST_FIRST(nconf)) != NULL) { -@@ -767,4 +723,3 @@ mrt_mergeconfig(struct mrt_head *xconf, - - return (0); - } -- diff --git a/net/openbgpd/files/patch-bgpd_mrt.h b/net/openbgpd/files/patch-bgpd_mrt.h index 08240024971e..a2ef64adf59f 100644 --- a/net/openbgpd/files/patch-bgpd_mrt.h +++ b/net/openbgpd/files/patch-bgpd_mrt.h @@ -1,208 +1,23 @@ Index: bgpd/mrt.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/mrt.h,v -retrieving revision 1.1.1.1 -retrieving revision 1.1.1.2 -diff -u -p -r1.1.1.1 -r1.1.1.2 ---- bgpd/mrt.h 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/mrt.h 9 Jul 2009 16:49:54 -0000 1.1.1.2 +retrieving revision 1.1.1.6 +retrieving revision 1.1.1.7 +diff -u -p -r1.1.1.6 -r1.1.1.7 +--- 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 @@ -1,4 +1,4 @@ --/* $OpenBSD: mrt.h,v 1.16 2007/05/30 04:28:27 msf Exp $ */ -+/* $OpenBSD: mrt.h,v 1.23 2009/06/29 12:22:16 claudio Exp $ */ +-/* $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 $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> -@@ -20,12 +20,10 @@ - - #include "bgpd.h" - --/* In cases of failure wait at least MRT_MIN_RETRY. */ --#define MRT_MIN_RETRY 300 -- - /* -- * MRT binary packet format as used by zebra. -+ * MRT binary packet format - * For more info see: -+ * draft-ietf-grow-mrt-04.txt, "MRT routing information export format" - * http://www.quagga.net/docs/docs-multi/Packet-Binary-Dump-Format.html - */ - -@@ -38,24 +36,33 @@ - * +--------+--------+--------+--------+ - * | length | length of packet excluding this header - * +--------+--------+--------+--------+ -+ * -+ * ET types include an additional 32bit microsecond field comming after the -+ * length field. - */ - #define MRT_HEADER_SIZE 12 - - enum MRT_MSG_TYPES { -- MSG_NULL, -+ MSG_NULL, /* 0 empty msg (deprecated) */ - MSG_START, /* 1 sender is starting up */ -- MSG_DIE, /* 2 receiver should shut down */ -+ MSG_DIE, /* 2 receiver should shut down (deprecated) */ - MSG_I_AM_DEAD, /* 3 sender is shutting down */ -- MSG_PEER_DOWN, /* 4 sender's peer is down */ -- MSG_PROTOCOL_BGP, /* 5 msg is a BGP packet */ -+ MSG_PEER_DOWN, /* 4 sender's peer is down (deprecated) */ -+ MSG_PROTOCOL_BGP, /* 5 msg is a BGP packet (deprecated) */ - MSG_PROTOCOL_RIP, /* 6 msg is a RIP packet */ -- MSG_PROTOCOL_IDRP, /* 7 msg is an IDRP packet */ -+ MSG_PROTOCOL_IDRP, /* 7 msg is an IDRP packet (deprecated) */ - MSG_PROTOCOL_RIPNG, /* 8 msg is a RIPNG packet */ -- MSG_PROTOCOL_BGP4PLUS, /* 9 msg is a BGP4+ packet */ -- MSG_PROTOCOL_BGP4PLUS1, /* 10 msg is a BGP4+ (draft 01) packet */ -+ MSG_PROTOCOL_BGP4PLUS, /* 9 msg is a BGP4+ packet (deprecated) */ -+ MSG_PROTOCOL_BGP4PLUS1, /* 10 msg is a BGP4+ (draft 01) (deprecated) */ - MSG_PROTOCOL_OSPF, /* 11 msg is an OSPF packet */ - MSG_TABLE_DUMP, /* 12 routing table dump */ -- MSG_PROTOCOL_BGP4MP=16 /* 16 zebras own packet format */ -+ MSG_TABLE_DUMP_V2, /* 13 routing table dump */ -+ MSG_PROTOCOL_BGP4MP=16, /* 16 zebras own packet format */ -+ MSG_PROTOCOL_BGP4MP_ET=17, -+ MSG_PROTOCOL_ISIS=32, /* 32 msg is a ISIS package */ -+ MSG_PROTOCOL_ISIS_ET=33, -+ MSG_PROTOCOL_OSPFV3=48, /* 48 msg is a OSPFv3 package */ -+ MSG_PROTOCOL_OSPFV3_ET=49 - }; - - /* -@@ -64,15 +71,20 @@ enum MRT_MSG_TYPES { - * In most cases this is the format to choose to dump updates et al. - */ - enum MRT_BGP4MP_TYPES { -- BGP4MP_STATE_CHANGE=0, /* state change */ -- BGP4MP_MESSAGE=1, /* bgp message */ -- BGP4MP_ENTRY=2, /* table dumps */ -- BGP4MP_SNAPSHOT=3 -+ BGP4MP_STATE_CHANGE, /* state change */ -+ BGP4MP_MESSAGE, /* bgp message */ -+ BGP4MP_ENTRY, /* table dumps (deprecated) */ -+ BGP4MP_SNAPSHOT, /* file name for dump (deprecated) */ -+ BGP4MP_STATE_CHANGE_AS4, -+ BGP4MP_MESSAGE_AS4 /* same as BGP4MP_MESSAGE with 4byte AS */ - }; - - /* size of the BGP4MP headers without payload */ - #define MRT_BGP4MP_IPv4_HEADER_SIZE 16 - #define MRT_BGP4MP_IPv6_HEADER_SIZE 40 -+/* 4-byte AS variants of the previous */ -+#define MRT_BGP4MP_AS4_IPv4_HEADER_SIZE 20 -+#define MRT_BGP4MP_AS4_IPv6_HEADER_SIZE 44 - - /* If the type is PROTOCOL_BGP4MP and the subtype is either BGP4MP_STATE_CHANGE - * or BGP4MP_MESSAGE the message consists of a common header plus the payload. -@@ -110,6 +122,7 @@ enum MRT_BGP4MP_TYPES { - */ - #define MRT_BGP4MP_IPv4_ENTRY_SIZE 18 - #define MRT_BGP4MP_IPv6_ENTRY_SIZE 30 -+#define MRT_BGP4MP_MAX_PREFIXLEN 17 - /* - * The "new" table dump format consists of messages of type PROTOCOL_BGP4MP - * and subtype BGP4MP_ENTRY. -@@ -151,9 +164,9 @@ enum MRT_BGP4MP_TYPES { - * +--------+--------+--------+--------+ - * | prefix | - * +--------+--------+--------+--------+ -- * | plen | status | originated -+ * | plen | status | originated time - * +--------+--------+--------+--------+ -- * originated | peer_ip -+ * originated time | peer_ip - * +--------+--------+--------+--------+ - * peer_ip | peer_as | - * +--------+--------+--------+--------+ -@@ -166,8 +179,7 @@ enum MRT_BGP4MP_TYPES { - * - * - * View is normaly 0 and seqnum just a simple counter for this dump. -- * The status seems to be 1 by default but probably something to indicate -- * the status of a prefix would be more useful. -+ * The status field is unused and should be set to 1. - */ - - /* size of the dump header until attr_len */ -@@ -186,10 +198,14 @@ enum MRT_BGP_TYPES { - and announcements) */ - MSG_BGP_PREF_UPDATE, /* tlv preferences followed by raw update */ - MSG_BGP_STATE_CHANGE, /* state change */ -- MSG_BGP_SYNC -+ MSG_BGP_SYNC, /* file name for a table dump */ -+ MSG_BGP_OPEN, /* BGP open messages */ -+ MSG_BGP_NOTIFY, /* BGP notify messages */ -+ MSG_BGP_KEEPALIVE /* BGP keepalives */ - }; - --/* if type MSG_PROTOCOL_BGP and subtype MSG_BGP_UPDATE -+/* if type MSG_PROTOCOL_BGP and subtype MSG_BGP_UPDATE, MSG_BGP_OPEN, -+ * MSG_BGP_NOTIFY or MSG_BGP_KEEPALIVE - * - * +--------+--------+--------+--------+ - * | source_as | source_ip -@@ -225,7 +241,7 @@ enum MRT_BGP_TYPES { - /* - * if type MSG_PROTOCOL_BGP and subtype MSG_BGP_SYNC OR - * if type MSG_PROTOCOL_BGP4MP and subtype BGP4MP_SNAPSHOT -- * What is this for? -+ * *DEPRECATED* - * - * +--------+--------+--------+--------+ - * | view | filename -@@ -255,22 +271,22 @@ enum mrt_state { - }; - - struct mrt { -- enum mrt_type type; -+ char rib[PEER_DESCR_LEN]; -+ struct msgbuf wbuf; -+ LIST_ENTRY(mrt) entry; - u_int32_t peer_id; - u_int32_t group_id; -- u_int32_t queued; -- int fd; -- TAILQ_HEAD(, buf) bufs; -- LIST_ENTRY(mrt) entry; -+ enum mrt_type type; -+ enum mrt_state state; -+ u_int16_t seqnum; - }; - - struct mrt_config { - struct mrt conf; -- time_t ReopenTimer; -- time_t ReopenTimerInterval; -- enum mrt_state state; - char name[MRT_FILE_LEN]; /* base file name */ - char file[MRT_FILE_LEN]; /* actual file name */ -+ time_t ReopenTimer; -+ time_t ReopenTimerInterval; - }; - - #define MRT2MC(x) ((struct mrt_config *)(x)) -@@ -278,16 +294,17 @@ struct mrt_config { - - struct peer; - struct prefix; --struct pt_entry; -+struct rib_entry; - - /* prototypes */ --int mrt_dump_bgp_msg(struct mrt *, void *, u_int16_t, -- struct peer *, struct bgpd_config *); --int mrt_dump_state(struct mrt *, u_int16_t, u_int16_t, -- struct peer *, struct bgpd_config *); -+void mrt_dump_bgp_msg(struct mrt *, void *, u_int16_t, -+ struct peer *); -+void mrt_dump_state(struct mrt *, u_int16_t, u_int16_t, -+ struct peer *); +@@ -303,7 +303,7 @@ void mrt_dump_state(struct mrt *, u_in + struct peer *); void mrt_clear_seq(void); --void mrt_dump_upcall(struct pt_entry *, void *); --int mrt_write(struct mrt *); -+void mrt_dump_upcall(struct rib_entry *, void *); -+void mrt_dump_done(void *); -+void mrt_write(struct mrt *); + void mrt_dump_upcall(struct rib_entry *, void *); +-void mrt_dump_done(void *); ++void mrt_done(void *); + void mrt_write(struct mrt *); void mrt_clean(struct mrt *); void mrt_init(struct imsgbuf *, struct imsgbuf *); - int mrt_timeout(struct mrt_head *); diff --git a/net/openbgpd/files/patch-bgpd_name2id.c b/net/openbgpd/files/patch-bgpd_name2id.c deleted file mode 100644 index 7a3cea38348d..000000000000 --- a/net/openbgpd/files/patch-bgpd_name2id.c +++ /dev/null @@ -1,14 +0,0 @@ -Index: bgpd/name2id.c -=================================================================== -RCS file: /home/cvs/private/hrs/openbgpd/bgpd/name2id.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.1.1.2 -diff -u -p -r1.1.1.1 -r1.1.1.2 ---- bgpd/name2id.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/name2id.c 9 Jul 2009 16:49:54 -0000 1.1.1.2 -@@ -1,4 +1,4 @@ --/* $OpenBSD: name2id.c,v 1.7 2006/05/02 14:41:26 claudio Exp $ */ -+/* $OpenBSD: name2id.c,v 1.9 2009/06/04 04:46:42 claudio Exp $ */ - - /* - * Copyright (c) 2004, 2005 Henning Brauer <henning@openbsd.org> diff --git a/net/openbgpd/files/patch-bgpd_parse.y b/net/openbgpd/files/patch-bgpd_parse.y index ac37d5be9483..4f60625dae3a 100644 --- a/net/openbgpd/files/patch-bgpd_parse.y +++ b/net/openbgpd/files/patch-bgpd_parse.y @@ -1,46 +1,45 @@ Index: bgpd/parse.y =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/parse.y,v -retrieving revision 1.1.1.1 -retrieving revision 1.6 -diff -u -p -r1.1.1.1 -r1.6 ---- bgpd/parse.y 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/parse.y 22 Oct 2009 15:10:02 -0000 1.6 +retrieving revision 1.1.1.8 +retrieving revision 1.7 +diff -u -p -r1.1.1.8 -r1.7 +--- bgpd/parse.y 14 Feb 2010 20:19:57 -0000 1.1.1.8 ++++ bgpd/parse.y 4 Feb 2010 16:22:23 -0000 1.7 @@ -1,4 +1,4 @@ --/* $OpenBSD: parse.y,v 1.217 2008/07/08 13:14:58 claudio Exp $ */ -+/* $OpenBSD: parse.y,v 1.233 2009/08/03 13:14:07 claudio Exp $ */ +-/* $OpenBSD: parse.y,v 1.231 2009/06/06 01:10:29 claudio Exp $ */ ++/* $OpenBSD: parse.y,v 1.248 2010/01/13 06:02:37 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -39,6 +39,7 @@ - #include "bgpd.h" - #include "mrt.h" - #include "session.h" -+#include "rde.h" +@@ -105,7 +105,7 @@ struct filter_match_l { + struct filter_match m; + struct filter_prefix_l *prefix_l; + struct filter_as_l *as_l; +- sa_family_t af; ++ u_int8_t aid; + } fmopts; - TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); - static struct file { -@@ -110,7 +111,10 @@ struct filter_match_l { struct peer *alloc_peer(void); - struct peer *new_peer(void); - struct peer *new_group(void); --int add_mrtconfig(enum mrt_type, char *, time_t, struct peer *); -+int add_mrtconfig(enum mrt_type, char *, time_t, struct peer *, +@@ -128,7 +128,11 @@ void move_filterset(struct filter_set_ + struct filter_rule *get_rule(enum action_types); + + int getcommunity(char *); +-int parsecommunity(char *, int *, int *); ++int parsecommunity(struct filter_community *, char *); ++int parsesubtype(char *); ++int parseextvalue(char *, u_int32_t *); ++int parseextcommunity(struct filter_extcommunity *, char *, + char *); -+int add_rib(char *, u_int16_t); -+int 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 *); -@@ -155,11 +159,11 @@ typedef struct { - %} + typedef struct { + union { +@@ -161,9 +165,9 @@ typedef struct { %token AS ROUTERID HOLDTIME YMIN LISTEN ON FIBUPDATE RTABLE --%token RDE EVALUATE IGNORE COMPARE -+%token RDE RIB EVALUATE IGNORE COMPARE + %token RDE RIB EVALUATE IGNORE COMPARE %token GROUP NEIGHBOR NETWORK -%token REMOTEAS DESCR LOCALADDR MULTIHOP PASSIVE MAXPREFIX RESTART --%token ANNOUNCE DEMOTE +-%token ANNOUNCE DEMOTE CONNECTRETRY -%token ENFORCE NEIGHBORAS CAPABILITIES REFLECTOR DEPEND DOWN SOFTRECONFIG +%token REMOTEAS DESCR LLIFACE LOCALADDR MULTIHOP PASSIVE MAXPREFIX RESTART +%token ANNOUNCE CAPABILITIES REFRESH AS4BYTE CONNECTRETRY @@ -48,21 +47,35 @@ diff -u -p -r1.1.1.1 -r1.6 %token DUMP IN OUT %token LOG ROUTECOLL TRANSPARENT %token TCP MD5SIG PASSWORD KEY TTLSECURITY -@@ -178,7 +182,7 @@ typedef struct { +@@ -171,17 +175,19 @@ typedef struct { + %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 SET LOCALPREF MED METRIC NEXTHOP REJECT BLACKHOLE NOMODIFY SELF +-%token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL ++%token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL ORIGIN + %token ERROR INCLUDE + %token IPSEC ESP AH SPI IKE + %token IPV4 IPV6 + %token QUALIFY VIA ++%token NE LE GE XRANGE + %token <v.string> STRING %token <v.number> NUMBER %type <v.number> asnumber as4number optnumber yesno inout - %type <v.number> espah family restart --%type <v.string> string -+%type <v.string> string filter_rib +-%type <v.number> espah family restart ++%type <v.number> espah family restart origincode + %type <v.string> string filter_rib %type <v.addr> address %type <v.prefix> prefix addrspec - %type <v.u8> action quick direction delete -@@ -207,8 +211,12 @@ grammar : /* empty */ +@@ -211,8 +217,12 @@ grammar : /* empty */ ; asnumber : NUMBER { -- if ($1 < 0 || $1 >= USHRT_MAX) { -- yyerror("AS too big: max %u", USHRT_MAX - 1); +- if ($1 < 0 || $1 >= ASNUM_MAX) { +- yyerror("AS too big: max %u", ASNUM_MAX - 1); + /* + * Accroding to iana 65535 and 4294967295 are reserved + * but enforcing this is not duty of the parser. @@ -72,7 +85,7 @@ diff -u -p -r1.1.1.1 -r1.6 YYERROR; } } -@@ -270,6 +278,8 @@ yesno : STRING { +@@ -274,6 +284,8 @@ yesno : STRING { else if (!strcmp($1, "no")) $$ = 0; else { @@ -81,76 +94,62 @@ diff -u -p -r1.1.1.1 -r1.6 free($1); YYERROR; } -@@ -381,6 +391,24 @@ conf_main : AS as4number { - else - conf->flags &= ~BGPD_FLAG_NO_EVALUATE; +@@ -318,7 +330,7 @@ conf_main : AS as4number { + conf->short_as = $3; } -+ | RDE RIB STRING { -+ if (add_rib($3, F_RIB_NOFIB)) { -+ free($3); -+ YYERROR; -+ } -+ free($3); -+ } -+ | RDE RIB STRING yesno EVALUATE { -+ if ($4) { -+ free($3); -+ YYERROR; -+ } -+ if (!add_rib($3, F_RIB_NOFIB | F_RIB_NOEVALUATE)) { -+ free($3); -+ YYERROR; -+ } -+ free($3); -+ } - | TRANSPARENT yesno { - if ($2 == 1) - conf->flags |= BGPD_FLAG_DECISION_TRANS_AS; -@@ -469,12 +497,42 @@ conf_main : AS as4number { + | ROUTERID address { +- if ($2.af != AF_INET) { ++ if ($2.aid != AID_INET) { + yyerror("router-id must be an IPv4 address"); YYERROR; } - free($2); -- if (add_mrtconfig(action, $3, $4, NULL) == -1) { -+ if (add_mrtconfig(action, $3, $4, NULL, NULL) == -1) { +@@ -342,35 +354,13 @@ conf_main : AS as4number { + } + | LISTEN ON address { + struct listen_addr *la; +- struct sockaddr_in *in; +- struct sockaddr_in6 *in6; + + if ((la = calloc(1, sizeof(struct listen_addr))) == + NULL) + fatal("parse conf_main listen on calloc"); + + la->fd = -1; +- la->sa.ss_family = $3.af; +- switch ($3.af) { +- case AF_INET: +- la->sa.ss_len = sizeof(struct sockaddr_in); +- in = (struct sockaddr_in *)&la->sa; +- in->sin_addr.s_addr = $3.v4.s_addr; +- in->sin_port = htons(BGP_PORT); +- break; +- case AF_INET6: +- la->sa.ss_len = sizeof(struct sockaddr_in6); +- in6 = (struct sockaddr_in6 *)&la->sa; +- memcpy(&in6->sin6_addr, &$3.v6, +- sizeof(in6->sin6_addr)); +- in6->sin6_port = htons(BGP_PORT); +- break; +- default: +- yyerror("king bula does not like family %u", +- $3.af); +- YYERROR; +- } +- ++ memcpy(&la->sa, addr2sa(&$3, BGP_PORT), sizeof(la->sa)); + TAILQ_INSERT_TAIL(listen_addrs, la, entry); + } + | FIBUPDATE yesno { +@@ -397,7 +387,7 @@ conf_main : AS as4number { free($3); YYERROR; } - free($3); - } -+ | DUMP RIB STRING STRING STRING optnumber { -+ int action; -+ -+ if ($6 < 0 || $6 > UINT_MAX) { -+ yyerror("bad timeout"); -+ free($3); -+ free($4); -+ free($5); -+ YYERROR; -+ } -+ if (!strcmp($4, "table")) -+ action = MRT_TABLE_DUMP; -+ else if (!strcmp($4, "table-mp")) -+ action = MRT_TABLE_DUMP_MP; -+ else { -+ yyerror("unknown mrt dump type"); -+ free($3); -+ free($4); -+ free($5); -+ YYERROR; -+ } -+ free($4); -+ if (add_mrtconfig(action, $5, $6, NULL, $3) == -1) { -+ free($3); -+ free($5); -+ YYERROR; -+ } -+ free($3); -+ free($5); -+ } - | mrtdump - | RDE STRING EVALUATE { - if (!strcmp($2, "route-age")) -@@ -523,11 +581,23 @@ conf_main : AS as4number { +- if (!add_rib($3, F_RIB_NOEVALUATE)) { ++ if (!add_rib($3, F_RIB_NOFIB | F_RIB_NOEVALUATE)) { + free($3); + YYERROR; + } +@@ -575,11 +565,16 @@ conf_main : AS as4number { free($4); } | RTABLE NUMBER { @@ -164,48 +163,50 @@ diff -u -p -r1.1.1.1 -r1.6 } conf->rtableid = $2; +#endif /* defined(__FreeBSD__) */ -+ } -+ | CONNECTRETRY NUMBER { -+ if ($2 > USHRT_MAX || $2 < 1) { -+ yyerror("invalid connect-retry"); -+ YYERROR; -+ } -+ conf->connectretry = $2; } - ; + | CONNECTRETRY NUMBER { + if ($2 > USHRT_MAX || $2 < 1) { +@@ -635,11 +630,11 @@ address : STRING { + } + free($1); -@@ -550,7 +620,8 @@ mrtdump : DUMP STRING inout STRING optn - free($4); +- if (($$.af == AF_INET && len != 32) || +- ($$.af == AF_INET6 && len != 128)) { ++ if (($$.aid == AID_INET && len != 32) || ++ ($$.aid == AID_INET6 && len != 128)) { + /* unreachable */ + yyerror("got prefixlen %u, expected %u", +- len, $$.af == AF_INET ? 32 : 128); ++ len, $$.aid == AID_INET ? 32 : 128); YYERROR; } -- if (add_mrtconfig(action, $4, $5, curpeer) == -1) { -+ if (add_mrtconfig(action, $4, $5, curpeer, NULL) == -+ -1) { - free($2); - free($4); - YYERROR; -@@ -653,6 +724,20 @@ neighbor : { curpeer = new_peer(); } - if (($3.prefix.af == AF_INET && $3.len != 32) || - ($3.prefix.af == AF_INET6 && $3.len != 128)) + } +@@ -686,7 +681,7 @@ prefix : STRING '/' NUMBER { + + addrspec : address { + memcpy(&$$.prefix, &$1, sizeof(struct bgpd_addr)); +- if ($$.prefix.af == AF_INET) ++ if ($$.prefix.aid == AID_INET) + $$.len = 32; + else + $$.len = 128; +@@ -710,9 +705,13 @@ neighbor : { curpeer = new_peer(); } + memcpy(&curpeer->conf.remote_addr, &$3.prefix, + sizeof(curpeer->conf.remote_addr)); + curpeer->conf.remote_masklen = $3.len; +- if (($3.prefix.af == AF_INET && $3.len != 32) || +- ($3.prefix.af == AF_INET6 && $3.len != 128)) ++ if (($3.prefix.aid == AID_INET && $3.len != 32) || ++ ($3.prefix.aid == AID_INET6 && $3.len != 128)) curpeer->conf.template = 1; -+ switch (curpeer->conf.remote_addr.af) { -+ case AF_INET: -+ if (curpeer->conf.capabilities.mp_v4 != -+ SAFI_ALL) -+ break; -+ curpeer->conf.capabilities.mp_v4 = SAFI_UNICAST; -+ break; -+ case AF_INET6: -+ if (curpeer->conf.capabilities.mp_v6 != -+ SAFI_ALL) -+ break; -+ curpeer->conf.capabilities.mp_v6 = SAFI_UNICAST; -+ break; -+ } ++ if (curpeer->conf.capabilities.mp[ ++ curpeer->conf.remote_addr.aid] == -1) ++ curpeer->conf.capabilities.mp[ ++ curpeer->conf.remote_addr.aid] = 1; if (get_id(curpeer)) { yyerror("get_id failed"); YYERROR; -@@ -742,6 +827,17 @@ peeropts : REMOTEAS as4number { +@@ -802,6 +801,17 @@ peeropts : REMOTEAS as4number { } free($2); } @@ -223,30 +224,48 @@ diff -u -p -r1.1.1.1 -r1.6 | LOCALADDR address { memcpy(&curpeer->conf.local_addr, &$2, sizeof(curpeer->conf.local_addr)); -@@ -759,6 +855,22 @@ peeropts : REMOTEAS as4number { - | DOWN { - curpeer->conf.down = 1; +@@ -852,13 +862,17 @@ peeropts : REMOTEAS as4number { + curpeer->conf.min_holdtime = $3; } -+ | RIB STRING { -+ if (!find_rib($2)) { -+ yyerror("rib \"%s\" does not exist.", $2); -+ free($2); -+ YYERROR; -+ } -+ if (strlcpy(curpeer->conf.rib, $2, -+ sizeof(curpeer->conf.rib)) >= -+ sizeof(curpeer->conf.rib)) { -+ yyerror("rib name \"%s\" too long: max %u", -+ $2, sizeof(curpeer->conf.rib) - 1); -+ free($2); + | ANNOUNCE family STRING { +- u_int8_t safi; ++ u_int8_t aid, safi; ++ int8_t val = 1; + +- if (!strcmp($3, "none")) +- safi = SAFI_NONE; +- else if (!strcmp($3, "unicast")) ++ if (!strcmp($3, "none")) { + safi = SAFI_UNICAST; +- else { ++ val = 0; ++ } else if (!strcmp($3, "unicast")) { ++ safi = SAFI_UNICAST; ++ } else if (!strcmp($3, "vpn")) { ++ safi = SAFI_MPLSVPN; ++ } else { + yyerror("unknown/unsupported SAFI \"%s\"", + $3); + free($3); +@@ -866,25 +880,31 @@ peeropts : REMOTEAS as4number { + } + free($3); + +- switch ($2) { +- case AFI_IPv4: +- curpeer->conf.capabilities.mp_v4 = safi; +- break; +- case AFI_IPv6: +- curpeer->conf.capabilities.mp_v6 = safi; +- break; +- default: +- fatal("king bula sees borked AFI"); ++ if (afi2aid($2, safi, &aid) == -1) { ++ yyerror("unknown AFI/SAFI pair"); + YYERROR; -+ } -+ free($2); -+ } - | HOLDTIME NUMBER { - if ($2 < MIN_HOLDTIME || $2 > USHRT_MAX) { - yyerror("holdtime must be between %u and %u", -@@ -804,11 +916,22 @@ peeropts : REMOTEAS as4number { + } ++ curpeer->conf.capabilities.mp[aid] = val; + } | ANNOUNCE CAPABILITIES yesno { curpeer->conf.announce_capa = $3; } @@ -270,81 +289,178 @@ diff -u -p -r1.1.1.1 -r1.6 curpeer->conf.announce_type = ANNOUNCE_NONE; else if (!strcmp($2, "all")) curpeer->conf.announce_type = ANNOUNCE_ALL; -@@ -1058,6 +1181,12 @@ peeropts : REMOTEAS as4number { - else - curpeer->conf.softreconfig_out = $3; +@@ -1083,7 +1103,7 @@ peeropts : REMOTEAS as4number { + curpeer->conf.reflector_client = 1; } -+ | TRANSPARENT yesno { -+ if ($2 == 1) -+ curpeer->conf.flags |= PEERFLAG_TRANS_AS; -+ else -+ curpeer->conf.flags &= ~PEERFLAG_TRANS_AS; -+ } + | REFLECTOR address { +- if ($2.af != AF_INET) { ++ if ($2.aid != AID_INET) { + yyerror("route reflector cluster-id must be " + "an IPv4 address"); + YYERROR; +@@ -1336,12 +1356,12 @@ filter_prefix_l : filter_prefix { $$ ; - restart : /* nada */ { $$ = 0; } -@@ -1115,16 +1244,37 @@ encspec : /* nada */ { + filter_prefix : prefix { +- if (fmopts.af && fmopts.af != $1.prefix.af) { ++ if (fmopts.aid && fmopts.aid != $1.prefix.aid) { + yyerror("rules with mixed address families " + "are not allowed"); + YYERROR; + } else +- fmopts.af = $1.prefix.af; ++ fmopts.aid = $1.prefix.aid; + if (($$ = calloc(1, sizeof(struct filter_prefix_l))) == + NULL) + fatal(NULL); +@@ -1437,18 +1457,18 @@ filter_elm : filter_prefix_h { + fmopts.prefix_l = $1; + } + | PREFIXLEN prefixlenop { +- if (fmopts.af == 0) { ++ if (fmopts.aid == 0) { + yyerror("address family needs to be specified " + "before \"prefixlen\""); + YYERROR; + } +- if (fmopts.m.prefixlen.af) { ++ if (fmopts.m.prefixlen.aid) { + yyerror("\"prefixlen\" already specified"); + YYERROR; + } + memcpy(&fmopts.m.prefixlen, &$2, + sizeof(fmopts.m.prefixlen)); +- fmopts.m.prefixlen.af = fmopts.af; ++ fmopts.m.prefixlen.aid = fmopts.aid; + } + | filter_as_h { + if (fmopts.as_l != NULL) { +@@ -1463,26 +1483,25 @@ filter_elm : filter_prefix_h { + free($2); + YYERROR; + } +- if (parsecommunity($2, &fmopts.m.community.as, +- &fmopts.m.community.type) == -1) { ++ if (parsecommunity(&fmopts.m.community, $2) == -1) { + free($2); + YYERROR; + } + free($2); + } + | IPV4 { +- if (fmopts.af) { ++ if (fmopts.aid) { + yyerror("address family already specified"); + YYERROR; + } +- fmopts.af = AF_INET; ++ fmopts.aid = AID_INET; + } + | IPV6 { +- if (fmopts.af) { ++ if (fmopts.aid) { + yyerror("address family already specified"); + YYERROR; + } +- fmopts.af = AF_INET6; ++ fmopts.aid = AID_INET6; } ; --filterrule : action quick direction filter_peer_h filter_match_h filter_set -+filterrule : action quick filter_rib direction filter_peer_h filter_match_h filter_set - { - struct filter_rule r; +@@ -1782,8 +1801,7 @@ filter_set_opt : LOCALPREF NUMBER { + else + $$->type = ACTION_SET_COMMUNITY; - bzero(&r, sizeof(r)); - r.action = $1; - r.quick = $2; -- r.dir = $3; -- -- if (expand_rule(&r, $4, &$5, $6) == -1) -+ r.dir = $4; -+ if ($3) { -+ if (r.dir != DIR_IN) { -+ yyerror("rib only allowed on \"from\" " -+ "rules."); -+ free($3); -+ YYERROR; -+ } -+ if (!find_rib($3)) { -+ yyerror("rib \"%s\" does not exist.", -+ $3); -+ free($3); -+ YYERROR; -+ } -+ if (strlcpy(r.rib, $3, sizeof(r.rib)) >= -+ sizeof(r.rib)) { -+ yyerror("rib name \"%s\" too long: " -+ "max %u", $3, sizeof(r.rib) - 1); -+ free($3); -+ YYERROR; -+ } -+ free($3); -+ } -+ if (expand_rule(&r, $5, &$6, $7) == -1) +- if (parsecommunity($3, &$$->action.community.as, +- &$$->action.community.type) == -1) { ++ if (parsecommunity(&$$->action.community, $3) == -1) { + free($3); + free($$); YYERROR; +@@ -1796,40 +1814,62 @@ filter_set_opt : LOCALPREF NUMBER { + free($$); + YYERROR; + } +- /* Don't allow setting of unknown well-known types */ +- if ($$->action.community.as == COMMUNITY_WELLKNOWN) { +- switch ($$->action.community.type) { +- case COMMUNITY_NO_EXPORT: +- case COMMUNITY_NO_ADVERTISE: +- case COMMUNITY_NO_EXPSUBCONFED: +- case COMMUNITY_NO_PEER: +- /* valid */ +- break; +- default: +- /* unknown */ +- yyerror("Invalid well-known community"); +- free($$); +- YYERROR; +- break; +- } ++ } ++ | EXTCOMMUNITY delete STRING STRING { ++ if (($$ = calloc(1, sizeof(struct filter_set))) == NULL) ++ fatal(NULL); ++ if ($2) ++ $$->type = ACTION_DEL_EXT_COMMUNITY; ++ else ++ $$->type = ACTION_SET_EXT_COMMUNITY; ++ ++ if (parseextcommunity(&$$->action.ext_community, ++ $3, $4) == -1) { ++ free($3); ++ free($4); ++ free($$); ++ YYERROR; + } ++ free($3); ++ free($4); ++ } ++ | ORIGIN origincode { ++ if (($$ = calloc(1, sizeof(struct filter_set))) == NULL) ++ fatal(NULL); ++ $$->type = ACTION_SET_ORIGIN; ++ $$->action.origin = $2; } ; -@@ -1142,6 +1292,9 @@ direction : FROM { $$ = DIR_IN; } - | TO { $$ = DIR_OUT; } - ; -+filter_rib : /* empty */ { $$ = NULL; } -+ | RIB STRING { $$ = $2; } ++origincode : string { ++ if (!strcmp($1, "egp")) ++ $$ = ORIGIN_EGP; ++ else if (!strcmp($1, "igp")) ++ $$ = ORIGIN_IGP; ++ else if (!strcmp($1, "incomplete")) ++ $$ = ORIGIN_INCOMPLETE; ++ else { ++ yyerror("unknown origin \"%s\"", $1); ++ free($1); ++ YYERROR; ++ } ++ free($1); ++ }; + - filter_peer_h : filter_peer - | '{' filter_peer_l '}' { $$ = $2; } + comma : "," + | /* empty */ ; -@@ -1396,7 +1549,7 @@ prefixlenop : unaryop NUMBER { - YYERROR; - } - if ($1 >= $3) { -- yyerror("start prefixlen is bigger that end"); -+ yyerror("start prefixlen is bigger than end"); - YYERROR; - } - $$.op = $2; -@@ -1767,10 +1920,12 @@ lookup(char *s) + + unaryop : '=' { $$ = OP_EQ; } +- | '!' '=' { $$ = OP_NE; } +- | '<' '=' { $$ = OP_LE; } ++ | NE { $$ = OP_NE; } ++ | LE { $$ = OP_LE; } + | '<' { $$ = OP_LT; } +- | '>' '=' { $$ = OP_GE; } ++ | GE { $$ = OP_GE; } + | '>' { $$ = OP_GT; } + ; + + binaryop : '-' { $$ = OP_RANGE; } +- | '>' '<' { $$ = OP_XRANGE; } ++ | XRANGE { $$ = OP_XRANGE; } + ; + + %% +@@ -1873,6 +1913,7 @@ lookup(char *s) { "allow", ALLOW}, { "announce", ANNOUNCE}, { "any", ANY}, @@ -352,12 +468,15 @@ diff -u -p -r1.1.1.1 -r1.6 { "blackhole", BLACKHOLE}, { "capabilities", CAPABILITIES}, { "community", COMMUNITY}, - { "compare", COMPARE}, -+ { "connect-retry", CONNECTRETRY}, - { "connected", CONNECTED}, - { "delete", DELETE}, - { "demote", DEMOTE}, -@@ -1792,6 +1947,9 @@ lookup(char *s) +@@ -1889,6 +1930,7 @@ lookup(char *s) + { "enforce", ENFORCE}, + { "esp", ESP}, + { "evaluate", EVALUATE}, ++ { "ext-community", EXTCOMMUNITY}, + { "fib-update", FIBUPDATE}, + { "from", FROM}, + { "group", GROUP}, +@@ -1899,6 +1941,9 @@ lookup(char *s) { "include", INCLUDE}, { "inet", IPV4}, { "inet6", IPV6}, @@ -367,7 +486,15 @@ diff -u -p -r1.1.1.1 -r1.6 { "ipsec", IPSEC}, { "key", KEY}, { "listen", LISTEN}, -@@ -1823,9 +1981,11 @@ lookup(char *s) +@@ -1918,6 +1963,7 @@ lookup(char *s) + { "nexthop", NEXTHOP}, + { "no-modify", NOMODIFY}, + { "on", ON}, ++ { "origin", ORIGIN}, + { "out", OUT}, + { "passive", PASSIVE}, + { "password", PASSWORD}, +@@ -1930,6 +1976,7 @@ lookup(char *s) { "qualify", QUALIFY}, { "quick", QUICK}, { "rde", RDE}, @@ -375,171 +502,308 @@ diff -u -p -r1.1.1.1 -r1.6 { "reject", REJECT}, { "remote-as", REMOTEAS}, { "restart", RESTART}, -+ { "rib", RIB}, - { "route-collector", ROUTECOLL}, - { "route-reflector", REFLECTOR}, - { "router-id", ROUTERID}, -@@ -1933,11 +2093,13 @@ findeol(void) - int c; +@@ -2135,6 +2182,26 @@ top: + if (yylval.v.string == NULL) + fatal("yylex: strdup"); + return (STRING); ++ case '!': ++ next = lgetc(0); ++ if (next == '=') ++ return (NE); ++ lungetc(next); ++ break; ++ case '<': ++ next = lgetc(0); ++ if (next == '=') ++ return (LE); ++ lungetc(next); ++ break; ++ case '>': ++ next = lgetc(0); ++ if (next == '<') ++ return (XRANGE); ++ else if (next == '=') ++ return (GE); ++ lungetc(next); ++ break; + } - parsebuf = NULL; -- pushback_index = 0; + #define allowed_to_end_number(x) \ +@@ -2505,27 +2572,27 @@ getcommunity(char *s) + } - /* skip to either EOF or the first real EOL */ - while (1) { -- c = lgetc(0); -+ if (pushback_index) -+ c = pushback_buffer[--pushback_index]; -+ else -+ c = lgetc(0); - if (c == '\n') { - file->lineno++; - break; -@@ -2118,11 +2280,15 @@ pushfile(const char *name, int secret) + int +-parsecommunity(char *s, int *as, int *type) ++parsecommunity(struct filter_community *c, char *s) { - struct file *nfile; + char *p; +- int i; ++ int i, as; -- if ((nfile = calloc(1, sizeof(struct file))) == NULL || -- (nfile->name = strdup(name)) == NULL) { -+ if ((nfile = calloc(1, sizeof(struct file))) == NULL) { - log_warn("malloc"); - return (NULL); + /* Well-known communities */ + if (strcasecmp(s, "NO_EXPORT") == 0) { +- *as = COMMUNITY_WELLKNOWN; +- *type = COMMUNITY_NO_EXPORT; ++ c->as = COMMUNITY_WELLKNOWN; ++ c->type = COMMUNITY_NO_EXPORT; + return (0); + } else if (strcasecmp(s, "NO_ADVERTISE") == 0) { +- *as = COMMUNITY_WELLKNOWN; +- *type = COMMUNITY_NO_ADVERTISE; ++ c->as = COMMUNITY_WELLKNOWN; ++ c->type = COMMUNITY_NO_ADVERTISE; + return (0); + } else if (strcasecmp(s, "NO_EXPORT_SUBCONFED") == 0) { +- *as = COMMUNITY_WELLKNOWN; +- *type = COMMUNITY_NO_EXPSUBCONFED; ++ c->as = COMMUNITY_WELLKNOWN; ++ c->type = COMMUNITY_NO_EXPSUBCONFED; + return (0); + } else if (strcasecmp(s, "NO_PEER") == 0) { +- *as = COMMUNITY_WELLKNOWN; +- *type = COMMUNITY_NO_PEER; ++ c->as = COMMUNITY_WELLKNOWN; ++ c->type = COMMUNITY_NO_PEER; + return (0); } -+ if ((nfile->name = strdup(name)) == NULL) { -+ log_warn("malloc"); -+ free(nfile); -+ return (NULL); -+ } - if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { - log_warn("%s", nfile->name); - free(nfile->name); -@@ -2207,6 +2373,9 @@ parse_config(char *filename, struct bgpd - /* init the empty filter list for later */ - TAILQ_INIT(xfilter_l); -+ add_rib("Adj-RIB-In", F_RIB_NOEVALUATE); -+ add_rib("Loc-RIB", 0); -+ - yyparse(); - errors = file->errors; - popfile(); -@@ -2447,11 +2616,13 @@ alloc_peer(void) - p->conf.distance = 1; - p->conf.announce_type = ANNOUNCE_UNDEF; - p->conf.announce_capa = 1; -- p->conf.capabilities.mp_v4 = SAFI_UNICAST; -- p->conf.capabilities.mp_v6 = SAFI_NONE; -+ p->conf.capabilities.mp_v4 = SAFI_ALL; -+ p->conf.capabilities.mp_v6 = SAFI_ALL; - p->conf.capabilities.refresh = 1; - p->conf.capabilities.restart = 0; -- p->conf.capabilities.as4byte = 0; -+ p->conf.capabilities.as4byte = 1; -+ p->conf.local_as = conf->as; -+ p->conf.local_short_as = conf->short_as; - p->conf.softreconfig_in = 1; - p->conf.softreconfig_out = 1; +@@ -2537,23 +2604,175 @@ parsecommunity(char *s, int *as, int *ty -@@ -2473,10 +2644,16 @@ new_peer(void) - if (strlcpy(p->conf.descr, curgroup->conf.descr, - sizeof(p->conf.descr)) >= sizeof(p->conf.descr)) - fatalx("new_peer descr strlcpy"); -+ if (strlcpy(p->conf.lliface, curgroup->conf.lliface, -+ sizeof(p->conf.lliface)) >= sizeof(p->conf.lliface)) -+ fatalx("new_peer lliface strlcpy"); - p->conf.groupid = curgroup->conf.id; -+ p->conf.local_as = curgroup->conf.local_as; -+ p->conf.local_short_as = curgroup->conf.local_short_as; + if ((i = getcommunity(s)) == COMMUNITY_ERROR) + return (-1); +- if (i == USHRT_MAX) { ++ if (i == COMMUNITY_WELLKNOWN) { + yyerror("Bad community AS number"); + return (-1); } - p->next = NULL; -- -+ if (conf->flags & BGPD_FLAG_DECISION_TRANS_AS) -+ p->conf.flags |= PEERFLAG_TRANS_AS; - return (p); - } +- *as = i; ++ as = i; -@@ -2487,11 +2664,15 @@ new_group(void) - } + if ((i = getcommunity(p)) == COMMUNITY_ERROR) + return (-1); +- *type = i; ++ c->as = as; ++ c->type = i; - int --add_mrtconfig(enum mrt_type type, char *name, time_t timeout, struct peer *p) -+add_mrtconfig(enum mrt_type type, char *name, time_t timeout, struct peer *p, -+ char *rib) - { - struct mrt *m, *n; + return (0); + } - LIST_FOREACH(m, mrtconf, entry) { -+ if ((rib && strcmp(rib, m->rib)) || -+ (!rib && *m->rib)) -+ continue; - if (p == NULL) { - if (m->peer_id != 0 || m->group_id != 0) - continue; -@@ -2527,6 +2708,20 @@ add_mrtconfig(enum mrt_type type, char * - n->group_id = 0; - } - } -+ if (rib) { -+ if (!find_rib(rib)) { -+ yyerror("rib \"%s\" does not exist.", rib); -+ free(n); ++int ++parsesubtype(char *type) ++{ ++ /* this has to be sorted always */ ++ static const struct keywords keywords[] = { ++ { "bdc", EXT_COMMUNITY_BGP_COLLECT }, ++ { "odi", EXT_COMMUNITY_OSPF_DOM_ID }, ++ { "ori", EXT_COMMUNITY_OSPF_RTR_ID }, ++ { "ort", EXT_COMMUNITY_OSPF_RTR_TYPE }, ++ { "rt", EXT_COMMUNITY_ROUTE_TGT }, ++ { "soo", EXT_CUMMUNITY_ROUTE_ORIG } ++ }; ++ const struct keywords *p; ++ ++ p = bsearch(type, keywords, sizeof(keywords)/sizeof(keywords[0]), ++ sizeof(keywords[0]), kw_cmp); ++ ++ if (p) ++ return (p->k_val); ++ else ++ return (-1); ++} ++ ++int ++parseextvalue(char *s, u_int32_t *v) ++{ ++ const char *errstr; ++ char *p; ++ struct in_addr ip; ++ u_int32_t uvalh = 0, uval; ++ ++ if ((p = strchr(s, '.')) == NULL) { ++ /* AS_PLAIN number (4 or 2 byte) */ ++ uval = strtonum(s, 0, UINT_MAX, &errstr); ++ if (errstr) { ++ yyerror("Bad ext-community %s is %s", s, errstr); ++ return (-1); ++ } ++ *v = uval; ++ if (uval > USHRT_MAX) ++ return (EXT_COMMUNITY_FOUR_AS); ++ else ++ return (EXT_COMMUNITY_TWO_AS); ++ } else if (strchr(p + 1, '.') == NULL) { ++ /* AS_DOT number (4-byte) */ ++ *p++ = '\0'; ++ uvalh = strtonum(s, 0, USHRT_MAX, &errstr); ++ if (errstr) { ++ yyerror("Bad ext-community %s is %s", s, errstr); ++ return (-1); ++ } ++ uval = strtonum(p, 0, USHRT_MAX, &errstr); ++ if (errstr) { ++ yyerror("Bad ext-community %s is %s", p, errstr); + return (-1); + } -+ if (strlcpy(n->rib, rib, sizeof(n->rib)) >= -+ sizeof(n->rib)) { -+ yyerror("rib name \"%s\" too long: max %u", -+ name, sizeof(n->rib) - 1); -+ free(n); ++ *v = uval | (uvalh << 16); ++ return (EXT_COMMUNITY_FOUR_AS); ++ } else { ++ /* more then one dot -> IP address */ ++ if (inet_aton(s, &ip) == 0) { ++ yyerror("Bad ext-community %s not parseable", s); + return (-1); + } ++ *v = ip.s_addr; ++ return (EXT_COMMUNITY_IPV4); + } - - LIST_INSERT_HEAD(mrtconf, n, entry); - -@@ -2534,6 +2729,42 @@ add_mrtconfig(enum mrt_type type, char * - } - - int -+add_rib(char *name, u_int16_t flags) ++ return (-1); ++} ++ ++int ++parseextcommunity(struct filter_extcommunity *c, char *t, char *s) +{ -+ struct rde_rib *rr; ++ const struct ext_comm_pairs iana[] = IANA_EXT_COMMUNITIES; ++ const char *errstr; ++ u_int64_t ullval = 0; ++ u_int32_t uval; ++ char *p, *ep; ++ unsigned int i; ++ int type, subtype; + -+ if (find_rib(name)) { -+ yyerror("rib \"%s\" allready exists.", name); ++ if ((subtype = parsesubtype(t)) == -1) { ++ yyerror("Bad ext-community unknown type"); + return (-1); + } + -+ 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); -+ return (-1); ++ if ((p = strchr(s, ':')) == NULL) { ++ type = EXT_COMMUNITY_OPAQUE, ++ errno = 0; ++ ullval = strtoull(s, &ep, 0); ++ if (s[0] == '\0' || *ep != '\0') { ++ yyerror("Bad ext-community bad value"); ++ return (-1); ++ } ++ if (errno == ERANGE && ullval > EXT_COMMUNITY_OPAQUE_MAX) { ++ yyerror("Bad ext-community value to big"); ++ return (-1); ++ } ++ c->data.ext_opaq = ullval; ++ } else { ++ *p++ = '\0'; ++ if ((type = parseextvalue(s, &uval)) == -1) ++ return (-1); ++ switch (type) { ++ case EXT_COMMUNITY_TWO_AS: ++ ullval = strtonum(p, 0, UINT_MAX, &errstr); ++ break; ++ case EXT_COMMUNITY_IPV4: ++ case EXT_COMMUNITY_FOUR_AS: ++ ullval = strtonum(p, 0, USHRT_MAX, &errstr); ++ break; ++ default: ++ fatalx("parseextcommunity: unexpected result"); ++ } ++ if (errstr) { ++ yyerror("Bad ext-community %s is %s", p, ++ errstr); ++ return (-1); ++ } ++ switch (type) { ++ case EXT_COMMUNITY_TWO_AS: ++ c->data.ext_as.as = uval; ++ c->data.ext_as.val = ullval; ++ break; ++ case EXT_COMMUNITY_IPV4: ++ c->data.ext_ip.addr.s_addr = uval; ++ c->data.ext_ip.val = ullval; ++ break; ++ case EXT_COMMUNITY_FOUR_AS: ++ c->data.ext_as4.as4 = uval; ++ c->data.ext_as4.val = ullval; ++ break; ++ } + } -+ rr->flags |= flags; -+ SIMPLEQ_INSERT_TAIL(&ribnames, rr, entry); -+ return (0); -+} ++ c->type = type; ++ c->subtype = subtype; + -+int -+find_rib(char *name) -+{ -+ struct rde_rib *rr; -+ -+ SIMPLEQ_FOREACH(rr, &ribnames, entry) { -+ if (!strcmp(rr->name, name)) -+ return (1); ++ /* verify type/subtype combo */ ++ for (i = 0; i < sizeof(iana)/sizeof(iana[0]); i++) { ++ if (iana[i].type == type && iana[i].subtype == subtype) { ++ if (iana[i].transitive) ++ c->type |= EXT_COMMUNITY_TRANSITIVE; ++ return (0); ++ } + } -+ return (0); ++ ++ yyerror("Bad ext-community bad format for type"); ++ return (-1); +} + -+int - get_id(struct peer *newpeer) + struct peer * + alloc_peer(void) { struct peer *p; -@@ -2713,10 +2944,6 @@ neighbor_consistent(struct peer *p) ++ u_int8_t i; + + if ((p = calloc(1, sizeof(struct peer))) == NULL) + fatal("new_peer"); +@@ -2564,11 +2783,11 @@ alloc_peer(void) + p->conf.distance = 1; + p->conf.announce_type = ANNOUNCE_UNDEF; + p->conf.announce_capa = 1; +- p->conf.capabilities.mp_v4 = SAFI_UNICAST; +- p->conf.capabilities.mp_v6 = SAFI_NONE; ++ for (i = 0; i < AID_MAX; i++) ++ p->conf.capabilities.mp[i] = -1; + p->conf.capabilities.refresh = 1; + p->conf.capabilities.restart = 0; +- p->conf.capabilities.as4byte = 0; ++ p->conf.capabilities.as4byte = 1; + p->conf.local_as = conf->as; + p->conf.local_short_as = conf->short_as; + p->conf.softreconfig_in = 1; +@@ -2592,6 +2811,9 @@ new_peer(void) + if (strlcpy(p->conf.descr, curgroup->conf.descr, + sizeof(p->conf.descr)) >= sizeof(p->conf.descr)) + fatalx("new_peer descr strlcpy"); ++ if (strlcpy(p->conf.lliface, curgroup->conf.lliface, ++ sizeof(p->conf.lliface)) >= sizeof(p->conf.lliface)) ++ fatalx("new_peer lliface strlcpy"); + p->conf.groupid = curgroup->conf.id; + p->conf.local_as = curgroup->conf.local_as; + p->conf.local_short_as = curgroup->conf.local_short_as; +@@ -2715,7 +2937,7 @@ get_id(struct peer *newpeer) + struct peer *p; + + for (p = peer_l_old; p != NULL; p = p->next) +- if (newpeer->conf.remote_addr.af) { ++ if (newpeer->conf.remote_addr.aid) { + if (!memcmp(&p->conf.remote_addr, + &newpeer->conf.remote_addr, + sizeof(p->conf.remote_addr))) { +@@ -2856,9 +3078,11 @@ str2key(char *s, char *dest, size_t max_ + int + neighbor_consistent(struct peer *p) + { ++ u_int8_t i; ++ + /* local-address and peer's address: same address family */ +- if (p->conf.local_addr.af && +- p->conf.local_addr.af != p->conf.remote_addr.af) { ++ if (p->conf.local_addr.aid && ++ p->conf.local_addr.aid != p->conf.remote_addr.aid) { + yyerror("local-address and neighbor address " + "must be of the same address family"); + return (-1); +@@ -2869,7 +3093,7 @@ neighbor_consistent(struct peer *p) + p->conf.auth.method == AUTH_IPSEC_IKE_AH || + p->conf.auth.method == AUTH_IPSEC_MANUAL_ESP || + p->conf.auth.method == AUTH_IPSEC_MANUAL_AH) && +- !p->conf.local_addr.af) { ++ !p->conf.local_addr.aid) { + yyerror("neighbors with any form of IPsec configured " + "need local-address to be specified"); + return (-1); +@@ -2889,10 +3113,6 @@ neighbor_consistent(struct peer *p) return (-1); } @@ -550,16 +814,48 @@ diff -u -p -r1.1.1.1 -r1.6 /* set default values if they where undefined */ p->conf.ebgp = (p->conf.remote_as != conf->as); if (p->conf.announce_type == ANNOUNCE_UNDEF) -@@ -2733,6 +2960,12 @@ neighbor_consistent(struct peer *p) +@@ -2909,6 +3129,11 @@ neighbor_consistent(struct peer *p) return (-1); } + /* the default MP capability is NONE */ -+ if (p->conf.capabilities.mp_v4 == SAFI_ALL) -+ p->conf.capabilities.mp_v4 = SAFI_NONE; -+ if (p->conf.capabilities.mp_v6 == SAFI_ALL) -+ p->conf.capabilities.mp_v6 = SAFI_NONE; ++ for (i = 0; i < AID_MAX; i++) ++ if (p->conf.capabilities.mp[i] == -1) ++ p->conf.capabilities.mp[i] = 0; + return (0); } +@@ -2927,6 +3152,11 @@ merge_filterset(struct filter_set_head * + yyerror("community is already set"); + else if (s->type == ACTION_DEL_COMMUNITY) + yyerror("community will already be deleted"); ++ else if (s->type == ACTION_SET_EXT_COMMUNITY) ++ yyerror("ext-community is already set"); ++ else if (s->type == ACTION_DEL_EXT_COMMUNITY) ++ yyerror( ++ "ext-community will already be deleted"); + else + yyerror("redefining set parameter %s", + filterset_name(s->type)); +@@ -2953,9 +3183,18 @@ merge_filterset(struct filter_set_head * + return (0); + } + break; ++ case ACTION_SET_EXT_COMMUNITY: ++ case ACTION_DEL_EXT_COMMUNITY: ++ if (memcmp(&s->action.ext_community, ++ &t->action.ext_community, ++ sizeof(s->action.ext_community)) < 0) { ++ TAILQ_INSERT_BEFORE(t, s, entry); ++ return (0); ++ } ++ break; + case ACTION_SET_NEXTHOP: +- if (s->action.nexthop.af < +- t->action.nexthop.af) { ++ if (s->action.nexthop.aid < ++ t->action.nexthop.aid) { + TAILQ_INSERT_BEFORE(t, s, entry); + return (0); + } diff --git a/net/openbgpd/files/patch-bgpd_pfkey.c b/net/openbgpd/files/patch-bgpd_pfkey.c index 1c57da3b9d06..a7d261db35ea 100644 --- a/net/openbgpd/files/patch-bgpd_pfkey.c +++ b/net/openbgpd/files/patch-bgpd_pfkey.c @@ -1,81 +1,120 @@ Index: bgpd/pfkey.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/pfkey.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.1.1.2 -diff -u -p -r1.1.1.1 -r1.1.1.2 ---- bgpd/pfkey.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/pfkey.c 9 Jul 2009 16:49:54 -0000 1.1.1.2 +retrieving revision 1.1.1.6 +retrieving revision 1.1.1.7 +diff -u -p -r1.1.1.6 -r1.1.1.7 +--- 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 @@ -1,4 +1,4 @@ --/* $OpenBSD: pfkey.c,v 1.34 2006/10/26 14:26:49 henning Exp $ */ -+/* $OpenBSD: pfkey.c,v 1.37 2009/04/21 15:25:52 henning Exp $ */ +-/* $OpenBSD: pfkey.c,v 1.37 2009/04/21 15:25:52 henning Exp $ */ ++/* $OpenBSD: pfkey.c,v 1.40 2009/12/14 17:38:18 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -36,7 +36,8 @@ - #define ROUNDUP(x) (((x) + (PFKEY2_CHUNK - 1)) & ~(PFKEY2_CHUNK - 1)) - #define IOV_CNT 20 - --static u_int32_t sadb_msg_seq = 1; -+static u_int32_t sadb_msg_seq = 0; -+static u_int32_t pid = 0; /* should pid_t but pfkey needs u_int32_t */ - static int fd; - - int pfkey_reply(int, u_int32_t *); -@@ -74,6 +75,9 @@ pfkey_send(int sd, uint8_t satype, uint8 +@@ -74,6 +74,7 @@ pfkey_send(int sd, uint8_t satype, uint8 + int len = 0; int iov_cnt; struct sockaddr_storage ssrc, sdst, speer, smask, dmask; ++ struct sockaddr *saptr; -+ if (!pid) -+ pid = getpid(); -+ + if (!pid) + pid = getpid(); +@@ -81,22 +82,17 @@ pfkey_send(int sd, uint8_t satype, uint8 /* we need clean sockaddr... no ports set */ bzero(&ssrc, sizeof(ssrc)); bzero(&smask, sizeof(smask)); -@@ -129,8 +133,8 @@ pfkey_send(int sd, uint8_t satype, uint8 +- switch (src->af) { +- case AF_INET: +- ((struct sockaddr_in *)&ssrc)->sin_addr = src->v4; +- ssrc.ss_len = sizeof(struct sockaddr_in); +- ssrc.ss_family = AF_INET; ++ if ((saptr = addr2sa(src, 0))) ++ memcpy(&ssrc, saptr, sizeof(ssrc)); ++ switch (src->aid) { ++ case AID_INET: + memset(&((struct sockaddr_in *)&smask)->sin_addr, 0xff, 32/8); + break; +- case AF_INET6: +- memcpy(&((struct sockaddr_in6 *)&ssrc)->sin6_addr, +- &src->v6, sizeof(struct in6_addr)); +- ssrc.ss_len = sizeof(struct sockaddr_in6); +- ssrc.ss_family = AF_INET6; ++ case AID_INET6: + memset(&((struct sockaddr_in6 *)&smask)->sin6_addr, 0xff, + 128/8); + break; +- case 0: ++ case AID_UNSPEC: + ssrc.ss_len = sizeof(struct sockaddr); + break; + default: +@@ -107,22 +103,17 @@ pfkey_send(int sd, uint8_t satype, uint8 - bzero(&smsg, sizeof(smsg)); - smsg.sadb_msg_version = PF_KEY_V2; -- smsg.sadb_msg_seq = sadb_msg_seq++; -- smsg.sadb_msg_pid = getpid(); -+ smsg.sadb_msg_seq = ++sadb_msg_seq; -+ smsg.sadb_msg_pid = pid; - smsg.sadb_msg_len = sizeof(smsg) / 8; - smsg.sadb_msg_type = mtype; - smsg.sadb_msg_satype = satype; -@@ -415,10 +419,23 @@ pfkey_reply(int sd, u_int32_t *spip) - u_int8_t *data; - ssize_t len; + bzero(&sdst, sizeof(sdst)); + bzero(&dmask, sizeof(dmask)); +- switch (dst->af) { +- case AF_INET: +- ((struct sockaddr_in *)&sdst)->sin_addr = dst->v4; +- sdst.ss_len = sizeof(struct sockaddr_in); +- sdst.ss_family = AF_INET; ++ if ((saptr = addr2sa(dst, 0))) ++ memcpy(&sdst, saptr, sizeof(sdst)); ++ switch (dst->aid) { ++ case AID_INET: + memset(&((struct sockaddr_in *)&dmask)->sin_addr, 0xff, 32/8); + break; +- case AF_INET6: +- memcpy(&((struct sockaddr_in6 *)&sdst)->sin6_addr, +- &dst->v6, sizeof(struct in6_addr)); +- sdst.ss_len = sizeof(struct sockaddr_in6); +- sdst.ss_family = AF_INET6; ++ case AID_INET6: + memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr, 0xff, + 128/8); + break; +- case 0: ++ case AID_UNSPEC: + sdst.ss_len = sizeof(struct sockaddr); + break; + default: +@@ -220,8 +211,8 @@ pfkey_send(int sd, uint8_t satype, uint8 + sa_dst.sadb_address_exttype = SADB_X_EXT_DST_FLOW; -- if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) { -- log_warn("pfkey peek"); -- return (-1); -+ for (;;) { -+ if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) { -+ log_warn("pfkey peek"); -+ return (-1); -+ } -+ -+ if (hdr.sadb_msg_seq == sadb_msg_seq && -+ hdr.sadb_msg_pid == pid) -+ break; -+ -+ /* not ours, discard */ -+ if (read(sd, &hdr, sizeof(hdr)) == -1) { -+ log_warn("pfkey read"); -+ return (-1); -+ } - } -+ - if (hdr.sadb_msg_errno != 0) { - errno = hdr.sadb_msg_errno; - if (errno == ESRCH) -@@ -497,6 +514,8 @@ pfkey_sa_remove(struct bgpd_addr *src, s - int - pfkey_md5sig_establish(struct peer *p) - { -+ sleep(1); -+ - if (!p->auth.spi_out) - if (pfkey_sa_add(&p->auth.local_addr, &p->conf.remote_addr, - p->conf.auth.md5key_len, p->conf.auth.md5key, + bzero(&smask, sizeof(smask)); +- switch (src->af) { +- case AF_INET: ++ switch (src->aid) { ++ case AID_INET: + smask.ss_len = sizeof(struct sockaddr_in); + smask.ss_family = AF_INET; + memset(&((struct sockaddr_in *)&smask)->sin_addr, +@@ -233,7 +224,7 @@ pfkey_send(int sd, uint8_t satype, uint8 + htons(0xffff); + } + break; +- case AF_INET6: ++ case AID_INET6: + smask.ss_len = sizeof(struct sockaddr_in6); + smask.ss_family = AF_INET6; + memset(&((struct sockaddr_in6 *)&smask)->sin6_addr, +@@ -247,8 +238,8 @@ pfkey_send(int sd, uint8_t satype, uint8 + break; + } + bzero(&dmask, sizeof(dmask)); +- switch (dst->af) { +- case AF_INET: ++ switch (dst->aid) { ++ case AID_INET: + dmask.ss_len = sizeof(struct sockaddr_in); + dmask.ss_family = AF_INET; + memset(&((struct sockaddr_in *)&dmask)->sin_addr, +@@ -260,7 +251,7 @@ pfkey_send(int sd, uint8_t satype, uint8 + htons(0xffff); + } + break; +- case AF_INET6: ++ case AID_INET6: + dmask.ss_len = sizeof(struct sockaddr_in6); + dmask.ss_family = AF_INET6; + memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr, diff --git a/net/openbgpd/files/patch-bgpd_pfkey_compat.c b/net/openbgpd/files/patch-bgpd_pfkey_compat.c deleted file mode 100644 index 21895c57fd4a..000000000000 --- a/net/openbgpd/files/patch-bgpd_pfkey_compat.c +++ /dev/null @@ -1,30 +0,0 @@ ---- /dev/null 1 Jan 1970 00:00:00 -0000 -+++ bgpd/pfkey_compat.c 8 Feb 2007 10:31:16 -0000 -@@ -0,0 +1,27 @@ -+#include "bgpd.h" -+#include "session.h" -+ -+int -+pfkey_establish(struct peer *p) -+{ -+ if (p->conf.auth.method) -+ return (-1); -+ return (0); -+} -+ -+int -+pfkey_remove(struct peer *p) -+{ -+ if (p->conf.auth.method) -+ return (-1); -+ return (0); -+} -+ -+int -+pfkey_init(struct bgpd_sysdep *sysdep) -+{ -+ log_warnx("no kernel support for PF_KEY"); -+ sysdep->no_pfkey = 1; -+ return (0); -+} -+ diff --git a/net/openbgpd/files/patch-bgpd_pftable.c b/net/openbgpd/files/patch-bgpd_pftable.c new file mode 100644 index 000000000000..a9f2092dd156 --- /dev/null +++ b/net/openbgpd/files/patch-bgpd_pftable.c @@ -0,0 +1,23 @@ +Index: bgpd/pftable.c +=================================================================== +RCS file: /home/cvs/private/hrs/openbgpd/bgpd/pftable.c,v +retrieving revision 1.1.1.5 +retrieving revision 1.1.1.6 +diff -u -p -r1.1.1.5 -r1.1.1.6 +--- bgpd/pftable.c 14 Feb 2010 20:19:57 -0000 1.1.1.5 ++++ bgpd/pftable.c 14 Feb 2010 20:27:06 -0000 1.1.1.6 +@@ -1,4 +1,4 @@ +-/* $OpenBSD: pftable.c,v 1.5 2005/07/01 09:19:24 claudio Exp $ */ ++/* $OpenBSD: pftable.c,v 1.6 2009/12/01 14:28:05 claudio Exp $ */ + + /* + * Copyright (c) 2004 Damien Miller <djm@openbsd.org> +@@ -214,7 +214,7 @@ pftable_add_work(const char *table, stru + + bzero(pfa, sizeof(*pfa)); + memcpy(&pfa->pfra_u, &addr->ba, (len + 7U) / 8); +- pfa->pfra_af = addr->af; ++ pfa->pfra_af = aid2af(addr->aid); + pfa->pfra_net = len; + + pft->naddrs++; diff --git a/net/openbgpd/files/patch-bgpd_printconf.c b/net/openbgpd/files/patch-bgpd_printconf.c index ae33630ad4bf..58cfb9a75c70 100644 --- a/net/openbgpd/files/patch-bgpd_printconf.c +++ b/net/openbgpd/files/patch-bgpd_printconf.c @@ -1,18 +1,18 @@ Index: bgpd/printconf.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/printconf.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.5 -diff -u -p -r1.1.1.1 -r1.5 ---- bgpd/printconf.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/printconf.c 22 Oct 2009 15:10:02 -0000 1.5 +retrieving revision 1.1.1.7 +retrieving revision 1.6 +diff -u -p -r1.1.1.7 -r1.6 +--- bgpd/printconf.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 ++++ bgpd/printconf.c 4 Feb 2010 16:22:23 -0000 1.6 @@ -1,4 +1,4 @@ --/* $OpenBSD: printconf.c,v 1.65 2007/11/22 11:37:25 henning Exp $ */ -+/* $OpenBSD: printconf.c,v 1.70 2009/06/06 01:10:29 claudio Exp $ */ +-/* $OpenBSD: printconf.c,v 1.70 2009/06/06 01:10:29 claudio Exp $ */ ++/* $OpenBSD: printconf.c,v 1.77 2009/12/17 09:32:59 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -19,10 +19,14 @@ +@@ -19,6 +19,9 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -22,40 +22,117 @@ diff -u -p -r1.1.1.1 -r1.5 #include "bgpd.h" #include "mrt.h" - #include "session.h" -+#include "rde.h" +@@ -27,6 +30,8 @@ void print_op(enum comp_ops); void print_community(int, int); -@@ -185,6 +189,8 @@ print_mainconf(struct bgpd_config *conf) - printf("holdtime %u\n", conf->holdtime); - if (conf->min_holdtime) - printf("holdtime min %u\n", conf->min_holdtime); -+ if (conf->connectretry) -+ printf("connect-retry %u\n", conf->connectretry); - - if (conf->flags & BGPD_FLAG_NO_FIB_UPDATE) - printf("fib-update no\n"); -@@ -200,9 +206,6 @@ print_mainconf(struct bgpd_config *conf) - if (conf->flags & BGPD_FLAG_DECISION_MED_ALWAYS) - printf("rde med compare always\n"); ++void print_extcommunity(struct filter_extcommunity *); ++void print_origin(u_int8_t); + void print_set(struct filter_set_head *); + void print_mainconf(struct bgpd_config *); + void print_network(struct network_config *); +@@ -34,7 +39,7 @@ void print_peer(struct peer_config *, + const char *); + const char *print_auth_alg(u_int8_t); + const char *print_enc_alg(u_int8_t); +-const char *print_safi(u_int8_t); ++void print_announce(struct peer_config *, const char *); + void print_rule(struct peer *, struct filter_rule *); + const char * mrt_type(enum mrt_type); + void print_mrt(u_int32_t, u_int32_t, const char *, const char *); +@@ -94,6 +99,45 @@ print_community(int as, int type) + } -- if (conf->flags & BGPD_FLAG_DECISION_TRANS_AS) -- printf("transparent-as yes\n"); -- - if (conf->log & BGPD_LOG_UPDATES) - printf("log updates\n"); + void ++print_extcommunity(struct filter_extcommunity *c) ++{ ++ switch (c->type & EXT_COMMUNITY_VALUE) { ++ case EXT_COMMUNITY_TWO_AS: ++ printf("%s %i:%i", log_ext_subtype(c->subtype), ++ c->data.ext_as.as, c->data.ext_as.val); ++ break; ++ case EXT_COMMUNITY_IPV4: ++ printf("%s %s:%i", log_ext_subtype(c->subtype), ++ inet_ntoa(c->data.ext_ip.addr), c->data.ext_ip.val); ++ break; ++ case EXT_COMMUNITY_FOUR_AS: ++ printf("%s %s:%i", log_ext_subtype(c->subtype), ++ log_as(c->data.ext_as4.as4), c->data.ext_as.val); ++ break; ++ case EXT_COMMUNITY_OPAQUE: ++ printf("%s 0x%llx", log_ext_subtype(c->subtype), ++ c->data.ext_opaq); ++ break; ++ default: ++ printf("0x%x 0x%llx", c->type, c->data.ext_opaq); ++ break; ++ } ++} ++ ++void ++print_origin(u_int8_t o) ++{ ++ if (o == ORIGIN_IGP) ++ printf("igp "); ++ else if (o == ORIGIN_EGP) ++ printf("egp "); ++ else if (o == ORIGIN_INCOMPLETE) ++ printf("incomplete "); ++ else ++ printf("%u ", o); ++} ++ ++void + print_set(struct filter_set_head *set) + { + struct filter_set *s; +@@ -161,11 +205,25 @@ print_set(struct filter_set_head *set) + case ACTION_RTLABEL: + printf("rtlabel %s ", s->action.rtlabel); + break; ++ case ACTION_SET_ORIGIN: ++ printf("origin "); ++ print_origin(s->action.origin); ++ break; + case ACTION_RTLABEL_ID: + case ACTION_PFTABLE_ID: + /* not possible */ + printf("king bula saiz: config broken"); + break; ++ case ACTION_SET_EXT_COMMUNITY: ++ printf("ext-community "); ++ print_extcommunity(&s->action.ext_community); ++ printf(" "); ++ break; ++ case ACTION_DEL_EXT_COMMUNITY: ++ printf("ext-community delete "); ++ print_extcommunity(&s->action.ext_community); ++ printf(" "); ++ break; + } + } + printf("}"); +@@ -263,8 +321,8 @@ print_peer(struct peer_config *p, struct + char *method; + struct in_addr ina; -@@ -271,6 +274,8 @@ print_peer(struct peer_config *p, struct - printf("%sneighbor %s {\n", c, log_addr(&p->remote_addr)); - if (p->descr[0]) - printf("%s\tdescr \"%s\"\n", c, p->descr); -+ if (p->rib[0]) -+ printf("%s\trib \"%s\"\n", c, p->rib); - if (p->remote_as) - printf("%s\tremote-as %s\n", c, log_as(p->remote_as)); - if (p->down) -@@ -293,6 +298,12 @@ print_peer(struct peer_config *p, struct +- if ((p->remote_addr.af == AF_INET && p->remote_masklen != 32) || +- (p->remote_addr.af == AF_INET6 && p->remote_masklen != 128)) ++ if ((p->remote_addr.aid == AID_INET && p->remote_masklen != 32) || ++ (p->remote_addr.aid == AID_INET6 && p->remote_masklen != 128)) + printf("%sneighbor %s/%u {\n", c, log_addr(&p->remote_addr), + p->remote_masklen); + else +@@ -281,7 +339,7 @@ print_peer(struct peer_config *p, struct + printf("%s\tmultihop %u\n", c, p->distance); + if (p->passive) + printf("%s\tpassive\n", c); +- if (p->local_addr.af) ++ if (p->local_addr.aid) + printf("%s\tlocal-address %s\n", c, log_addr(&p->local_addr)); + if (p->max_prefix) { + printf("%s\tmax-prefix %u", c, p->max_prefix); +@@ -295,6 +353,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); @@ -68,12 +145,10 @@ diff -u -p -r1.1.1.1 -r1.5 if (p->announce_type == ANNOUNCE_SELF) printf("%s\tannounce self\n", c); else if (p->announce_type == ANNOUNCE_NONE) -@@ -320,6 +331,12 @@ print_peer(struct peer_config *p, struct - printf("%s\tdemote %s\n", c, p->demote_group); - if (p->if_depend[0]) +@@ -324,6 +388,10 @@ print_peer(struct peer_config *p, struct printf("%s\tdepend on \"%s\"\n", c, p->if_depend); -+ if (p->flags & PEERFLAG_TRANS_AS) -+ printf("%s\ttransparent-as yes\n", c); + if (p->flags & PEERFLAG_TRANS_AS) + printf("%s\ttransparent-as yes\n", c); +#if defined(IPV6_LINKLOCAL_PEER) + if (p->lliface[0]) + printf("%s\tinterface %s\n", c, p->lliface); @@ -81,64 +156,57 @@ diff -u -p -r1.1.1.1 -r1.5 if (p->auth.method == AUTH_MD5SIG) printf("%s\ttcp md5sig\n", c); -@@ -419,10 +436,12 @@ print_rule(struct peer *peer_l, struct f - printf("deny "); - else - printf("match "); -- - if (r->quick) - printf("quick "); +@@ -354,8 +422,7 @@ print_peer(struct peer_config *p, struct + if (p->ttlsec) + printf("%s\tttl-security yes\n", c); -+ if (r->rib[0]) -+ printf("rib %s ", r->rib); +- printf("%s\tannounce IPv4 %s\n", c, print_safi(p->capabilities.mp_v4)); +- printf("%s\tannounce IPv6 %s\n", c, print_safi(p->capabilities.mp_v6)); ++ print_announce(p, c); + + if (p->softreconfig_in == 1) + printf("%s\tsoftreconfig in yes\n", c); +@@ -399,17 +466,14 @@ print_enc_alg(u_int8_t alg) + } + } + +-const char * +-print_safi(u_int8_t safi) ++void ++print_announce(struct peer_config *p, const char *c) + { +- switch (safi) { +- case SAFI_NONE: +- return ("none"); +- case SAFI_UNICAST: +- return ("unicast"); +- default: +- return ("?"); +- } ++ u_int8_t aid; + - if (r->dir == DIR_IN) - printf("from "); - else if (r->dir == DIR_OUT) -@@ -532,12 +551,14 @@ print_mrt(u_int32_t pid, u_int32_t gid, - LIST_FOREACH(m, xmrt_l, entry) - if ((gid != 0 && m->group_id == gid) || - (m->peer_id == pid && m->group_id == gid)) { -+ printf("%s%sdump ", prep, prep2); -+ if (m->rib[0]) -+ printf("rib %s ", m->rib); - if (MRT2MC(m)->ReopenTimerInterval == 0) -- printf("%s%sdump %s %s\n", prep, prep2, -- mrt_type(m->type), MRT2MC(m)->name); -+ printf("%s %s\n", mrt_type(m->type), -+ MRT2MC(m)->name); - else -- printf("%s%sdump %s %s %d\n", prep, prep2, -- mrt_type(m->type), -+ printf("%s %s %d\n", mrt_type(m->type), - MRT2MC(m)->name, - MRT2MC(m)->ReopenTimerInterval); - } -@@ -602,16 +623,25 @@ peer_compare(const void *aa, const void ++ for (aid = 0; aid < AID_MAX; aid++) ++ if (p->capabilities.mp[aid]) ++ printf("%s\tannounce %s\n", c, aid2str(aid)); } void --print_config(struct bgpd_config *conf, struct network_head *net_l, -- struct peer *peer_l, struct filter_head *rules_l, struct mrt_head *mrt_l) -+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_rule *r; - struct network *n; -+ struct rde_rib *rr; +@@ -455,14 +519,14 @@ print_rule(struct peer *peer_l, struct f + } else + printf("any "); + +- if (r->match.prefix.addr.af) ++ if (r->match.prefix.addr.aid) + printf("prefix %s/%u ", log_addr(&r->match.prefix.addr), + r->match.prefix.len); + +- if (r->match.prefix.addr.af == 0 && r->match.prefixlen.af) { +- if (r->match.prefixlen.af == AF_INET) ++ if (r->match.prefix.addr.aid == 0 && r->match.prefixlen.aid) { ++ if (r->match.prefixlen.aid == AID_INET) + printf("inet "); +- if (r->match.prefixlen.af == AF_INET6) ++ if (r->match.prefixlen.aid == AID_INET6) + printf("inet6 "); + } - xmrt_l = mrt_l; - printf("\n"); - print_mainconf(conf); - printf("\n"); -+ SIMPLEQ_FOREACH(rr, rib_l, entry) { -+ if (rr->flags & F_RIB_NOEVALUATE) -+ printf("rde rib %s no evaluate\n", rr->name); -+ else -+ printf("rde rib %s\n", rr->name); -+ } -+ printf("\n"); - TAILQ_FOREACH(n, net_l, entry) - print_network(&n->net); - printf("\n"); diff --git a/net/openbgpd/files/patch-bgpd_rde.c b/net/openbgpd/files/patch-bgpd_rde.c index f31d1d4c5ec2..7a2e01710e95 100644 --- a/net/openbgpd/files/patch-bgpd_rde.c +++ b/net/openbgpd/files/patch-bgpd_rde.c @@ -1,411 +1,335 @@ Index: bgpd/rde.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.6 -diff -u -p -r1.1.1.1 -r1.6 ---- bgpd/rde.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/rde.c 22 Oct 2009 15:10:02 -0000 1.6 +retrieving revision 1.1.1.8 +retrieving revision 1.8 +diff -u -p -r1.1.1.8 -r1.8 +--- bgpd/rde.c 14 Feb 2010 20:19:57 -0000 1.1.1.8 ++++ bgpd/rde.c 14 Feb 2010 19:53:36 -0000 1.8 @@ -1,4 +1,4 @@ --/* $OpenBSD: rde.c,v 1.232.2.1 2009/01/30 22:37:34 claudio Exp $ */ -+/* $OpenBSD: rde.c,v 1.265 2009/08/06 08:53:11 claudio Exp $ */ +-/* $OpenBSD: rde.c,v 1.264 2009/06/29 12:22:16 claudio Exp $ */ ++/* $OpenBSD: rde.c,v 1.284 2010/01/13 06:02:37 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -38,24 +38,28 @@ - #define PFD_PIPE_MAIN 0 - #define PFD_PIPE_SESSION 1 - #define PFD_PIPE_SESSION_CTL 2 --#define PFD_MRT_FILE 3 -+#define PFD_PIPE_COUNT 3 - - void rde_sighdlr(int); - void rde_dispatch_imsg_session(struct imsgbuf *); - void rde_dispatch_imsg_parent(struct imsgbuf *); - int rde_update_dispatch(struct imsg *); -+void rde_update_update(struct rde_peer *, struct rde_aspath *, -+ struct bgpd_addr *, u_int8_t); -+void rde_update_withdraw(struct rde_peer *, struct bgpd_addr *, -+ u_int8_t); +@@ -51,12 +51,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); - int rde_get_mp_nexthop(u_char *, u_int16_t, u_int16_t, +-int rde_get_mp_nexthop(u_char *, u_int16_t, u_int16_t, - struct rde_aspath *); ++int rde_get_mp_nexthop(u_char *, u_int16_t, u_int8_t, + struct rde_aspath *, struct rde_peer *); ++int rde_update_extract_prefix(u_char *, u_int16_t, void *, ++ u_int8_t, u_int8_t); int rde_update_get_prefix(u_char *, u_int16_t, struct bgpd_addr *, u_int8_t *); int rde_update_get_prefix6(u_char *, u_int16_t, struct bgpd_addr *, u_int8_t *); ++int rde_update_get_vpn4(u_char *, u_int16_t, struct bgpd_addr *, ++ u_int8_t *); void rde_update_err(struct rde_peer *, u_int8_t , u_int8_t, void *, u_int16_t); --void rde_update_log(const char *, -+void rde_update_log(const char *, u_int16_t, - const struct rde_peer *, const struct bgpd_addr *, - const struct bgpd_addr *, u_int8_t); - void rde_as4byte_fixup(struct rde_peer *, struct rde_aspath *); -@@ -67,19 +71,17 @@ void rde_dump_filter(struct prefix *, - struct ctl_show_rib_request *); - void rde_dump_filterout(struct rde_peer *, struct prefix *, - struct ctl_show_rib_request *); --void rde_dump_upcall(struct pt_entry *, void *); --void rde_dump_as(struct ctl_show_rib_request *); --void rde_dump_prefix_upcall(struct pt_entry *, void *); --void rde_dump_prefix(struct ctl_show_rib_request *); --void rde_dump_community(struct ctl_show_rib_request *); -+void rde_dump_upcall(struct rib_entry *, void *); -+void rde_dump_prefix_upcall(struct rib_entry *, void *); - void rde_dump_ctx_new(struct ctl_show_rib_request *, pid_t, - enum imsg_type); --void rde_dump_runner(void); --int rde_dump_pending(void); -+void rde_dump_mrt_new(struct mrt *, pid_t, int); -+void rde_dump_done(void *); - --void rde_up_dump_upcall(struct pt_entry *, void *); --void rde_softreconfig_out(struct pt_entry *, void *); --void rde_softreconfig_in(struct pt_entry *, void *); -+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_update_log(const char *, u_int16_t, +@@ -81,8 +85,9 @@ void rde_dump_done(void *); + 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_update_queue_runner(void); - void rde_update6_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 + struct rde_peer *peer_get(u_int32_t); + void peer_up(u_int32_t, struct session_up *); + void peer_down(u_int32_t); +-void peer_dump(u_int32_t, u_int16_t, u_int8_t); +-void peer_send_eor(struct rde_peer *, u_int16_t, u_int16_t); ++void peer_dump(u_int32_t, u_int8_t); ++void peer_send_eor(struct rde_peer *, u_int8_t); -@@ -96,8 +98,7 @@ void peer_send_eor(struct rde_peer *, void network_init(struct network_head *); void network_add(struct network_config *, int); - void network_delete(struct network_config *, int); --void network_dump_upcall(struct pt_entry *, void *); --void network_flush(int); -+void network_dump_upcall(struct rib_entry *, void *); - - void rde_shutdown(void); - int sa_cmp(struct bgpd_addr *, struct sockaddr *); -@@ -106,23 +107,26 @@ volatile sig_atomic_t rde_quit = 0; - struct bgpd_config *conf, *nconf; - time_t reloadtime; - struct rde_peer_head peerlist; --struct rde_peer peerself; --struct rde_peer peerdynamic; -+struct rde_peer *peerself; - struct filter_head *rules_l, *newrules; - struct imsgbuf *ibuf_se; - struct imsgbuf *ibuf_se_ctl; - struct imsgbuf *ibuf_main; --struct mrt *mrt; - struct rde_memstats rdemem; - - struct rde_dump_ctx { -- TAILQ_ENTRY(rde_dump_ctx) entry; -- struct pt_context ptc; -+ struct rib_context ribctx; - struct ctl_show_rib_request req; - sa_family_t af; +@@ -120,11 +125,12 @@ struct rde_dump_ctx { }; --TAILQ_HEAD(, rde_dump_ctx) rde_dump_h = TAILQ_HEAD_INITIALIZER(rde_dump_h); -+struct rde_mrt_ctx { -+ struct mrt mrt; -+ struct rib_context ribctx; -+}; -+ -+struct mrt_head rde_mrts = LIST_HEAD_INITIALIZER(rde_mrts); -+u_int rde_mrt_cnt; + struct rde_mrt_ctx { +- struct mrt mrt; +- struct rib_context ribctx; ++ struct mrt mrt; ++ struct rib_context ribctx; ++ LIST_ENTRY(rde_mrt_ctx) entry; + }; + +-struct mrt_head rde_mrts = LIST_HEAD_INITIALIZER(rde_mrts); ++LIST_HEAD(, rde_mrt_ctx) rde_mrts = LIST_HEAD_INITIALIZER(rde_mrts); + u_int rde_mrt_cnt; void - rde_sighdlr(int sig) -@@ -143,18 +147,22 @@ u_int32_t nexthophashsize = 64; +@@ -144,24 +150,17 @@ u_int32_t attrhashsize = 512; + u_int32_t nexthophashsize = 64; + pid_t - rde_main(struct bgpd_config *config, struct peer *peer_l, - struct network_head *net_l, struct filter_head *rules, -- struct mrt_head *mrt_l, int pipe_m2r[2], int pipe_s2r[2], int pipe_m2s[2], -- int pipe_s2rctl[2], int debug) -+ struct mrt_head *mrt_l, struct rib_names *rib_n, int pipe_m2r[2], -+ int pipe_s2r[2], int pipe_m2s[2], int pipe_s2rctl[2], int debug) +-rde_main(struct bgpd_config *config, struct peer *peer_l, +- struct network_head *net_l, struct filter_head *rules, +- struct mrt_head *mrt_l, struct rib_names *rib_n, int pipe_m2r[2], +- int pipe_s2r[2], int pipe_m2s[2], int pipe_s2rctl[2], int debug) ++rde_main(int pipe_m2r[2], int pipe_s2r[2], int pipe_m2s[2], int pipe_s2rctl[2], ++ int debug) { pid_t pid; struct passwd *pw; - struct peer *p; - struct listen_addr *la; -- struct pollfd pfd[4]; -+ struct pollfd *pfd = NULL; - struct filter_rule *f; - struct filter_set *set; - struct nexthop *nh; -- int i, timeout; -+ struct rde_rib *rr; -+ struct mrt *mrt, *xmrt; -+ void *newp; -+ u_int pfd_elms = 0, i, j; -+ int timeout; +- struct peer *p; +- struct listen_addr *la; + struct pollfd *pfd = NULL; +- struct filter_rule *f; +- struct filter_set *set; +- struct nexthop *nh; +- struct rde_rib *rr; +- struct mrt *mrt, *xmrt; ++ struct rde_mrt_ctx *mctx, *xmctx; + void *newp; + u_int pfd_elms = 0, i, j; + int timeout; ++ u_int8_t aid; switch (pid = fork()) { case -1: -@@ -213,7 +221,6 @@ rde_main(struct bgpd_config *config, str - LIST_REMOVE(mrt, entry); - free(mrt); +@@ -172,8 +171,6 @@ rde_main(struct bgpd_config *config, str + return (pid); } -- mrt = NULL; - - while ((la = TAILQ_FIRST(config->listen_addrs)) != NULL) { - TAILQ_REMOVE(config->listen_addrs, la, entry); -@@ -223,6 +230,11 @@ rde_main(struct bgpd_config *config, str - free(config->listen_addrs); +- conf = config; +- + if ((pw = getpwnam(BGPD_USER)) == NULL) + fatal("getpwnam"); + +@@ -194,6 +191,8 @@ rde_main(struct bgpd_config *config, str + signal(SIGINT, rde_sighdlr); + signal(SIGPIPE, SIG_IGN); + signal(SIGHUP, SIG_IGN); ++ signal(SIGALRM, SIG_IGN); ++ signal(SIGUSR1, SIG_IGN); + + close(pipe_s2r[0]); + close(pipe_s2rctl[0]); +@@ -210,50 +209,21 @@ rde_main(struct bgpd_config *config, str + imsg_init(ibuf_se_ctl, pipe_s2rctl[1]); + imsg_init(ibuf_main, pipe_m2r[1]); + +- /* peer list, mrt list and listener list are not used in the RDE */ +- while ((p = peer_l) != NULL) { +- peer_l = p->next; +- free(p); +- } +- +- while ((mrt = LIST_FIRST(mrt_l)) != NULL) { +- LIST_REMOVE(mrt, entry); +- free(mrt); +- } +- +- while ((la = TAILQ_FIRST(config->listen_addrs)) != NULL) { +- TAILQ_REMOVE(config->listen_addrs, la, entry); +- close(la->fd); +- free(la); +- } +- free(config->listen_addrs); +- pt_init(); -+ while ((rr = SIMPLEQ_FIRST(&ribnames))) { -+ SIMPLEQ_REMOVE_HEAD(&ribnames, entry); -+ rib_new(-1, rr->name, rr->flags); -+ free(rr); -+ } +- while ((rr = SIMPLEQ_FIRST(&ribnames))) { +- SIMPLEQ_REMOVE_HEAD(&ribnames, entry); +- rib_new(-1, rr->name, rr->flags); +- free(rr); +- } path_init(pathhashsize); aspath_init(pathhashsize); attr_init(attrhashsize); -@@ -234,6 +246,7 @@ rde_main(struct bgpd_config *config, str + nexthop_init(nexthophashsize); + peer_init(peerhashsize); +- rules_l = rules; +- network_init(net_l); + ++ rules_l = calloc(1, sizeof(struct filter_head)); ++ if (rules_l == NULL) ++ fatal(NULL); ++ TAILQ_INIT(rules_l); ++ if ((conf = malloc(sizeof(struct bgpd_config))) == NULL) ++ fatal(NULL); log_info("route decision engine ready"); - TAILQ_FOREACH(f, rules, entry) { -+ f->peer.ribid = rib_find(f->rib); - TAILQ_FOREACH(set, &f->set, entry) { - if (set->type == ACTION_SET_NEXTHOP) { - nh = nexthop_get(&set->action.nexthop); -@@ -243,8 +256,20 @@ rde_main(struct bgpd_config *config, str - } - +- TAILQ_FOREACH(f, rules, entry) { +- f->peer.ribid = rib_find(f->rib); +- TAILQ_FOREACH(set, &f->set, entry) { +- if (set->type == ACTION_SET_NEXTHOP) { +- nh = nexthop_get(&set->action.nexthop); +- nh->refcnt++; +- } +- } +- } +- while (rde_quit == 0) { -+ if (pfd_elms < PFD_PIPE_COUNT + rde_mrt_cnt) { -+ if ((newp = realloc(pfd, sizeof(struct pollfd) * -+ (PFD_PIPE_COUNT + rde_mrt_cnt))) == NULL) { -+ /* panic for now */ -+ log_warn("could not resize pfd from %u -> %u" -+ " entries", pfd_elms, PFD_PIPE_COUNT + -+ rde_mrt_cnt); -+ fatalx("exiting"); -+ } -+ pfd = newp; -+ pfd_elms = PFD_PIPE_COUNT + rde_mrt_cnt; -+ } - timeout = INFTIM; -- bzero(pfd, sizeof(pfd)); -+ bzero(pfd, sizeof(struct pollfd) * pfd_elms); - pfd[PFD_PIPE_MAIN].fd = ibuf_main->fd; - pfd[PFD_PIPE_MAIN].events = POLLIN; - if (ibuf_main->w.queued > 0) -@@ -259,14 +284,16 @@ rde_main(struct bgpd_config *config, str - pfd[PFD_PIPE_SESSION_CTL].events = POLLIN; - if (ibuf_se_ctl->w.queued > 0) - pfd[PFD_PIPE_SESSION_CTL].events |= POLLOUT; -- else if (rde_dump_pending()) -+ else if (rib_dump_pending()) + 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 timeout = 0; -- i = 3; -- if (mrt && mrt->queued) { -- pfd[PFD_MRT_FILE].fd = mrt->fd; -- pfd[PFD_MRT_FILE].events = POLLOUT; -- i++; -+ i = PFD_PIPE_COUNT; -+ LIST_FOREACH(mrt, &rde_mrts, entry) { -+ if (mrt->wbuf.queued) { -+ pfd[i].fd = mrt->wbuf.fd; -+ pfd[i].events = POLLOUT; -+ i++; -+ } - } - - if (poll(pfd, i, timeout) == -1) { -@@ -299,24 +326,39 @@ rde_main(struct bgpd_config *config, str + 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) { ++ if (mctx->mrt.wbuf.queued) { ++ pfd[i].fd = mctx->mrt.wbuf.fd; + pfd[i].events = POLLOUT; + i++; + } +@@ -325,24 +295,26 @@ rde_main(struct bgpd_config *config, str if (pfd[PFD_PIPE_SESSION_CTL].revents & POLLIN) rde_dispatch_imsg_session(ibuf_se_ctl); -- if (pfd[PFD_MRT_FILE].revents & POLLOUT) { -- if (mrt_write(mrt) == -1) { -+ for (j = PFD_PIPE_COUNT, mrt = LIST_FIRST(&rde_mrts); -+ j < i && mrt != 0; j++) { -+ xmrt = LIST_NEXT(mrt, entry); -+ if (pfd[j].fd == mrt->wbuf.fd && -+ pfd[j].revents & POLLOUT) -+ mrt_write(mrt); -+ if (mrt->wbuf.queued == 0 && -+ mrt->state == MRT_STATE_REMOVE) { -+ close(mrt->wbuf.fd); -+ LIST_REMOVE(mrt, entry); - free(mrt); -- mrt = NULL; -- } else if (mrt->queued == 0) -- close(mrt->fd); -+ rde_mrt_cnt--; -+ } -+ mrt = xmrt; +- for (j = PFD_PIPE_COUNT, mrt = LIST_FIRST(&rde_mrts); +- j < i && mrt != 0; j++) { +- xmrt = LIST_NEXT(mrt, entry); +- if (pfd[j].fd == mrt->wbuf.fd && ++ for (j = PFD_PIPE_COUNT, mctx = LIST_FIRST(&rde_mrts); ++ j < i && mctx != 0; j++) { ++ xmctx = LIST_NEXT(mctx, entry); ++ if (pfd[j].fd == mctx->mrt.wbuf.fd && + pfd[j].revents & POLLOUT) +- mrt_write(mrt); +- if (mrt->wbuf.queued == 0 && +- mrt->state == MRT_STATE_REMOVE) { +- close(mrt->wbuf.fd); +- LIST_REMOVE(mrt, entry); +- free(mrt); ++ 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--; + } +- mrt = xmrt; ++ mctx = xmctx; } rde_update_queue_runner(); - rde_update6_queue_runner(); +- rde_update6_queue_runner(); ++ for (aid = AID_INET6; aid < AID_MAX; aid++) ++ rde_update6_queue_runner(aid); if (ibuf_se_ctl->w.queued <= 0) -- rde_dump_runner(); -+ rib_dump_runner(); + rib_dump_runner(); } - - /* do not clean up on shutdown on production, it takes ages. */ +@@ -351,11 +323,12 @@ rde_main(struct bgpd_config *config, str if (debug) rde_shutdown(); -+ while ((mrt = LIST_FIRST(&rde_mrts)) != NULL) { -+ msgbuf_clear(&mrt->wbuf); -+ close(mrt->wbuf.fd); -+ LIST_REMOVE(mrt, entry); -+ free(mrt); -+ } -+ +- while ((mrt = LIST_FIRST(&rde_mrts)) != NULL) { +- msgbuf_clear(&mrt->wbuf); +- close(mrt->wbuf.fd); +- LIST_REMOVE(mrt, entry); +- free(mrt); ++ while ((mctx = LIST_FIRST(&rde_mrts)) != NULL) { ++ msgbuf_clear(&mctx->mrt.wbuf); ++ close(mctx->mrt.wbuf.fd); ++ LIST_REMOVE(&mctx->ribctx, entry); ++ LIST_REMOVE(mctx, entry); ++ free(mctx); + } + msgbuf_clear(&ibuf_se->w); - free(ibuf_se); - msgbuf_clear(&ibuf_se_ctl->w); -@@ -344,7 +386,6 @@ rde_dispatch_imsg_session(struct imsgbuf +@@ -378,13 +351,14 @@ rde_dispatch_imsg_session(struct imsgbuf + struct imsg imsg; + struct peer p; + struct peer_config pconf; +- struct rrefresh r; + struct rde_peer *peer; + struct session_up sup; + struct ctl_show_rib_request req; struct filter_set *s; struct nexthop *nh; - int n; -- sa_family_t af = AF_UNSPEC; +- int n; ++ ssize_t n; ++ int verbose; ++ u_int8_t aid; if ((n = imsg_read(ibuf)) == -1) fatal("rde_dispatch_imsg_session: imsg_read error"); -@@ -438,7 +479,8 @@ badnet: +@@ -423,12 +397,14 @@ rde_dispatch_imsg_session(struct imsgbuf + peer_down(imsg.hdr.peerid); + break; + case IMSG_REFRESH: +- if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(r)) { ++ if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(aid)) { log_warnx("rde_dispatch: wrong imsg len"); break; } -- network_flush(0); -+ prefix_network_clean(peerself, time(NULL), -+ F_ANN_DYNAMIC); +- memcpy(&r, imsg.data, sizeof(r)); +- peer_dump(imsg.hdr.peerid, r.afi, r.safi); ++ memcpy(&aid, imsg.data, sizeof(aid)); ++ if (aid >= AID_MAX) ++ fatalx("IMSG_REFRESH: bad AID"); ++ peer_dump(imsg.hdr.peerid, aid); break; - case IMSG_FILTER_SET: + case IMSG_NETWORK_ADD: if (imsg.hdr.len - IMSG_HEADER_SIZE != -@@ -462,54 +504,16 @@ badnet: - } - break; - case IMSG_CTL_SHOW_NETWORK: -- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(af)) { -- log_warnx("rde_dispatch: wrong imsg len"); -- break; -- } -- bzero(&req, sizeof(req)); -- memcpy(&req.af, imsg.data, sizeof(af)); -- rde_dump_ctx_new(&req, imsg.hdr.pid, imsg.hdr.type); -- break; - case IMSG_CTL_SHOW_RIB: -- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(req)) { -- log_warnx("rde_dispatch: wrong imsg len"); -- break; -- } -- memcpy(&req, imsg.data, sizeof(req)); -- rde_dump_ctx_new(&req, imsg.hdr.pid, imsg.hdr.type); -- break; - case IMSG_CTL_SHOW_RIB_AS: -- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(req)) { -- log_warnx("rde_dispatch: wrong imsg len"); -- break; -- } -- memcpy(&req, imsg.data, sizeof(req)); -- req.pid = imsg.hdr.pid; -- rde_dump_as(&req); -- imsg_compose(ibuf_se_ctl, IMSG_CTL_END, 0, req.pid, -1, -- NULL, 0); -- break; -- case IMSG_CTL_SHOW_RIB_PREFIX: -- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(req)) { -- log_warnx("rde_dispatch: wrong imsg len"); -- break; -- } -- memcpy(&req, imsg.data, sizeof(req)); -- req.pid = imsg.hdr.pid; -- rde_dump_prefix(&req); -- imsg_compose(ibuf_se_ctl, IMSG_CTL_END, 0, req.pid, -1, -- NULL, 0); -- break; - case IMSG_CTL_SHOW_RIB_COMMUNITY: -+ case IMSG_CTL_SHOW_RIB_PREFIX: - if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(req)) { - log_warnx("rde_dispatch: wrong imsg len"); +@@ -446,13 +422,13 @@ rde_dispatch_imsg_session(struct imsgbuf break; } - memcpy(&req, imsg.data, sizeof(req)); -- req.pid = imsg.hdr.pid; -- rde_dump_community(&req); -- imsg_compose(ibuf_se_ctl, IMSG_CTL_END, 0, req.pid, -1, -- NULL, 0); -+ rde_dump_ctx_new(&req, imsg.hdr.pid, imsg.hdr.type); - break; - case IMSG_CTL_SHOW_NEIGHBOR: - if (imsg.hdr.len - IMSG_HEADER_SIZE != -@@ -552,12 +556,14 @@ void - rde_dispatch_imsg_parent(struct imsgbuf *ibuf) - { - struct imsg imsg; -+ struct mrt xmrt; -+ struct rde_rib rn; - struct rde_peer *peer; - struct filter_rule *r; - struct filter_set *s; -- struct mrt *xmrt; - struct nexthop *nh; -- int n, reconf_in = 0, reconf_out = 0; -+ int n, fd, reconf_in = 0, reconf_out = 0; -+ u_int16_t rid; - - if ((n = imsg_read(ibuf)) == -1) - fatal("rde_dispatch_imsg_parent: imsg_read error"); -@@ -581,6 +587,8 @@ rde_dispatch_imsg_parent(struct imsgbuf - 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: - memcpy(&netconf_p, imsg.data, sizeof(netconf_p)); -@@ -601,6 +609,17 @@ rde_dispatch_imsg_parent(struct imsgbuf - TAILQ_INIT(&netconf_p.attrset); - network_delete(&netconf_p, 1); + session_set = NULL; +- switch (netconf_s.prefix.af) { +- case AF_INET: ++ switch (netconf_s.prefix.aid) { ++ case AID_INET: + if (netconf_s.prefixlen > 32) + goto badnet; + network_add(&netconf_s, 0); + break; +- case AF_INET6: ++ case AID_INET6: + if (netconf_s.prefixlen > 128) + goto badnet; + network_add(&netconf_s, 0); +@@ -544,6 +520,11 @@ badnet: + imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_RIB_MEM, 0, + imsg.hdr.pid, -1, &rdemem, sizeof(rdemem)); break; -+ case IMSG_RECONF_RIB: -+ if (imsg.hdr.len - IMSG_HEADER_SIZE != -+ sizeof(struct rde_rib)) -+ fatalx("IMSG_RECONF_RIB bad len"); -+ memcpy(&rn, imsg.data, sizeof(rn)); -+ rid = rib_find(rn.name); -+ if (rid == RIB_FAILED) -+ rib_new(-1, rn.name, rn.flags); -+ else -+ ribs[rid].state = RIB_ACTIVE; ++ case IMSG_CTL_LOG_VERBOSE: ++ /* already checked by SE */ ++ memcpy(&verbose, imsg.data, sizeof(verbose)); ++ log_verbose(verbose); + break; - case IMSG_RECONF_FILTER: - if (imsg.hdr.len - IMSG_HEADER_SIZE != - sizeof(struct filter_rule)) -@@ -609,6 +628,7 @@ rde_dispatch_imsg_parent(struct imsgbuf - fatal(NULL); - memcpy(r, imsg.data, sizeof(struct filter_rule)); - TAILQ_INIT(&r->set); -+ r->peer.ribid = rib_find(r->rib); - parent_set = &r->set; - TAILQ_INSERT_TAIL(newrules, r, entry); + default: break; -@@ -628,10 +648,12 @@ rde_dispatch_imsg_parent(struct imsgbuf + } +@@ -644,9 +625,17 @@ rde_dispatch_imsg_parent(struct imsgbuf + nconf->flags &= ~BGPD_FLAG_NO_EVALUATE; + } + memcpy(conf, nconf, sizeof(struct bgpd_config)); ++ conf->listen_addrs = NULL; ++ conf->csock = NULL; ++ conf->rcsock = NULL; free(nconf); nconf = NULL; parent_set = NULL; -- prefix_network_clean(&peerself, reloadtime); -+ 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); /* check if filter changed */ - LIST_FOREACH(peer, &peerlist, peer_l) { -+ if (peer->conf.id == 0) -+ continue; - peer->reconf_out = 0; - peer->reconf_in = 0; - if (peer->conf.softreconfig_out && -@@ -647,12 +669,30 @@ rde_dispatch_imsg_parent(struct imsgbuf +@@ -668,17 +657,29 @@ rde_dispatch_imsg_parent(struct imsgbuf reconf_in = 1; } } +- /* XXX this needs rework anyway */ + /* bring ribs in sync before softreconfig dance */ + for (rid = 0; rid < rib_size; rid++) { + if (ribs[rid].state == RIB_DELETE) @@ -413,82 +337,65 @@ diff -u -p -r1.1.1.1 -r1.6 + else if (ribs[rid].state == RIB_NEW) + rib_dump(&ribs[0], + rde_softreconfig_load, &ribs[rid], -+ AF_UNSPEC); ++ AID_UNSPEC); + } /* sync local-RIB first */ if (reconf_in) -- pt_dump(rde_softreconfig_in, NULL, AF_UNSPEC); -+ rib_dump(&ribs[0], rde_softreconfig_in, NULL, -+ AF_UNSPEC); + rib_dump(&ribs[0], rde_softreconfig_in, NULL, +- AF_UNSPEC); ++ AID_UNSPEC); /* then sync peers */ -- if (reconf_out) -- pt_dump(rde_softreconfig_out, NULL, AF_UNSPEC); -+ if (reconf_out) { -+ int i; + if (reconf_out) { + int i; +- for (i = 1; i < rib_size; i++) + for (i = 1; i < rib_size; i++) { + if (ribs[i].state == RIB_NEW) + /* already synced by _load */ + continue; -+ rib_dump(&ribs[i], rde_softreconfig_out, -+ NULL, AF_UNSPEC); + rib_dump(&ribs[i], rde_softreconfig_out, +- NULL, AF_UNSPEC); ++ NULL, AID_UNSPEC); + } -+ } + } while ((r = TAILQ_FIRST(rules_l)) != NULL) { - TAILQ_REMOVE(rules_l, r, entry); -@@ -689,30 +729,15 @@ rde_dispatch_imsg_parent(struct imsgbuf - log_warnx("wrong imsg len"); - break; +@@ -688,10 +689,6 @@ rde_dispatch_imsg_parent(struct imsgbuf } -- -- xmrt = calloc(1, sizeof(struct mrt)); -- if (xmrt == NULL) -- fatal("rde_dispatch_imsg_parent"); -- memcpy(xmrt, imsg.data, sizeof(struct mrt)); -- TAILQ_INIT(&xmrt->bufs); -- -- if ((xmrt->fd = imsg_get_fd(ibuf)) == -1) -+ memcpy(&xmrt, imsg.data, sizeof(xmrt)); -+ if ((fd = imsg.fd) == -1) - log_warnx("expected to receive fd for mrt dump " - "but didn't receive any"); -- -- if (xmrt->type == MRT_TABLE_DUMP) { -- /* do not dump if another is still running */ -- if (mrt == NULL || mrt->queued == 0) { -- free(mrt); -- mrt = xmrt; -- mrt_clear_seq(); -- pt_dump(mrt_dump_upcall, mrt, -- AF_UNSPEC); -- break; -- } + free(rules_l); + rules_l = newrules; +- for (rid = 0; rid < rib_size; rid++) { +- if (ribs[rid].state == RIB_DELETE) +- rib_free(&ribs[rid]); - } -- close(xmrt->fd); -- free(xmrt); -+ else if (xmrt.type == MRT_TABLE_DUMP || -+ xmrt.type == MRT_TABLE_DUMP_MP) { -+ rde_dump_mrt_new(&xmrt, imsg.hdr.pid, fd); -+ } else -+ close(fd); + log_info("RDE reconfigured"); break; - case IMSG_MRT_CLOSE: - /* ignore end message because a dump is atomic */ -@@ -729,7 +754,7 @@ int + case IMSG_NEXTHOP_UPDATE: +@@ -744,6 +741,8 @@ rde_dispatch_imsg_parent(struct imsgbuf + int rde_update_dispatch(struct imsg *imsg) { ++ struct bgpd_addr prefix; ++ struct mpattr mpa; struct rde_peer *peer; -- struct rde_aspath *asp = NULL, *fasp; -+ struct rde_aspath *asp = NULL; + struct rde_aspath *asp = NULL; u_char *p, *mpp = NULL; - int error = -1, pos = 0; - u_int16_t afi, len, mplen; -@@ -794,20 +819,15 @@ rde_update_dispatch(struct imsg *imsg) +@@ -752,9 +751,7 @@ rde_update_dispatch(struct imsg *imsg) + u_int16_t withdrawn_len; + u_int16_t attrpath_len; + u_int16_t nlri_len; +- u_int8_t prefixlen, safi, subtype; +- struct bgpd_addr prefix; +- struct mpattr mpa; ++ u_int8_t aid, prefixlen, safi, subtype; + + peer = peer_get(imsg->hdr.peerid); + if (peer == NULL) /* unknown peer, cannot happen */ +@@ -810,14 +807,7 @@ rde_update_dispatch(struct imsg *imsg) goto done; } - /* -- * if either ATTR_NEW_AGGREGATOR or ATTR_NEW_ASPATH is present +- * if either ATTR_AS4_AGGREGATOR or ATTR_AS4_PATH is present - * try to fixup the attributes. - * XXX do not fixup if F_ATTR_LOOP is set. - */ @@ -499,176 +406,222 @@ diff -u -p -r1.1.1.1 -r1.6 /* enforce remote AS if requested */ if (asp->flags & F_ATTR_ASPATH && - peer->conf.enforce_as == ENFORCE_AS_ON) - if (peer->conf.remote_as != - aspath_neighbor(asp->aspath)) { -+ log_peer_warnx(&peer->conf, "bad path, " -+ "enforce remote-as enabled"); - rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH, - NULL, 0); - goto done; -@@ -850,14 +870,19 @@ rde_update_dispatch(struct imsg *imsg) +@@ -860,9 +850,9 @@ rde_update_dispatch(struct imsg *imsg) + p += pos; + len -= pos; + +- if (peer->capa_received.mp_v4 == SAFI_NONE && +- peer->capa_received.mp_v6 != SAFI_NONE) { +- log_peer_warnx(&peer->conf, "bad AFI, IPv4 disabled"); ++ if (peer->capa.mp[AID_INET] == 0) { ++ log_peer_warnx(&peer->conf, ++ "bad withdraw, %s disabled", aid2str(AID_INET)); + rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, + NULL, 0); goto done; - } - -- peer->prefix_rcvd_withdraw++; -- rde_update_log("withdraw", peer, NULL, &prefix, prefixlen); -- prefix_remove(peer, &prefix, prefixlen, F_LOCAL); -- prefix_remove(peer, &prefix, prefixlen, F_ORIGINAL); -+ rde_update_withdraw(peer, &prefix, prefixlen); - } - -- if (attrpath_len == 0) /* 0 = no NLRI information in this message */ -+ if (attrpath_len == 0) { -+ /* 0 = no NLRI information in this message */ -+ if (nlri_len != 0) { -+ /* crap at end of update which should not be there */ -+ rde_update_err(peer, ERR_UPDATE, -+ ERR_UPD_ATTRLIST, NULL, 0); -+ return (-1); +@@ -892,15 +882,25 @@ rde_update_dispatch(struct imsg *imsg) + afi = ntohs(afi); + safi = *mpp++; + mplen--; +- switch (afi) { +- case AFI_IPv6: +- if (peer->capa_received.mp_v6 == SAFI_NONE) { +- log_peer_warnx(&peer->conf, "bad AFI, " +- "IPv6 disabled"); +- rde_update_err(peer, ERR_UPDATE, +- ERR_UPD_OPTATTR, NULL, 0); +- goto done; +- } ++ ++ if (afi2aid(afi, safi, &aid) == -1) { ++ log_peer_warnx(&peer->conf, ++ "bad AFI/SAFI pair in withdraw"); ++ rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, ++ NULL, 0); ++ goto done; + } - return (0); -+ } - - /* withdraw MP_UNREACH_NLRI if available */ - if (mpa.unreach_len != 0) { -@@ -900,13 +925,7 @@ rde_update_dispatch(struct imsg *imsg) - mpp += pos; - mplen -= pos; - -- peer->prefix_rcvd_withdraw++; -- rde_update_log("withdraw", peer, NULL, -- &prefix, prefixlen); -- prefix_remove(peer, &prefix, prefixlen, -- F_LOCAL); -- prefix_remove(peer, &prefix, prefixlen, -- F_ORIGINAL); -+ rde_update_withdraw(peer, &prefix, prefixlen); ++ ++ if (peer->capa.mp[aid] == 0) { ++ log_peer_warnx(&peer->conf, ++ "bad withdraw, %s disabled", aid2str(aid)); ++ rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, ++ NULL, 0); ++ goto done; ++ } ++ ++ switch (aid) { ++ case AID_INET6: + while (mplen > 0) { + if ((pos = rde_update_get_prefix6(mpp, mplen, + &prefix, &prefixlen)) == -1) { +@@ -926,6 +926,32 @@ rde_update_dispatch(struct imsg *imsg) + rde_update_withdraw(peer, &prefix, prefixlen); } break; ++ case AID_VPN_IPv4: ++ while (mplen > 0) { ++ if ((pos = rde_update_get_vpn4(mpp, mplen, ++ &prefix, &prefixlen)) == -1) { ++ log_peer_warnx(&peer->conf, ++ "bad VPNv4 withdraw prefix"); ++ rde_update_err(peer, ERR_UPDATE, ++ ERR_UPD_OPTATTR, ++ mpa.unreach, mpa.unreach_len); ++ goto done; ++ } ++ if (prefixlen > 32) { ++ log_peer_warnx(&peer->conf, ++ "bad VPNv4 withdraw prefix"); ++ rde_update_err(peer, ERR_UPDATE, ++ ERR_UPD_OPTATTR, ++ mpa.unreach, mpa.unreach_len); ++ goto done; ++ } ++ ++ mpp += pos; ++ mplen -= pos; ++ ++ rde_update_withdraw(peer, &prefix, prefixlen); ++ } ++ break; default: -@@ -954,17 +973,7 @@ rde_update_dispatch(struct imsg *imsg) - goto done; - } - -- peer->prefix_rcvd_update++; -- /* add original path to the Adj-RIB-In */ -- if (peer->conf.softreconfig_in) -- path_update(peer, asp, &prefix, prefixlen, F_ORIGINAL); -- -- /* input filter */ -- if (rde_filter(&fasp, rules_l, peer, asp, &prefix, prefixlen, -- peer, DIR_IN) == ACTION_DENY) { -- path_put(fasp); -- continue; -- } -+ rde_update_update(peer, asp, &prefix, prefixlen); - - /* max prefix checker */ - if (peer->conf.max_prefix && -@@ -972,20 +981,9 @@ rde_update_dispatch(struct imsg *imsg) - log_peer_warnx(&peer->conf, "prefix limit reached"); - rde_update_err(peer, ERR_CEASE, ERR_CEASE_MAX_PREFIX, + /* silently ignore unsupported multiprotocol AF */ + break; +@@ -963,9 +989,9 @@ rde_update_dispatch(struct imsg *imsg) + p += pos; + nlri_len -= pos; + +- if (peer->capa_received.mp_v4 == SAFI_NONE && +- peer->capa_received.mp_v6 != SAFI_NONE) { +- log_peer_warnx(&peer->conf, "bad AFI, IPv4 disabled"); ++ if (peer->capa.mp[AID_INET] == 0) { ++ log_peer_warnx(&peer->conf, ++ "bad update, %s disabled", aid2str(AID_INET)); + rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, NULL, 0); -- path_put(fasp); goto done; - } - -- if (fasp == NULL) -- fasp = asp; -- -- rde_update_log("update", peer, &fasp->nexthop->exit_nexthop, -- &prefix, prefixlen); -- path_update(peer, fasp, &prefix, prefixlen, F_LOCAL); -- -- /* free modified aspath */ -- if (fasp != asp) -- path_put(fasp); - } - - /* add MP_REACH_NLRI if available */ -@@ -1008,7 +1006,7 @@ rde_update_dispatch(struct imsg *imsg) +@@ -995,6 +1021,22 @@ rde_update_dispatch(struct imsg *imsg) + safi = *mpp++; + mplen--; + ++ if (afi2aid(afi, safi, &aid) == -1) { ++ log_peer_warnx(&peer->conf, ++ "bad AFI/SAFI pair in update"); ++ rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, ++ NULL, 0); ++ goto done; ++ } ++ ++ if (peer->capa.mp[aid] == 0) { ++ log_peer_warnx(&peer->conf, ++ "bad update, %s disabled", aid2str(aid)); ++ rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, ++ NULL, 0); ++ goto done; ++ } ++ + /* + * this works because asp is not linked. + * But first unlock the previously locked nexthop. +@@ -1004,8 +1046,8 @@ rde_update_dispatch(struct imsg *imsg) (void)nexthop_delete(asp->nexthop); asp->nexthop = NULL; } - if ((pos = rde_get_mp_nexthop(mpp, mplen, afi, asp)) == -1) { -+ if ((pos = rde_get_mp_nexthop(mpp, mplen, afi, asp, peer)) == -1) { - log_peer_warnx(&peer->conf, "bad IPv6 nlri prefix"); +- log_peer_warnx(&peer->conf, "bad IPv6 nlri prefix"); ++ if ((pos = rde_get_mp_nexthop(mpp, mplen, aid, asp, peer)) == -1) { ++ log_peer_warnx(&peer->conf, "bad nlri prefix"); rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR, mpa.reach, mpa.reach_len); -@@ -1047,19 +1045,8 @@ rde_update_dispatch(struct imsg *imsg) - mpp += pos; - mplen -= pos; - -- peer->prefix_rcvd_update++; -- /* add original path to the Adj-RIB-In */ -- if (peer->conf.softreconfig_in) -- path_update(peer, asp, &prefix, -- prefixlen, F_ORIGINAL); + goto done; +@@ -1013,16 +1055,8 @@ rde_update_dispatch(struct imsg *imsg) + mpp += pos; + mplen -= pos; + +- switch (afi) { +- case AFI_IPv6: +- if (peer->capa_received.mp_v6 == SAFI_NONE) { +- log_peer_warnx(&peer->conf, "bad AFI, " +- "IPv6 disabled"); +- rde_update_err(peer, ERR_UPDATE, +- ERR_UPD_OPTATTR, NULL, 0); +- goto done; +- } - -- /* input filter */ -- if (rde_filter(&fasp, rules_l, peer, asp, -- &prefix, prefixlen, peer, DIR_IN) == -- ACTION_DENY) { -- path_put(fasp); -- continue; -- } -+ rde_update_update(peer, asp, &prefix, -+ prefixlen); - - /* max prefix checker */ - if (peer->conf.max_prefix && -@@ -1068,22 +1055,9 @@ rde_update_dispatch(struct imsg *imsg) - "prefix limit reached"); - rde_update_err(peer, ERR_CEASE, - ERR_CEASE_MAX_PREFIX, NULL, 0); -- path_put(fasp); - goto done; - } ++ switch (aid) { ++ case AID_INET6: + while (mplen > 0) { + if ((pos = rde_update_get_prefix6(mpp, mplen, + &prefix, &prefixlen)) == -1) { +@@ -1058,6 +1092,42 @@ rde_update_dispatch(struct imsg *imsg) -- if (fasp == NULL) -- fasp = asp; -- -- rde_update_log("update", peer, -- &asp->nexthop->exit_nexthop, -- &prefix, prefixlen); -- path_update(peer, fasp, &prefix, prefixlen, -- F_LOCAL); -- -- /* free modified aspath */ -- if (fasp != asp) -- path_put(fasp); } break; - default: -@@ -1106,6 +1080,76 @@ done: - return (error); - } - -+extern u_int16_t rib_size; ++ case AID_VPN_IPv4: ++ while (mplen > 0) { ++ if ((pos = rde_update_get_vpn4(mpp, mplen, ++ &prefix, &prefixlen)) == -1) { ++ log_peer_warnx(&peer->conf, ++ "bad VPNv4 nlri prefix"); ++ rde_update_err(peer, ERR_UPDATE, ++ ERR_UPD_OPTATTR, ++ mpa.reach, mpa.reach_len); ++ goto done; ++ } ++ if (prefixlen > 32) { ++ rde_update_err(peer, ERR_UPDATE, ++ ERR_UPD_OPTATTR, ++ mpa.reach, mpa.reach_len); ++ goto done; ++ } + -+void -+rde_update_update(struct rde_peer *peer, struct rde_aspath *asp, -+ struct bgpd_addr *prefix, u_int8_t prefixlen) -+{ -+ struct rde_aspath *fasp; -+ enum filter_actions action; -+ int r = 0, f = 0; -+ u_int16_t i; ++ mpp += pos; ++ mplen -= pos; + -+ peer->prefix_rcvd_update++; -+ /* add original path to the Adj-RIB-In */ -+ if (peer->conf.softreconfig_in) -+ r += path_update(&ribs[0], peer, asp, prefix, prefixlen); ++ rde_update_update(peer, asp, &prefix, ++ prefixlen); + -+ for (i = 1; i < rib_size; i++) { -+ /* input filter */ ++ /* max prefix checker */ ++ if (peer->conf.max_prefix && ++ peer->prefix_cnt >= peer->conf.max_prefix) { ++ log_peer_warnx(&peer->conf, ++ "prefix limit reached"); ++ rde_update_err(peer, ERR_CEASE, ++ ERR_CEASE_MAX_PREFIX, NULL, 0); ++ goto done; ++ } ++ ++ } ++ break; + default: + /* silently ignore unsupported multiprotocol AF */ + break; +@@ -1085,7 +1155,8 @@ rde_update_update(struct rde_peer *peer, + struct bgpd_addr *prefix, u_int8_t prefixlen) + { + struct rde_aspath *fasp; +- int r = 0; ++ enum filter_actions action; ++ int r = 0, f = 0; + u_int16_t i; + + peer->prefix_rcvd_update++; +@@ -1095,18 +1166,24 @@ rde_update_update(struct rde_peer *peer, + + for (i = 1; i < rib_size; i++) { + /* input filter */ +- if (rde_filter(i, &fasp, rules_l, peer, asp, prefix, prefixlen, +- peer, DIR_IN) == ACTION_DENY) +- goto done; + action = rde_filter(i, &fasp, rules_l, peer, asp, prefix, + prefixlen, peer, DIR_IN); -+ -+ if (fasp == NULL) -+ fasp = asp; -+ + + if (fasp == NULL) + fasp = asp; + +- rde_update_log("update", i, peer, &fasp->nexthop->exit_nexthop, +- prefix, prefixlen); +- r += path_update(&ribs[i], peer, fasp, prefix, prefixlen); + if (action == ACTION_ALLOW) { + rde_update_log("update", i, peer, + &fasp->nexthop->exit_nexthop, prefix, prefixlen); @@ -680,45 +633,30 @@ diff -u -p -r1.1.1.1 -r1.6 + NULL, prefix, prefixlen); + f++; + } -+ -+ /* free modified aspath */ -+ if (fasp != asp) -+ path_put(fasp); -+ } -+ -+ if (r) -+ peer->prefix_cnt++; + +-done: + /* free modified aspath */ + if (fasp != asp) + path_put(fasp); +@@ -1114,6 +1191,8 @@ done: + + if (r) + peer->prefix_cnt++; + else if (f) + peer->prefix_cnt--; -+} -+ -+void -+rde_update_withdraw(struct rde_peer *peer, struct bgpd_addr *prefix, -+ u_int8_t prefixlen) -+{ -+ int r = 0; -+ u_int16_t i; -+ -+ peer->prefix_rcvd_withdraw++; -+ -+ for (i = rib_size - 1; ; i--) { -+ if (prefix_remove(&ribs[i], peer, prefix, prefixlen, 0)) { -+ rde_update_log("withdraw", i, peer, NULL, prefix, -+ prefixlen); -+ r++; -+ } -+ if (i == 0) -+ break; -+ } -+ -+ if (r) -+ peer->prefix_cnt--; -+} -+ - /* - * BGP UPDATE parser functions - */ -@@ -1272,9 +1316,19 @@ bad_flags: + } + + void +@@ -1248,7 +1327,7 @@ bad_flags: + a->flags |= F_ATTR_NEXTHOP; + + bzero(&nexthop, sizeof(nexthop)); +- nexthop.af = AF_INET; ++ nexthop.aid = AID_INET; + UPD_READ(&nexthop.v4.s_addr, p, plen, 4); + /* + * Check if the nexthop is a valid IP address. We consider +@@ -1305,9 +1384,19 @@ bad_flags: goto optattr; case ATTR_AGGREGATOR: if ((!rde_as4byte(peer) && attr_len != 6) || @@ -741,7 +679,7 @@ diff -u -p -r1.1.1.1 -r1.6 goto bad_flags; if (!rde_as4byte(peer)) { /* need to inflate aggregator AS to 4-byte */ -@@ -1290,8 +1344,17 @@ bad_flags: +@@ -1323,8 +1412,33 @@ bad_flags: /* 4-byte ready server take the default route */ goto optattr; case ATTR_COMMUNITIES: @@ -758,17 +696,31 @@ diff -u -p -r1.1.1.1 -r1.6 + else + a->flags |= F_ATTR_PARSE_ERR; + } ++ if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, ++ ATTR_PARTIAL)) ++ goto bad_flags; ++ goto optattr; ++ case ATTR_EXT_COMMUNITIES: ++ if ((attr_len & 0x7) != 0) { ++ /* ++ * mark update as bad and withdraw all routes as per ++ * draft-ietf-idr-optional-transitive-00.txt ++ * but only if partial bit is set ++ */ ++ if ((flags & ATTR_PARTIAL) == 0) ++ goto bad_len; ++ else ++ a->flags |= F_ATTR_PARSE_ERR; ++ } if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, ATTR_PARTIAL)) goto bad_flags; -@@ -1336,15 +1399,21 @@ bad_flags: - mpa->unreach_len = attr_len; +@@ -1370,8 +1484,14 @@ bad_flags: plen += attr_len; break; -- case ATTR_NEW_AGGREGATOR: + case ATTR_AS4_AGGREGATOR: - if (attr_len != 8) - goto bad_len; -+ case ATTR_AS4_AGGREGATOR: + if (attr_len != 8) { + /* see ATTR_AGGREGATOR ... */ + if ((flags & ATTR_PARTIAL) == 0) @@ -780,14 +732,7 @@ diff -u -p -r1.1.1.1 -r1.6 if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, ATTR_PARTIAL)) goto bad_flags; - a->flags |= F_ATTR_AS4BYTE_NEW; - goto optattr; -- case ATTR_NEW_ASPATH: -+ case ATTR_AS4_PATH: - if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, - ATTR_PARTIAL)) - goto bad_flags; -@@ -1352,13 +1421,21 @@ bad_flags: +@@ -1385,13 +1505,21 @@ bad_flags: /* * XXX RFC does not specify how to handle errors. * XXX Instead of dropping the session because of a @@ -815,19 +760,36 @@ diff -u -p -r1.1.1.1 -r1.6 } a->flags |= F_ATTR_AS4BYTE_NEW; goto optattr; -@@ -1408,7 +1485,7 @@ rde_attr_missing(struct rde_aspath *a, i +@@ -1440,8 +1568,8 @@ rde_attr_missing(struct rde_aspath *a, i + } int - rde_get_mp_nexthop(u_char *data, u_int16_t len, u_int16_t afi, +-rde_get_mp_nexthop(u_char *data, u_int16_t len, u_int16_t afi, - struct rde_aspath *asp) ++rde_get_mp_nexthop(u_char *data, u_int16_t len, u_int8_t aid, + struct rde_aspath *asp, struct rde_peer *peer) { struct bgpd_addr nexthop; u_int8_t totlen, nhlen; -@@ -1440,6 +1517,18 @@ rde_get_mp_nexthop(u_char *data, u_int16 +@@ -1457,8 +1585,9 @@ rde_get_mp_nexthop(u_char *data, u_int16 + return (-1); + + bzero(&nexthop, sizeof(nexthop)); +- switch (afi) { +- case AFI_IPv6: ++ nexthop.aid = aid; ++ switch (aid) { ++ case AID_INET6: + /* + * RFC2545 describes that there may be a link-local + * address carried in nexthop. Yikes! +@@ -1471,72 +1600,143 @@ rde_get_mp_nexthop(u_char *data, u_int16 + log_warnx("bad multiprotocol nexthop, bad size"); + return (-1); } - nexthop.af = AF_INET6; +- nexthop.af = AF_INET6; memcpy(&nexthop.v6.s6_addr, data, 16); +- asp->nexthop = nexthop_get(&nexthop); +#if defined(__KAME__) && defined(IPV6_LINKLOCAL_PEER) + if (IN6_IS_ADDR_LINKLOCAL(&nexthop.v6) && + peer->conf.lliface[0]) { @@ -840,35 +802,225 @@ diff -u -p -r1.1.1.1 -r1.6 + log_warnx("bad interface: %s", peer->conf.lliface); + } +#endif - asp->nexthop = nexthop_get(&nexthop); ++ break; ++ case AID_VPN_IPv4: /* - * lock the nexthop because it is not yet linked else -@@ -1540,13 +1629,12 @@ rde_update_err(struct rde_peer *peer, u_ - imsg_add(wbuf, &suberr, sizeof(suberr)) == -1 || - imsg_add(wbuf, data, size) == -1) - fatal("imsg_add error"); -- if (imsg_close(ibuf_se, wbuf) == -1) -- fatal("imsg_close error"); -+ imsg_close(ibuf_se, wbuf); - peer->state = PEER_ERR; +- * lock the nexthop because it is not yet linked else +- * withdraws may remove this nexthop which in turn would +- * cause a use after free error. ++ * Neither RFC4364 nor RFC3107 specify the format of the ++ * nexthop in an explicit way. The quality of RFC went down ++ * the toilet the larger the the number got. ++ * RFC4364 is very confusing about VPN-IPv4 address and the ++ * VPN-IPv4 prefix that carries also a MPLS label. ++ * So the nexthop is a 12-byte address with a 64bit RD and ++ * an IPv4 address following. In the nexthop case the RD can ++ * be ignored. ++ * Since the nexthop has to be in the main IPv4 table just ++ * create an AID_INET nexthop. So we don't need to handle ++ * AID_VPN_IPv4 in nexthop and kroute. + */ +- asp->nexthop->refcnt++; +- +- /* ignore reserved (old SNPA) field as per RFC 4760 */ +- totlen += nhlen + 1; +- data += nhlen + 1; +- +- return (totlen); +- default: +- log_warnx("bad multiprotocol nexthop, bad AF"); ++ if (nhlen != 12) { ++ log_warnx("bad multiprotocol nexthop, bad size"); ++ return (-1); ++ } ++ data += sizeof(u_int64_t); ++ nexthop.aid = AID_INET; ++ memcpy(&nexthop.v4, data, sizeof(nexthop.v4)); + break; ++ default: ++ log_warnx("bad multiprotocol nexthop, bad AID"); ++ return (-1); + } + +- return (-1); ++ asp->nexthop = nexthop_get(&nexthop); ++ /* ++ * lock the nexthop because it is not yet linked else ++ * withdraws may remove this nexthop which in turn would ++ * cause a use after free error. ++ */ ++ asp->nexthop->refcnt++; ++ ++ /* ignore reserved (old SNPA) field as per RFC4760 */ ++ totlen += nhlen + 1; ++ data += nhlen + 1; ++ ++ return (totlen); ++} ++ ++int ++rde_update_extract_prefix(u_char *p, u_int16_t len, void *va, ++ u_int8_t pfxlen, u_int8_t max) ++{ ++ static u_char addrmask[] = { ++ 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; ++ u_char *a = va; ++ int i; ++ u_int16_t plen = 0; ++ ++ for (i = 0; pfxlen && i < max; i++) { ++ if (len <= plen) ++ return (-1); ++ if (pfxlen < 8) { ++ a[i] = *p++ & addrmask[pfxlen]; ++ plen++; ++ break; ++ } else { ++ a[i] = *p++; ++ plen++; ++ pfxlen -= 8; ++ } ++ } ++ return (plen); } - void --rde_update_log(const char *message, -+rde_update_log(const char *message, u_int16_t rid, - const struct rde_peer *peer, const struct bgpd_addr *next, - const struct bgpd_addr *prefix, u_int8_t prefixlen) + int + rde_update_get_prefix(u_char *p, u_int16_t len, struct bgpd_addr *prefix, + u_int8_t *prefixlen) { -@@ -1563,7 +1651,7 @@ rde_update_log(const char *message, - if (asprintf(&p, "%s/%u", log_addr(prefix), prefixlen) == -1) - p = NULL; - l = log_fmt_peer(&peer->conf); -- log_info("%s AS%s: %s %s%s", -+ log_info("Rib %s: %s AS%s: %s %s%s", ribs[rid].name, - l, log_as(peer->conf.remote_as), message, - p ? p : "out of memory", n ? n : ""); - -@@ -1584,9 +1672,17 @@ rde_as4byte_fixup(struct rde_peer *peer, +- int i; +- u_int8_t pfxlen; +- u_int16_t plen; +- union { +- struct in_addr a32; +- u_int8_t a8[4]; +- } addr; ++ u_int8_t pfxlen; ++ int plen; + + if (len < 1) + return (-1); + +- memcpy(&pfxlen, p, 1); +- p += 1; +- plen = 1; ++ pfxlen = *p++; ++ len--; + + bzero(prefix, sizeof(struct bgpd_addr)); +- addr.a32.s_addr = 0; +- for (i = 0; i <= 3; i++) { +- if (pfxlen > i * 8) { +- if (len - plen < 1) +- return (-1); +- memcpy(&addr.a8[i], p++, 1); +- plen++; +- } +- } +- prefix->af = AF_INET; +- prefix->v4.s_addr = addr.a32.s_addr; ++ prefix->aid = AID_INET; + *prefixlen = pfxlen; + +- return (plen); ++ if ((plen = rde_update_extract_prefix(p, len, &prefix->v4, pfxlen, ++ sizeof(prefix->v4))) == -1) ++ return (-1); ++ ++ return (plen + 1); /* pfxlen needs to be added */ + } + + int + rde_update_get_prefix6(u_char *p, u_int16_t len, struct bgpd_addr *prefix, + u_int8_t *prefixlen) + { +- int i; ++ int plen; + u_int8_t pfxlen; +- u_int16_t plen; ++ ++ if (len < 1) ++ return (-1); ++ ++ pfxlen = *p++; ++ len--; ++ ++ bzero(prefix, sizeof(struct bgpd_addr)); ++ prefix->aid = AID_INET6; ++ *prefixlen = pfxlen; ++ ++ if ((plen = rde_update_extract_prefix(p, len, &prefix->v6, pfxlen, ++ sizeof(prefix->v6))) == -1) ++ return (-1); ++ ++ return (plen + 1); /* pfxlen needs to be added */ ++} ++ ++int ++rde_update_get_vpn4(u_char *p, u_int16_t len, struct bgpd_addr *prefix, ++ u_int8_t *prefixlen) ++{ ++ int rv, done = 0; ++ u_int8_t pfxlen; ++ u_int16_t plen; + + if (len < 1) + return (-1); +@@ -1546,18 +1746,43 @@ rde_update_get_prefix6(u_char *p, u_int1 + plen = 1; + + bzero(prefix, sizeof(struct bgpd_addr)); +- for (i = 0; i <= 15; i++) { +- if (pfxlen > i * 8) { +- if (len - plen < 1) +- return (-1); +- memcpy(&prefix->v6.s6_addr[i], p++, 1); +- plen++; +- } +- } +- prefix->af = AF_INET6; ++ ++ /* label stack */ ++ do { ++ if (len - plen < 3 || pfxlen < 3 * 8) ++ return (-1); ++ if (prefix->vpn4.labellen + 3U > ++ sizeof(prefix->vpn4.labelstack)) ++ return (-1); ++ prefix->vpn4.labelstack[prefix->vpn4.labellen++] = *p++; ++ prefix->vpn4.labelstack[prefix->vpn4.labellen++] = *p++; ++ prefix->vpn4.labelstack[prefix->vpn4.labellen] = *p++; ++ if (prefix->vpn4.labelstack[prefix->vpn4.labellen] & ++ BGP_MPLS_BOS) ++ done = 1; ++ prefix->vpn4.labellen++; ++ plen += 3; ++ pfxlen -= 3 * 8; ++ } while (!done); ++ ++ /* RD */ ++ if (len - plen < (int)sizeof(u_int64_t) || ++ pfxlen < sizeof(u_int64_t) * 8) ++ return (-1); ++ memcpy(&prefix->vpn4.rd, p, sizeof(u_int64_t)); ++ pfxlen -= sizeof(u_int64_t) * 8; ++ p += sizeof(u_int64_t); ++ plen += sizeof(u_int64_t); ++ ++ /* prefix */ ++ prefix->aid = AID_VPN_IPv4; + *prefixlen = pfxlen; + +- return (plen); ++ if ((rv = rde_update_extract_prefix(p, len, &prefix->vpn4.addr, ++ pfxlen, sizeof(prefix->vpn4.addr))) == -1) ++ return (-1); ++ ++ return (plen + rv); + } + + void +@@ -1616,6 +1841,14 @@ rde_as4byte_fixup(struct rde_peer *peer, struct attr *nasp, *naggr, *oaggr; u_int32_t as; @@ -881,37 +1033,9 @@ diff -u -p -r1.1.1.1 -r1.6 + return; + /* first get the attributes */ -- nasp = attr_optget(a, ATTR_NEW_ASPATH); -- naggr = attr_optget(a, ATTR_NEW_AGGREGATOR); -+ nasp = attr_optget(a, ATTR_AS4_PATH); -+ naggr = attr_optget(a, ATTR_AS4_AGGREGATOR); - - if (rde_as4byte(peer)) { - /* NEW session using 4-byte ASNs */ -@@ -1601,7 +1697,7 @@ rde_as4byte_fixup(struct rde_peer *peer, - if ((oaggr = attr_optget(a, ATTR_AGGREGATOR))) { - memcpy(&as, oaggr->data, sizeof(as)); - if (ntohl(as) != AS_TRANS) { -- /* per RFC draft ignore NEW_ASPATH and NEW_AGGREGATOR */ -+ /* per RFC ignore AS4_PATH and AS4_AGGREGATOR */ - if (nasp) - attr_free(a, nasp); - if (naggr) -@@ -1616,11 +1712,11 @@ rde_as4byte_fixup(struct rde_peer *peer, - fatalx("attr_optadd failed but impossible"); - } - } -- /* there is no need for NEW_AGGREGATOR any more */ -+ /* there is no need for AS4_AGGREGATOR any more */ - if (naggr) - attr_free(a, naggr); - -- /* merge NEW_ASPATH with ASPATH */ -+ /* merge AS4_PATH with ASPATH */ - if (nasp) - aspath_merge(a, nasp); - } -@@ -1637,6 +1733,10 @@ rde_reflector(struct rde_peer *peer, str + 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 u_int16_t len; u_int32_t id; @@ -922,323 +1046,98 @@ diff -u -p -r1.1.1.1 -r1.6 /* 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) { -@@ -1703,7 +1803,6 @@ rde_dump_rib_as(struct prefix *p, struct - rib.med = asp->med; - rib.prefix_cnt = asp->prefix_cnt; - rib.active_cnt = asp->active_cnt; -- rib.adjrib_cnt = asp->adjrib_cnt; - strlcpy(rib.descr, asp->peer->conf.descr, sizeof(rib.descr)); - memcpy(&rib.remote_addr, &asp->peer->remote_addr, - sizeof(rib.remote_addr)); -@@ -1724,7 +1823,7 @@ rde_dump_rib_as(struct prefix *p, struct +@@ -1748,8 +1985,8 @@ rde_dump_rib_as(struct prefix *p, struct + /* announced network may have a NULL nexthop */ + bzero(&rib.true_nexthop, sizeof(rib.true_nexthop)); + bzero(&rib.exit_nexthop, sizeof(rib.exit_nexthop)); +- rib.true_nexthop.af = p->prefix->af; +- rib.exit_nexthop.af = p->prefix->af; ++ rib.true_nexthop.aid = p->prefix->aid; ++ rib.exit_nexthop.aid = p->prefix->aid; + } + pt_getaddr(p->prefix, &rib.prefix); rib.prefixlen = p->prefix->prefixlen; - rib.origin = asp->origin; - rib.flags = 0; -- if (p->prefix->active == p) -+ if (p->rib->active == p) - rib.flags |= F_RIB_ACTIVE; - if (asp->peer->conf.ebgp == 0) - rib.flags |= F_RIB_INTERNAL; -@@ -1743,8 +1842,7 @@ rde_dump_rib_as(struct prefix *p, struct - imsg_add(wbuf, aspath_dump(asp->aspath), - rib.aspath_len) == -1) - return; -- if (imsg_close(ibuf_se_ctl, wbuf) == -1) -- return; -+ imsg_close(ibuf_se_ctl, wbuf); - - if (flags & F_CTL_DETAIL) - for (l = 0; l < asp->others_len; l++) { -@@ -1763,8 +1861,7 @@ rde_dump_rib_as(struct prefix *p, struct - buf_free(wbuf); - return; - } -- if (imsg_close(ibuf_se_ctl, wbuf) == -1) -- return; -+ imsg_close(ibuf_se_ctl, wbuf); - } - } - -@@ -1780,7 +1877,7 @@ rde_dump_filterout(struct rde_peer *peer - return; - - pt_getaddr(p->prefix, &addr); -- a = rde_filter(&asp, rules_l, peer, p->aspath, &addr, -+ a = rde_filter(1 /* XXX */, &asp, rules_l, peer, p->aspath, &addr, - p->prefix->prefixlen, p->aspath->peer, DIR_OUT); - if (asp) - asp->peer = p->aspath->peer; -@@ -1799,108 +1896,57 @@ rde_dump_filter(struct prefix *p, struct - { - struct rde_peer *peer; - -- if ((req->flags & F_CTL_ADJ_IN && p->flags & F_ORIGINAL) || -- (!(req->flags & (F_CTL_ADJ_IN|F_CTL_ADJ_OUT)) && -- p->flags & F_LOCAL)) { -+ if (req->flags & F_CTL_ADJ_IN || -+ !(req->flags & (F_CTL_ADJ_IN|F_CTL_ADJ_OUT))) { - if (req->peerid && req->peerid != p->aspath->peer->conf.id) - return; -+ if (req->type == IMSG_CTL_SHOW_RIB_AS && -+ !aspath_match(p->aspath->aspath, req->as.type, req->as.as)) -+ return; -+ if (req->type == IMSG_CTL_SHOW_RIB_COMMUNITY && -+ !rde_filter_community(p->aspath, req->community.as, -+ req->community.type)) -+ return; - rde_dump_rib_as(p, p->aspath, req->pid, req->flags); -- } else if (req->flags & F_CTL_ADJ_OUT && p->flags & F_LOCAL) { -- if (p->prefix->active != p) -+ } else if (req->flags & F_CTL_ADJ_OUT) { -+ if (p->rib->active != p) - /* only consider active prefix */ +@@ -1836,7 +2073,7 @@ rde_dump_filter(struct prefix *p, struct + !aspath_match(p->aspath->aspath, req->as.type, req->as.as)) return; -- - if (req->peerid) { - if ((peer = peer_get(req->peerid)) != NULL) - rde_dump_filterout(peer, p, req); + if (req->type == IMSG_CTL_SHOW_RIB_COMMUNITY && +- !rde_filter_community(p->aspath, req->community.as, ++ !community_match(p->aspath, req->community.as, + req->community.type)) return; - } -- LIST_FOREACH(peer, &peerlist, peer_l) -- rde_dump_filterout(peer, p, req); - } - } - - void --rde_dump_upcall(struct pt_entry *pt, void *ptr) -+rde_dump_upcall(struct rib_entry *re, void *ptr) - { - struct prefix *p; -- struct ctl_show_rib_request *req = ptr; -- -- LIST_FOREACH(p, &pt->prefix_h, prefix_l) -- rde_dump_filter(p, req); --} -+ struct rde_dump_ctx *ctx = ptr; - --void --rde_dump_as(struct ctl_show_rib_request *req) --{ -- extern struct path_table pathtable; -- struct rde_aspath *asp; -- struct prefix *p; -- u_int32_t i; -- -- for (i = 0; i <= pathtable.path_hashmask; i++) { -- LIST_FOREACH(asp, &pathtable.path_hashtbl[i], path_l) { -- if (!aspath_match(asp->aspath, req->as.type, -- req->as.as)) -- continue; -- /* match found */ -- LIST_FOREACH(p, &asp->prefix_h, path_l) -- rde_dump_filter(p, req); -- } -- } -+ LIST_FOREACH(p, &re->prefix_h, rib_l) -+ rde_dump_filter(p, &ctx->req); - } - - void --rde_dump_prefix_upcall(struct pt_entry *pt, void *ptr) -+rde_dump_prefix_upcall(struct rib_entry *re, void *ptr) - { -- struct ctl_show_rib_request *req = ptr; -- struct prefix *p; -- struct bgpd_addr addr; -+ struct rde_dump_ctx *ctx = ptr; -+ struct prefix *p; -+ struct pt_entry *pt; -+ struct bgpd_addr addr; + rde_dump_rib_as(p, p->aspath, req->pid, req->flags); +@@ -1872,7 +2109,7 @@ rde_dump_prefix_upcall(struct rib_entry -+ pt = re->prefix; + pt = re->prefix; pt_getaddr(pt, &addr); -- if (addr.af != req->prefix.af) -+ if (addr.af != ctx->req.prefix.af) +- if (addr.af != ctx->req.prefix.af) ++ if (addr.aid != ctx->req.prefix.aid) return; -- if (req->prefixlen > pt->prefixlen) -+ if (ctx->req.prefixlen > pt->prefixlen) + if (ctx->req.prefixlen > pt->prefixlen) return; -- if (!prefix_compare(&req->prefix, &addr, req->prefixlen)) -- LIST_FOREACH(p, &pt->prefix_h, prefix_l) -- rde_dump_filter(p, req); --} -- --void --rde_dump_prefix(struct ctl_show_rib_request *req) --{ -- struct pt_entry *pt; -- -- if (req->prefixlen == 32) { -- if ((pt = pt_lookup(&req->prefix)) != NULL) -- rde_dump_upcall(pt, req); -- } else if (req->flags & F_LONGER) { -- pt_dump(rde_dump_prefix_upcall, req, req->prefix.af); -- } else { -- if ((pt = pt_get(&req->prefix, req->prefixlen)) != NULL) -- rde_dump_upcall(pt, req); -- } --} -- --void --rde_dump_community(struct ctl_show_rib_request *req) --{ -- extern struct path_table pathtable; -- struct rde_aspath *asp; -- struct prefix *p; -- u_int32_t i; -- -- for (i = 0; i <= pathtable.path_hashmask; i++) { -- LIST_FOREACH(asp, &pathtable.path_hashtbl[i], path_l) { -- if (!rde_filter_community(asp, req->community.as, -- req->community.type)) -- continue; -- /* match found */ -- LIST_FOREACH(p, &asp->prefix_h, path_l) -- rde_dump_filter(p, req); -- } -- } -+ if (!prefix_compare(&ctx->req.prefix, &addr, ctx->req.prefixlen)) -+ LIST_FOREACH(p, &re->prefix_h, rib_l) -+ rde_dump_filter(p, &ctx->req); - } - - void -@@ -1908,7 +1954,9 @@ rde_dump_ctx_new(struct ctl_show_rib_req - enum imsg_type type) - { - struct rde_dump_ctx *ctx; -+ struct rib_entry *re; - u_int error; -+ u_int16_t id; - - if ((ctx = calloc(1, sizeof(*ctx))) == NULL) { - log_warn("rde_dump_ctx_new"); -@@ -1917,52 +1965,89 @@ rde_dump_ctx_new(struct ctl_show_rib_req +@@ -1902,6 +2139,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req + error = CTL_RES_NOSUCHPEER; + imsg_compose(ibuf_se_ctl, IMSG_CTL_RESULT, 0, pid, -1, &error, sizeof(error)); ++ free(ctx); return; } -+ if ((id = rib_find(req->rib)) == RIB_FAILED) { -+ log_warnx("rde_dump_ctx_new: no such rib %s", req->rib); -+ error = CTL_RES_NOSUCHPEER; -+ imsg_compose(ibuf_se_ctl, IMSG_CTL_RESULT, 0, pid, -1, &error, -+ sizeof(error)); -+ return; -+ } -+ - memcpy(&ctx->req, req, sizeof(struct ctl_show_rib_request)); - ctx->req.pid = pid; - ctx->req.type = type; -- ctx->ptc.count = RDE_RUNNER_ROUNDS; -- ctx->af = ctx->req.af; -- if (ctx->af == AF_UNSPEC) -- ctx->af = AF_INET; -- -- TAILQ_INSERT_TAIL(&rde_dump_h, ctx, entry); -+ ctx->ribctx.ctx_count = RDE_RUNNER_ROUNDS; -+ ctx->ribctx.ctx_rib = &ribs[id]; -+ switch (ctx->req.type) { -+ case IMSG_CTL_SHOW_NETWORK: -+ ctx->ribctx.ctx_upcall = network_dump_upcall; -+ break; -+ case IMSG_CTL_SHOW_RIB: -+ case IMSG_CTL_SHOW_RIB_AS: -+ case IMSG_CTL_SHOW_RIB_COMMUNITY: -+ ctx->ribctx.ctx_upcall = rde_dump_upcall; -+ break; -+ case IMSG_CTL_SHOW_RIB_PREFIX: -+ if (req->flags & F_LONGER) { -+ ctx->ribctx.ctx_upcall = rde_dump_prefix_upcall; -+ break; -+ } -+ if (req->prefixlen == 32) -+ re = rib_lookup(&ribs[id], &req->prefix); -+ else -+ re = rib_get(&ribs[id], &req->prefix, req->prefixlen); -+ if (re) -+ rde_dump_upcall(re, ctx); -+ rde_dump_done(ctx); -+ return; -+ default: -+ fatalx("rde_dump_ctx_new: unsupported imsg type"); -+ } -+ ctx->ribctx.ctx_done = rde_dump_done; -+ ctx->ribctx.ctx_arg = ctx; -+ ctx->ribctx.ctx_af = ctx->req.af; -+ rib_dump_r(&ctx->ribctx); + +@@ -1937,7 +2175,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req + } + ctx->ribctx.ctx_done = rde_dump_done; + ctx->ribctx.ctx_arg = ctx; +- ctx->ribctx.ctx_af = ctx->req.af; ++ ctx->ribctx.ctx_aid = ctx->req.aid; + rib_dump_r(&ctx->ribctx); } - void --rde_dump_runner(void) -+rde_dump_done(void *arg) - { -- struct rde_dump_ctx *ctx, *next; -+ struct rde_dump_ctx *ctx = arg; - -- for (ctx = TAILQ_FIRST(&rde_dump_h); ctx != NULL; ctx = next) { -- next = TAILQ_NEXT(ctx, entry); -- if (ctx->ptc.done) { -- imsg_compose(ibuf_se_ctl, IMSG_CTL_END, 0, ctx->req.pid, -- -1, NULL, 0); -- TAILQ_REMOVE(&rde_dump_h, ctx, entry); -- free(ctx); -- continue; -- } -- switch (ctx->req.type) { -- case IMSG_CTL_SHOW_NETWORK: -- pt_dump_r(network_dump_upcall, &ctx->req.pid, -- ctx->af, &ctx->ptc); -- break; -- case IMSG_CTL_SHOW_RIB: -- pt_dump_r(rde_dump_upcall, &ctx->req, ctx->af, -- &ctx->ptc); -- break; -- default: -- fatalx("rde_dump_runner: unsupported imsg type"); -- } -- if (ctx->ptc.done && ctx->req.af == AF_UNSPEC) -- ctx->af = AF_INET6; -- } -+ imsg_compose(ibuf_se_ctl, IMSG_CTL_END, 0, ctx->req.pid, -+ -1, NULL, 0); -+ free(ctx); +@@ -1974,10 +2212,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; +- ctx->ribctx.ctx_done = mrt_dump_done; ++ ctx->ribctx.ctx_done = mrt_done; + ctx->ribctx.ctx_arg = &ctx->mrt; +- ctx->ribctx.ctx_af = AF_UNSPEC; +- LIST_INSERT_HEAD(&rde_mrts, &ctx->mrt, entry); ++ ctx->ribctx.ctx_aid = AID_UNSPEC; ++ LIST_INSERT_HEAD(&rde_mrts, ctx, entry); + rde_mrt_cnt++; + rib_dump_r(&ctx->ribctx); } +@@ -2011,8 +2249,8 @@ rde_send_kroute(struct prefix *new, stru + } --int --rde_dump_pending(void) -+void -+rde_dump_mrt_new(struct mrt *mrt, pid_t pid, int fd) - { -- return (!TAILQ_EMPTY(&rde_dump_h)); -+ struct rde_mrt_ctx *ctx; -+ u_int16_t id; -+ -+ if ((ctx = calloc(1, sizeof(*ctx))) == NULL) { -+ log_warn("rde_dump_mrt_new"); -+ return; -+ } -+ memcpy(&ctx->mrt, mrt, sizeof(struct mrt)); -+ TAILQ_INIT(&ctx->mrt.wbuf.bufs); -+ ctx->mrt.wbuf.fd = fd; -+ ctx->mrt.state = MRT_STATE_RUNNING; -+ id = rib_find(ctx->mrt.rib); -+ if (id == RIB_FAILED) { -+ log_warnx("non existing RIB %s for mrt dump", ctx->mrt.rib); -+ free(ctx); -+ return; -+ } -+ ctx->ribctx.ctx_count = RDE_RUNNER_ROUNDS; -+ ctx->ribctx.ctx_rib = &ribs[id]; -+ ctx->ribctx.ctx_upcall = mrt_dump_upcall; -+ ctx->ribctx.ctx_done = mrt_dump_done; -+ ctx->ribctx.ctx_arg = &ctx->mrt; -+ ctx->ribctx.ctx_af = AF_UNSPEC; -+ LIST_INSERT_HEAD(&rde_mrts, &ctx->mrt, entry); -+ rde_mrt_cnt++; -+ rib_dump_r(&ctx->ribctx); + pt_getaddr(p->prefix, &addr); +- switch (addr.af) { +- case AF_INET: ++ 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"); + 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) + fatal("imsg_compose error"); + break; ++ case AID_VPN_IPv4: ++ break; ++ default: ++ fatal("rde_send_kroute: unhandled AID"); + } } - /* -@@ -2081,7 +2166,6 @@ rde_send_pftable_commit(void) +@@ -2098,7 +2340,6 @@ rde_send_pftable_commit(void) void rde_send_nexthop(struct bgpd_addr *next, int valid) { @@ -1246,7 +1145,7 @@ diff -u -p -r1.1.1.1 -r1.6 int type; if (valid) -@@ -2089,8 +2173,6 @@ rde_send_nexthop(struct bgpd_addr *next, +@@ -2106,8 +2347,6 @@ rde_send_nexthop(struct bgpd_addr *next, else type = IMSG_NEXTHOP_REMOVE; @@ -1255,127 +1154,30 @@ diff -u -p -r1.1.1.1 -r1.6 if (imsg_compose(ibuf_main, type, 0, 0, -1, next, sizeof(struct bgpd_addr)) == -1) fatal("imsg_compose error"); -@@ -2100,9 +2182,10 @@ rde_send_nexthop(struct bgpd_addr *next, - * soft reconfig specific functions - */ - void --rde_softreconfig_out(struct pt_entry *pt, void *ptr) -+rde_softreconfig_out(struct rib_entry *re, void *ptr) - { -- struct prefix *p = pt->active; -+ struct prefix *p = re->active; -+ struct pt_entry *pt; - struct rde_peer *peer; - struct rde_aspath *oasp, *nasp; - enum filter_actions oa, na; -@@ -2111,17 +2194,22 @@ rde_softreconfig_out(struct pt_entry *pt - if (p == NULL) - return; - -+ pt = re->prefix; - pt_getaddr(pt, &addr); - LIST_FOREACH(peer, &peerlist, peer_l) { -+ if (peer->conf.id == 0) -+ continue; -+ if (peer->ribid != re->ribid) -+ continue; - if (peer->reconf_out == 0) - continue; - if (up_test_update(peer, p) != 1) +@@ -2201,6 +2440,10 @@ rde_softreconfig_in(struct rib_entry *re continue; -- oa = rde_filter(&oasp, rules_l, peer, p->aspath, &addr, -- pt->prefixlen, p->aspath->peer, DIR_OUT); -- na = rde_filter(&nasp, newrules, peer, p->aspath, &addr, -- pt->prefixlen, p->aspath->peer, DIR_OUT); -+ oa = rde_filter(re->ribid, &oasp, rules_l, peer, p->aspath, -+ &addr, pt->prefixlen, p->aspath->peer, DIR_OUT); -+ na = rde_filter(re->ribid, &nasp, newrules, peer, p->aspath, -+ &addr, pt->prefixlen, p->aspath->peer, DIR_OUT); - oasp = oasp != NULL ? oasp : p->aspath; - nasp = nasp != NULL ? nasp : p->aspath; - -@@ -2154,58 +2242,103 @@ done: - } - - void --rde_softreconfig_in(struct pt_entry *pt, void *ptr) -+rde_softreconfig_in(struct rib_entry *re, void *ptr) - { - struct prefix *p, *np; -+ struct pt_entry *pt; - struct rde_peer *peer; - struct rde_aspath *asp, *oasp, *nasp; - enum filter_actions oa, na; - struct bgpd_addr addr; -+ u_int16_t i; - -+ pt = re->prefix; - pt_getaddr(pt, &addr); -- for (p = LIST_FIRST(&pt->prefix_h); p != NULL; p = np) { -- np = LIST_NEXT(p, prefix_l); -- if (!(p->flags & F_ORIGINAL)) -- continue; -+ for (p = LIST_FIRST(&re->prefix_h); p != NULL; p = np) { -+ np = LIST_NEXT(p, rib_l); - - /* store aspath as prefix may change till we're done */ - asp = p->aspath; - peer = asp->peer; - -+ /* XXX how can this happen ??? */ - if (peer->reconf_in == 0) - continue; - -- /* check if prefix changed */ -- oa = rde_filter(&oasp, rules_l, peer, asp, &addr, -- pt->prefixlen, peer, DIR_IN); -- na = rde_filter(&nasp, newrules, peer, asp, &addr, -+ for (i = 1; i < rib_size; i++) { + for (i = 1; i < rib_size; i++) { + /* only active ribs need a softreconfig rerun */ + if (ribs[i].state != RIB_ACTIVE) + continue; + -+ /* check if prefix changed */ -+ oa = rde_filter(i, &oasp, rules_l, peer, asp, &addr, -+ pt->prefixlen, peer, DIR_IN); -+ na = rde_filter(i, &nasp, newrules, peer, asp, &addr, -+ pt->prefixlen, peer, DIR_IN); -+ oasp = oasp != NULL ? oasp : asp; -+ nasp = nasp != NULL ? nasp : asp; -+ -+ if (oa == ACTION_DENY && na == ACTION_DENY) -+ /* nothing todo */ -+ goto done; -+ if (oa == ACTION_DENY && na == ACTION_ALLOW) { -+ /* update Local-RIB */ -+ path_update(&ribs[i], peer, nasp, &addr, -+ pt->prefixlen); -+ goto done; -+ } -+ if (oa == ACTION_ALLOW && na == ACTION_DENY) { -+ /* remove from Local-RIB */ -+ prefix_remove(&ribs[i], peer, &addr, -+ pt->prefixlen, 0); -+ goto done; -+ } -+ if (oa == ACTION_ALLOW && na == ACTION_ALLOW) { -+ if (path_compare(nasp, oasp) == 0) -+ goto done; -+ /* send update */ + /* 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 + if (path_compare(nasp, oasp) == 0) + goto done; + /* send update */ +- path_update(&ribs[1], peer, nasp, &addr, + path_update(&ribs[i], peer, nasp, &addr, -+ pt->prefixlen); -+ } -+ -+done: -+ if (oasp != asp) -+ path_put(oasp); -+ if (nasp != asp) -+ path_put(nasp); -+ } -+ } -+} -+ + pt->prefixlen); + } + +@@ -2241,6 +2484,40 @@ done: + } + } + +void +rde_softreconfig_load(struct rib_entry *re, void *ptr) +{ @@ -1397,146 +1199,238 @@ diff -u -p -r1.1.1.1 -r1.6 + peer = asp->peer; + + action = rde_filter(rib->id, &nasp, newrules, peer, asp, &addr, - pt->prefixlen, peer, DIR_IN); -- oasp = oasp != NULL ? oasp : asp; - nasp = nasp != NULL ? nasp : asp; - -- if (oa == ACTION_DENY && na == ACTION_DENY) -- /* nothing todo */ -- goto done; -- if (oa == ACTION_DENY && na == ACTION_ALLOW) { ++ pt->prefixlen, peer, DIR_IN); ++ nasp = nasp != NULL ? nasp : asp; ++ + if (action == ACTION_ALLOW) { - /* update Local-RIB */ -- path_update(peer, nasp, &addr, pt->prefixlen, F_LOCAL); -- goto done; -- } -- if (oa == ACTION_ALLOW && na == ACTION_DENY) { -- /* remove from Local-RIB */ -- prefix_remove(peer, &addr, pt->prefixlen, F_LOCAL); -- goto done; -- } -- if (oa == ACTION_ALLOW && na == ACTION_ALLOW) { -- if (path_compare(nasp, oasp) == 0) -- goto done; -- /* send update */ -- path_update(peer, nasp, &addr, pt->prefixlen, F_LOCAL); ++ /* update Local-RIB */ + path_update(rib, peer, nasp, &addr, pt->prefixlen); - } - --done: -- if (oasp != asp) -- path_put(oasp); - if (nasp != asp) - path_put(nasp); - } -@@ -2217,17 +2350,19 @@ done: - u_char queue_buf[4096]; - - void --rde_up_dump_upcall(struct pt_entry *pt, void *ptr) -+rde_up_dump_upcall(struct rib_entry *re, void *ptr) ++ } ++ ++ if (nasp != asp) ++ path_put(nasp); ++ } ++} ++ + /* + * update specific functions + */ +@@ -2286,7 +2563,7 @@ void + rde_update_queue_runner(void) { - struct rde_peer *peer = ptr; + struct rde_peer *peer; +- int r, sent, max = RDE_RUNNER_ROUNDS; ++ int r, sent, max = RDE_RUNNER_ROUNDS, eor = 0; + u_int16_t len, wd_len, wpos; -- if (pt->active == NULL) -+ if (re->ribid != peer->ribid) -+ fatalx("King Bula: monsterous evil horror."); -+ if (re->active == NULL) - return; -- up_generate_updates(rules_l, peer, pt->active, NULL); -+ up_generate_updates(rules_l, peer, re->active, NULL); + len = sizeof(queue_buf) - MSGSIZE_HEADER; +@@ -2300,7 +2577,7 @@ rde_update_queue_runner(void) + /* first withdraws */ + wpos = 2; /* reserve space for the length field */ + r = up_dump_prefix(queue_buf + wpos, len - wpos - 2, +- &peer->withdraws, peer); ++ &peer->withdraws[AID_INET], peer); + wd_len = r; + /* write withdraws length filed */ + wd_len = htons(wd_len); +@@ -2310,31 +2587,49 @@ rde_update_queue_runner(void) + /* now bgp path attributes */ + r = up_dump_attrnlri(queue_buf + wpos, len - wpos, + peer); +- wpos += r; +- +- if (wpos == 4) +- /* +- * No packet to send. The 4 bytes are the +- * needed withdraw and path attribute length. +- */ +- continue; ++ switch (r) { ++ case -1: ++ eor = 1; ++ if (wd_len == 0) { ++ /* no withdraws queued just send EoR */ ++ peer_send_eor(peer, AID_INET); ++ continue; ++ } ++ break; ++ case 2: ++ if (wd_len == 0) { ++ /* ++ * No packet to send. No withdraws and ++ * no path attributes. Skip. ++ */ ++ continue; ++ } ++ /* FALLTHROUGH */ ++ default: ++ wpos += r; ++ break; ++ } + + /* finally send message to SE */ + if (imsg_compose(ibuf_se, IMSG_UPDATE, peer->conf.id, + 0, -1, queue_buf, wpos) == -1) + fatal("imsg_compose error"); + sent++; ++ if (eor) { ++ eor = 0; ++ peer_send_eor(peer, AID_INET); ++ } + } + max -= sent; + } while (sent != 0 && max > 0); } void --rde_generate_updates(struct prefix *new, struct prefix *old) -+rde_generate_updates(u_int16_t ribid, struct prefix *new, struct prefix *old) +-rde_update6_queue_runner(void) ++rde_update6_queue_runner(u_int8_t aid) { - struct rde_peer *peer; - -@@ -2240,6 +2375,10 @@ rde_generate_updates(struct prefix *new, - return; + struct rde_peer *peer; + u_char *b; +- int sent, max = RDE_RUNNER_ROUNDS / 2; ++ int r, sent, max = RDE_RUNNER_ROUNDS / 2; + u_int16_t len; - LIST_FOREACH(peer, &peerlist, peer_l) { -+ if (peer->conf.id == 0) -+ continue; -+ if (peer->ribid != ribid) -+ continue; - if (peer->state != PEER_UP) - continue; - up_generate_updates(rules_l, peer, new, old); -@@ -2257,6 +2396,8 @@ rde_update_queue_runner(void) - do { - sent = 0; - LIST_FOREACH(peer, &peerlist, peer_l) { -+ if (peer->conf.id == 0) -+ continue; - if (peer->state != PEER_UP) - continue; - /* first withdraws */ -@@ -2303,6 +2444,8 @@ rde_update6_queue_runner(void) - do { - sent = 0; - LIST_FOREACH(peer, &peerlist, peer_l) { -+ if (peer->conf.id == 0) -+ continue; + /* first withdraws ... */ +@@ -2346,7 +2641,7 @@ rde_update6_queue_runner(void) if (peer->state != PEER_UP) continue; len = sizeof(queue_buf) - MSGSIZE_HEADER; -@@ -2324,6 +2467,8 @@ rde_update6_queue_runner(void) - do { - sent = 0; - LIST_FOREACH(peer, &peerlist, peer_l) { -+ if (peer->conf.id == 0) -+ continue; +- b = up_dump_mp_unreach(queue_buf, &len, peer); ++ b = up_dump_mp_unreach(queue_buf, &len, peer, aid); + + if (b == NULL) + continue; +@@ -2369,10 +2664,18 @@ rde_update6_queue_runner(void) if (peer->state != PEER_UP) continue; len = sizeof(queue_buf) - MSGSIZE_HEADER; -@@ -2386,6 +2531,8 @@ struct peer_table { - void +- b = up_dump_mp_reach(queue_buf, &len, peer); +- +- if (b == NULL) ++ r = up_dump_mp_reach(queue_buf, &len, peer, aid); ++ switch (r) { ++ case -2: + continue; ++ case -1: ++ peer_send_eor(peer, aid); ++ continue; ++ default: ++ b = queue_buf + r; ++ break; ++ } ++ + /* finally send message to SE */ + if (imsg_compose(ibuf_se, IMSG_UPDATE, peer->conf.id, + 0, -1, b, len) == -1) +@@ -2411,7 +2714,7 @@ rde_decisionflags(void) + int + rde_as4byte(struct rde_peer *peer) + { +- return (peer->capa_announced.as4byte && peer->capa_received.as4byte); ++ return (peer->capa.as4byte); + } + + /* +@@ -2429,7 +2732,6 @@ void peer_init(u_int32_t hashsize) { -+ struct peer_config pc; -+ struct in_addr id; + struct peer_config pc; +- struct in_addr id; u_int32_t hs, i; for (hs = 1; hs < hashsize; hs <<= 1) -@@ -2399,6 +2546,19 @@ peer_init(u_int32_t hashsize) - LIST_INIT(&peerlist); - +@@ -2445,17 +2747,13 @@ peer_init(u_int32_t hashsize) peertable.peer_hashmask = hs - 1; -+ -+ bzero(&pc, sizeof(pc)); -+ pc.remote_as = conf->as; -+ id.s_addr = conf->bgpid; -+ snprintf(pc.descr, sizeof(pc.descr), "LOCAL: ID %s", inet_ntoa(id)); -+ -+ peerself = peer_add(0, &pc); -+ if (peerself == NULL) -+ fatalx("peer_init add self"); -+ -+ peerself->state = PEER_UP; -+ peerself->remote_bgpid = ntohl(conf->bgpid); -+ peerself->short_as = conf->short_as; + + bzero(&pc, sizeof(pc)); +- pc.remote_as = conf->as; +- id.s_addr = conf->bgpid; +- snprintf(pc.descr, sizeof(pc.descr), "LOCAL: ID %s", inet_ntoa(id)); ++ snprintf(pc.descr, sizeof(pc.descr), "LOCAL"); + + peerself = peer_add(0, &pc); + if (peerself == NULL) + fatalx("peer_init add self"); + + peerself->state = PEER_UP; +- peerself->remote_bgpid = ntohl(conf->bgpid); +- peerself->short_as = conf->short_as; } void -@@ -2444,6 +2604,7 @@ peer_add(u_int32_t id, struct peer_confi - LIST_INIT(&peer->path_h); - memcpy(&peer->conf, p_conf, sizeof(struct peer_config)); - peer->remote_bgpid = 0; -+ peer->ribid = rib_find(peer->conf.rib); - peer->state = PEER_NONE; - up_init(peer); - -@@ -2573,6 +2734,7 @@ peer_down(u_int32_t id) - path_remove(asp); +@@ -2534,14 +2832,10 @@ peer_localaddrs(struct rde_peer *peer, s + if (ifa->ifa_addr->sa_family == + match->ifa_addr->sa_family) + ifa = match; +- peer->local_v4_addr.af = AF_INET; +- peer->local_v4_addr.v4.s_addr = +- ((struct sockaddr_in *)ifa->ifa_addr)-> +- sin_addr.s_addr; ++ sa2addr(ifa->ifa_addr, &peer->local_v4_addr); + break; + } + } +- + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr->sa_family == AF_INET6 && + strcmp(ifa->ifa_name, match->ifa_name) == 0) { +@@ -2559,13 +2853,7 @@ peer_localaddrs(struct rde_peer *peer, s + &((struct sockaddr_in6 *)ifa-> + ifa_addr)->sin6_addr)) + continue; +- peer->local_v6_addr.af = AF_INET6; +- memcpy(&peer->local_v6_addr.v6, +- &((struct sockaddr_in6 *)ifa->ifa_addr)-> +- sin6_addr, sizeof(struct in6_addr)); +- peer->local_v6_addr.scope_id = +- ((struct sockaddr_in6 *)ifa->ifa_addr)-> +- sin6_scope_id; ++ sa2addr(ifa->ifa_addr, &peer->local_v6_addr); + break; + } } - LIST_INIT(&peer->path_h); -+ peer->prefix_cnt = 0; +@@ -2577,6 +2865,7 @@ void + peer_up(u_int32_t id, struct session_up *sup) + { + struct rde_peer *peer; ++ u_int8_t i; - /* Deletions are performed in path_remove() */ - rde_send_pftable_commit(); -@@ -2589,32 +2751,38 @@ peer_dump(u_int32_t id, u_int16_t afi, u + peer = peer_get(id); + if (peer == NULL) { +@@ -2590,10 +2879,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)); +- memcpy(&peer->capa_announced, &sup->capa_announced, +- sizeof(peer->capa_announced)); +- memcpy(&peer->capa_received, &sup->capa_received, +- sizeof(peer->capa_received)); ++ memcpy(&peer->capa, &sup->capa, sizeof(peer->capa)); + + peer_localaddrs(peer, &sup->local_addr); + +@@ -2607,7 +2893,10 @@ peer_up(u_int32_t id, struct session_up + */ + return; + +- peer_dump(id, AFI_ALL, SAFI_ALL); ++ for (i = 0; i < AID_MAX; i++) { ++ if (peer->capa.mp[i] == 1) ++ peer_dump(id, i); ++ } + } + + void +@@ -2642,42 +2931,32 @@ peer_down(u_int32_t id) + } + + void +-peer_dump(u_int32_t id, u_int16_t afi, u_int8_t safi) ++peer_dump(u_int32_t id, u_int8_t aid) + { + struct rde_peer *peer; peer = peer_get(id); if (peer == NULL) { @@ -1545,219 +1439,110 @@ diff -u -p -r1.1.1.1 -r1.6 return; } - if (afi == AFI_ALL || afi == AFI_IPv4) +- if (afi == AFI_ALL || afi == AFI_IPv4) - if (safi == SAFI_ALL || safi == SAFI_UNICAST) { -- if (peer->conf.announce_type == -- ANNOUNCE_DEFAULT_ROUTE) -+ if ((safi == SAFI_ALL || safi == SAFI_UNICAST) && -+ peer->conf.capabilities.mp_v4 != SAFI_NONE) { -+ if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE) - up_generate_default(rules_l, peer, AF_INET); - else -- pt_dump(rde_up_dump_upcall, peer, AF_INET); -+ rib_dump(&ribs[peer->ribid], rde_up_dump_upcall, -+ peer, AF_INET); -+ if (peer->capa_received.restart && -+ peer->capa_announced.restart) -+ peer_send_eor(peer, AFI_IPv4, SAFI_UNICAST); - } - if (afi == AFI_ALL || afi == AFI_IPv6) +- if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE) +- up_generate_default(rules_l, peer, AF_INET); +- else +- rib_dump(&ribs[peer->ribid], rde_up_dump_upcall, +- peer, AF_INET); +- } +- if (afi == AFI_ALL || afi == AFI_IPv6) - if (safi == SAFI_ALL || safi == SAFI_UNICAST) { -- if (peer->conf.announce_type == -- ANNOUNCE_DEFAULT_ROUTE) -+ if ((safi == SAFI_ALL || safi == SAFI_UNICAST) && -+ peer->capa_announced.mp_v6 != SAFI_NONE && -+ peer->capa_received.mp_v6 != SAFI_NONE) { -+ if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE) - up_generate_default(rules_l, peer, AF_INET6); - else -- pt_dump(rde_up_dump_upcall, peer, AF_INET6); -+ rib_dump(&ribs[peer->ribid], rde_up_dump_upcall, -+ peer, AF_INET6); -+ if (peer->capa_received.restart && -+ peer->capa_announced.restart) -+ peer_send_eor(peer, AFI_IPv6, SAFI_UNICAST); - } +- if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE) +- up_generate_default(rules_l, peer, AF_INET6); +- else +- rib_dump(&ribs[peer->ribid], rde_up_dump_upcall, +- peer, AF_INET6); +- } - - if (peer->capa_received.restart && peer->capa_announced.restart) - peer_send_eor(peer, afi, safi); ++ if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE) ++ up_generate_default(rules_l, peer, aid); ++ else ++ rib_dump(&ribs[peer->ribid], rde_up_dump_upcall, peer, aid); ++ if (peer->capa.restart) ++ up_generate_marker(peer, aid); } -/* End-of-RIB marker, draft-ietf-idr-restart-13.txt */ +/* End-of-RIB marker, RFC 4724 */ void - peer_send_eor(struct rde_peer *peer, u_int16_t afi, u_int16_t safi) - { -@@ -2653,24 +2821,8 @@ void - network_init(struct network_head *net_l) - { - struct network *n; -- struct in_addr id; - - reloadtime = time(NULL); -- bzero(&peerself, sizeof(peerself)); -- peerself.state = PEER_UP; -- peerself.remote_bgpid = ntohl(conf->bgpid); -- id.s_addr = conf->bgpid; -- peerself.conf.remote_as = conf->as; -- peerself.short_as = conf->short_as; -- snprintf(peerself.conf.descr, sizeof(peerself.conf.descr), -- "LOCAL: ID %s", inet_ntoa(id)); -- bzero(&peerdynamic, sizeof(peerdynamic)); -- peerdynamic.state = PEER_UP; -- peerdynamic.remote_bgpid = ntohl(conf->bgpid); -- peerdynamic.conf.remote_as = conf->as; -- peerdynamic.short_as = conf->short_as; -- snprintf(peerdynamic.conf.descr, sizeof(peerdynamic.conf.descr), -- "LOCAL: ID %s", inet_ntoa(id)); - - while ((n = TAILQ_FIRST(net_l)) != NULL) { - TAILQ_REMOVE(net_l, n, entry); -@@ -2683,7 +2835,7 @@ void - network_add(struct network_config *nc, int flagstatic) - { - struct rde_aspath *asp; -- struct rde_peer *p; -+ u_int16_t i; - - asp = path_get(); - asp->aspath = aspath_get(NULL, 0); -@@ -2691,15 +2843,13 @@ network_add(struct network_config *nc, i - asp->flags = F_ATTR_ORIGIN | F_ATTR_ASPATH | - F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED; - /* the nexthop is unset unless a default set overrides it */ -+ if (!flagstatic) -+ asp->flags |= F_ANN_DYNAMIC; - -- if (flagstatic) -- p = &peerself; -- else -- p = &peerdynamic; -- -- rde_apply_set(asp, &nc->attrset, nc->prefix.af, p, p); -- path_update(p, asp, &nc->prefix, nc->prefixlen, F_ORIGINAL); -- path_update(p, asp, &nc->prefix, nc->prefixlen, F_LOCAL); -+ rde_apply_set(asp, &nc->attrset, nc->prefix.af, peerself, peerself); -+ for (i = 1; i < rib_size; i++) -+ path_update(&ribs[i], peerself, asp, &nc->prefix, -+ nc->prefixlen); - - path_put(asp); - filterset_free(&nc->attrset); -@@ -2708,29 +2858,27 @@ network_add(struct network_config *nc, i - void - network_delete(struct network_config *nc, int flagstatic) +-peer_send_eor(struct rde_peer *peer, u_int16_t afi, u_int16_t safi) ++peer_send_eor(struct rde_peer *peer, u_int8_t aid) { -- struct rde_peer *p; -+ u_int32_t flags = F_PREFIX_ANNOUNCED; -+ u_int32_t i; - -- if (flagstatic) -- p = &peerself; -- else -- p = &peerdynamic; -+ if (!flagstatic) -+ flags |= F_ANN_DYNAMIC; - -- prefix_remove(p, &nc->prefix, nc->prefixlen, F_LOCAL); -- prefix_remove(p, &nc->prefix, nc->prefixlen, F_ORIGINAL); -+ for (i = rib_size - 1; i > 0; i--) -+ prefix_remove(&ribs[i], peerself, &nc->prefix, nc->prefixlen, -+ flags); - } +- if (afi == AFI_IPv4 && safi == SAFI_UNICAST) { ++ u_int16_t afi; ++ u_int8_t safi; ++ ++ if (aid == AID_INET) { + u_char null[4]; - void --network_dump_upcall(struct pt_entry *pt, void *ptr) -+network_dump_upcall(struct rib_entry *re, void *ptr) - { - struct prefix *p; - struct kroute k; - struct kroute6 k6; - struct bgpd_addr addr; -- pid_t pid; -- -- memcpy(&pid, ptr, sizeof(pid)); -+ struct rde_dump_ctx *ctx = ptr; + bzero(&null, 4); +@@ -2688,6 +2967,9 @@ peer_send_eor(struct rde_peer *peer, u_i + u_int16_t i; + u_char buf[10]; -- LIST_FOREACH(p, &pt->prefix_h, prefix_l) { -+ LIST_FOREACH(p, &re->prefix_h, rib_l) { ++ if (aid2afi(aid, &afi, &safi) == -1) ++ fatalx("peer_send_eor: bad AID"); ++ + i = 0; /* v4 withdrawn len */ + bcopy(&i, &buf[0], sizeof(i)); + i = htons(6); /* path attr len */ +@@ -2737,7 +3019,7 @@ 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, aid2af(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 + LIST_FOREACH(p, &re->prefix_h, rib_l) { if (!(p->aspath->flags & F_PREFIX_ANNOUNCED)) continue; - if (p->prefix->af == AF_INET) { -@@ -2738,10 +2886,10 @@ network_dump_upcall(struct pt_entry *pt, - pt_getaddr(p->prefix, &addr); +- if (p->prefix->af == AF_INET) { ++ pt_getaddr(p->prefix, &addr); ++ switch (addr.aid) { ++ case AID_INET: + bzero(&k, sizeof(k)); +- pt_getaddr(p->prefix, &addr); k.prefix.s_addr = addr.v4.s_addr; k.prefixlen = p->prefix->prefixlen; -- if (p->aspath->peer == &peerself) -+ if (p->aspath->peer == peerself) - k.flags = F_KERNEL; - if (imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NETWORK, 0, -- pid, -1, &k, sizeof(k)) == -1) -+ ctx->req.pid, -1, &k, sizeof(k)) == -1) + 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"); - } -@@ -2750,31 +2898,21 @@ network_dump_upcall(struct pt_entry *pt, - pt_getaddr(p->prefix, &addr); +- } +- if (p->prefix->af == AF_INET6) { ++ break; ++ case AID_INET6: + bzero(&k6, sizeof(k6)); +- pt_getaddr(p->prefix, &addr); memcpy(&k6.prefix, &addr.v6, sizeof(k6.prefix)); k6.prefixlen = p->prefix->prefixlen; -- if (p->aspath->peer == &peerself) -+ if (p->aspath->peer == peerself) - k6.flags = F_KERNEL; - if (imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NETWORK6, 0, -- pid, -1, &k6, sizeof(k6)) == -1) -+ ctx->req.pid, -1, &k6, sizeof(k6)) == -1) + 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; } } } - --void --network_flush(int flagstatic) --{ -- if (flagstatic) -- prefix_network_clean(&peerself, time(NULL)); -- else -- prefix_network_clean(&peerdynamic, time(NULL)); --} -- - /* clean up */ - void - rde_shutdown(void) - { - struct rde_peer *p; -- struct rde_aspath *asp, *nasp; - struct filter_rule *r; - u_int32_t i; - -@@ -2790,21 +2928,6 @@ rde_shutdown(void) - while ((p = LIST_FIRST(&peertable.peer_hashtbl[i])) != NULL) - peer_down(p->conf.id); - -- /* free announced network prefixes */ -- peerself.remote_bgpid = 0; -- peerself.state = PEER_DOWN; -- for (asp = LIST_FIRST(&peerself.path_h); asp != NULL; asp = nasp) { -- nasp = LIST_NEXT(asp, peer_l); -- path_remove(asp); -- } -- -- peerdynamic.remote_bgpid = 0; -- peerdynamic.state = PEER_DOWN; -- for (asp = LIST_FIRST(&peerdynamic.path_h); asp != NULL; asp = nasp) { -- nasp = LIST_NEXT(asp, peer_l); -- path_remove(asp); -- } -- - /* free filters */ - while ((r = TAILQ_FIRST(rules_l)) != NULL) { - TAILQ_REMOVE(rules_l, r, entry); -@@ -2819,7 +2942,6 @@ rde_shutdown(void) - attr_shutdown(); - pt_shutdown(); - peer_shutdown(); -- free(mrt); - } - - int +@@ -2841,10 +3124,10 @@ sa_cmp(struct bgpd_addr *a, struct socka + struct sockaddr_in *in_b; + struct sockaddr_in6 *in6_b; + +- if (a->af != b->sa_family) ++ if (aid2af(a->aid) != b->sa_family) + return (1); + +- switch (a->af) { ++ switch (b->sa_family) { + case AF_INET: + in_b = (struct sockaddr_in *)b; + if (a->v4.s_addr != in_b->sin_addr.s_addr) diff --git a/net/openbgpd/files/patch-bgpd_rde.h b/net/openbgpd/files/patch-bgpd_rde.h index e8fd5aaa7e0a..479725479263 100644 --- a/net/openbgpd/files/patch-bgpd_rde.h +++ b/net/openbgpd/files/patch-bgpd_rde.h @@ -1,311 +1,161 @@ Index: bgpd/rde.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde.h,v -retrieving revision 1.1.1.1 -retrieving revision 1.1.1.4 -diff -u -p -r1.1.1.1 -r1.1.1.4 ---- bgpd/rde.h 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/rde.h 22 Oct 2009 14:24:02 -0000 1.1.1.4 +retrieving revision 1.1.1.8 +retrieving revision 1.1.1.9 +diff -u -p -r1.1.1.8 -r1.1.1.9 +--- bgpd/rde.h 14 Feb 2010 20:19:57 -0000 1.1.1.8 ++++ bgpd/rde.h 14 Feb 2010 20:27:06 -0000 1.1.1.9 @@ -1,4 +1,4 @@ --/* $OpenBSD: rde.h,v 1.102 2008/01/23 08:11:32 claudio Exp $ */ -+/* $OpenBSD: rde.h,v 1.121 2009/08/06 08:53:11 claudio Exp $ */ +-/* $OpenBSD: rde.h,v 1.120 2009/06/06 01:10:29 claudio Exp $ */ ++/* $OpenBSD: rde.h,v 1.129 2010/01/13 06:02:37 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and -@@ -42,6 +42,7 @@ LIST_HEAD(rde_peer_head, rde_peer); - LIST_HEAD(aspath_head, rde_aspath); - RB_HEAD(uptree_prefix, update_prefix); - RB_HEAD(uptree_attr, update_attr); -+RB_HEAD(rib_tree, rib_entry); - TAILQ_HEAD(uplist_prefix, update_prefix); - TAILQ_HEAD(uplist_attr, update_attr); - -@@ -66,13 +67,13 @@ struct rde_peer { +@@ -56,12 +56,9 @@ struct rde_peer { + struct bgpd_addr local_v6_addr; + struct uptree_prefix up_prefix; + struct uptree_attr up_attrs; +- struct uplist_attr updates; +- struct uplist_prefix withdraws; +- struct uplist_attr updates6; +- struct uplist_prefix withdraws6; +- struct capabilities capa_announced; +- struct capabilities capa_received; ++ struct uplist_attr updates[AID_MAX]; ++ struct uplist_prefix withdraws[AID_MAX]; ++ struct capabilities capa; + u_int64_t prefix_rcvd_update; + u_int64_t prefix_rcvd_withdraw; u_int64_t prefix_sent_update; - u_int64_t prefix_sent_withdraw; - u_int32_t prefix_cnt; /* # of prefixes */ -- u_int32_t adjrib_cnt; /* # of p. in Adj-RIB-In */ - u_int32_t remote_bgpid; /* host byte order! */ - u_int32_t up_pcnt; - u_int32_t up_acnt; - u_int32_t up_nlricnt; - u_int32_t up_wcnt; - enum peer_state state; -+ u_int16_t ribid; - u_int16_t short_as; - u_int8_t reconf_in; /* in filter changed */ - u_int8_t reconf_out; /* out filter changed */ -@@ -107,8 +108,8 @@ enum attrtypes { - ATTR_MP_REACH_NLRI=14, - ATTR_MP_UNREACH_NLRI=15, - ATTR_EXT_COMMUNITIES=16, -- ATTR_NEW_ASPATH=17, -- ATTR_NEW_AGGREGATOR=18 -+ ATTR_AS4_PATH=17, -+ ATTR_AS4_AGGREGATOR=18 - }; - - /* attribute flags. 4 low order bits reserved */ -@@ -154,16 +155,16 @@ LIST_HEAD(prefix_head, prefix); - #define F_ATTR_MED_ANNOUNCE 0x00020 - #define F_ATTR_MP_REACH 0x00040 - #define F_ATTR_MP_UNREACH 0x00080 --#define F_ATTR_AS4BYTE_NEW 0x00100 /* NEW_ASPATH or NEW_AGGREGATOR */ -+#define F_ATTR_AS4BYTE_NEW 0x00100 /* AS4_PATH or AS4_AGGREGATOR */ - #define F_ATTR_LOOP 0x00200 /* path would cause a route loop */ --#define F_PREFIX_ANNOUNCED 0x01000 -+#define F_PREFIX_ANNOUNCED 0x00400 -+#define F_ANN_DYNAMIC 0x00800 -+#define F_NEXTHOP_SELF 0x01000 +@@ -163,6 +160,7 @@ LIST_HEAD(prefix_head, prefix); #define F_NEXTHOP_REJECT 0x02000 #define F_NEXTHOP_BLACKHOLE 0x04000 #define F_NEXTHOP_NOMODIFY 0x08000 --#define F_NEXTHOP_SELF 0x10000 +#define F_ATTR_PARSE_ERR 0x10000 #define F_ATTR_LINKED 0x20000 --#define F_LOCAL 0x40000 /* Local-RIB */ --#define F_ORIGINAL 0x80000 /* Adj-RIB-In */ - #define ORIGIN_IGP 0 -@@ -184,7 +185,6 @@ struct rde_aspath { - u_int32_t weight; /* low prio lpref */ - u_int32_t prefix_cnt; /* # of prefixes */ - u_int32_t active_cnt; /* # of active prefixes */ -- u_int32_t adjrib_cnt; /* # of p. in Adj-RIB-In */ - u_int32_t flags; /* internally used */ - u_int16_t rtlabelid; /* route label id */ - u_int16_t pftableid; /* pf table id */ -@@ -223,53 +223,72 @@ struct pt_entry { +@@ -220,14 +218,14 @@ struct nexthop { + /* generic entry without address specific part */ + struct pt_entry { RB_ENTRY(pt_entry) pt_e; - sa_family_t af; +- sa_family_t af; ++ u_int8_t aid; u_int8_t prefixlen; -- struct prefix_head prefix_h; -- struct prefix *active; /* for fast access */ -+ u_int16_t refcnt; + u_int16_t refcnt; }; struct pt_entry4 { RB_ENTRY(pt_entry) pt_e; - sa_family_t af; +- sa_family_t af; ++ u_int8_t aid; u_int8_t prefixlen; -- struct prefix_head prefix_h; -- struct prefix *active; /* for fast access */ -+ u_int16_t refcnt; + u_int16_t refcnt; struct in_addr prefix4; -- /* -- * Route Flap Damping structures -- * Currently I think they belong into the prefix but for the moment -- * we just ignore the dampening at all. -- */ - }; +@@ -235,12 +233,25 @@ struct pt_entry4 { struct pt_entry6 { RB_ENTRY(pt_entry) pt_e; - sa_family_t af; +- sa_family_t af; ++ u_int8_t aid; u_int8_t prefixlen; -- struct prefix_head prefix_h; -- struct prefix *active; /* for fast access */ -+ u_int16_t refcnt; + u_int16_t refcnt; struct in6_addr prefix6; }; --struct pt_context { -- union { -- struct pt_entry p; -- struct pt_entry4 p4; -- struct pt_entry6 p6; -- } pu; --#define ctx_p pu.p --#define ctx_p4 pu.p4 --#define ctx_p6 pu.p6 -- /* only count and done should be accessed by callers */ -- unsigned int count; -- int done; --}; -+struct rib_context { -+ LIST_ENTRY(rib_context) entry; -+ struct rib_entry *ctx_re; -+ struct rib *ctx_rib; -+ void (*ctx_upcall)(struct rib_entry *, void *); -+ void (*ctx_done)(void *); -+ void (*ctx_wait)(void *); -+ void *ctx_arg; -+ unsigned int ctx_count; -+ sa_family_t ctx_af; -+}; -+ -+struct rib_entry { -+ RB_ENTRY(rib_entry) rib_e; -+ struct prefix_head prefix_h; -+ struct prefix *active; /* for fast access */ -+ struct pt_entry *prefix; -+ u_int16_t ribid; -+ u_int16_t flags; -+}; -+ -+enum rib_state { -+ RIB_NONE, -+ RIB_NEW, -+ RIB_ACTIVE, -+ RIB_DELETE -+}; -+ -+struct rib { -+ char name[PEER_DESCR_LEN]; -+ struct rib_tree rib; -+ enum rib_state state; -+ u_int16_t flags; -+ u_int16_t id; ++struct pt_entry_vpn4 { ++ RB_ENTRY(pt_entry) pt_e; ++ u_int8_t aid; ++ u_int8_t prefixlen; ++ u_int16_t refcnt; ++ struct in_addr prefix4; ++ u_int64_t rd; ++ u_int8_t labelstack[21]; ++ u_int8_t labellen; ++ u_int8_t pad1; ++ u_int8_t pad2; +}; + -+#define F_RIB_ENTRYLOCK 0x0001 -+#define F_RIB_NOEVALUATE 0x0002 -+#define F_RIB_NOFIB 0x0004 -+#define RIB_FAILED 0xffff - - struct prefix { -- LIST_ENTRY(prefix) prefix_l, path_l; -+ LIST_ENTRY(prefix) rib_l, path_l; - struct rde_aspath *aspath; - struct pt_entry *prefix; -+ struct rib_entry *rib; /* NULL for Adj-RIB-In */ - time_t lastchange; -- u_int32_t flags; + struct rib_context { + LIST_ENTRY(rib_context) entry; + struct rib_entry *ctx_re; +@@ -250,7 +261,7 @@ struct rib_context { + void (*ctx_wait)(void *); + void *ctx_arg; + unsigned int ctx_count; +- sa_family_t ctx_af; ++ u_int8_t ctx_aid; }; - extern struct rde_memstats rdemem; -@@ -282,7 +301,8 @@ void rde_send_pftable(u_int16_t, struc - u_int8_t, int); - void rde_send_pftable_commit(void); + struct rib_entry { +@@ -264,6 +275,7 @@ struct rib_entry { --void rde_generate_updates(struct prefix *, struct prefix *); -+void rde_generate_updates(u_int16_t, struct prefix *, -+ struct prefix *); - u_int32_t rde_local_as(void); - int rde_noevaluate(void); - int rde_decisionflags(void); -@@ -291,6 +311,8 @@ 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 *, -+ u_int16_t); - void attr_init(u_int32_t); - void attr_shutdown(void); - int attr_optadd(struct rde_aspath *, u_int8_t, u_int8_t, -@@ -327,10 +349,24 @@ int community_set(struct rde_aspath *, + enum rib_state { + RIB_NONE, ++ RIB_NEW, + RIB_ACTIVE, + RIB_DELETE + }; +@@ -342,9 +354,13 @@ 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 community_match(struct rde_aspath *, int, int); + int community_set(struct rde_aspath *, int, int); void community_delete(struct rde_aspath *, int, int); ++int community_ext_set(struct rde_aspath *, ++ struct filter_extcommunity *, u_int16_t); ++void community_ext_delete(struct rde_aspath *, ++ struct filter_extcommunity *, u_int16_t); /* rde_rib.c */ -+extern u_int16_t rib_size; -+extern struct rib *ribs; -+ -+u_int16_t rib_new(int, char *, u_int16_t); -+u_int16_t rib_find(char *); -+void rib_free(struct rib *); -+struct rib_entry *rib_get(struct rib *, struct bgpd_addr *, int); -+struct rib_entry *rib_lookup(struct rib *, struct bgpd_addr *); -+void rib_dump(struct rib *, void (*)(struct rib_entry *, void *), -+ void *, sa_family_t); -+void rib_dump_r(struct rib_context *); -+void rib_dump_runner(void); -+int rib_dump_pending(void); -+ - void path_init(u_int32_t); - void path_shutdown(void); --void path_update(struct rde_peer *, struct rde_aspath *, -- struct bgpd_addr *, int, u_int32_t); -+int path_update(struct rib *, struct rde_peer *, -+ struct rde_aspath *, struct bgpd_addr *, int); - int path_compare(struct rde_aspath *, struct rde_aspath *); - struct rde_aspath *path_lookup(struct rde_aspath *, struct rde_peer *); - void path_remove(struct rde_aspath *); -@@ -343,18 +379,20 @@ void path_put(struct rde_aspath *); - #define PREFIX_SIZE(x) (((x) + 7) / 8 + 1) - int prefix_compare(const struct bgpd_addr *, - const struct bgpd_addr *, int); --struct prefix *prefix_get(struct rde_peer *, struct bgpd_addr *, int, -- u_int32_t); --struct pt_entry *prefix_add(struct rde_aspath *, struct bgpd_addr *, int, -- u_int32_t); --struct pt_entry *prefix_move(struct rde_aspath *, struct prefix *, u_int32_t); --void prefix_remove(struct rde_peer *, struct bgpd_addr *, int, -- u_int32_t); -+struct prefix *prefix_get(struct rib *, struct rde_peer *, -+ struct bgpd_addr *, int, u_int32_t); -+int prefix_add(struct rib *, struct rde_aspath *, -+ struct bgpd_addr *, int); -+void prefix_move(struct rde_aspath *, struct prefix *); -+int prefix_remove(struct rib *, struct rde_peer *, -+ struct bgpd_addr *, int, u_int32_t); - int prefix_write(u_char *, int, struct bgpd_addr *, u_int8_t); --struct prefix *prefix_bypeer(struct pt_entry *, struct rde_peer *, u_int32_t); --void prefix_updateall(struct rde_aspath *, enum nexthop_state); -+struct prefix *prefix_bypeer(struct rib_entry *, struct rde_peer *, -+ u_int32_t); -+void prefix_updateall(struct rde_aspath *, enum nexthop_state, -+ enum nexthop_state); - void prefix_destroy(struct prefix *); --void prefix_network_clean(struct rde_peer *, time_t); -+void prefix_network_clean(struct rde_peer *, time_t, u_int32_t); - + extern u_int16_t rib_size; +@@ -356,7 +372,7 @@ void rib_free(struct rib *); + struct rib_entry *rib_get(struct rib *, struct bgpd_addr *, int); + struct rib_entry *rib_lookup(struct rib *, struct bgpd_addr *); + void rib_dump(struct rib *, void (*)(struct rib_entry *, void *), +- void *, sa_family_t); ++ void *, u_int8_t); + void rib_dump_r(struct rib_context *); + void rib_dump_runner(void); + int rib_dump_pending(void); +@@ -395,7 +411,7 @@ void prefix_network_clean(struct rde_p void nexthop_init(u_int32_t); void nexthop_shutdown(void); -@@ -368,7 +406,7 @@ struct nexthop *nexthop_get(struct bgpd_ - int nexthop_compare(struct nexthop *, struct nexthop *); - - /* rde_decide.c */ --void prefix_evaluate(struct prefix *, struct pt_entry *); -+void prefix_evaluate(struct prefix *, struct rib_entry *); - - /* rde_update.c */ - void up_init(struct rde_peer *); -@@ -387,24 +425,34 @@ u_char *up_dump_mp_unreach(u_char *, u_ - u_char *up_dump_mp_reach(u_char *, u_int16_t *, struct rde_peer *); - - /* rde_prefix.c */ --void pt_init(void); --void pt_shutdown(void); --int pt_empty(struct pt_entry *); --void pt_getaddr(struct pt_entry *, struct bgpd_addr *); -+#define pt_empty(pt) ((pt)->refcnt == 0) -+#define pt_ref(pt) do { \ -+ ++(pt)->refcnt; \ -+ if ((pt)->refcnt == 0) \ -+ fatalx("pt_ref: overflow"); \ -+} while(0) -+#define pt_unref(pt) do { \ -+ if ((pt)->refcnt == 0) \ -+ fatalx("pt_unref: underflow"); \ -+ --(pt)->refcnt; \ -+} while(0) -+ -+void pt_init(void); -+void pt_shutdown(void); -+void pt_getaddr(struct pt_entry *, struct bgpd_addr *); -+struct pt_entry *pt_fill(struct bgpd_addr *, int); - struct pt_entry *pt_get(struct bgpd_addr *, int); - struct pt_entry *pt_add(struct bgpd_addr *, int); --void pt_remove(struct pt_entry *); -+void pt_remove(struct pt_entry *); - struct pt_entry *pt_lookup(struct bgpd_addr *); --void pt_dump(void (*)(struct pt_entry *, void *), void *, + void nexthop_modify(struct rde_aspath *, struct bgpd_addr *, +- enum action_types, sa_family_t); ++ enum action_types, u_int8_t); + void nexthop_link(struct rde_aspath *); + void nexthop_unlink(struct rde_aspath *); + int nexthop_delete(struct nexthop *); +@@ -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 *, - sa_family_t); --void pt_dump_r(void (*)(struct pt_entry *, void *), void *, -- sa_family_t, struct pt_context *); -+int pt_prefix_cmp(const struct pt_entry *, const struct pt_entry *); -+ ++ u_int8_t); ++int up_generate_marker(struct rde_peer *, u_int8_t); + int up_dump_prefix(u_char *, int, struct uplist_prefix *, + struct rde_peer *); + int up_dump_attrnlri(u_char *, int, struct rde_peer *); +-u_char *up_dump_mp_unreach(u_char *, u_int16_t *, struct rde_peer *); +-u_char *up_dump_mp_reach(u_char *, u_int16_t *, struct rde_peer *); ++u_char *up_dump_mp_unreach(u_char *, u_int16_t *, struct rde_peer *, ++ u_int8_t); ++int up_dump_mp_reach(u_char *, u_int16_t *, struct rde_peer *, ++ u_int8_t); - /* rde_filter.c */ --enum filter_actions rde_filter(struct rde_aspath **, struct filter_head *, -- struct rde_peer *, struct rde_aspath *, -- struct bgpd_addr *, u_int8_t, struct rde_peer *, -- enum directions); -+enum filter_actions rde_filter(u_int16_t, struct rde_aspath **, -+ struct filter_head *, struct rde_peer *, -+ struct rde_aspath *, struct bgpd_addr *, u_int8_t, -+ struct rde_peer *, enum directions); + /* rde_prefix.c */ + #define pt_empty(pt) ((pt)->refcnt == 0) +@@ -452,8 +471,7 @@ enum filter_actions rde_filter(u_int16_t + struct rde_aspath *, struct bgpd_addr *, u_int8_t, + struct rde_peer *, enum directions); void rde_apply_set(struct rde_aspath *, struct filter_set_head *, - sa_family_t, struct rde_peer *, struct rde_peer *); - int rde_filter_community(struct rde_aspath *, int, int); +- sa_family_t, struct rde_peer *, struct rde_peer *); +-int rde_filter_community(struct rde_aspath *, int, int); ++ u_int8_t, struct rde_peer *, struct rde_peer *); + int rde_filter_equal(struct filter_head *, struct filter_head *, + struct rde_peer *, enum directions); + diff --git a/net/openbgpd/files/patch-bgpd_rde_attr.c b/net/openbgpd/files/patch-bgpd_rde_attr.c index b6ad8ab1872c..7aa74567837d 100644 --- a/net/openbgpd/files/patch-bgpd_rde_attr.c +++ b/net/openbgpd/files/patch-bgpd_rde_attr.c @@ -1,14 +1,14 @@ Index: bgpd/rde_attr.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_attr.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.3 -diff -u -p -r1.1.1.1 -r1.3 ---- bgpd/rde_attr.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/rde_attr.c 9 Jul 2009 17:22:14 -0000 1.3 +retrieving revision 1.1.1.6 +retrieving revision 1.4 +diff -u -p -r1.1.1.6 -r1.4 +--- bgpd/rde_attr.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 ++++ bgpd/rde_attr.c 4 Feb 2010 16:22:23 -0000 1.4 @@ -1,4 +1,4 @@ --/* $OpenBSD: rde_attr.c,v 1.76.2.1 2009/02/18 20:30:36 claudio Exp $ */ -+/* $OpenBSD: rde_attr.c,v 1.79 2009/03/19 06:52:59 claudio Exp $ */ +-/* $OpenBSD: rde_attr.c,v 1.79 2009/03/19 06:52:59 claudio Exp $ */ ++/* $OpenBSD: rde_attr.c,v 1.81 2009/12/18 15:51:37 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -34,44 +34,222 @@ diff -u -p -r1.1.1.1 -r1.3 #include "bgpd.h" #include "rde.h" -@@ -62,6 +69,31 @@ attr_write(void *p, u_int16_t p_len, u_i - return (tot_len); +@@ -971,13 +978,26 @@ aspath_match(struct aspath *a, enum as_s + return (0); } ++/* ++ * Functions handling communities and extended communities. ++ */ ++ ++int community_ext_conv(struct filter_extcommunity *, u_int16_t, u_int64_t *); ++ + int +-community_match(void *data, u_int16_t len, int as, int type) ++community_match(struct rde_aspath *asp, int as, int type) + { +- u_int8_t *p = data; +- u_int16_t eas, etype; ++ struct attr *a; ++ u_int8_t *p; ++ u_int16_t eas, etype, len; + +- len >>= 2; /* divide by four */ ++ a = attr_optget(asp, ATTR_COMMUNITIES); ++ if (a == NULL) ++ /* no communities, no match */ ++ return (0); ++ ++ len = a->len / 4; ++ p = a->data; + + for (; len > 0; len--) { + eas = *p++; +@@ -1000,7 +1020,6 @@ community_set(struct rde_aspath *asp, in + u_int8_t *p = NULL; + unsigned int i, ncommunities = 0; + u_int8_t f = ATTR_OPTIONAL|ATTR_TRANSITIVE; +- u_int8_t t = ATTR_COMMUNITIES; + + attr = attr_optget(asp, ATTR_COMMUNITIES); + if (attr != NULL) { +@@ -1017,7 +1036,7 @@ community_set(struct rde_aspath *asp, in + p += 4; + } + +- if (ncommunities++ >= 0x3fff) ++ if (ncommunities++ >= USHRT_MAX / 4) + /* overflow */ + return (0); + +@@ -1032,11 +1051,10 @@ community_set(struct rde_aspath *asp, in + if (attr != NULL) { + memcpy(p + 4, attr->data, attr->len); + f = attr->flags; +- t = attr->type; + attr_free(asp, attr); + } + +- attr_optadd(asp, f, t, p, ncommunities << 2); ++ attr_optadd(asp, f, ATTR_COMMUNITIES, p, ncommunities << 2); + + free(p); + return (1); +@@ -1049,7 +1067,7 @@ community_delete(struct rde_aspath *asp, + u_int8_t *p, *n; + u_int16_t l, len = 0; + u_int16_t eas, etype; +- u_int8_t f, t; ++ u_int8_t f; + + attr = attr_optget(asp, ATTR_COMMUNITIES); + if (attr == NULL) +@@ -1100,10 +1118,146 @@ community_delete(struct rde_aspath *asp, + } + + f = attr->flags; +- t = attr->type; + + attr_free(asp, attr); +- attr_optadd(asp, f, t, n, len); ++ attr_optadd(asp, f, ATTR_COMMUNITIES, n, len); ++ free(n); ++} ++ +int -+attr_writebuf(struct buf *buf, u_int8_t flags, u_int8_t type, void *data, -+ u_int16_t data_len) ++community_ext_set(struct rde_aspath *asp, struct filter_extcommunity *c, ++ u_int16_t neighas) +{ -+ u_char hdr[4]; -+ -+ if (data_len > 255) { -+ flags |= ATTR_EXTLEN; -+ hdr[2] = (data_len >> 8) & 0xff; -+ hdr[3] = data_len & 0xff; -+ } else { -+ flags &= ~ATTR_EXTLEN; -+ hdr[2] = data_len & 0xff; ++ struct attr *attr; ++ u_int8_t *p = NULL; ++ u_int64_t community; ++ unsigned int i, ncommunities = 0; ++ u_int8_t f = ATTR_OPTIONAL|ATTR_TRANSITIVE; ++ ++ if (community_ext_conv(c, neighas, &community)) ++ return (0); ++ ++ attr = attr_optget(asp, ATTR_EXT_COMMUNITIES); ++ if (attr != NULL) { ++ p = attr->data; ++ ncommunities = attr->len / 8; /* 64bit per ext-community */ + } + -+ hdr[0] = flags; -+ hdr[1] = type; ++ /* first check if the community is not already set */ ++ for (i = 0; i < ncommunities; i++) { ++ if (memcmp(&community, p, sizeof(community)) == 0) ++ /* already present, nothing todo */ ++ return (1); ++ p += sizeof(community); ++ } + -+ if (buf_add(buf, hdr, flags & ATTR_EXTLEN ? 4 : 3) == -1) -+ return (-1); -+ if (buf_add(buf, data, data_len) == -1) -+ return (-1); -+ return (0); ++ if (ncommunities++ >= USHRT_MAX / sizeof(community)) ++ /* overflow */ ++ return (0); ++ ++ if ((p = malloc(ncommunities * sizeof(community))) == NULL) ++ fatal("community_ext_set"); ++ ++ memcpy(p, &community, sizeof(community)); ++ if (attr != NULL) { ++ memcpy(p + sizeof(community), attr->data, attr->len); ++ f = attr->flags; ++ attr_free(asp, attr); ++ } ++ ++ attr_optadd(asp, f, ATTR_EXT_COMMUNITIES, p, ++ ncommunities * sizeof(community)); ++ ++ free(p); ++ return (1); +} + - /* optional attribute specific functions */ - int attr_diff(struct attr *, struct attr *); - struct attr *attr_alloc(u_int8_t, u_int8_t, const void *, u_int16_t); -@@ -588,7 +620,7 @@ aspath_merge(struct rde_aspath *a, struc - - ascnt = aspath_count(attr->data, attr->len); - if (ascnt > a->aspath->ascnt) { -- /* ASPATH is shorter then NEW_ASPATH no way to merge */ -+ /* ASPATH is shorter then AS4_PATH no way to merge */ - attr_free(a, attr); - return; - } ++void ++community_ext_delete(struct rde_aspath *asp, struct filter_extcommunity *c, ++ u_int16_t neighas) ++{ ++ struct attr *attr; ++ u_int8_t *p, *n; ++ u_int64_t community; ++ u_int16_t l, len = 0; ++ u_int8_t f; ++ ++ if (community_ext_conv(c, neighas, &community)) ++ return; ++ ++ attr = attr_optget(asp, ATTR_EXT_COMMUNITIES); ++ if (attr == NULL) ++ /* no attr nothing to do */ ++ return; ++ ++ p = attr->data; ++ for (l = 0; l < attr->len; l += sizeof(community)) { ++ if (memcmp(&community, p + l, sizeof(community)) == 0) ++ /* match */ ++ continue; ++ len += sizeof(community); ++ } ++ ++ if (len == 0) { ++ attr_free(asp, attr); ++ return; ++ } ++ ++ if ((n = malloc(len)) == NULL) ++ fatal("community_delete"); ++ ++ p = attr->data; ++ for (l = 0; l < len && p < attr->data + attr->len; ++ p += sizeof(community)) { ++ if (memcmp(&community, p, sizeof(community)) == 0) ++ /* match */ ++ continue; ++ memcpy(n + l, p, sizeof(community)); ++ l += sizeof(community); ++ } ++ ++ f = attr->flags; ++ ++ attr_free(asp, attr); ++ attr_optadd(asp, f, ATTR_EXT_COMMUNITIES, n, len); + free(n); + } + ++int ++community_ext_conv(struct filter_extcommunity *c, u_int16_t neighas, ++ u_int64_t *community) ++{ ++ u_int64_t com; ++ u_int32_t ip; ++ ++ com = (u_int64_t)c->type << 56; ++ switch (c->type & EXT_COMMUNITY_VALUE) { ++ case EXT_COMMUNITY_TWO_AS: ++ com |= (u_int64_t)c->subtype << 48; ++ com |= (u_int64_t)c->data.ext_as.as << 32; ++ com |= c->data.ext_as.val; ++ break; ++ case EXT_COMMUNITY_IPV4: ++ com |= (u_int64_t)c->subtype << 48; ++ ip = ntohl(c->data.ext_ip.addr.s_addr); ++ com |= (u_int64_t)ip << 16; ++ com |= c->data.ext_ip.val; ++ break; ++ case EXT_COMMUNITY_FOUR_AS: ++ com |= (u_int64_t)c->subtype << 48; ++ com |= (u_int64_t)c->data.ext_as4.as4 << 16; ++ com |= c->data.ext_as4.val; ++ break; ++ case EXT_COMMUNITY_OPAQUE: ++ com |= (u_int64_t)c->subtype << 48; ++ com |= c->data.ext_opaq & EXT_COMMUNITY_OPAQUE_MAX; ++ break; ++ default: ++ com |= c->data.ext_opaq & 0xffffffffffffffULL; ++ break; ++ } ++ ++ *community = htobe64(com); ++ ++ return (0); ++} diff --git a/net/openbgpd/files/patch-bgpd_rde_decide.c b/net/openbgpd/files/patch-bgpd_rde_decide.c index 68fa6768d8ea..84cafd11beef 100644 --- a/net/openbgpd/files/patch-bgpd_rde_decide.c +++ b/net/openbgpd/files/patch-bgpd_rde_decide.c @@ -1,27 +1,18 @@ Index: bgpd/rde_decide.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_decide.c,v -retrieving revision 1.1.1.1 +retrieving revision 1.1.1.6 retrieving revision 1.2 -diff -u -p -r1.1.1.1 -r1.2 ---- bgpd/rde_decide.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 +diff -u -p -r1.1.1.6 -r1.2 +--- 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 @@ -1,4 +1,4 @@ --/* $OpenBSD: rde_decide.c,v 1.51 2008/05/08 09:51:46 henning Exp $ */ +-/* $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 $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> -@@ -115,15 +115,15 @@ prefix_cmp(struct prefix *p1, struct pre - if (p2 == NULL) - return (1); - -- /* only prefixes in the Local-RIB are eligible */ -- if (!(p1->flags & F_LOCAL)) -- return (-1); -- if (!(p2->flags & F_LOCAL)) -- return (1); -- +@@ -118,6 +118,12 @@ prefix_cmp(struct prefix *p1, struct pre asp1 = p1->aspath; asp2 = p2->aspath; @@ -34,104 +25,21 @@ diff -u -p -r1.1.1.1 -r1.2 /* only loop free pathes are eligible */ if (asp1->flags & F_ATTR_LOOP) return (-1); -@@ -201,9 +201,16 @@ prefix_cmp(struct prefix *p1, struct pre - &p2->aspath->peer->remote_addr, - sizeof(p1->aspath->peer->remote_addr))); +@@ -204,7 +210,7 @@ prefix_cmp(struct prefix *p1, struct pre + } -+ /* 12. for announced prefixes prefer dynamic routes */ -+ if ((asp1->flags & F_ANN_DYNAMIC) != (asp2->flags & F_ANN_DYNAMIC)) { -+ if (asp1->flags & F_ANN_DYNAMIC) -+ return (1); -+ else -+ return (-1); -+ } -+ fatalx("Uh, oh a politician in the decision process"); - /* NOTREACHED */ -- return (0); + return(0); /* NOTREACHED */ } /* -@@ -212,59 +219,59 @@ prefix_cmp(struct prefix *p1, struct pre - * The to evaluate prefix must not be in the prefix list. - */ - void --prefix_evaluate(struct prefix *p, struct pt_entry *pte) -+prefix_evaluate(struct prefix *p, struct rib_entry *re) - { - struct prefix *xp; - -- if (rde_noevaluate()) { -+ if (re->flags & F_RIB_NOEVALUATE || rde_noevaluate()) { - /* decision process is turned off */ - if (p != NULL) -- LIST_INSERT_HEAD(&pte->prefix_h, p, prefix_l); -- if (pte->active != NULL) { -- pte->active->aspath->active_cnt--; -- pte->active = NULL; -+ LIST_INSERT_HEAD(&re->prefix_h, p, rib_l); -+ if (re->active != NULL) { -+ re->active->aspath->active_cnt--; -+ re->active = NULL; - } - return; - } - - if (p != NULL) { -- if (LIST_EMPTY(&pte->prefix_h)) -- LIST_INSERT_HEAD(&pte->prefix_h, p, prefix_l); -+ if (LIST_EMPTY(&re->prefix_h)) -+ LIST_INSERT_HEAD(&re->prefix_h, p, rib_l); - else { -- LIST_FOREACH(xp, &pte->prefix_h, prefix_l) -+ LIST_FOREACH(xp, &re->prefix_h, rib_l) - if (prefix_cmp(p, xp) > 0) { -- LIST_INSERT_BEFORE(xp, p, prefix_l); -+ LIST_INSERT_BEFORE(xp, p, rib_l); - break; -- } else if (LIST_NEXT(xp, prefix_l) == NULL) { -+ } else if (LIST_NEXT(xp, rib_l) == NULL) { - /* if xp last element ... */ -- LIST_INSERT_AFTER(xp, p, prefix_l); -+ LIST_INSERT_AFTER(xp, p, rib_l); - break; - } - } +@@ -245,7 +251,7 @@ prefix_evaluate(struct prefix *p, struct } -- xp = LIST_FIRST(&pte->prefix_h); -- if (xp == NULL || !(xp->flags & F_LOCAL) || -- xp->aspath->flags & F_ATTR_LOOP || -+ xp = LIST_FIRST(&re->prefix_h); + xp = LIST_FIRST(&re->prefix_h); +- if (xp == NULL || xp->aspath->flags & F_ATTR_LOOP || + if (xp == NULL || xp->aspath->flags & (F_ATTR_LOOP|F_ATTR_PARSE_ERR) || (xp->aspath->nexthop != NULL && xp->aspath->nexthop->state != NEXTHOP_REACH)) /* xp is ineligible */ - xp = NULL; - -- if (pte->active != xp) { -+ if (re->active != xp) { - /* need to generate an update */ -- if (pte->active != NULL) -- pte->active->aspath->active_cnt--; -+ if (re->active != NULL) -+ re->active->aspath->active_cnt--; - - /* -- * Send update with remove for pte->active and add for xp -+ * Send update with remove for re->active and add for xp - * but remember that xp may be NULL aka ineligible. - * Additional decision may be made by the called functions. - */ -- rde_generate_updates(xp, pte->active); -- rde_send_kroute(xp, pte->active); -+ rde_generate_updates(re->ribid, xp, re->active); -+ if ((re->flags & F_RIB_NOFIB) == 0) -+ rde_send_kroute(xp, re->active); - -- pte->active = xp; -+ re->active = xp; - if (xp != NULL) - xp->aspath->active_cnt++; - } diff --git a/net/openbgpd/files/patch-bgpd_rde_filter.c b/net/openbgpd/files/patch-bgpd_rde_filter.c index b22c6b36efc2..a19d044bb451 100644 --- a/net/openbgpd/files/patch-bgpd_rde_filter.c +++ b/net/openbgpd/files/patch-bgpd_rde_filter.c @@ -1,27 +1,18 @@ Index: bgpd/rde_filter.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_filter.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.4 -diff -u -p -r1.1.1.1 -r1.4 ---- bgpd/rde_filter.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/rde_filter.c 10 Aug 2009 21:20:05 -0000 1.4 +retrieving revision 1.1.1.7 +retrieving revision 1.5 +diff -u -p -r1.1.1.7 -r1.5 +--- bgpd/rde_filter.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 ++++ bgpd/rde_filter.c 4 Feb 2010 16:22:23 -0000 1.5 @@ -1,4 +1,4 @@ --/* $OpenBSD: rde_filter.c,v 1.54 2008/06/15 10:19:21 claudio Exp $ */ -+/* $OpenBSD: rde_filter.c,v 1.57 2009/08/06 08:53:11 claudio Exp $ */ +-/* $OpenBSD: rde_filter.c,v 1.56 2009/06/06 01:10:29 claudio Exp $ */ ++/* $OpenBSD: rde_filter.c,v 1.61 2009/12/18 15:51:37 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> -@@ -30,7 +30,7 @@ int rde_filter_match(struct filter_rule - int filterset_equal(struct filter_set_head *, struct filter_set_head *); - - enum filter_actions --rde_filter(struct rde_aspath **new, struct filter_head *rules, -+rde_filter(u_int16_t ribid, struct rde_aspath **new, struct filter_head *rules, - struct rde_peer *peer, struct rde_aspath *asp, struct bgpd_addr *prefix, - u_int8_t prefixlen, struct rde_peer *from, enum directions dir) - { -@@ -40,9 +40,18 @@ rde_filter(struct rde_aspath **new, stru +@@ -40,6 +40,13 @@ rde_filter(u_int16_t ribid, struct rde_a if (new != NULL) *new = NULL; @@ -35,26 +26,148 @@ diff -u -p -r1.1.1.1 -r1.4 TAILQ_FOREACH(f, rules, entry) { if (dir != f->dir) continue; -+ if (dir == DIR_IN && f->peer.ribid != ribid) -+ continue; - if (f->peer.groupid != 0 && - f->peer.groupid != peer->conf.groupid) - continue; -@@ -283,8 +292,11 @@ rde_filter_match(struct filter_rule *f, +@@ -59,7 +66,7 @@ rde_filter(u_int16_t ribid, struct rde_a + /* ... and use the copy from now on */ + asp = *new; + } +- rde_apply_set(asp, &f->set, prefix->af, ++ rde_apply_set(asp, &f->set, prefix->aid, + from, peer); + } + if (f->action != ACTION_NONE) +@@ -73,7 +80,7 @@ rde_filter(u_int16_t ribid, struct rde_a + + void + rde_apply_set(struct rde_aspath *asp, struct filter_set_head *sh, +- sa_family_t af, struct rde_peer *from, struct rde_peer *peer) ++ u_int8_t aid, struct rde_peer *from, struct rde_peer *peer) + { + struct filter_set *set; + u_char *np; +@@ -167,7 +174,7 @@ rde_apply_set(struct rde_aspath *asp, st + case ACTION_SET_NEXTHOP_NOMODIFY: + case ACTION_SET_NEXTHOP_SELF: + nexthop_modify(asp, &set->action.nexthop, set->type, +- af); ++ aid); + break; + case ACTION_SET_COMMUNITY: + switch (set->action.community.as) { +@@ -243,6 +250,17 @@ rde_apply_set(struct rde_aspath *asp, st + asp->rtlabelid = set->action.id; + rtlabel_ref(asp->rtlabelid); + break; ++ case ACTION_SET_ORIGIN: ++ asp->origin = set->action.origin; ++ break; ++ case ACTION_SET_EXT_COMMUNITY: ++ community_ext_set(asp, &set->action.ext_community, ++ peer->conf.remote_as); ++ break; ++ case ACTION_DEL_EXT_COMMUNITY: ++ community_ext_delete(asp, &set->action.ext_community, ++ peer->conf.remote_as); ++ break; + } + } + } +@@ -281,12 +299,12 @@ rde_filter_match(struct filter_rule *f, + break; + } + +- if (rde_filter_community(asp, as, type) == 0) ++ if (community_match(asp, as, type) == 0) return (0); } -- if (f->match.prefix.addr.af != 0 && -- f->match.prefix.addr.af == prefix->af) { -+ if (f->match.prefix.addr.af != 0) { -+ if (f->match.prefix.addr.af != prefix->af) -+ /* don't use IPv4 rules for IPv6 and vice versa */ -+ return (0); -+ - if (prefix_compare(prefix, &f->match.prefix.addr, - f->match.prefix.len)) +- if (f->match.prefix.addr.af != 0) { +- if (f->match.prefix.addr.af != prefix->af) ++ if (f->match.prefix.addr.aid != 0) { ++ if (f->match.prefix.addr.aid != prefix->aid) + /* don't use IPv4 rules for IPv6 and vice versa */ + return (0); + +@@ -322,7 +340,7 @@ rde_filter_match(struct filter_rule *f, + } else if (f->match.prefixlen.op != OP_NONE) { + /* only prefixlen without a prefix */ + +- if (f->match.prefixlen.af != prefix->af) ++ if (f->match.prefixlen.aid != prefix->aid) + /* don't use IPv4 rules for IPv6 and vice versa */ return (0); -@@ -614,4 +626,5 @@ filterset_name(enum action_types type) + +@@ -356,19 +374,6 @@ rde_filter_match(struct filter_rule *f, + } + + int +-rde_filter_community(struct rde_aspath *asp, int as, int type) +-{ +- struct attr *a; +- +- a = attr_optget(asp, ATTR_COMMUNITIES); +- if (a == NULL) +- /* no communities, no match */ +- return (0); +- +- return (community_match(a->data, a->len, as, type)); +-} +- +-int + rde_filter_equal(struct filter_head *a, struct filter_head *b, + struct rde_peer *peer, enum directions dir) + { +@@ -476,6 +481,12 @@ filterset_cmp(struct filter_set *a, stru + return (a->action.community.type - b->action.community.type); + } + ++ if (a->type == ACTION_SET_EXT_COMMUNITY || ++ a->type == ACTION_DEL_EXT_COMMUNITY) { /* a->type == b->type */ ++ return (memcmp(&a->action.ext_community, ++ &b->action.ext_community, sizeof(a->action.ext_community))); ++ } ++ + if (a->type == ACTION_SET_NEXTHOP && b->type == ACTION_SET_NEXTHOP) { + /* + * This is the only interesting case, all others are considered +@@ -483,7 +494,7 @@ filterset_cmp(struct filter_set *a, stru + * reject it at the same time. Allow one IPv4 and one IPv6 + * per filter set or only one of the other nexthop modifiers. + */ +- return (a->action.nexthop.af - b->action.nexthop.af); ++ return (a->action.nexthop.aid - b->action.nexthop.aid); + } + + /* equal */ +@@ -574,6 +585,19 @@ filterset_equal(struct filter_set_head * + if (strcmp(as, bs) == 0) + continue; + break; ++ case ACTION_SET_ORIGIN: ++ if (a->type == b->type && ++ a->action.origin == b->action.origin) ++ continue; ++ break; ++ case ACTION_SET_EXT_COMMUNITY: ++ case ACTION_DEL_EXT_COMMUNITY: ++ if (a->type == b->type && memcmp( ++ &a->action.ext_community, ++ &b->action.ext_community, ++ sizeof(a->action.ext_community)) == 0) ++ continue; ++ break; + } + /* compare failed */ + return (0); +@@ -616,7 +640,14 @@ filterset_name(enum action_types type) + case ACTION_RTLABEL: + case ACTION_RTLABEL_ID: + return ("rtlabel"); ++ case ACTION_SET_ORIGIN: ++ return ("origin"); ++ case ACTION_SET_EXT_COMMUNITY: ++ return ("ext-community"); ++ case ACTION_DEL_EXT_COMMUNITY: ++ return ("ext-community delete"); } fatalx("filterset_name: got lost"); diff --git a/net/openbgpd/files/patch-bgpd_rde_prefix.c b/net/openbgpd/files/patch-bgpd_rde_prefix.c index 60093010f27a..7df1c4ee65e0 100644 --- a/net/openbgpd/files/patch-bgpd_rde_prefix.c +++ b/net/openbgpd/files/patch-bgpd_rde_prefix.c @@ -1,332 +1,294 @@ Index: bgpd/rde_prefix.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_prefix.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.3 -diff -u -p -r1.1.1.1 -r1.3 ---- bgpd/rde_prefix.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/rde_prefix.c 9 Jul 2009 17:22:14 -0000 1.3 +retrieving revision 1.1.1.6 +retrieving revision 1.4 +diff -u -p -r1.1.1.6 -r1.4 +--- bgpd/rde_prefix.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 ++++ bgpd/rde_prefix.c 4 Feb 2010 16:22:23 -0000 1.4 @@ -1,4 +1,4 @@ --/* $OpenBSD: rde_prefix.c,v 1.25 2007/05/11 11:27:59 claudio Exp $ */ -+/* $OpenBSD: rde_prefix.c,v 1.29 2009/05/30 18:27:17 claudio Exp $ */ +-/* $OpenBSD: rde_prefix.c,v 1.29 2009/05/30 18:27:17 claudio Exp $ */ ++/* $OpenBSD: rde_prefix.c,v 1.31 2010/01/13 06:02:37 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> -@@ -40,46 +40,30 @@ +@@ -38,15 +38,16 @@ + * pt_lookup: lookup a IP in the prefix table. Mainly for "show ip bgp". + * pt_empty: returns true if there is no bgp prefix linked to the pt_entry. * pt_init: initialize prefix table. - * pt_alloc?: allocate a AF specific pt_entry. Internal function. +- * pt_alloc?: allocate a AF specific pt_entry. Internal function. ++ * pt_alloc: allocate a AF specific pt_entry. Internal function. * pt_free: free a pt_entry. Internal function. -- * pt_restart used to restart a tree walk at the spot it was aborted earlier. */ /* internal prototypes */ - static struct pt_entry4 *pt_alloc4(void); - static struct pt_entry6 *pt_alloc6(void); +-static struct pt_entry4 *pt_alloc4(void); +-static struct pt_entry6 *pt_alloc6(void); ++static struct pt_entry *pt_alloc(struct pt_entry *); static void pt_free(struct pt_entry *); --static struct pt_entry *pt_restart(struct pt_context *); --int pt_prefix_cmp(const struct pt_entry *, const struct pt_entry *); -- --#define MIN_PREFIX 0 --#define MAX_PREFIX 32 ++size_t pt_sizes[AID_MAX] = AID_PTSIZE; ++ RB_HEAD(pt_tree, pt_entry); RB_PROTOTYPE(pt_tree, pt_entry, pt_e, pt_prefix_cmp); RB_GENERATE(pt_tree, pt_entry, pt_e, pt_prefix_cmp); - --struct pt_tree pttable4; --struct pt_tree pttable6; -+struct pt_tree pttable; - - void - pt_init(void) +@@ -70,17 +71,24 @@ void + pt_getaddr(struct pt_entry *pte, struct bgpd_addr *addr) { -- RB_INIT(&pttable4); -- RB_INIT(&pttable6); -+ RB_INIT(&pttable); - } - - void - pt_shutdown(void) - { -- if (!RB_EMPTY(&pttable4)) -- log_debug("pt_shutdown: IPv4 tree is not empty."); -- if (!RB_EMPTY(&pttable6)) -- log_debug("pt_shutdown: IPv6 tree is not empty."); --} -- --int --pt_empty(struct pt_entry *pte) --{ -- return LIST_EMPTY(&pte->prefix_h); -+ if (!RB_EMPTY(&pttable)) -+ log_debug("pt_shutdown: tree is not empty."); - } - - void -@@ -103,14 +87,15 @@ pt_getaddr(struct pt_entry *pte, struct - } - + bzero(addr, sizeof(struct bgpd_addr)); +- switch (pte->af) { +- case AF_INET: +- addr->af = pte->af; ++ addr->aid = pte->aid; ++ switch (addr->aid) { ++ case AID_INET: + addr->v4 = ((struct pt_entry4 *)pte)->prefix4; + break; +- case AF_INET6: +- addr->af = pte->af; ++ case AID_INET6: + memcpy(&addr->v6, &((struct pt_entry6 *)pte)->prefix6, + sizeof(addr->v6)); + /* XXX scope_id ??? */ + break; ++ case AID_VPN_IPv4: ++ addr->vpn4.addr = ((struct pt_entry_vpn4 *)pte)->prefix4; ++ addr->vpn4.rd = ((struct pt_entry_vpn4 *)pte)->rd; ++ addr->vpn4.labellen = ((struct pt_entry_vpn4 *)pte)->labellen; ++ memcpy(addr->vpn4.labelstack, ++ ((struct pt_entry_vpn4 *)pte)->labelstack, ++ addr->vpn4.labellen); ++ break; + default: + fatalx("pt_getaddr: unknown af"); + } +@@ -89,33 +97,49 @@ pt_getaddr(struct pt_entry *pte, struct struct pt_entry * --pt_get(struct bgpd_addr *prefix, int prefixlen) -+pt_fill(struct bgpd_addr *prefix, int prefixlen) + pt_fill(struct bgpd_addr *prefix, int prefixlen) { -- struct pt_entry4 pte4; -- struct pt_entry6 pte6; -+ static struct pt_entry4 pte4; -+ static struct pt_entry6 pte6; - in_addr_t addr_hbo; +- static struct pt_entry4 pte4; +- static struct pt_entry6 pte6; +- in_addr_t addr_hbo; ++ static struct pt_entry4 pte4; ++ static struct pt_entry6 pte6; ++ static struct pt_entry_vpn4 pte_vpn4; ++ in_addr_t addr_hbo; - switch (prefix->af) { - case AF_INET: -+ bzero(&pte4, sizeof(pte4)); +- switch (prefix->af) { +- case AF_INET: ++ switch (prefix->aid) { ++ case AID_INET: + bzero(&pte4, sizeof(pte4)); ++ pte4.aid = prefix->aid; if (prefixlen > 32) - fatalx("pt_get: bad IPv4 prefixlen"); - pte4.af = AF_INET; -@@ -118,24 +103,33 @@ pt_get(struct bgpd_addr *prefix, int pre +- fatalx("pt_get: bad IPv4 prefixlen"); +- pte4.af = AF_INET; ++ fatalx("pt_fill: bad IPv4 prefixlen"); + addr_hbo = ntohl(prefix->v4.s_addr); pte4.prefix4.s_addr = htonl(addr_hbo & prefixlen2mask(prefixlen)); pte4.prefixlen = prefixlen; -- return RB_FIND(pt_tree, &pttable4, (struct pt_entry *)&pte4); -+ return ((struct pt_entry *)&pte4); - case AF_INET6: -+ bzero(&pte6, sizeof(pte6)); + return ((struct pt_entry *)&pte4); +- case AF_INET6: ++ case AID_INET6: + bzero(&pte6, sizeof(pte6)); ++ pte6.aid = prefix->aid; if (prefixlen > 128) fatalx("pt_get: bad IPv6 prefixlen"); - pte6.af = AF_INET6; +- pte6.af = AF_INET6; pte6.prefixlen = prefixlen; inet6applymask(&pte6.prefix6, &prefix->v6, prefixlen); -- return RB_FIND(pt_tree, &pttable6, (struct pt_entry *)&pte6); -+ return ((struct pt_entry *)&pte6); + return ((struct pt_entry *)&pte6); ++ case AID_VPN_IPv4: ++ bzero(&pte_vpn4, sizeof(pte_vpn4)); ++ pte_vpn4.aid = prefix->aid; ++ if (prefixlen > 32) ++ fatalx("pt_fill: bad IPv4 prefixlen"); ++ addr_hbo = ntohl(prefix->vpn4.addr.s_addr); ++ pte_vpn4.prefix4.s_addr = htonl(addr_hbo & ++ prefixlen2mask(prefixlen)); ++ pte_vpn4.prefixlen = prefixlen; ++ pte_vpn4.rd = prefix->vpn4.rd; ++ pte_vpn4.labellen = prefix->vpn4.labellen; ++ memcpy(pte_vpn4.labelstack, prefix->vpn4.labelstack, ++ prefix->vpn4.labellen); ++ return ((struct pt_entry *)&pte_vpn4); default: - log_warnx("pt_get: unknown af"); -+ return (NULL); +- log_warnx("pt_get: unknown af"); +- return (NULL); ++ fatalx("pt_fill: unknown af"); } -- return (NULL); -+} -+ -+struct pt_entry * -+pt_get(struct bgpd_addr *prefix, int prefixlen) -+{ -+ struct pt_entry *pte; -+ -+ pte = pt_fill(prefix, prefixlen); -+ return RB_FIND(pt_tree, &pttable, pte); ++ /* NOT REACHED */ ++ return (NULL); } struct pt_entry * +@@ -131,34 +155,9 @@ struct pt_entry * pt_add(struct bgpd_addr *prefix, int prefixlen) { -- struct pt_tree *tree = NULL; struct pt_entry *p = NULL; - struct pt_entry4 *p4; - struct pt_entry6 *p6; -@@ -152,7 +146,6 @@ pt_add(struct bgpd_addr *prefix, int pre - p4->prefix4.s_addr = htonl(addr_hbo & - prefixlen2mask(prefixlen)); - p = (struct pt_entry *)p4; -- tree = &pttable4; - break; - case AF_INET6: - p6 = pt_alloc6(); -@@ -162,15 +155,13 @@ pt_add(struct bgpd_addr *prefix, int pre - p6->prefixlen = prefixlen; - inet6applymask(&p6->prefix6, &prefix->v6, prefixlen); - p = (struct pt_entry *)p6; -- tree = &pttable6; - break; - default: - fatalx("pt_add: unknown af"); - } -- LIST_INIT(&p->prefix_h); - -- if (RB_INSERT(pt_tree, tree, p) != NULL) { -- log_warnx("prefix_add: insert failed"); -+ if (RB_INSERT(pt_tree, &pttable, p) != NULL) { -+ log_warnx("pt_add: insert failed"); - return (NULL); - } - -@@ -181,101 +172,35 @@ void - pt_remove(struct pt_entry *pte) - { - if (!pt_empty(pte)) -- fatalx("pt_remove: entry not empty"); +- struct pt_entry4 *p4; +- struct pt_entry6 *p6; +- in_addr_t addr_hbo; - -- switch (pte->af) { +- switch (prefix->af) { - case AF_INET: -- if (RB_REMOVE(pt_tree, &pttable4, pte) == NULL) -- log_warnx("pt_remove: remove failed."); +- p4 = pt_alloc4(); +- if (prefixlen > 32) +- fatalx("pt_add: bad IPv4 prefixlen"); +- p4->af = AF_INET; +- p4->prefixlen = prefixlen; +- addr_hbo = ntohl(prefix->v4.s_addr); +- p4->prefix4.s_addr = htonl(addr_hbo & +- prefixlen2mask(prefixlen)); +- p = (struct pt_entry *)p4; - break; - case AF_INET6: -- if (RB_REMOVE(pt_tree, &pttable6, pte) == NULL) -- log_warnx("pt_remove: remove failed."); +- p6 = pt_alloc6(); +- if (prefixlen > 128) +- fatalx("pt_add: bad IPv6 prefixlen"); +- p6->af = AF_INET6; +- p6->prefixlen = prefixlen; +- inet6applymask(&p6->prefix6, &prefix->v6, prefixlen); +- p = (struct pt_entry *)p6; - break; - default: -- fatalx("pt_remove: unknown af"); +- fatalx("pt_add: unknown af"); - } -+ fatalx("pt_remove: entry still holds references"); - -+ if (RB_REMOVE(pt_tree, &pttable, pte) == NULL) -+ log_warnx("pt_remove: remove failed."); - pt_free(pte); - } ++ ++ p = pt_fill(prefix, prefixlen); ++ p = pt_alloc(p); - struct pt_entry * --pt_lookup(struct bgpd_addr *prefix) -+pt_lookup(struct bgpd_addr *addr) + if (RB_INSERT(pt_tree, &pttable, p) != NULL) { + log_warnx("pt_add: insert failed"); +@@ -183,13 +182,14 @@ struct pt_entry * + pt_lookup(struct bgpd_addr *addr) { struct pt_entry *p; - int i; +- int i; ++ int i = 0; -- switch (prefix->af) { -+ switch (addr->af) { - case AF_INET: -- for (i = 32; i >= 0; i--) { -- p = pt_get(prefix, i); -- if (p != NULL) -- return (p); -- } -+ i = 32; +- switch (addr->af) { +- case AF_INET: ++ switch (addr->aid) { ++ case AID_INET: ++ case AID_VPN_IPv4: + i = 32; break; - case AF_INET6: -- for (i = 128; i >= 0; i--) { -- p = pt_get(prefix, i); -- if (p != NULL) -- return (p); -- } -+ i = 128; +- case AF_INET6: ++ case AID_INET6: + i = 128; break; default: - fatalx("pt_lookup: unknown af"); - } -- return (NULL); --} -- --void --pt_dump(void (*upcall)(struct pt_entry *, void *), void *arg, sa_family_t af) --{ -- if (af == AF_INET || af == AF_UNSPEC) -- pt_dump_r(upcall, arg, AF_INET, NULL); -- if (af == AF_INET6 || af == AF_UNSPEC) -- pt_dump_r(upcall, arg, AF_INET6, NULL); --} -- --void --pt_dump_r(void (*upcall)(struct pt_entry *, void *), void *arg, -- sa_family_t af, struct pt_context *ctx) --{ -- struct pt_entry *p; -- unsigned int i; -- -- if (ctx == NULL || ctx->ctx_p.af != af) { -- switch (af) { -- case AF_INET: -- p = RB_MIN(pt_tree, &pttable4); -- break; -- case AF_INET6: -- p = RB_MIN(pt_tree, &pttable6); -- break; -- default: -- return; -- } -- } else -- p = pt_restart(ctx); -- -- for (i = 0; p != NULL; p = RB_NEXT(pt_tree, unused, p)) { -- if (ctx && i++ >= ctx->count) { -- /* store next start point */ -- switch (p->af) { -- case AF_INET: -- ctx->ctx_p4 = *(struct pt_entry4 *)p; -- break; -- case AF_INET6: -- ctx->ctx_p6 = *(struct pt_entry6 *)p; -- break; -- default: -- fatalx("pt_dump_r: unknown af"); -- } -- return; -- } -- upcall(p, arg); -+ for (; i >= 0; i--) { -+ p = pt_get(addr, i); -+ if (p != NULL) -+ return (p); - } -- -- if (ctx) -- ctx->done = 1; -+ return (NULL); - } - +@@ -206,17 +206,18 @@ pt_lookup(struct bgpd_addr *addr) int -@@ -285,8 +210,10 @@ pt_prefix_cmp(const struct pt_entry *a, - const struct pt_entry6 *a6, *b6; - int i; + pt_prefix_cmp(const struct pt_entry *a, const struct pt_entry *b) + { +- const struct pt_entry4 *a4, *b4; +- const struct pt_entry6 *a6, *b6; +- int i; ++ const struct pt_entry4 *a4, *b4; ++ const struct pt_entry6 *a6, *b6; ++ const struct pt_entry_vpn4 *va4, *vb4; ++ int i; -- if (a->af != b->af) -- fatalx("king bula sez: comparing pears with apples"); -+ if (a->af > b->af) -+ return (1); -+ if (a->af < b->af) -+ return (-1); +- if (a->af > b->af) ++ if (a->aid > b->aid) + return (1); +- if (a->af < b->af) ++ if (a->aid < b->aid) + return (-1); - switch (a->af) { - case AF_INET: -@@ -361,56 +288,3 @@ pt_free(struct pt_entry *pte) +- switch (a->af) { +- case AF_INET: ++ switch (a->aid) { ++ case AID_INET: + a4 = (const struct pt_entry4 *)a; + b4 = (const struct pt_entry4 *)b; + if (ntohl(a4->prefix4.s_addr) > ntohl(b4->prefix4.s_addr)) +@@ -228,7 +229,7 @@ pt_prefix_cmp(const struct pt_entry *a, + if (a4->prefixlen < b4->prefixlen) + return (-1); + return (0); +- case AF_INET6: ++ case AID_INET6: + a6 = (const struct pt_entry6 *)a; + b6 = (const struct pt_entry6 *)b; + +@@ -242,49 +243,49 @@ pt_prefix_cmp(const struct pt_entry *a, + if (a6->prefixlen > b6->prefixlen) + return (1); + return (0); ++ case AID_VPN_IPv4: ++ va4 = (const struct pt_entry_vpn4 *)a; ++ vb4 = (const struct pt_entry_vpn4 *)b; ++ if (ntohl(va4->prefix4.s_addr) > ntohl(vb4->prefix4.s_addr)) ++ return (1); ++ if (ntohl(va4->prefix4.s_addr) < ntohl(vb4->prefix4.s_addr)) ++ return (-1); ++ if (va4->prefixlen > vb4->prefixlen) ++ return (1); ++ if (va4->prefixlen < vb4->prefixlen) ++ return (-1); ++ if (betoh64(va4->rd) > betoh64(vb4->rd)) ++ return (1); ++ if (betoh64(va4->rd) < betoh64(vb4->rd)) ++ return (-1); ++ return (0); + default: + fatalx("pt_prefix_cmp: unknown af"); } - free(pte); + return (-1); } -- --static struct pt_entry * --pt_restart(struct pt_context *ctx) + +-/* returns a zeroed pt_entry function may not return on fail */ +-static struct pt_entry4 * +-pt_alloc4(void) ++/* ++ * Returns a pt_entry cloned from the one passed in. ++ * Function may not return on failure. ++ */ ++static struct pt_entry * ++pt_alloc(struct pt_entry *op) + { +- struct pt_entry4 *p; ++ struct pt_entry *p; + +- p = calloc(1, sizeof(*p)); ++ p = malloc(pt_sizes[op->aid]); + if (p == NULL) + fatal("pt_alloc"); +- rdemem.pt4_cnt++; +- return (p); +-} ++ rdemem.pt_cnt[op->aid]++; ++ memcpy(p, op, pt_sizes[op->aid]); + +-static struct pt_entry6 * +-pt_alloc6(void) -{ -- struct pt_entry *tmp, *prev = NULL; -- int comp; +- struct pt_entry6 *p; - -- /* first select correct tree */ -- switch (ctx->ctx_p.af) { +- p = calloc(1, sizeof(*p)); +- if (p == NULL) +- fatal("pt_alloc"); +- rdemem.pt6_cnt++; + return (p); + } + + static void + pt_free(struct pt_entry *pte) + { +- switch (pte->af) { - case AF_INET: -- tmp = RB_ROOT(&pttable4); +- rdemem.pt4_cnt--; - break; - case AF_INET6: -- tmp = RB_ROOT(&pttable6); +- rdemem.pt6_cnt--; - break; - default: -- fatalx("pt_restart: unknown af"); -- } -- -- /* then try to find the element */ -- while (tmp) { -- prev = tmp; -- comp = pt_prefix_cmp(&ctx->ctx_p, tmp); -- if (comp < 0) -- tmp = RB_LEFT(tmp, pt_e); -- else if (comp > 0) -- tmp = RB_RIGHT(tmp, pt_e); -- else -- return (tmp); +- break; - } -- -- /* no match, empty tree */ -- if (prev == NULL) -- return (NULL); -- -- /* -- * no perfect match -- * if last element was bigger use that as new start point -- */ -- if (comp < 0) -- return (prev); -- -- /* backtrack until parent is bigger */ -- do { -- prev = RB_PARENT(prev, pt_e); -- if (prev == NULL) -- /* all elements in the tree are smaler */ -- return (NULL); -- comp = pt_prefix_cmp(&ctx->ctx_p, prev); -- } while (comp > 0); -- -- return (prev); --} ++ rdemem.pt_cnt[pte->aid]--; + free(pte); + } diff --git a/net/openbgpd/files/patch-bgpd_rde_rib.c b/net/openbgpd/files/patch-bgpd_rde_rib.c index b97227681b84..369b44477475 100644 --- a/net/openbgpd/files/patch-bgpd_rde_rib.c +++ b/net/openbgpd/files/patch-bgpd_rde_rib.c @@ -1,14 +1,14 @@ Index: bgpd/rde_rib.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_rib.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.4 -diff -u -p -r1.1.1.1 -r1.4 ---- bgpd/rde_rib.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/rde_rib.c 22 Oct 2009 15:10:02 -0000 1.4 +retrieving revision 1.1.1.7 +retrieving revision 1.5 +diff -u -p -r1.1.1.7 -r1.5 +--- bgpd/rde_rib.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 ++++ bgpd/rde_rib.c 4 Feb 2010 16:22:23 -0000 1.5 @@ -1,4 +1,4 @@ --/* $OpenBSD: rde_rib.c,v 1.96 2007/06/01 04:17:30 claudio Exp $ */ -+/* $OpenBSD: rde_rib.c,v 1.116 2009/06/29 14:13:48 claudio Exp $ */ +-/* $OpenBSD: rde_rib.c,v 1.116 2009/06/29 14:13:48 claudio Exp $ */ ++/* $OpenBSD: rde_rib.c,v 1.120 2010/01/13 06:02:37 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -24,891 +24,232 @@ diff -u -p -r1.1.1.1 -r1.4 #include <stdlib.h> #include <string.h> -@@ -33,14 +37,312 @@ - * Therefore one thing needs to be absolutely avoided, long table walks. - * This is achieved by heavily linking the different parts together. - */ -+u_int16_t rib_size; -+struct rib *ribs; -+ -+LIST_HEAD(, rib_context) rib_dump_h = LIST_HEAD_INITIALIZER(rib_dump_h); -+ -+struct rib_entry *rib_add(struct rib *, struct bgpd_addr *, int); -+int rib_compare(const struct rib_entry *, const struct rib_entry *); -+void rib_remove(struct rib_entry *); -+int rib_empty(struct rib_entry *); -+struct rib_entry *rib_restart(struct rib_context *); -+ -+RB_PROTOTYPE(rib_tree, rib_entry, rib_e, rib_compare); -+RB_GENERATE(rib_tree, rib_entry, rib_e, rib_compare); -+ -+ -+/* RIB specific functions */ -+u_int16_t -+rib_new(int id, char *name, u_int16_t flags) -+{ -+ struct rib *xribs; -+ size_t newsize; -+ -+ if (id < 0) { -+ for (id = 0; id < rib_size; id++) { -+ if (*ribs[id].name == '\0') -+ break; -+ } -+ } -+ -+ if (id == RIB_FAILED) -+ fatalx("rib_new: trying to use reserved id"); -+ -+ if (id >= rib_size) { -+ newsize = sizeof(struct rib) * (id + 1); -+ if ((xribs = realloc(ribs, newsize)) == NULL) { -+ /* XXX this is not clever */ -+ fatal("rib_add"); -+ } -+ ribs = xribs; -+ rib_size = id + 1; -+ } -+ -+ bzero(&ribs[id], sizeof(struct rib)); -+ strlcpy(ribs[id].name, name, sizeof(ribs[id].name)); -+ RB_INIT(&ribs[id].rib); +@@ -78,7 +82,7 @@ rib_new(int id, char *name, u_int16_t fl + bzero(&ribs[id], sizeof(struct rib)); + strlcpy(ribs[id].name, name, sizeof(ribs[id].name)); + RB_INIT(&ribs[id].rib); +- ribs[id].state = RIB_ACTIVE; + ribs[id].state = RIB_NEW; -+ ribs[id].id = id; -+ ribs[id].flags = flags; -+ -+ return (id); -+} -+ -+u_int16_t -+rib_find(char *name) -+{ -+ u_int16_t id; -+ -+ if (name == NULL || *name == '\0') -+ return (1); /* XXX */ -+ -+ for (id = 0; id < rib_size; id++) { -+ if (!strcmp(ribs[id].name, name)) -+ return (id); -+ } -+ -+ return (RIB_FAILED); -+} -+ -+void -+rib_free(struct rib *rib) -+{ -+ struct rib_context *ctx, *next; -+ struct rib_entry *re, *xre; -+ struct prefix *p, *np; -+ -+ for (ctx = LIST_FIRST(&rib_dump_h); ctx != NULL; ctx = next) { -+ next = LIST_NEXT(ctx, entry); -+ if (ctx->ctx_rib == rib) { -+ re = ctx->ctx_re; -+ re->flags &= ~F_RIB_ENTRYLOCK; -+ LIST_REMOVE(ctx, entry); -+ if (ctx->ctx_done) -+ ctx->ctx_done(ctx->ctx_arg); -+ else -+ free(ctx); -+ } -+ } -+ -+ for (re = RB_MIN(rib_tree, &rib->rib); re != NULL; re = xre) { -+ xre = RB_NEXT(rib_tree, &rib->rib, re); -+ -+ /* -+ * Removing the prefixes is tricky because the last one -+ * will remove the rib_entry as well and at because we do -+ * a empty check in prefix_destroy() it is not possible to -+ * use the default for loop. -+ */ -+ while ((p = LIST_FIRST(&re->prefix_h))) { -+ np = LIST_NEXT(p, rib_l); -+ if (p->aspath->pftableid) { -+ struct bgpd_addr addr; -+ -+ pt_getaddr(p->prefix, &addr); -+ /* Commit is done in peer_down() */ -+ rde_send_pftable(p->aspath->pftableid, &addr, -+ p->prefix->prefixlen, 1); -+ } -+ prefix_destroy(p); -+ if (np == NULL) -+ break; -+ } -+ } -+ bzero(rib, sizeof(struct rib)); -+} -+ -+int -+rib_compare(const struct rib_entry *a, const struct rib_entry *b) -+{ -+ return (pt_prefix_cmp(a->prefix, b->prefix)); -+} -+ -+struct rib_entry * -+rib_get(struct rib *rib, struct bgpd_addr *prefix, int prefixlen) -+{ -+ struct rib_entry xre; -+ struct pt_entry *pte; -+ -+ pte = pt_fill(prefix, prefixlen); -+ bzero(&xre, sizeof(xre)); -+ xre.prefix = pte; -+ -+ return (RB_FIND(rib_tree, &rib->rib, &xre)); -+} -+ -+struct rib_entry * -+rib_lookup(struct rib *rib, struct bgpd_addr *addr) -+{ -+ struct rib_entry *re; -+ int i; -+ -+ switch (addr->af) { -+ case AF_INET: -+ for (i = 32; i >= 0; i--) { -+ re = rib_get(rib, addr, i); -+ if (re != NULL) -+ return (re); -+ } -+ break; -+ case AF_INET6: -+ for (i = 128; i >= 0; i--) { -+ re = rib_get(rib, addr, i); -+ if (re != NULL) -+ return (re); -+ } -+ break; -+ default: -+ fatalx("rib_lookup: unknown af"); -+ } -+ return (NULL); -+} -+ -+ -+struct rib_entry * -+rib_add(struct rib *rib, struct bgpd_addr *prefix, int prefixlen) -+{ -+ struct pt_entry *pte; -+ struct rib_entry *re; -+ -+ pte = pt_get(prefix, prefixlen); -+ if (pte == NULL) -+ pte = pt_add(prefix, prefixlen); -+ -+ if ((re = calloc(1, sizeof(*re))) == NULL) -+ fatal("rib_add"); -+ -+ LIST_INIT(&re->prefix_h); -+ re->prefix = pte; -+ re->flags = rib->flags; -+ re->ribid = rib->id; -+ -+ if (RB_INSERT(rib_tree, &rib->rib, re) != NULL) { -+ log_warnx("rib_add: insert failed"); -+ return (NULL); -+ } -+ -+ pt_ref(pte); -+ -+ rdemem.rib_cnt++; -+ -+ return (re); -+} -+ -+void -+rib_remove(struct rib_entry *re) -+{ -+ if (!rib_empty(re)) -+ fatalx("rib_remove: entry not empty"); -+ -+ if (re->flags & F_RIB_ENTRYLOCK) -+ /* entry is locked, don't free it. */ -+ return; -+ -+ pt_unref(re->prefix); -+ if (pt_empty(re->prefix)) -+ pt_remove(re->prefix); -+ -+ if (RB_REMOVE(rib_tree, &ribs[re->ribid].rib, re) == NULL) -+ log_warnx("rib_remove: remove failed."); -+ -+ free(re); -+ rdemem.rib_cnt--; -+} -+ -+int -+rib_empty(struct rib_entry *re) -+{ -+ return LIST_EMPTY(&re->prefix_h); -+} -+ -+void -+rib_dump(struct rib *rib, void (*upcall)(struct rib_entry *, void *), -+ void *arg, sa_family_t af) -+{ -+ struct rib_context *ctx; -+ -+ if ((ctx = calloc(1, sizeof(*ctx))) == NULL) -+ fatal("rib_dump"); -+ ctx->ctx_rib = rib; -+ ctx->ctx_upcall = upcall; -+ ctx->ctx_arg = arg; -+ ctx->ctx_af = af; -+ rib_dump_r(ctx); -+} -+ -+void -+rib_dump_r(struct rib_context *ctx) -+{ -+ struct rib_entry *re; -+ unsigned int i; -+ -+ if (ctx->ctx_re == NULL) { -+ re = RB_MIN(rib_tree, &ctx->ctx_rib->rib); -+ LIST_INSERT_HEAD(&rib_dump_h, ctx, entry); -+ } else -+ re = rib_restart(ctx); -+ -+ for (i = 0; re != NULL; re = RB_NEXT(rib_tree, unused, re)) { -+ if (ctx->ctx_af != AF_UNSPEC && ctx->ctx_af != re->prefix->af) -+ continue; -+ if (ctx->ctx_count && i++ >= ctx->ctx_count && -+ (re->flags & F_RIB_ENTRYLOCK) == 0) { -+ /* store and lock last element */ -+ ctx->ctx_re = re; -+ re->flags |= F_RIB_ENTRYLOCK; -+ return; -+ } -+ ctx->ctx_upcall(re, ctx->ctx_arg); -+ } -+ -+ LIST_REMOVE(ctx, entry); -+ if (ctx->ctx_done) -+ ctx->ctx_done(ctx->ctx_arg); -+ else -+ free(ctx); -+} -+ -+struct rib_entry * -+rib_restart(struct rib_context *ctx) -+{ -+ struct rib_entry *re; -+ -+ re = ctx->ctx_re; -+ re->flags &= ~F_RIB_ENTRYLOCK; -+ -+ /* find first non empty element */ -+ while (rib_empty(re)) -+ re = RB_NEXT(rib_tree, unused, re); -+ -+ /* free the previously locked rib element if empty */ -+ if (rib_empty(ctx->ctx_re)) -+ rib_remove(ctx->ctx_re); -+ ctx->ctx_re = NULL; -+ return (re); -+} -+ -+void -+rib_dump_runner(void) -+{ -+ struct rib_context *ctx, *next; -+ -+ for (ctx = LIST_FIRST(&rib_dump_h); ctx != NULL; ctx = next) { -+ next = LIST_NEXT(ctx, entry); -+ rib_dump_r(ctx); -+ } -+} -+ -+int -+rib_dump_pending(void) -+{ -+ return (!LIST_EMPTY(&rib_dump_h)); -+} - - /* used to bump correct prefix counters */ --#define PREFIX_COUNT(x, f, op) \ -- do { \ -- if (f & F_LOCAL) \ -- (x)->prefix_cnt += (op); \ -- if (f & F_ORIGINAL) \ -- (x)->adjrib_cnt += (op); \ -+#define PREFIX_COUNT(x, op) \ -+ do { \ -+ (x)->prefix_cnt += (op); \ - } while (0) - - /* path specific functions */ -@@ -83,62 +385,29 @@ path_shutdown(void) - free(pathtable.path_hashtbl); - } - --void --path_update(struct rde_peer *peer, struct rde_aspath *nasp, -- struct bgpd_addr *prefix, int prefixlen, u_int32_t flags) -+int -+path_update(struct rib *rib, struct rde_peer *peer, struct rde_aspath *nasp, -+ struct bgpd_addr *prefix, int prefixlen) - { - struct rde_aspath *asp; -- struct prefix *p, *oldp = NULL; -+ struct prefix *p; - -- if (flags & F_LOCAL) { -+ if (nasp->pftableid) { - rde_send_pftable(nasp->pftableid, prefix, prefixlen, 0); - rde_send_pftable_commit(); - } - - /* -- * First try to find a prefix in the specified RIB or in the -- * Adj-RIB-In. This works because Local-RIB has precedence over the -- * Adj-RIB-In. In the end this saves use some additional lookups. -+ * First try to find a prefix in the specified RIB. - */ -- if ((p = prefix_get(peer, prefix, prefixlen, flags | F_ORIGINAL)) != -- NULL) { -- do { -- if (path_compare(nasp, p->aspath) == 0) { -- if ((p->flags & flags) == 0) { -- if (oldp != NULL) { -- asp = oldp->aspath; -- prefix_destroy(oldp); -- if (path_empty(asp)) -- path_destroy(asp); -- } -- p->flags |= flags; -- PREFIX_COUNT(p->aspath, flags, 1); -- PREFIX_COUNT(peer, flags, 1); -- -- /* re-evaluate prefix */ -- LIST_REMOVE(p, prefix_l); -- prefix_evaluate(p, p->prefix); -- } -- /* update last change */ -- p->lastchange = time(NULL); -- return; -- } -- /* -- * If the prefix is not already part of the Adj-RIB-In -- * do a lookup in there. But keep the original prefix -- * around so that it can be removed later. -- */ -- if (p->flags & F_ORIGINAL) -- break; -- oldp = p; -- p = prefix_get(peer, prefix, prefixlen, F_ORIGINAL); -- } while (p != NULL); -+ if ((p = prefix_get(rib, peer, prefix, prefixlen, 0)) != NULL) { -+ if (path_compare(nasp, p->aspath) == 0) { -+ /* no change, update last change */ -+ p->lastchange = time(NULL); -+ return (0); -+ } - } - -- /* Do not try to move a prefix that is in the wrong RIB. */ -- if (p == NULL || (p->flags & flags) == 0) -- p = oldp; -- - /* - * Either the prefix does not exist or the path changed. - * In both cases lookup the new aspath to make sure it is not -@@ -152,9 +421,10 @@ path_update(struct rde_peer *peer, struc - - /* If the prefix was found move it else add it to the aspath. */ - if (p != NULL) -- prefix_move(asp, p, flags); -+ prefix_move(asp, p); - else -- prefix_add(asp, prefix, prefixlen, flags); -+ return (prefix_add(rib, asp, prefix, prefixlen)); -+ return (0); - } + ribs[id].id = id; + ribs[id].flags = flags; + +@@ -173,15 +177,16 @@ rib_lookup(struct rib *rib, struct bgpd_ + struct rib_entry *re; + int i; + +- switch (addr->af) { +- case AF_INET: ++ switch (addr->aid) { ++ case AID_INET: ++ case AID_VPN_IPv4: + for (i = 32; i >= 0; i--) { + re = rib_get(rib, addr, i); + if (re != NULL) + return (re); + } + break; +- case AF_INET6: ++ case AID_INET6: + for (i = 128; i >= 0; i--) { + re = rib_get(rib, addr, i); + if (re != NULL) +@@ -254,7 +259,7 @@ rib_empty(struct rib_entry *re) - int -@@ -220,19 +490,20 @@ path_lookup(struct rde_aspath *aspath, s void - path_remove(struct rde_aspath *asp) - { -- struct prefix *p; -- struct bgpd_addr addr; -+ struct prefix *p, *np; - -- while ((p = LIST_FIRST(&asp->prefix_h)) != NULL) { -- /* Commit is done in peer_down() */ -- pt_getaddr(p->prefix, &addr); -- if (p->flags & F_LOCAL) -+ for (p = LIST_FIRST(&asp->prefix_h); p != NULL; p = np) { -+ np = LIST_NEXT(p, path_l); -+ if (asp->pftableid) { -+ struct bgpd_addr addr; -+ -+ pt_getaddr(p->prefix, &addr); -+ /* Commit is done in peer_down() */ - rde_send_pftable(p->aspath->pftableid, &addr, - p->prefix->prefixlen, 1); -- -+ } - prefix_destroy(p); - } -- path_destroy(asp); - } - - /* this function is only called by prefix_remove and path_remove */ -@@ -240,8 +511,7 @@ void - path_destroy(struct rde_aspath *asp) - { - /* path_destroy can only unlink and free empty rde_aspath */ -- if (asp->prefix_cnt != 0 || asp->active_cnt != 0 || -- asp->adjrib_cnt != 0) -+ if (asp->prefix_cnt != 0 || asp->active_cnt != 0) - log_warnx("path_destroy: prefix count out of sync"); - - nexthop_unlink(asp); -@@ -354,8 +624,8 @@ path_put(struct rde_aspath *asp) - - static struct prefix *prefix_alloc(void); - static void prefix_free(struct prefix *); --static void prefix_link(struct prefix *, struct pt_entry *, -- struct rde_aspath *, u_int32_t); -+static void prefix_link(struct prefix *, struct rib_entry *, -+ struct rde_aspath *); - static void prefix_unlink(struct prefix *); - - int -@@ -404,51 +674,52 @@ prefix_compare(const struct bgpd_addr *a - * search for specified prefix of a peer. Returns NULL if not found. - */ - struct prefix * --prefix_get(struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen, -- u_int32_t flags) -+prefix_get(struct rib *rib, struct rde_peer *peer, struct bgpd_addr *prefix, -+ int prefixlen, u_int32_t flags) - { -- struct pt_entry *pte; -+ struct rib_entry *re; - -- pte = pt_get(prefix, prefixlen); -- if (pte == NULL) -+ re = rib_get(rib, prefix, prefixlen); -+ if (re == NULL) - return (NULL); -- return (prefix_bypeer(pte, peer, flags)); -+ return (prefix_bypeer(re, peer, flags)); - } - - /* - * Adds or updates a prefix. - */ --struct pt_entry * --prefix_add(struct rde_aspath *asp, struct bgpd_addr *prefix, int prefixlen, -- u_int32_t flags) -+int -+prefix_add(struct rib *rib, struct rde_aspath *asp, struct bgpd_addr *prefix, -+ int prefixlen) - + rib_dump(struct rib *rib, void (*upcall)(struct rib_entry *, void *), +- void *arg, sa_family_t af) ++ void *arg, u_int8_t aid) { -- struct prefix *p; -- struct pt_entry *pte; -+ struct prefix *p; -+ struct rib_entry *re; - -- pte = pt_get(prefix, prefixlen); -- if (pte == NULL) -- pte = pt_add(prefix, prefixlen); -+ re = rib_get(rib, prefix, prefixlen); -+ if (re == NULL) -+ re = rib_add(rib, prefix, prefixlen); - -- p = prefix_bypeer(pte, asp->peer, flags); -+ p = prefix_bypeer(re, asp->peer, asp->flags); - if (p == NULL) { - p = prefix_alloc(); -- prefix_link(p, pte, asp, flags); -+ prefix_link(p, re, asp); -+ return (1); - } else { -- if (p->aspath != asp) -+ if (p->aspath != asp) { - /* prefix belongs to a different aspath so move */ -- return (prefix_move(asp, p, flags)); -- p->lastchange = time(NULL); -+ prefix_move(asp, p); -+ } else -+ p->lastchange = time(NULL); -+ return (0); - } -- -- return (pte); + struct rib_context *ctx; + +@@ -263,7 +268,7 @@ rib_dump(struct rib *rib, void (*upcall) + ctx->ctx_rib = rib; + ctx->ctx_upcall = upcall; + ctx->ctx_arg = arg; +- ctx->ctx_af = af; ++ ctx->ctx_aid = aid; + rib_dump_r(ctx); } - /* - * Move the prefix to the specified as path, removes the old asp if needed. - */ --struct pt_entry * --prefix_move(struct rde_aspath *asp, struct prefix *p, u_int32_t flags) -+void -+prefix_move(struct rde_aspath *asp, struct prefix *p) - { - struct prefix *np; - struct rde_aspath *oasp; -@@ -461,45 +732,18 @@ prefix_move(struct rde_aspath *asp, stru - np->aspath = asp; - /* peer and prefix pointers are still equal */ - np->prefix = p->prefix; -+ np->rib = p->rib; - np->lastchange = time(NULL); -- np->flags = flags; - - /* add to new as path */ - LIST_INSERT_HEAD(&asp->prefix_h, np, path_l); -- PREFIX_COUNT(asp, flags, 1); -+ PREFIX_COUNT(asp, 1); - /* - * no need to update the peer prefix count because we are only moving - * the prefix without changing the peer. - */ - - /* -- * fiddle around with the flags. If the p->flags is not equal -- * to flags the old prefix p may not be removed but instead p->flags -- * needs to be adjusted. -- */ -- if (p->flags != flags) { -- if ((p->flags & flags) == 0) -- fatalx("prefix_move: " -- "prefix is not part of desired RIB"); -- -- p->flags &= ~flags; -- PREFIX_COUNT(p->aspath, flags, -1); -- /* as before peer count needs no update because of move */ -- -- /* redo the route decision for p */ -- LIST_REMOVE(p, prefix_l); -- /* If the prefix is the active one remove it first. */ -- if (p == p->prefix->active) -- prefix_evaluate(NULL, p->prefix); -- prefix_evaluate(p, p->prefix); -- -- /* and now for np */ -- prefix_evaluate(np, np->prefix); -- -- return (np->prefix); -- } -- -- /* - * First kick the old prefix node out of the prefix list, - * afterwards run the route decision for new prefix node. - * Because of this only one update is generated if the prefix -@@ -507,78 +751,57 @@ prefix_move(struct rde_aspath *asp, stru - * This is save because we create a new prefix and so the change - * is noticed by prefix_evaluate(). - */ -- LIST_REMOVE(p, prefix_l); -- prefix_evaluate(np, np->prefix); -+ LIST_REMOVE(p, rib_l); -+ prefix_evaluate(np, np->rib); - - /* remove old prefix node */ - oasp = p->aspath; - LIST_REMOVE(p, path_l); -- PREFIX_COUNT(oasp, flags, -1); -+ PREFIX_COUNT(oasp, -1); - /* as before peer count needs no update because of move */ - - /* destroy all references to other objects and free the old prefix */ - p->aspath = NULL; - p->prefix = NULL; -+ p->rib = NULL; - prefix_free(p); - - /* destroy old path if empty */ - if (path_empty(oasp)) - path_destroy(oasp); -- -- return (np->prefix); - } +@@ -280,7 +285,8 @@ rib_dump_r(struct rib_context *ctx) + re = rib_restart(ctx); - /* - * Removes a prefix from all lists. If the parent objects -- path or - * pt_entry -- become empty remove them too. - */ --void --prefix_remove(struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen, -- u_int32_t flags) -+int -+prefix_remove(struct rib *rib, struct rde_peer *peer, struct bgpd_addr *prefix, -+ int prefixlen, u_int32_t flags) - { - struct prefix *p; -- struct pt_entry *pte; -+ struct rib_entry *re; - struct rde_aspath *asp; - -- pte = pt_get(prefix, prefixlen); -- if (pte == NULL) /* Got a dummy withdrawn request */ -- return; -+ re = rib_get(rib, prefix, prefixlen); -+ if (re == NULL) /* Got a dummy withdrawn request */ -+ return (0); - -- p = prefix_bypeer(pte, peer, flags); -+ p = prefix_bypeer(re, peer, flags); - if (p == NULL) /* Got a dummy withdrawn request. */ -- return; -+ return (0); - - asp = p->aspath; - -- if (p->flags & F_LOCAL) { -+ if (asp->pftableid) { - /* only prefixes in the local RIB were pushed into pf */ - rde_send_pftable(asp->pftableid, prefix, prefixlen, 1); - rde_send_pftable_commit(); - } - -- /* if prefix belongs to more than one RIB just remove one instance */ -- if (p->flags != flags) { -- p->flags &= ~flags; -- -- PREFIX_COUNT(p->aspath, flags, -1); -- PREFIX_COUNT(peer, flags, -1); -- -- /* redo the route decision for p */ -- LIST_REMOVE(p, prefix_l); -- /* If the prefix is the active one remove it first. */ -- if (p == p->prefix->active) -- prefix_evaluate(NULL, p->prefix); -- prefix_evaluate(p, p->prefix); -- return; -- } -- -- prefix_unlink(p); -- prefix_free(p); -+ prefix_destroy(p); - -- if (pt_empty(pte)) -- pt_remove(pte); -- if (path_empty(asp)) -- path_destroy(asp); -+ return (1); - } - - /* dump a prefix into specified buffer */ -@@ -604,36 +827,50 @@ prefix_write(u_char *buf, int len, struc - * belonging to the peer peer. Returns NULL if no match found. - */ - struct prefix * --prefix_bypeer(struct pt_entry *pte, struct rde_peer *peer, u_int32_t flags) -+prefix_bypeer(struct rib_entry *re, struct rde_peer *peer, u_int32_t flags) - { - struct prefix *p; - -- LIST_FOREACH(p, &pte->prefix_h, prefix_l) { -- if (p->aspath->peer == peer && p->flags & flags) -- return (p); -+ LIST_FOREACH(p, &re->prefix_h, rib_l) { -+ if (p->aspath->peer != peer) -+ continue; -+ if (p->aspath->flags & flags && -+ (flags & F_ANN_DYNAMIC) != -+ (p->aspath->flags & F_ANN_DYNAMIC)) -+ continue; -+ return (p); - } - return (NULL); - } - - void --prefix_updateall(struct rde_aspath *asp, enum nexthop_state state) -+prefix_updateall(struct rde_aspath *asp, enum nexthop_state state, -+ enum nexthop_state oldstate) - { - struct prefix *p; - -- if (rde_noevaluate()) -- /* if the decision process is turned off this is a no-op */ -- return; -- - LIST_FOREACH(p, &asp->prefix_h, path_l) { - /* -- * skip non local-RIB nodes, only local-RIB prefixes are -- * eligible. Both F_LOCAL and F_ORIGINAL may be set. -+ * skip non local-RIBs or RIBs that are flagged as noeval. - */ -- if (!(p->flags & F_LOCAL)) -+ if (p->rib->flags & F_RIB_NOEVALUATE) + for (i = 0; re != NULL; re = RB_NEXT(rib_tree, unused, re)) { +- if (ctx->ctx_af != AF_UNSPEC && ctx->ctx_af != re->prefix->af) ++ if (ctx->ctx_aid != AID_UNSPEC && ++ ctx->ctx_aid != re->prefix->aid) continue; - -+ if (oldstate == state && state == NEXTHOP_REACH) { -+ /* -+ * The state of the nexthop did not change. The only -+ * thing that may have changed is the true_nexthop -+ * or other internal infos. This will not change -+ * the routing decision so shortcut here. -+ */ -+ if ((p->rib->flags & F_RIB_NOFIB) == 0 && -+ p == p->rib->active) -+ rde_send_kroute(p, NULL); -+ continue; -+ } -+ - /* redo the route decision */ -- LIST_REMOVE(p, prefix_l); -+ LIST_REMOVE(p, rib_l); - /* - * If the prefix is the active one remove it first, - * this has to be done because we can not detect when -@@ -642,31 +879,35 @@ prefix_updateall(struct rde_aspath *asp, - * prefix_evaluate() will generate no update because - * the nexthop is unreachable or ineligible. - */ -- if (p == p->prefix->active) -- prefix_evaluate(NULL, p->prefix); -- prefix_evaluate(p, p->prefix); -+ if (p == p->rib->active) -+ prefix_evaluate(NULL, p->rib); -+ prefix_evaluate(p, p->rib); + if (ctx->ctx_count && i++ >= ctx->ctx_count && + (re->flags & F_RIB_ENTRYLOCK) == 0) { +@@ -632,11 +638,11 @@ prefix_compare(const struct bgpd_addr *a + int i; + u_int8_t m; + +- if (a->af != b->af) +- return (a->af - b->af); ++ if (a->aid != b->aid) ++ return (a->aid - b->aid); + +- switch (a->af) { +- case AF_INET: ++ switch (a->aid) { ++ case AID_INET: + if (prefixlen > 32) + fatalx("prefix_cmp: bad IPv4 prefixlen"); + mask = htonl(prefixlen2mask(prefixlen)); +@@ -645,7 +651,7 @@ prefix_compare(const struct bgpd_addr *a + if (aa != ba) + return (aa - ba); + return (0); +- case AF_INET6: ++ case AID_INET6: + if (prefixlen > 128) + fatalx("prefix_cmp: bad IPv6 prefixlen"); + for (i = 0; i < prefixlen / 8; i++) +@@ -660,6 +666,24 @@ prefix_compare(const struct bgpd_addr *a + (b->v6.s6_addr[prefixlen / 8] & m)); + } + return (0); ++ case AID_VPN_IPv4: ++ if (prefixlen > 32) ++ fatalx("prefix_cmp: bad IPv4 VPN prefixlen"); ++ if (betoh64(a->vpn4.rd) > betoh64(b->vpn4.rd)) ++ return (1); ++ if (betoh64(a->vpn4.rd) < betoh64(b->vpn4.rd)) ++ return (-1); ++ mask = htonl(prefixlen2mask(prefixlen)); ++ aa = ntohl(a->vpn4.addr.s_addr & mask); ++ ba = ntohl(b->vpn4.addr.s_addr & mask); ++ if (aa != ba) ++ return (aa - ba); ++ if (a->vpn4.labellen > b->vpn4.labellen) ++ return (1); ++ if (a->vpn4.labellen < b->vpn4.labellen) ++ return (-1); ++ return (memcmp(a->vpn4.labelstack, b->vpn4.labelstack, ++ a->vpn4.labellen)); + default: + fatalx("prefix_cmp: unknown af"); } - } - --/* kill a prefix. Only called by path_remove and path_update. */ -+/* kill a prefix. */ - void - prefix_destroy(struct prefix *p) +@@ -806,16 +830,33 @@ prefix_write(u_char *buf, int len, struc { -- struct pt_entry *pte; -+ struct rib_entry *re; -+ struct rde_aspath *asp; - -- pte = p->prefix; -+ re = p->rib; -+ asp = p->aspath; - prefix_unlink(p); - prefix_free(p); - -- if (pt_empty(pte)) -- pt_remove(pte); -+ if (rib_empty(re)) -+ rib_remove(re); -+ if (path_empty(asp)) -+ path_destroy(asp); + int totlen; + +- if (prefix->af != AF_INET && prefix->af != AF_INET6) +- return (-1); ++ switch (prefix->aid) { ++ case AID_INET: ++ case AID_INET6: ++ totlen = PREFIX_SIZE(plen); + +- totlen = PREFIX_SIZE(plen); ++ if (totlen > len) ++ return (-1); ++ *buf++ = plen; ++ memcpy(buf, &prefix->ba, totlen - 1); ++ return (totlen); ++ case AID_VPN_IPv4: ++ totlen = PREFIX_SIZE(plen) + sizeof(prefix->vpn4.rd) + ++ prefix->vpn4.labellen; ++ plen += (sizeof(prefix->vpn4.rd) + prefix->vpn4.labellen) * 8; + +- if (totlen > len) ++ if (totlen > len) ++ return (-1); ++ *buf++ = plen; ++ memcpy(buf, &prefix->vpn4.labelstack, prefix->vpn4.labellen); ++ buf += prefix->vpn4.labellen; ++ memcpy(buf, &prefix->vpn4.rd, sizeof(prefix->vpn4.rd)); ++ buf += sizeof(prefix->vpn4.rd); ++ memcpy(buf, &prefix->vpn4.addr, PREFIX_SIZE(plen) - 1); ++ return (totlen); ++ default: + return (-1); +- *buf++ = plen; +- memcpy(buf, &prefix->ba, totlen - 1); +- return (totlen); ++ } } /* - * helper function to clean up the connected networks after a reload - */ - void --prefix_network_clean(struct rde_peer *peer, time_t reloadtime) -+prefix_network_clean(struct rde_peer *peer, time_t reloadtime, u_int32_t flags) - { - struct rde_aspath *asp, *xasp; - struct prefix *p, *xp; -@@ -674,6 +915,8 @@ prefix_network_clean(struct rde_peer *pe - - for (asp = LIST_FIRST(&peer->path_h); asp != NULL; asp = xasp) { - xasp = LIST_NEXT(asp, peer_l); -+ if ((asp->flags & F_ANN_DYNAMIC) == flags) -+ continue; - for (p = LIST_FIRST(&asp->prefix_h); p != NULL; p = xp) { - xp = LIST_NEXT(p, path_l); - if (reloadtime > p->lastchange) { -@@ -694,20 +937,19 @@ prefix_network_clean(struct rde_peer *pe - * Link a prefix into the different parent objects. - */ - static void --prefix_link(struct prefix *pref, struct pt_entry *pte, struct rde_aspath *asp, -- u_int32_t flags) -+prefix_link(struct prefix *pref, struct rib_entry *re, struct rde_aspath *asp) - { - LIST_INSERT_HEAD(&asp->prefix_h, pref, path_l); -- PREFIX_COUNT(asp, flags, 1); -- PREFIX_COUNT(asp->peer, flags, 1); -+ PREFIX_COUNT(asp, 1); - - pref->aspath = asp; -- pref->prefix = pte; -+ pref->rib = re; -+ pref->prefix = re->prefix; -+ pt_ref(pref->prefix); - pref->lastchange = time(NULL); -- pref->flags = flags; - - /* make route decision */ -- prefix_evaluate(pref, pte); -+ prefix_evaluate(pref, re); - } +@@ -1088,15 +1129,15 @@ nexthop_update(struct kroute_nexthop *ms + memcpy(&nh->true_nexthop, &msg->gateway, + sizeof(nh->true_nexthop)); + +- switch (msg->nexthop.af) { +- case AF_INET: ++ switch (msg->nexthop.aid) { ++ case AID_INET: + nh->nexthop_netlen = msg->kr.kr4.prefixlen; +- nh->nexthop_net.af = AF_INET; ++ nh->nexthop_net.aid = AID_INET; + nh->nexthop_net.v4.s_addr = msg->kr.kr4.prefix.s_addr; + break; +- case AF_INET6: ++ case AID_INET6: + nh->nexthop_netlen = msg->kr.kr6.prefixlen; +- nh->nexthop_net.af = AF_INET6; ++ nh->nexthop_net.aid = AID_INET6; + memcpy(&nh->nexthop_net.v6, &msg->kr.kr6.prefix, + sizeof(struct in6_addr)); + break; +@@ -1118,7 +1159,7 @@ nexthop_update(struct kroute_nexthop *ms - /* -@@ -716,17 +958,23 @@ prefix_link(struct prefix *pref, struct - static void - prefix_unlink(struct prefix *pref) - { -- /* make route decision */ -- LIST_REMOVE(pref, prefix_l); -- prefix_evaluate(NULL, pref->prefix); -+ if (pref->rib) { -+ /* make route decision */ -+ LIST_REMOVE(pref, rib_l); -+ prefix_evaluate(NULL, pref->rib); -+ } - - LIST_REMOVE(pref, path_l); -- PREFIX_COUNT(pref->aspath, pref->flags, -1); -- PREFIX_COUNT(pref->aspath->peer, pref->flags, -1); -+ PREFIX_COUNT(pref->aspath, -1); -+ -+ pt_unref(pref->prefix); -+ if (pt_empty(pref->prefix)) -+ pt_remove(pref->prefix); - - /* destroy all references to other objects */ - pref->aspath = NULL; - pref->prefix = NULL; -+ pref->rib = NULL; - - /* - * It's the caller's duty to remove empty aspath respectively pt_entry -@@ -817,6 +1065,7 @@ nexthop_update(struct kroute_nexthop *ms + void + nexthop_modify(struct rde_aspath *asp, struct bgpd_addr *nexthop, +- enum action_types type, sa_family_t af) ++ enum action_types type, u_int8_t aid) { - struct nexthop *nh; - struct rde_aspath *asp; -+ enum nexthop_state oldstate; + struct nexthop *nh; - nh = nexthop_lookup(&msg->nexthop); - if (nh == NULL) { -@@ -825,15 +1074,16 @@ nexthop_update(struct kroute_nexthop *ms +@@ -1138,7 +1179,7 @@ nexthop_modify(struct rde_aspath *asp, s + asp->flags |= F_NEXTHOP_SELF; return; } - -+ if (nexthop_delete(nh)) -+ /* nexthop no longer used */ -+ return; -+ -+ oldstate = nh->state; - if (msg->valid) - nh->state = NEXTHOP_REACH; - else - nh->state = NEXTHOP_UNREACH; - -- if (nexthop_delete(nh)) -- /* nexthop no longer used */ -- return; -- - if (msg->connected) { - nh->flags |= NEXTHOP_CONNECTED; - memcpy(&nh->true_nexthop, &nh->exit_nexthop, -@@ -866,7 +1116,7 @@ nexthop_update(struct kroute_nexthop *ms +- if (af != nexthop->af) ++ if (aid != nexthop->aid) return; - LIST_FOREACH(asp, &nh->path_h, nexthop_l) { -- prefix_updateall(asp, nh->state); -+ prefix_updateall(asp, nh->state, oldstate); - } - } - + nh = nexthop_get(nexthop); +@@ -1233,17 +1274,17 @@ nexthop_compare(struct nexthop *na, stru + a = &na->exit_nexthop; + b = &nb->exit_nexthop; + +- if (a->af != b->af) +- return (a->af - b->af); ++ if (a->aid != b->aid) ++ return (a->aid - b->aid); + +- switch (a->af) { +- case AF_INET: ++ switch (a->aid) { ++ case AID_INET: + if (ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr)) + return (1); + if (ntohl(a->v4.s_addr) < ntohl(b->v4.s_addr)) + return (-1); + return (0); +- case AF_INET6: ++ case AID_INET6: + return (memcmp(&a->v6, &b->v6, sizeof(struct in6_addr))); + default: + fatalx("nexthop_cmp: unknown af"); +@@ -1269,14 +1310,14 @@ nexthop_hash(struct bgpd_addr *nexthop) + { + u_int32_t h = 0; + +- switch (nexthop->af) { +- case AF_INET: ++ switch (nexthop->aid) { ++ case AID_INET: + h = (AF_INET ^ ntohl(nexthop->v4.s_addr) ^ + ntohl(nexthop->v4.s_addr) >> 13) & + nexthoptable.nexthop_hashmask; + break; +- case AF_INET6: +- h = hash32_buf(nexthop->v6.s6_addr, sizeof(struct in6_addr), ++ case AID_INET6: ++ h = hash32_buf(&nexthop->v6, sizeof(struct in6_addr), + HASHINIT) & nexthoptable.nexthop_hashmask; + break; + default: diff --git a/net/openbgpd/files/patch-bgpd_rde_update.c b/net/openbgpd/files/patch-bgpd_rde_update.c index fc034a3f7429..bbd2c19ce25f 100644 --- a/net/openbgpd/files/patch-bgpd_rde_update.c +++ b/net/openbgpd/files/patch-bgpd_rde_update.c @@ -1,18 +1,18 @@ Index: bgpd/rde_update.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_update.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.4 -diff -u -p -r1.1.1.1 -r1.4 ---- bgpd/rde_update.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/rde_update.c 10 Aug 2009 21:20:05 -0000 1.4 +retrieving revision 1.1.1.7 +retrieving revision 1.6 +diff -u -p -r1.1.1.7 -r1.6 +--- 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 @@ -1,4 +1,4 @@ --/* $OpenBSD: rde_update.c,v 1.61 2007/11/27 01:13:54 claudio Exp $ */ -+/* $OpenBSD: rde_update.c,v 1.69 2009/08/06 08:53:11 claudio Exp $ */ +-/* $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,10 +17,17 @@ +@@ -17,19 +17,26 @@ */ #include <sys/types.h> #include <sys/queue.h> @@ -30,7 +30,120 @@ diff -u -p -r1.1.1.1 -r1.4 #include "bgpd.h" #include "rde.h" -@@ -270,6 +277,8 @@ up_test_update(struct rde_peer *peer, st + + in_addr_t up_get_nexthop(struct rde_peer *, struct rde_aspath *); + int up_generate_mp_reach(struct rde_peer *, struct update_attr *, +- struct rde_aspath *, sa_family_t); ++ struct rde_aspath *, u_int8_t); + int up_generate_attr(struct rde_peer *, struct update_attr *, +- struct rde_aspath *, sa_family_t); ++ struct rde_aspath *, u_int8_t); + + /* update stuff. */ + struct update_prefix { +@@ -65,10 +72,12 @@ RB_GENERATE(uptree_attr, update_attr, en + void + up_init(struct rde_peer *peer) + { +- TAILQ_INIT(&peer->updates); +- TAILQ_INIT(&peer->withdraws); +- TAILQ_INIT(&peer->updates6); +- TAILQ_INIT(&peer->withdraws6); ++ u_int8_t i; ++ ++ for (i = 0; i < AID_MAX; i++) { ++ TAILQ_INIT(&peer->updates[i]); ++ TAILQ_INIT(&peer->withdraws[i]); ++ } + RB_INIT(&peer->up_prefix); + RB_INIT(&peer->up_attrs); + peer->up_pcnt = 0; +@@ -103,8 +112,10 @@ up_clear(struct uplist_attr *updates, st + void + up_down(struct rde_peer *peer) + { +- up_clear(&peer->updates, &peer->withdraws); +- up_clear(&peer->updates6, &peer->withdraws6); ++ u_int8_t i; ++ ++ for (i = 0; i < AID_MAX; i++) ++ up_clear(&peer->updates[i], &peer->withdraws[i]); + + RB_INIT(&peer->up_prefix); + RB_INIT(&peer->up_attrs); +@@ -120,19 +131,19 @@ up_prefix_cmp(struct update_prefix *a, s + { + int i; + +- if (a->prefix.af < b->prefix.af) ++ if (a->prefix.aid < b->prefix.aid) + return (-1); +- if (a->prefix.af > b->prefix.af) ++ if (a->prefix.aid > b->prefix.aid) + return (1); + +- switch (a->prefix.af) { +- case AF_INET: ++ switch (a->prefix.aid) { ++ case AID_INET: + if (ntohl(a->prefix.v4.s_addr) < ntohl(b->prefix.v4.s_addr)) + return (-1); + if (ntohl(a->prefix.v4.s_addr) > ntohl(b->prefix.v4.s_addr)) + return (1); + break; +- case AF_INET6: ++ case AID_INET6: + i = memcmp(&a->prefix.v6, &b->prefix.v6, + sizeof(struct in6_addr)); + if (i > 0) +@@ -140,6 +151,25 @@ up_prefix_cmp(struct update_prefix *a, s + if (i < 0) + return (-1); + break; ++ case AID_VPN_IPv4: ++ if (betoh64(a->prefix.vpn4.rd) < betoh64(b->prefix.vpn4.rd)) ++ return (-1); ++ if (betoh64(a->prefix.vpn4.rd) > betoh64(b->prefix.vpn4.rd)) ++ return (1); ++ if (ntohl(a->prefix.v4.s_addr) < ntohl(b->prefix.v4.s_addr)) ++ return (-1); ++ if (ntohl(a->prefix.v4.s_addr) > ntohl(b->prefix.v4.s_addr)) ++ return (1); ++ if (a->prefixlen < b->prefixlen) ++ return (-1); ++ if (a->prefixlen > b->prefixlen) ++ return (1); ++ if (a->prefix.vpn4.labellen < b->prefix.vpn4.labellen) ++ return (-1); ++ if (a->prefix.vpn4.labellen > b->prefix.vpn4.labellen) ++ return (1); ++ return (memcmp(a->prefix.vpn4.labelstack, ++ b->prefix.vpn4.labelstack, a->prefix.vpn4.labellen)); + default: + fatalx("pt_prefix_cmp: unknown af"); + } +@@ -174,18 +204,8 @@ up_add(struct rde_peer *peer, struct upd + struct uplist_attr *upl = NULL; + struct uplist_prefix *wdl = NULL; + +- switch (p->prefix.af) { +- case AF_INET: +- upl = &peer->updates; +- wdl = &peer->withdraws; +- break; +- case AF_INET6: +- upl = &peer->updates6; +- wdl = &peer->withdraws6; +- break; +- default: +- fatalx("up_add: unknown AF"); +- } ++ upl = &peer->updates[p->prefix.aid]; ++ wdl = &peer->withdraws[p->prefix.aid]; + + /* 1. search for attr */ + if (a != NULL && (na = RB_FIND(uptree_attr, &peer->up_attrs, a)) == +@@ -270,21 +290,14 @@ up_test_update(struct rde_peer *peer, st /* Do not send routes back to sender */ return (0); @@ -39,154 +152,461 @@ diff -u -p -r1.1.1.1 -r1.4 if (p->aspath->flags & F_ATTR_LOOP) fatalx("try to send out a looped path"); -@@ -360,7 +369,7 @@ up_generate(struct rde_peer *peer, struc - if (asp) { - ua = calloc(1, sizeof(struct update_attr)); + pt_getaddr(p->prefix, &addr); +- switch (addr.af) { +- case AF_INET: +- if (peer->capa_announced.mp_v4 == SAFI_NONE && +- peer->capa_received.mp_v6 != SAFI_NONE) +- return (-1); +- break; +- case AF_INET6: +- if (peer->capa_announced.mp_v6 == SAFI_NONE) +- return (-1); +- break; +- } ++ if (peer->capa.mp[addr.aid] == 0) ++ return (-1); + + if (p->aspath->peer->conf.ebgp == 0 && peer->conf.ebgp == 0) { + /* +@@ -325,13 +338,13 @@ up_test_update(struct rde_peer *peer, st + } + + /* well known communities */ +- if (rde_filter_community(p->aspath, ++ if (community_match(p->aspath, + COMMUNITY_WELLKNOWN, COMMUNITY_NO_ADVERTISE)) + return (0); +- if (peer->conf.ebgp && rde_filter_community(p->aspath, ++ if (peer->conf.ebgp && community_match(p->aspath, + COMMUNITY_WELLKNOWN, COMMUNITY_NO_EXPORT)) + return (0); +- if (peer->conf.ebgp && rde_filter_community(p->aspath, ++ if (peer->conf.ebgp && community_match(p->aspath, + COMMUNITY_WELLKNOWN, COMMUNITY_NO_EXPSUBCONFED)) + return (0); + +@@ -362,7 +375,7 @@ up_generate(struct rde_peer *peer, struc if (ua == NULL) -- fatal("up_generate_updates"); -+ fatal("up_generate"); + fatal("up_generate"); - if (up_generate_attr(peer, ua, asp, addr->af) == -1) { +- if (up_generate_attr(peer, ua, asp, addr->af) == -1) { ++ if (up_generate_attr(peer, ua, asp, addr->aid) == -1) { log_warnx("generation of bgp path attributes failed"); -@@ -379,7 +388,7 @@ up_generate(struct rde_peer *peer, struc - - up = calloc(1, sizeof(struct update_prefix)); - if (up == NULL) -- fatal("up_generate_updates"); -+ fatal("up_generate"); - up->prefix = *addr; - up->prefixlen = prefixlen; - -@@ -404,9 +413,9 @@ up_generate_updates(struct filter_head * - return; - - pt_getaddr(old->prefix, &addr); -- if (rde_filter(NULL, rules, peer, old->aspath, &addr, -- old->prefix->prefixlen, old->aspath->peer, DIR_OUT) == -- ACTION_DENY) -+ if (rde_filter(peer->ribid, NULL, rules, peer, old->aspath, -+ &addr, old->prefix->prefixlen, old->aspath->peer, -+ DIR_OUT) == ACTION_DENY) - return; - - /* withdraw prefix */ -@@ -423,9 +432,9 @@ up_generate_updates(struct filter_head * - } + free(ua); + return (-1); +@@ -444,18 +457,12 @@ up_generate_updates(struct filter_head * + /* send a default route to the specified peer */ + void + up_generate_default(struct filter_head *rules, struct rde_peer *peer, +- sa_family_t af) ++ u_int8_t aid) + { + struct rde_aspath *asp, *fasp; + struct bgpd_addr addr; - pt_getaddr(new->prefix, &addr); -- if (rde_filter(&asp, rules, peer, new->aspath, &addr, -- new->prefix->prefixlen, new->aspath->peer, DIR_OUT) == -- ACTION_DENY) { -+ if (rde_filter(peer->ribid, &asp, rules, peer, new->aspath, -+ &addr, new->prefix->prefixlen, new->aspath->peer, -+ DIR_OUT) == ACTION_DENY) { - path_put(asp); - up_generate_updates(rules, peer, NULL, old); - return; -@@ -473,8 +482,8 @@ up_generate_default(struct filter_head * - bzero(&addr, sizeof(addr)); - addr.af = af; - -- if (rde_filter(&fasp, rules, peer, asp, &addr, 0, NULL, DIR_OUT) == -- ACTION_DENY) { -+ if (rde_filter(peer->ribid, &fasp, rules, peer, asp, &addr, 0, NULL, -+ DIR_OUT) == ACTION_DENY) { - path_put(fasp); - path_put(asp); +- if (peer->capa_received.mp_v4 == SAFI_NONE && +- peer->capa_received.mp_v6 != SAFI_NONE && +- af == AF_INET) +- return; +- +- if (peer->capa_received.mp_v6 == SAFI_NONE && +- af == AF_INET6) ++ if (peer->capa.mp[aid] == 0) return; -@@ -617,7 +626,7 @@ up_generate_attr(struct rde_peer *peer, - u_char *pdata; - u_int32_t tmp32; - in_addr_t nexthop; -- int r, ismp = 0, neednewpath = 0; -+ int flags, r, ismp = 0, neednewpath = 0; - u_int16_t len = sizeof(up_attr_buf), wlen = 0, plen; - u_int8_t l; - -@@ -629,7 +638,7 @@ up_generate_attr(struct rde_peer *peer, - - /* aspath */ - if (!peer->conf.ebgp || -- rde_decisionflags() & BGPD_FLAG_DECISION_TRANS_AS) -+ peer->conf.flags & PEERFLAG_TRANS_AS) - pdata = aspath_prepend(a->aspath, rde_local_as(), 0, &plen); - else - pdata = aspath_prepend(a->aspath, rde_local_as(), 1, &plen); -@@ -762,25 +771,29 @@ up_generate_attr(struct rde_peer *peer, - /* NEW to OLD conversion when going sending stuff to a 2byte AS peer */ - if (neednewpath) { - if (!peer->conf.ebgp || -- rde_decisionflags() & BGPD_FLAG_DECISION_TRANS_AS) -+ peer->conf.flags & PEERFLAG_TRANS_AS) - pdata = aspath_prepend(a->aspath, rde_local_as(), 0, - &plen); - else - pdata = aspath_prepend(a->aspath, rde_local_as(), 1, - &plen); -+ flags = ATTR_OPTIONAL|ATTR_TRANSITIVE; -+ if (!(a->flags & F_PREFIX_ANNOUNCED)) -+ flags |= ATTR_PARTIAL; - if (plen == 0) - r = 0; -- else if ((r = attr_write(up_attr_buf + wlen, len, -- ATTR_OPTIONAL|ATTR_TRANSITIVE, ATTR_NEW_ASPATH, -- pdata, plen)) == -1) -+ else if ((r = attr_write(up_attr_buf + wlen, len, flags, -+ ATTR_AS4_PATH, pdata, plen)) == -1) - return (-1); - wlen += r; len -= r; - free(pdata); + + asp = path_get(); +@@ -471,7 +478,7 @@ up_generate_default(struct filter_head * + + /* filter as usual */ + bzero(&addr, sizeof(addr)); +- addr.af = af; ++ addr.aid = aid; + + if (rde_filter(peer->ribid, &fasp, rules, peer, asp, &addr, 0, NULL, + DIR_OUT) == ACTION_DENY) { +@@ -491,6 +498,43 @@ up_generate_default(struct filter_head * + path_put(asp); + } + ++/* generate a EoR marker in the update list. This is a horrible hack. */ ++int ++up_generate_marker(struct rde_peer *peer, u_int8_t aid) ++{ ++ struct update_attr *ua; ++ struct update_attr *na = NULL; ++ struct uplist_attr *upl = NULL; ++ ++ ua = calloc(1, sizeof(struct update_attr)); ++ if (ua == NULL) ++ fatal("up_generate_marker"); ++ ++ upl = &peer->updates[aid]; ++ ++ /* 1. search for attr */ ++ if ((na = RB_FIND(uptree_attr, &peer->up_attrs, ua)) == NULL) { ++ /* 1.1 if not found -> add */ ++ TAILQ_INIT(&ua->prefix_h); ++ if (RB_INSERT(uptree_attr, &peer->up_attrs, ua) != NULL) { ++ log_warnx("uptree_attr insert failed"); ++ /* cleanup */ ++ free(ua); ++ return (-1); ++ } ++ TAILQ_INSERT_TAIL(upl, ua, attr_l); ++ peer->up_acnt++; ++ } else { ++ /* 1.2 if found -> use that, free ua */ ++ free(ua); ++ ua = na; ++ /* move to end of update queue */ ++ TAILQ_REMOVE(upl, ua, attr_l); ++ TAILQ_INSERT_TAIL(upl, ua, attr_l); ++ } ++ return (0); ++} ++ + u_char up_attr_buf[4096]; + + /* only for IPv4 */ +@@ -551,28 +595,41 @@ up_get_nexthop(struct rde_peer *peer, st + + int + up_generate_mp_reach(struct rde_peer *peer, struct update_attr *upa, +- struct rde_aspath *a, sa_family_t af) ++ struct rde_aspath *a, u_int8_t aid) + { + u_int16_t tmp; + +- switch (af) { +- case AF_INET6: ++ switch (aid) { ++ case AID_INET6: + upa->mpattr_len = 21; /* AFI + SAFI + NH LEN + NH + Reserved */ + upa->mpattr = malloc(upa->mpattr_len); + if (upa->mpattr == NULL) + fatal("up_generate_mp_reach"); +- tmp = htons(AFI_IPv6); ++ if (aid2afi(aid, &tmp, &upa->mpattr[2])) ++ fatalx("up_generate_mp_reachi: bad AID"); ++ tmp = htons(tmp); + memcpy(upa->mpattr, &tmp, sizeof(tmp)); +- upa->mpattr[2] = SAFI_UNICAST; + upa->mpattr[3] = sizeof(struct in6_addr); + upa->mpattr[20] = 0; /* Reserved must be 0 */ + + /* nexthop dance see also up_get_nexthop() */ +- if (peer->conf.ebgp == 0) { ++ if (a->flags & F_NEXTHOP_NOMODIFY) { ++ /* no modify flag set */ ++ if (a->nexthop == NULL) ++ memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, ++ sizeof(struct in6_addr)); ++ else ++ memcpy(&upa->mpattr[4], ++ &a->nexthop->exit_nexthop.v6, ++ sizeof(struct in6_addr)); ++ } else if (a->flags & F_NEXTHOP_SELF) ++ memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, ++ sizeof(struct in6_addr)); ++ else if (!peer->conf.ebgp) { + /* ibgp */ + if (a->nexthop == NULL || +- (a->nexthop->exit_nexthop.af == AF_INET6 && +- memcmp(&a->nexthop->exit_nexthop.v6, ++ (a->nexthop->exit_nexthop.aid == AID_INET6 && ++ !memcmp(&a->nexthop->exit_nexthop.v6, + &peer->remote_addr.v6, sizeof(struct in6_addr)))) + memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, + sizeof(struct in6_addr)); +@@ -603,6 +660,68 @@ up_generate_mp_reach(struct rde_peer *pe + memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, + sizeof(struct in6_addr)); + return (0); ++ case AID_VPN_IPv4: ++ upa->mpattr_len = 17; /* AFI + SAFI + NH LEN + NH + Reserved */ ++ upa->mpattr = calloc(upa->mpattr_len, 1); ++ if (upa->mpattr == NULL) ++ fatal("up_generate_mp_reach"); ++ if (aid2afi(aid, &tmp, &upa->mpattr[2])) ++ fatalx("up_generate_mp_reachi: bad AID"); ++ tmp = htons(tmp); ++ memcpy(upa->mpattr, &tmp, sizeof(tmp)); ++ upa->mpattr[3] = sizeof(u_int64_t) + sizeof(struct in_addr); ++ ++ /* nexthop dance see also up_get_nexthop() */ ++ if (a->flags & F_NEXTHOP_NOMODIFY) { ++ /* no modify flag set */ ++ if (a->nexthop == NULL) ++ memcpy(&upa->mpattr[12], ++ &peer->local_v4_addr.v4, ++ sizeof(struct in_addr)); ++ else ++ /* nexthops are stored as IPv4 addrs */ ++ memcpy(&upa->mpattr[12], ++ &a->nexthop->exit_nexthop.v4, ++ sizeof(struct in_addr)); ++ } else if (a->flags & F_NEXTHOP_SELF) ++ memcpy(&upa->mpattr[12], &peer->local_v4_addr.v4, ++ sizeof(struct in_addr)); ++ else if (!peer->conf.ebgp) { ++ /* ibgp */ ++ if (a->nexthop == NULL || ++ (a->nexthop->exit_nexthop.aid == AID_INET && ++ !memcmp(&a->nexthop->exit_nexthop.v4, ++ &peer->remote_addr.v4, sizeof(struct in_addr)))) ++ memcpy(&upa->mpattr[12], ++ &peer->local_v4_addr.v4, ++ sizeof(struct in_addr)); ++ else ++ memcpy(&upa->mpattr[12], ++ &a->nexthop->exit_nexthop.v4, ++ sizeof(struct in_addr)); ++ } else if (peer->conf.distance == 1) { ++ /* ebgp directly connected */ ++ if (a->nexthop != NULL && ++ a->nexthop->flags & NEXTHOP_CONNECTED) ++ if (prefix_compare(&peer->remote_addr, ++ &a->nexthop->nexthop_net, ++ a->nexthop->nexthop_netlen) == 0) { ++ /* ++ * nexthop and peer are in the same ++ * subnet ++ */ ++ memcpy(&upa->mpattr[12], ++ &a->nexthop->exit_nexthop.v4, ++ sizeof(struct in_addr)); ++ return (0); ++ } ++ memcpy(&upa->mpattr[12], &peer->local_v4_addr.v4, ++ sizeof(struct in_addr)); ++ } else ++ /* ebgp multihop */ ++ memcpy(&upa->mpattr[12], &peer->local_v4_addr.v4, ++ sizeof(struct in_addr)); ++ return (0); + default: + break; } - if (newaggr) { -- if ((r = attr_write(up_attr_buf + wlen, len, -- ATTR_OPTIONAL|ATTR_TRANSITIVE, ATTR_NEW_AGGREGATOR, -- newaggr->data, newaggr->len)) == -1) -+ flags = ATTR_OPTIONAL|ATTR_TRANSITIVE; -+ if (!(a->flags & F_PREFIX_ANNOUNCED)) -+ flags |= ATTR_PARTIAL; -+ if ((r = attr_write(up_attr_buf + wlen, len, flags, -+ ATTR_AS4_AGGREGATOR, newaggr->data, newaggr->len)) == -1) +@@ -611,7 +730,7 @@ up_generate_mp_reach(struct rde_peer *pe + + int + up_generate_attr(struct rde_peer *peer, struct update_attr *upa, +- struct rde_aspath *a, sa_family_t af) ++ struct rde_aspath *a, u_int8_t aid) + { + struct attr *oa, *newaggr = NULL; + u_char *pdata; +@@ -643,8 +762,8 @@ up_generate_attr(struct rde_peer *peer, + wlen += r; len -= r; + free(pdata); + +- switch (af) { +- case AF_INET: ++ switch (aid) { ++ case AID_INET: + nexthop = up_get_nexthop(peer, a); + if ((r = attr_write(up_attr_buf + wlen, len, ATTR_WELL_KNOWN, + ATTR_NEXTHOP, &nexthop, 4)) == -1) +@@ -659,9 +778,11 @@ up_generate_attr(struct rde_peer *peer, + /* + * The old MED from other peers MUST not be announced to others + * unless the MED is originating from us or the peer is an IBGP one. ++ * Only exception are routers with "transparent-as yes" set. + */ + if (a->flags & F_ATTR_MED && (peer->conf.ebgp == 0 || +- a->flags & F_ATTR_MED_ANNOUNCE)) { ++ a->flags & F_ATTR_MED_ANNOUNCE || ++ peer->conf.flags & PEERFLAG_TRANS_AS)) { + tmp32 = htonl(a->med); + if ((r = attr_write(up_attr_buf + wlen, len, ATTR_OPTIONAL, + ATTR_MED, &tmp32, 4)) == -1) +@@ -791,7 +912,7 @@ up_generate_attr(struct rde_peer *peer, + + /* write mp attribute to different buffer */ + if (ismp) +- if (up_generate_mp_reach(peer, upa, a, AF_INET6) == -1) ++ if (up_generate_mp_reach(peer, upa, a, aid) == -1) return (-1); - wlen += r; len -= r; + + /* the bgp path attributes are now stored in the global buf */ +@@ -810,6 +931,7 @@ up_dump_prefix(u_char *buf, int len, str + { + struct update_prefix *upp; + int r, wpos = 0; ++ u_int8_t i; + + while ((upp = TAILQ_FIRST(prefix_head)) != NULL) { + if ((r = prefix_write(buf + wpos, len - wpos, +@@ -820,13 +942,14 @@ up_dump_prefix(u_char *buf, int len, str + log_warnx("dequeuing update failed."); + TAILQ_REMOVE(upp->prefix_h, upp, prefix_l); + peer->up_pcnt--; +- if (upp->prefix_h == &peer->withdraws || +- upp->prefix_h == &peer->withdraws6) { +- peer->up_wcnt--; +- peer->prefix_sent_withdraw++; +- } else { +- peer->up_nlricnt--; +- peer->prefix_sent_update++; ++ for (i = 0; i < AID_MAX; i++) { ++ if (upp->prefix_h == &peer->withdraws[i]) { ++ peer->up_wcnt--; ++ peer->prefix_sent_withdraw++; ++ } else { ++ peer->up_nlricnt--; ++ peer->prefix_sent_update++; ++ } + } + free(upp); } -@@ -913,13 +926,7 @@ up_dump_mp_unreach(u_char *buf, u_int16_ +@@ -844,16 +967,21 @@ up_dump_attrnlri(u_char *buf, int len, s + * It is possible that a queued path attribute has no nlri prefix. + * Ignore and remove those path attributes. + */ +- while ((upa = TAILQ_FIRST(&peer->updates)) != NULL) ++ while ((upa = TAILQ_FIRST(&peer->updates[AID_INET])) != NULL) + if (TAILQ_EMPTY(&upa->prefix_h)) { ++ attr_len = upa->attr_len; + if (RB_REMOVE(uptree_attr, &peer->up_attrs, + upa) == NULL) + log_warnx("dequeuing update failed."); +- TAILQ_REMOVE(&peer->updates, upa, attr_l); ++ TAILQ_REMOVE(&peer->updates[AID_INET], upa, attr_l); + free(upa->attr); + free(upa->mpattr); + free(upa); + peer->up_acnt--; ++ /* XXX horrible hack, ++ * if attr_len is 0, it is a EoR marker */ ++ if (attr_len == 0) ++ return (-1); + } else + break; + +@@ -884,7 +1012,7 @@ up_dump_attrnlri(u_char *buf, int len, s + if (TAILQ_EMPTY(&upa->prefix_h)) { + if (RB_REMOVE(uptree_attr, &peer->up_attrs, upa) == NULL) + log_warnx("dequeuing update failed."); +- TAILQ_REMOVE(&peer->updates, upa, attr_l); ++ TAILQ_REMOVE(&peer->updates[AID_INET], upa, attr_l); + free(upa->attr); + free(upa->mpattr); + free(upa); +@@ -895,12 +1023,13 @@ up_dump_attrnlri(u_char *buf, int len, s + } + + u_char * +-up_dump_mp_unreach(u_char *buf, u_int16_t *len, struct rde_peer *peer) ++up_dump_mp_unreach(u_char *buf, u_int16_t *len, struct rde_peer *peer, ++ u_int8_t aid) + { + int wpos; + u_int16_t datalen, tmp; + u_int16_t attrlen = 2; /* attribute header (without len) */ +- u_int8_t flags = ATTR_OPTIONAL; ++ u_int8_t flags = ATTR_OPTIONAL, safi; + + /* + * reserve space for withdraw len, attr len, the attribute header +@@ -912,7 +1041,7 @@ up_dump_mp_unreach(u_char *buf, u_int16_ return (NULL); - datalen += 3; /* afi + safi */ -- if (datalen > 255) { -- attrlen += 2 + datalen; -- flags |= ATTR_EXTLEN; -- } else { -- attrlen += 1 + datalen; -- buf++; -- } -+ + datalen = up_dump_prefix(buf + wpos, *len - wpos, +- &peer->withdraws6, peer); ++ &peer->withdraws[aid], peer); + if (datalen == 0) + return (NULL); + +@@ -920,9 +1049,11 @@ up_dump_mp_unreach(u_char *buf, u_int16_ + /* prepend header, need to do it reverse */ /* safi & afi */ - buf[--wpos] = SAFI_UNICAST; -@@ -929,11 +936,15 @@ up_dump_mp_unreach(u_char *buf, u_int16_ +- buf[--wpos] = SAFI_UNICAST; ++ if (aid2afi(aid, &tmp, &safi)) ++ fatalx("up_dump_mp_unreach: bad AID"); ++ buf[--wpos] = safi; + wpos -= sizeof(u_int16_t); +- tmp = htons(AFI_IPv6); ++ tmp = htons(tmp); + memcpy(buf + wpos, &tmp, sizeof(u_int16_t)); /* attribute length */ - if (datalen > 255) { -+ attrlen += 2 + datalen; -+ flags |= ATTR_EXTLEN; - wpos -= sizeof(u_int16_t); - tmp = htons(datalen); - memcpy(buf + wpos, &tmp, sizeof(u_int16_t)); -- } else -+ } else { -+ attrlen += 1 + datalen; - buf[--wpos] = (u_char)datalen; -+ } +@@ -959,33 +1090,39 @@ up_dump_mp_unreach(u_char *buf, u_int16_ + return (buf + wpos); + } - /* mp attribute */ - buf[--wpos] = (u_char)ATTR_MP_UNREACH_NLRI; -@@ -954,7 +965,7 @@ up_dump_mp_unreach(u_char *buf, u_int16_ - /* total length includes the two 2-bytes length fields. */ - *len = attrlen + 2 * sizeof(u_int16_t); +-u_char * +-up_dump_mp_reach(u_char *buf, u_int16_t *len, struct rde_peer *peer) ++int ++up_dump_mp_reach(u_char *buf, u_int16_t *len, struct rde_peer *peer, ++ u_int8_t aid) + { + struct update_attr *upa; + int wpos; +- u_int16_t datalen, tmp; ++ u_int16_t attr_len, datalen, tmp; + u_int8_t flags = ATTR_OPTIONAL; -- return (buf); -+ return (buf + wpos); - } + /* + * It is possible that a queued path attribute has no nlri prefix. + * Ignore and remove those path attributes. + */ +- while ((upa = TAILQ_FIRST(&peer->updates6)) != NULL) ++ while ((upa = TAILQ_FIRST(&peer->updates[aid])) != NULL) + if (TAILQ_EMPTY(&upa->prefix_h)) { ++ attr_len = upa->attr_len; + if (RB_REMOVE(uptree_attr, &peer->up_attrs, + upa) == NULL) + log_warnx("dequeuing update failed."); +- TAILQ_REMOVE(&peer->updates6, upa, attr_l); ++ TAILQ_REMOVE(&peer->updates[aid], upa, attr_l); + free(upa->attr); + free(upa->mpattr); + free(upa); + peer->up_acnt--; ++ /* XXX horrible hack, ++ * if attr_len is 0, it is a EoR marker */ ++ if (attr_len == 0) ++ return (-1); + } else + break; - u_char * + if (upa == NULL) +- return (NULL); ++ return (-2); + + /* + * reserve space for attr len, the attributes, the +@@ -993,12 +1130,12 @@ up_dump_mp_reach(u_char *buf, u_int16_t + */ + wpos = 2 + 2 + upa->attr_len + 4 + upa->mpattr_len; + if (*len < wpos) +- return (NULL); ++ return (-2); + + datalen = up_dump_prefix(buf + wpos, *len - wpos, + &upa->prefix_h, peer); + if (datalen == 0) +- return (NULL); ++ return (-2); + + if (upa->mpattr_len == 0 || upa->mpattr == NULL) + fatalx("mulitprotocol update without MP attrs"); +@@ -1038,7 +1175,7 @@ up_dump_mp_reach(u_char *buf, u_int16_t + if (TAILQ_EMPTY(&upa->prefix_h)) { + if (RB_REMOVE(uptree_attr, &peer->up_attrs, upa) == NULL) + log_warnx("dequeuing update failed."); +- TAILQ_REMOVE(&peer->updates6, upa, attr_l); ++ TAILQ_REMOVE(&peer->updates[aid], upa, attr_l); + free(upa->attr); + free(upa->mpattr); + free(upa); +@@ -1046,6 +1183,5 @@ up_dump_mp_reach(u_char *buf, u_int16_t + } + + *len = datalen + 4; +- return (buf + wpos); ++ return (wpos); + } +- diff --git a/net/openbgpd/files/patch-bgpd_session.c b/net/openbgpd/files/patch-bgpd_session.c index 5b7b15c9f99b..b6659f236a79 100644 --- a/net/openbgpd/files/patch-bgpd_session.c +++ b/net/openbgpd/files/patch-bgpd_session.c @@ -1,14 +1,14 @@ Index: bgpd/session.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/session.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.5 -diff -u -p -r1.1.1.1 -r1.5 ---- bgpd/session.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/session.c 22 Oct 2009 15:10:02 -0000 1.5 +retrieving revision 1.1.1.8 +retrieving revision 1.7 +diff -u -p -r1.1.1.8 -r1.7 +--- 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 @@ -1,4 +1,4 @@ --/* $OpenBSD: session.c,v 1.282 2008/06/26 00:01:51 claudio Exp $ */ -+/* $OpenBSD: session.c,v 1.294 2009/07/24 13:09:29 claudio Exp $ */ +-/* $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> @@ -23,57 +23,190 @@ diff -u -p -r1.1.1.1 -r1.5 void session_sighdlr(int); int setup_listeners(u_int *); void init_conf(struct bgpd_config *); -@@ -65,8 +69,7 @@ void session_accept(int); +@@ -65,9 +69,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_int16_t, u_int8_t); ++int session_capa_add_mp(struct buf *, u_int8_t); struct bgp_msg *session_newmsg(enum msg_type, u_int16_t); int session_sendmsg(struct bgp_msg *, struct peer *); -@@ -177,8 +180,8 @@ setup_listeners(u_int *la_cnt) + void session_open(struct peer *); +@@ -75,7 +78,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); +-void session_rrefresh(struct peer *, u_int16_t, u_int8_t); ++void session_rrefresh(struct peer *, u_int8_t); + 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 *); + int parse_refresh(struct peer *); + int parse_notification(struct peer *); + int parse_capabilities(struct peer *, u_char *, u_int16_t, u_int32_t *); ++int capa_neg_calc(struct peer *); + void session_dispatch_imsg(struct imsgbuf *, int, u_int *); + void session_up(struct peer *); + void session_down(struct peer *); + void session_demote(struct peer *, int); + +-int la_cmp(struct listen_addr *, struct listen_addr *); +-struct peer *getpeerbyip(struct sockaddr *); +-int session_match_mask(struct peer *, struct sockaddr *); +-struct peer *getpeerbyid(u_int32_t); +-static struct sockaddr *addr2sa(struct bgpd_addr *, u_int16_t); ++int la_cmp(struct listen_addr *, struct listen_addr *); ++struct peer *getpeerbyip(struct sockaddr *); ++int session_match_mask(struct peer *, struct bgpd_addr *); ++struct peer *getpeerbyid(u_int32_t); + +-struct bgpd_config *conf, *nconf = NULL; ++struct bgpd_config *conf, *nconf; + struct bgpd_sysdep sysdep; +-struct peer *npeers; +-volatile sig_atomic_t session_quit = 0; +-int pending_reconf = 0; ++struct peer *peers, *npeers; ++volatile sig_atomic_t session_quit; ++int pending_reconf; + int csock = -1, rcsock = -1; + u_int peer_cnt; + struct imsgbuf *ibuf_rde; +@@ -175,10 +178,8 @@ setup_listeners(u_int *la_cnt) + } + pid_t - session_main(struct bgpd_config *config, struct peer *cpeers, - struct network_head *net_l, struct filter_head *rules, -- struct mrt_head *m_l, int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2], -- int pipe_s2rctl[2]) -+ 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(struct bgpd_config *config, struct peer *cpeers, +- struct network_head *net_l, struct filter_head *rules, +- struct mrt_head *m_l, struct rib_names *rib_l, int pipe_m2s[2], +- int pipe_s2r[2], int pipe_m2r[2], int pipe_s2rctl[2]) ++session_main(int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2], ++ int pipe_s2rctl[2], char *cname, char *rcname) { int nfds, timeout; unsigned int i, j, idx_peers, idx_listeners, idx_mrts; -@@ -195,6 +198,7 @@ session_main(struct bgpd_config *config, +@@ -189,19 +190,13 @@ session_main(struct bgpd_config *config, + u_int32_t ctl_queued; + struct passwd *pw; + struct peer *p, **peer_l = NULL, *last, *next; +- struct network *net; +- struct mrt *m, **mrt_l = NULL; +- struct filter_rule *r; ++ struct mrt *m, *xm, **mrt_l = NULL; struct pollfd *pfd = NULL; struct ctl_conn *ctl_conn; struct listen_addr *la; -+ struct rde_rib *rr; +- struct rde_rib *rr; void *newp; short events; -@@ -283,6 +287,11 @@ session_main(struct bgpd_config *config, - LIST_REMOVE(m, entry); - free(m); +- conf = config; +- peers = cpeers; +- + switch (pid = fork()) { + case -1: + fatal("cannot fork"); +@@ -212,10 +207,9 @@ session_main(struct bgpd_config *config, } -+ /* rib names not used in the SE */ -+ while ((rr = SIMPLEQ_FIRST(&ribnames))) { -+ SIMPLEQ_REMOVE_HEAD(&ribnames, entry); -+ free(rr); -+ } + + /* 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"); +- 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"); + + if ((pw = getpwnam(BGPD_USER)) == NULL) +@@ -237,20 +231,18 @@ session_main(struct bgpd_config *config, + setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) + fatal("can't drop privileges"); + +- listener_cnt = 0; +- setup_listeners(&listener_cnt); +- + signal(SIGTERM, session_sighdlr); + signal(SIGINT, session_sighdlr); + signal(SIGPIPE, SIG_IGN); + signal(SIGHUP, SIG_IGN); +- log_info("session engine ready"); ++ signal(SIGALRM, SIG_IGN); ++ signal(SIGUSR1, SIG_IGN); ++ + close(pipe_m2s[0]); + close(pipe_s2r[1]); + close(pipe_s2rctl[1]); + close(pipe_m2r[0]); + close(pipe_m2r[1]); +- init_conf(conf); + if ((ibuf_rde = malloc(sizeof(struct imsgbuf))) == NULL || + (ibuf_rde_ctl = malloc(sizeof(struct imsgbuf))) == NULL || + (ibuf_main = malloc(sizeof(struct imsgbuf))) == NULL) +@@ -258,37 +250,23 @@ session_main(struct bgpd_config *config, + imsg_init(ibuf_rde, pipe_s2r[0]); + imsg_init(ibuf_rde_ctl, pipe_s2rctl[0]); + imsg_init(ibuf_main, pipe_m2s[1]); ++ + TAILQ_INIT(&ctl_conns); + control_listen(csock); + control_listen(rcsock); + LIST_INIT(&mrthead); ++ listener_cnt = 0; + peer_cnt = 0; + ctl_cnt = 0; + +- /* filter rules are not used in the SE */ +- while ((r = TAILQ_FIRST(rules)) != NULL) { +- TAILQ_REMOVE(rules, r, entry); +- free(r); +- } +- free(rules); +- +- /* network list is not used in the SE */ +- while ((net = TAILQ_FIRST(net_l)) != NULL) { +- TAILQ_REMOVE(net_l, net, entry); +- filterset_free(&net->net.attrset); +- free(net); +- } ++ if ((conf = malloc(sizeof(struct bgpd_config))) == NULL) ++ fatal(NULL); ++ if ((conf->listen_addrs = calloc(1, sizeof(struct listen_addrs))) == ++ NULL) ++ fatal(NULL); ++ TAILQ_INIT(conf->listen_addrs); + +- /* main mrt list is not used in the SE */ +- while ((m = LIST_FIRST(m_l)) != NULL) { +- LIST_REMOVE(m, entry); +- free(m); +- } +- /* rib names not used in the SE */ +- while ((rr = SIMPLEQ_FIRST(&ribnames))) { +- SIMPLEQ_REMOVE_HEAD(&ribnames, entry); +- free(rr); +- } ++ log_info("session engine ready"); while (session_quit == 0) { /* check for peers to be initialized or deleted */ -@@ -302,7 +311,7 @@ session_main(struct bgpd_config *config, +@@ -308,8 +286,9 @@ session_main(struct bgpd_config *config, /* reinit due? */ if (p->conf.reconf_action == RECONF_REINIT) { - bgp_fsm(p, EVNT_STOP); +- timer_set(p, Timer_IdleHold, 0); + session_stop(p, ERR_CEASE_ADMIN_RESET); - timer_set(p, Timer_IdleHold, 0); ++ if (!p->conf.down) ++ timer_set(p, Timer_IdleHold, 0); } -@@ -311,7 +320,7 @@ session_main(struct bgpd_config *config, + /* deletion due? */ +@@ -317,7 +296,7 @@ session_main(struct bgpd_config *config, if (p->demoted) session_demote(p, -1); p->conf.demote_group[0] = 0; @@ -82,58 +215,26 @@ diff -u -p -r1.1.1.1 -r1.5 log_peer_warnx(&p->conf, "removed"); if (last != NULL) last->next = next; -@@ -341,7 +350,7 @@ session_main(struct bgpd_config *config, +@@ -346,9 +325,17 @@ session_main(struct bgpd_config *config, + } mrt_cnt = 0; - LIST_FOREACH(m, &mrthead, entry) -- if (m->queued) -+ if (m->wbuf.queued) +- LIST_FOREACH(m, &mrthead, entry) ++ for (m = LIST_FIRST(&mrthead); m != NULL; m = xm) { ++ xm = LIST_NEXT(m, entry); ++ if (m->state == MRT_STATE_REMOVE) { ++ mrt_clean(m); ++ LIST_REMOVE(m, entry); ++ free(m); ++ continue; ++ } + if (m->wbuf.queued) mrt_cnt++; ++ } if (mrt_cnt > mrt_l_elms) { -@@ -438,6 +447,12 @@ session_main(struct bgpd_config *config, - Timer_IdleHoldReset, - p->IdleHoldTime); - break; -+ case Timer_CarpUndemote: -+ timer_stop(p, Timer_CarpUndemote); -+ if (p->demoted && -+ p->state == STATE_ESTABLISHED) -+ session_demote(p, -1); -+ break; - default: - fatalx("King Bula lost in time"); - } -@@ -446,17 +461,6 @@ session_main(struct bgpd_config *config, - nextaction < timeout) - timeout = nextaction; - -- /* XXX carp demotion */ -- if (p->demoted && p->state == STATE_ESTABLISHED) { -- if (time(NULL) - p->stats.last_updown >= -- INTERVAL_HOLD_DEMOTED) -- session_demote(p, -1); -- if (p->stats.last_updown + INTERVAL_HOLD_DEMOTED -- - time(NULL) < timeout) -- timeout = p->stats.last_updown + -- INTERVAL_HOLD_DEMOTED - time(NULL); -- } -- - /* are we waiting for a write? */ - events = POLLIN; - if (p->wbuf.queued > 0 || p->state == STATE_CONNECT) -@@ -474,8 +478,8 @@ session_main(struct bgpd_config *config, - idx_peers = i; - - LIST_FOREACH(m, &mrthead, entry) -- if (m->queued) { -- pfd[i].fd = m->fd; -+ if (m->wbuf.queued) { -+ pfd[i].fd = m->wbuf.fd; - pfd[i].events = POLLOUT; - mrt_l[i - idx_peers] = m; - i++; -@@ -556,7 +560,7 @@ session_main(struct bgpd_config *config, + if ((newp = realloc(mrt_l, sizeof(struct mrt *) * +@@ -557,7 +544,7 @@ session_main(struct bgpd_config *config, while ((p = peers) != NULL) { peers = p->next; @@ -142,50 +243,7 @@ diff -u -p -r1.1.1.1 -r1.5 pfkey_remove(p); free(p); } -@@ -594,6 +598,8 @@ init_conf(struct bgpd_config *c) - { - if (!c->holdtime) - c->holdtime = INTERVAL_HOLD; -+ if (!c->connectretry) -+ c->connectretry = INTERVAL_CONNECTRETRY; - } - - void -@@ -668,7 +674,7 @@ bgp_fsm(struct peer *peer, enum session_ - } else { - change_state(peer, STATE_CONNECT, event); - timer_set(peer, Timer_ConnectRetry, -- INTERVAL_CONNECTRETRY); -+ conf->connectretry); - session_connect(peer); - } - peer->passive = 0; -@@ -693,13 +699,13 @@ bgp_fsm(struct peer *peer, enum session_ - break; - case EVNT_CON_OPENFAIL: - timer_set(peer, Timer_ConnectRetry, -- INTERVAL_CONNECTRETRY); -+ conf->connectretry); - session_close_connection(peer); - change_state(peer, STATE_ACTIVE, event); - break; - case EVNT_TIMER_CONNRETRY: - timer_set(peer, Timer_ConnectRetry, -- INTERVAL_CONNECTRETRY); -+ conf->connectretry); - session_connect(peer); - break; - default: -@@ -722,7 +728,7 @@ bgp_fsm(struct peer *peer, enum session_ - break; - case EVNT_CON_OPENFAIL: - timer_set(peer, Timer_ConnectRetry, -- INTERVAL_CONNECTRETRY); -+ conf->connectretry); - session_close_connection(peer); - change_state(peer, STATE_ACTIVE, event); - break; -@@ -743,13 +749,12 @@ bgp_fsm(struct peer *peer, enum session_ +@@ -746,7 +733,6 @@ bgp_fsm(struct peer *peer, enum session_ /* ignore */ break; case EVNT_STOP: @@ -193,14 +251,7 @@ diff -u -p -r1.1.1.1 -r1.5 change_state(peer, STATE_IDLE, event); break; case EVNT_CON_CLOSED: - session_close_connection(peer); - timer_set(peer, Timer_ConnectRetry, -- INTERVAL_CONNECTRETRY); -+ conf->connectretry); - change_state(peer, STATE_ACTIVE, event); - break; - case EVNT_CON_FATAL: -@@ -788,7 +793,6 @@ bgp_fsm(struct peer *peer, enum session_ +@@ -791,7 +777,6 @@ bgp_fsm(struct peer *peer, enum session_ /* ignore */ break; case EVNT_STOP: @@ -208,7 +259,7 @@ diff -u -p -r1.1.1.1 -r1.5 change_state(peer, STATE_IDLE, event); break; case EVNT_CON_CLOSED: -@@ -823,7 +827,6 @@ bgp_fsm(struct peer *peer, enum session_ +@@ -826,7 +811,6 @@ bgp_fsm(struct peer *peer, enum session_ /* ignore */ break; case EVNT_STOP: @@ -216,35 +267,139 @@ diff -u -p -r1.1.1.1 -r1.5 change_state(peer, STATE_IDLE, event); break; case EVNT_CON_CLOSED: -@@ -953,6 +956,9 @@ change_state(struct peer *peer, enum ses - break; - case STATE_ESTABLISHED: - timer_set(peer, Timer_IdleHoldReset, peer->IdleHoldTime); -+ if (peer->demoted) -+ timer_set(peer, Timer_CarpUndemote, -+ INTERVAL_HOLD_DEMOTED); - session_up(peer); - break; - default: /* something seriously fucked */ -@@ -961,13 +967,12 @@ change_state(struct peer *peer, enum ses - - log_statechange(peer, state, event); - LIST_FOREACH(mrt, &mrthead, entry) { -- if (mrt->type != MRT_ALL_IN && mrt->type != MRT_ALL_OUT) -+ if (!(mrt->type == MRT_ALL_IN || mrt->type == MRT_ALL_OUT)) - continue; - if ((mrt->peer_id == 0 && mrt->group_id == 0) || -- mrt->peer_id == peer->conf.id || -- mrt->group_id == peer->conf.groupid) -- mrt_dump_state(mrt, peer->state, state, -- peer, conf); -+ mrt->peer_id == peer->conf.id || (mrt->group_id != 0 && -+ mrt->group_id == peer->conf.groupid)) -+ mrt_dump_state(mrt, peer->state, state, peer); +@@ -923,6 +907,7 @@ change_state(struct peer *peer, enum ses + timer_stop(peer, Timer_ConnectRetry); + timer_stop(peer, Timer_Keepalive); + timer_stop(peer, Timer_Hold); ++ timer_stop(peer, Timer_IdleHold); + timer_stop(peer, Timer_IdleHoldReset); + session_close_connection(peer); + msgbuf_clear(&peer->wbuf); +@@ -1069,7 +1054,7 @@ session_connect(struct peer *peer) + if (peer->fd != -1) + return (-1); + +- if ((peer->fd = socket(peer->conf.remote_addr.af, SOCK_STREAM, ++ if ((peer->fd = socket(aid2af(peer->conf.remote_addr.aid), SOCK_STREAM, + IPPROTO_TCP)) == -1) { + log_peer_warn(&peer->conf, "session_connect socket"); + bgp_fsm(peer, EVNT_CON_OPENFAIL); +@@ -1100,8 +1085,7 @@ session_connect(struct peer *peer) + peer->wbuf.fd = peer->fd; + + /* if update source is set we need to bind() */ +- if (peer->conf.local_addr.af) { +- sa = addr2sa(&peer->conf.local_addr, 0); ++ if ((sa = addr2sa(&peer->conf.local_addr, 0)) != NULL) { + if (bind(peer->fd, sa, sa->sa_len) == -1) { + log_peer_warn(&peer->conf, "session_connect bind"); + bgp_fsm(peer, EVNT_CON_OPENFAIL); +@@ -1139,42 +1123,50 @@ session_setup_socket(struct peer *p) + int nodelay = 1; + int bsize; + +- if (p->conf.ebgp && p->conf.remote_addr.af == AF_INET) { +- /* set TTL to foreign router's distance - 1=direct n=multihop +- with ttlsec, we always use 255 */ +- if (p->conf.ttlsec) { +- ttl = 256 - p->conf.distance; +- if (setsockopt(p->fd, IPPROTO_IP, IP_MINTTL, &ttl, ++ switch (p->conf.remote_addr.aid) { ++ case AID_INET: ++ /* set precedence, see RFC 1771 appendix 5 */ ++ if (setsockopt(p->fd, IPPROTO_IP, IP_TOS, &pre, sizeof(pre)) == ++ -1) { ++ log_peer_warn(&p->conf, ++ "session_setup_socket setsockopt TOS"); ++ return (-1); ++ } ++ ++ if (p->conf.ebgp) { ++ /* set TTL to foreign router's distance ++ 1=direct n=multihop with ttlsec, we always use 255 */ ++ if (p->conf.ttlsec) { ++ ttl = 256 - p->conf.distance; ++ if (setsockopt(p->fd, IPPROTO_IP, IP_MINTTL, ++ &ttl, sizeof(ttl)) == -1) { ++ log_peer_warn(&p->conf, ++ "session_setup_socket: " ++ "setsockopt MINTTL"); ++ return (-1); ++ } ++ ttl = 255; ++ } ++ ++ if (setsockopt(p->fd, IPPROTO_IP, IP_TTL, &ttl, + sizeof(ttl)) == -1) { + log_peer_warn(&p->conf, +- "session_setup_socket setsockopt MINTTL"); ++ "session_setup_socket setsockopt TTL"); + return (-1); + } +- ttl = 255; +- } +- +- if (setsockopt(p->fd, IPPROTO_IP, IP_TTL, &ttl, +- sizeof(ttl)) == -1) { +- log_peer_warn(&p->conf, +- "session_setup_socket setsockopt TTL"); +- return (-1); + } +- } +- +- if (p->conf.ebgp && p->conf.remote_addr.af == AF_INET6) +- /* set hoplimit to foreign router's distance */ +- if (setsockopt(p->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, +- sizeof(ttl)) == -1) { +- log_peer_warn(&p->conf, +- "session_setup_socket setsockopt hoplimit"); +- return (-1); ++ break; ++ case AID_INET6: ++ if (p->conf.ebgp) { ++ /* set hoplimit to foreign router's distance */ ++ if (setsockopt(p->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, ++ &ttl, sizeof(ttl)) == -1) { ++ log_peer_warn(&p->conf, ++ "session_setup_socket setsockopt hoplimit"); ++ return (-1); ++ } + } +- +- /* if ttlsec is in use, set minttl */ +- if (p->conf.ttlsec) { +- ttl = 256 - p->conf.distance; +- setsockopt(p->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)); +- ++ break; } - peer->prev_state = peer->state; - peer->state = state; -@@ -1247,21 +1252,12 @@ session_capa_ann_none(struct peer *peer) + + /* set TCP_NODELAY */ +@@ -1185,14 +1177,6 @@ session_setup_socket(struct peer *p) + return (-1); + } + +- /* set precedence, see RFC 1771 appendix 5 */ +- if (p->conf.remote_addr.af == AF_INET && +- setsockopt(p->fd, IPPROTO_IP, IP_TOS, &pre, sizeof(pre)) == -1) { +- log_peer_warn(&p->conf, +- "session_setup_socket setsockopt TOS"); +- return (-1); +- } +- + /* only increase bufsize (and thus window) if md5 or ipsec is in use */ + if (p->conf.auth.method != AUTH_NONE) { + /* try to increase bufsize. no biggie if it fails */ +@@ -1244,36 +1228,28 @@ session_tcp_established(struct peer *pee + void + session_capa_ann_none(struct peer *peer) + { +- peer->capa.ann.mp_v4 = SAFI_NONE; +- peer->capa.ann.mp_v4 = SAFI_NONE; +- peer->capa.ann.refresh = 0; +- peer->capa.ann.restart = 0; +- peer->capa.ann.as4byte = 0; ++ bzero(&peer->capa.ann, sizeof(peer->capa.ann)); } int @@ -258,8 +413,6 @@ diff -u -p -r1.1.1.1 -r1.5 - op_type = OPT_PARAM_CAPABILITIES; - op_len = sizeof(capa_code) + sizeof(capa_len) + capa_len; - tot_len = sizeof(op_type) + sizeof(op_len) + op_len; -- if (buf_grow(opb, tot_len) == NULL) -- return (1); - 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)); @@ -268,45 +421,30 @@ diff -u -p -r1.1.1.1 -r1.5 return (errs); } -@@ -1317,22 +1313,16 @@ session_sendmsg(struct bgp_msg *msg, str - struct mrt *mrt; - - LIST_FOREACH(mrt, &mrthead, entry) { -- if (mrt->type != MRT_ALL_OUT && -- msg->type == UPDATE && mrt->type != MRT_UPDATE_OUT) -+ if (!(mrt->type == MRT_ALL_OUT || (msg->type == UPDATE && -+ mrt->type == MRT_UPDATE_OUT))) - continue; - if ((mrt->peer_id == 0 && mrt->group_id == 0) || -- mrt->peer_id == p->conf.id || -- mrt->group_id == p->conf.groupid) -- mrt_dump_bgp_msg(mrt, msg->buf->buf, msg->len, p, conf); -- } -- -- if (buf_close(&p->wbuf, msg->buf) == -1) { -- log_peer_warn(&p->conf, "session_sendmsg buf_close"); -- buf_free(msg->buf); -- free(msg); -- return (-1); -+ mrt->peer_id == p->conf.id || (mrt->group_id == 0 && -+ mrt->group_id == p->conf.groupid)) -+ mrt_dump_bgp_msg(mrt, msg->buf->buf, msg->len, p); - } + 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) + { +- u_int8_t pad = 0; ++ u_int8_t safi, pad = 0; ++ u_int16_t afi; + int errs = 0; -+ buf_close(&p->wbuf, msg->buf); - free(msg); - return (0); - } -@@ -1344,36 +1334,37 @@ session_open(struct peer *p) ++ 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; struct msg_open msg; u_int16_t len; - u_int8_t optparamlen = 0; -+ u_int8_t op_type, optparamlen = 0; ++ u_int8_t i, op_type, optparamlen = 0; u_int errs = 0; -- if ((opb = buf_open(0)) == NULL) { +- if ((opb = buf_dynamic(0, MAX_PKTSIZE - MSGSIZE_OPEN_MIN)) == NULL) { + if ((opb = buf_dynamic(0, UCHAR_MAX - sizeof(op_type) - + sizeof(optparamlen))) == NULL) { bgp_fsm(p, EVNT_CON_FATAL); @@ -314,16 +452,19 @@ diff -u -p -r1.1.1.1 -r1.5 } /* multiprotocol extensions, RFC 4760 */ - if (p->capa.ann.mp_v4) { /* 4 bytes data */ +- if (p->capa.ann.mp_v4) { /* 4 bytes data */ - errs += session_capa_add(p, opb, CAPA_MP, 4, &optparamlen); -+ errs += session_capa_add(opb, CAPA_MP, 4); - errs += session_capa_add_mp(opb, AFI_IPv4, p->capa.ann.mp_v4); - } - if (p->capa.ann.mp_v6) { /* 4 bytes data */ +- errs += session_capa_add_mp(opb, AFI_IPv4, p->capa.ann.mp_v4); +- } +- if (p->capa.ann.mp_v6) { /* 4 bytes data */ - errs += session_capa_add(p, opb, CAPA_MP, 4, &optparamlen); -+ errs += session_capa_add(opb, CAPA_MP, 4); - errs += session_capa_add_mp(opb, AFI_IPv6, p->capa.ann.mp_v6); - } +- errs += session_capa_add_mp(opb, AFI_IPv6, p->capa.ann.mp_v6); +- } ++ for (i = 0; i < AID_MAX; i++) ++ if (p->capa.ann.mp[i]) { /* 4 bytes data */ ++ errs += session_capa_add(opb, CAPA_MP, 4); ++ errs += session_capa_add_mp(opb, i); ++ } /* route refresh, RFC 2918 */ if (p->capa.ann.refresh) /* no data */ @@ -342,7 +483,7 @@ diff -u -p -r1.1.1.1 -r1.5 errs += buf_add(opb, &c, 2); } -@@ -1382,10 +1373,14 @@ session_open(struct peer *p) +@@ -1379,10 +1353,14 @@ session_open(struct peer *p) u_int32_t nas; nas = htonl(conf->as); @@ -359,19 +500,7 @@ diff -u -p -r1.1.1.1 -r1.5 len = MSGSIZE_OPEN_MIN + optparamlen; if (errs || (buf = session_newmsg(OPEN, len)) == NULL) { buf_free(opb); -@@ -1394,10 +1389,7 @@ session_open(struct peer *p) - } - - msg.version = 4; -- if (conf->as > USHRT_MAX) -- msg.myas = htons(conf->short_as); -- else -- msg.myas = htons(conf->as); -+ msg.myas = htons(conf->short_as); - if (p->conf.holdtime) - msg.holdtime = htons(p->conf.holdtime); - else -@@ -1411,8 +1403,13 @@ session_open(struct peer *p) +@@ -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)); @@ -387,7 +516,7 @@ diff -u -p -r1.1.1.1 -r1.5 buf_free(opb); -@@ -1487,7 +1484,6 @@ session_notification(struct peer *p, u_i +@@ -1481,7 +1464,6 @@ session_notification(struct peer *p, u_i { struct bgp_msg *buf; u_int errs = 0; @@ -395,7 +524,7 @@ diff -u -p -r1.1.1.1 -r1.5 if (p->stats.last_sent_errcode) /* some notification already sent */ return; -@@ -1499,10 +1495,7 @@ session_notification(struct peer *p, u_i +@@ -1493,10 +1475,7 @@ session_notification(struct peer *p, u_i } errs += buf_add(buf->buf, &errcode, sizeof(errcode)); @@ -407,26 +536,43 @@ diff -u -p -r1.1.1.1 -r1.5 if (datalen > 0) errs += buf_add(buf->buf, data, datalen); -@@ -1809,13 +1802,13 @@ parse_header(struct peer *peer, u_char * +@@ -1521,23 +1500,29 @@ session_notification(struct peer *p, u_i + int + session_neighbor_rrefresh(struct peer *p) + { ++ u_int8_t i; ++ + if (!p->capa.peer.refresh) return (-1); - } - LIST_FOREACH(mrt, &mrthead, entry) { -- if (mrt->type != MRT_ALL_IN && (mrt->type != MRT_UPDATE_IN || -- *type != UPDATE)) -+ if (!(mrt->type == MRT_ALL_IN || (*type == UPDATE && -+ mrt->type == MRT_UPDATE_IN))) - continue; - if ((mrt->peer_id == 0 && mrt->group_id == 0) || -- mrt->peer_id == peer->conf.id || -- mrt->group_id == peer->conf.groupid) -- mrt_dump_bgp_msg(mrt, data, *len, peer, conf); -+ mrt->peer_id == peer->conf.id || (mrt->group_id != 0 && -+ mrt->group_id == peer->conf.groupid)) -+ mrt_dump_bgp_msg(mrt, data, *len, peer); - } + +- if (p->capa.peer.mp_v4 != SAFI_NONE) +- session_rrefresh(p, AFI_IPv4, p->capa.peer.mp_v4); +- if (p->capa.peer.mp_v6 != SAFI_NONE) +- session_rrefresh(p, AFI_IPv6, p->capa.peer.mp_v6); ++ for (i = 0; i < AID_MAX; i++) { ++ if (p->capa.peer.mp[i] != 0) ++ session_rrefresh(p, i); ++ } + return (0); } -@@ -1859,12 +1852,6 @@ parse_open(struct peer *peer) + + void +-session_rrefresh(struct peer *p, u_int16_t afi, u_int8_t safi) ++session_rrefresh(struct peer *p, u_int8_t aid) + { + struct bgp_msg *buf; + int errs = 0; +- u_int8_t null8 = 0; ++ u_int16_t afi; ++ u_int8_t safi, null8 = 0; ++ ++ if (aid2afi(aid, &afi, &safi) == -1) ++ fatalx("session_rrefresh: bad afi/safi pair"); + + if ((buf = session_newmsg(RREFRESH, MSGSIZE_RREFRESH)) == NULL) { + bgp_fsm(p, EVNT_CON_FATAL); +@@ -1853,12 +1838,6 @@ parse_open(struct peer *peer) p += sizeof(short_as); as = peer->short_as = ntohs(short_as); @@ -439,7 +585,7 @@ diff -u -p -r1.1.1.1 -r1.5 memcpy(&oholdtime, p, sizeof(oholdtime)); p += sizeof(oholdtime); -@@ -1972,6 +1959,15 @@ parse_open(struct peer *peer) +@@ -1966,6 +1945,15 @@ parse_open(struct peer *peer) } } @@ -455,47 +601,202 @@ diff -u -p -r1.1.1.1 -r1.5 if (peer->conf.remote_as != as) { log_peer_warnx(&peer->conf, "peer sent wrong AS %s", log_as(as)); -@@ -2193,22 +2189,20 @@ parse_capabilities(struct peer *peer, u_ - memcpy(&mp_safi, capa_val + 3, sizeof(mp_safi)); - switch (mp_afi) { - case AFI_IPv4: -- if (mp_safi < 1 || mp_safi > 3) { -+ if (mp_safi < 1 || mp_safi > 3) - log_peer_warnx(&peer->conf, - "parse_capabilities: AFI IPv4, " -- "mp_safi %u illegal", mp_safi); -- return (-1); -- } -- peer->capa.peer.mp_v4 = mp_safi; -+ "mp_safi %u unknown", mp_safi); -+ else -+ peer->capa.peer.mp_v4 = mp_safi; - break; - case AFI_IPv6: -- if (mp_safi < 1 || mp_safi > 3) { -+ if (mp_safi < 1 || mp_safi > 3) - log_peer_warnx(&peer->conf, - "parse_capabilities: AFI IPv6, " -- "mp_safi %u illegal", mp_safi); -- return (-1); -- } -- peer->capa.peer.mp_v6 = mp_safi; -+ "mp_safi %u unknown", mp_safi); -+ else -+ peer->capa.peer.mp_v6 = mp_safi; +@@ -1974,6 +1962,14 @@ parse_open(struct peer *peer) + return (-1); + } + ++ if (capa_neg_calc(peer) == -1) { ++ log_peer_warnx(&peer->conf, ++ "capabilitiy negotiation calculation failed"); ++ session_notification(peer, ERR_OPEN, 0, NULL, 0); ++ change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); ++ return (-1); ++ } ++ + return (0); + } + +@@ -2008,24 +2004,35 @@ int + parse_refresh(struct peer *peer) + { + u_char *p; +- struct rrefresh r; ++ u_int16_t afi; ++ u_int8_t aid, safi; + + p = peer->rbuf->rptr; + p += MSGSIZE_HEADER; /* header is already checked */ + ++ /* ++ * We could check if we actually announced the capability but ++ * as long as the message is correctly encoded we don't care. ++ */ ++ + /* afi, 2 byte */ +- memcpy(&r.afi, p, sizeof(r.afi)); +- r.afi = ntohs(r.afi); ++ memcpy(&afi, p, sizeof(afi)); ++ afi = ntohs(afi); + p += 2; + /* reserved, 1 byte */ + p += 1; + /* safi, 1 byte */ +- memcpy(&r.safi, p, sizeof(r.safi)); ++ memcpy(&safi, p, sizeof(safi)); + + /* afi/safi unchecked - unrecognized values will be ignored anyway */ ++ if (afi2aid(afi, safi, &aid) == -1) { ++ log_peer_warnx(&peer->conf, "peer sent bad refresh, " ++ "invalid afi/safi pair"); ++ return (0); ++ } + +- if (imsg_compose(ibuf_rde, IMSG_REFRESH, peer->conf.id, 0, -1, &r, +- sizeof(r)) == -1) ++ if (imsg_compose(ibuf_rde, IMSG_REFRESH, peer->conf.id, 0, -1, &aid, ++ sizeof(aid)) == -1) + return (-1); + + return (0); +@@ -2035,11 +2042,12 @@ int + parse_notification(struct peer *peer) + { + u_char *p; ++ u_int16_t datalen; + u_int8_t errcode; + u_int8_t subcode; +- u_int16_t datalen; + u_int8_t capa_code; + u_int8_t capa_len; ++ u_int8_t i; + + /* just log */ + p = peer->rbuf->rptr; +@@ -2094,8 +2102,8 @@ parse_notification(struct peer *peer) + datalen -= capa_len; + switch (capa_code) { + case CAPA_MP: +- peer->capa.ann.mp_v4 = SAFI_NONE; +- peer->capa.ann.mp_v6 = SAFI_NONE; ++ for (i = 0; i < AID_MAX; i++) ++ peer->capa.ann.mp[i] = 0; + log_peer_warnx(&peer->conf, + "disabling multiprotocol capability"); break; - default: /* ignore */ +@@ -2139,13 +2147,14 @@ parse_notification(struct peer *peer) + int + parse_capabilities(struct peer *peer, u_char *d, u_int16_t dlen, u_int32_t *as) + { ++ u_char *capa_val; ++ u_int32_t remote_as; + u_int16_t len; ++ u_int16_t afi; ++ u_int8_t safi; ++ u_int8_t aid; + u_int8_t capa_code; + u_int8_t capa_len; +- u_char *capa_val; +- u_int16_t mp_afi; +- u_int8_t mp_safi; +- u_int32_t remote_as; + + len = dlen; + while (len > 0) { +@@ -2182,29 +2191,16 @@ parse_capabilities(struct peer *peer, u_ + "expect len 4, len is %u", capa_len); + return (-1); + } +- memcpy(&mp_afi, capa_val, sizeof(mp_afi)); +- mp_afi = ntohs(mp_afi); +- memcpy(&mp_safi, capa_val + 3, sizeof(mp_safi)); +- switch (mp_afi) { +- case AFI_IPv4: +- if (mp_safi < 1 || mp_safi > 3) +- log_peer_warnx(&peer->conf, +- "parse_capabilities: AFI IPv4, " +- "mp_safi %u unknown", mp_safi); +- else +- peer->capa.peer.mp_v4 = mp_safi; +- break; +- case AFI_IPv6: +- if (mp_safi < 1 || mp_safi > 3) +- log_peer_warnx(&peer->conf, +- "parse_capabilities: AFI IPv6, " +- "mp_safi %u unknown", mp_safi); +- else +- peer->capa.peer.mp_v6 = mp_safi; +- break; +- default: /* ignore */ ++ memcpy(&afi, capa_val, sizeof(afi)); ++ afi = ntohs(afi); ++ memcpy(&safi, capa_val + 3, sizeof(safi)); ++ if (afi2aid(afi, safi, &aid) == -1) { ++ log_peer_warnx(&peer->conf, ++ "parse_capabilities: AFI %u, " ++ "safi %u unknown", afi, safi); break; -@@ -2318,7 +2312,7 @@ session_dispatch_imsg(struct imsgbuf *ib - fatalx("king bula sez: " - "expected REINIT"); - -- if ((nla->fd = imsg_get_fd(ibuf)) == -1) -+ if ((nla->fd = imsg.fd) == -1) - log_warnx("expected to receive fd for " - "%s but didn't receive any", - log_sockaddr((struct sockaddr *) -@@ -2416,7 +2410,8 @@ session_dispatch_imsg(struct imsgbuf *ib + } ++ peer->capa.peer.mp[aid] = 1; + break; + case CAPA_REFRESH: + peer->capa.peer.refresh = 1; +@@ -2232,6 +2228,37 @@ parse_capabilities(struct peer *peer, u_ + return (0); + } + ++int ++capa_neg_calc(struct peer *p) ++{ ++ u_int8_t i, hasmp = 0; ++ ++ /* refresh: does not realy matter here, use peer setting */ ++ p->capa.neg.refresh = p->capa.peer.refresh; ++ ++ /* as4byte: both side must announce capability */ ++ if (p->capa.ann.as4byte && p->capa.peer.as4byte) ++ p->capa.neg.as4byte = 1; ++ else ++ p->capa.neg.as4byte = 0; ++ ++ /* MP: both side must announce capability */ ++ for (i = 0; i < AID_MAX; i++) { ++ if (p->capa.ann.mp[i] && p->capa.peer.mp[i]) { ++ p->capa.neg.mp[i] = 1; ++ hasmp = 1; ++ } else ++ p->capa.neg.mp[i] = 0; ++ } ++ /* if no MP capability present for default IPv4 unicast mode */ ++ if (!hasmp) ++ p->capa.neg.mp[AID_INET] = 1; ++ ++ p->capa.neg.restart = p->capa.peer.restart; ++ ++ return (0); ++} ++ + void + session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt) + { +@@ -2337,10 +2364,16 @@ session_dispatch_imsg(struct imsgbuf *ib + 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; ++ conf->short_as = nconf->short_as; + conf->holdtime = nconf->holdtime; +- conf->bgpid = nconf->bgpid; + conf->min_holdtime = nconf->min_holdtime; ++ conf->connectretry = nconf->connectretry; + + /* add new peers */ + for (p = npeers; p != NULL; p = next) { +@@ -2408,7 +2441,8 @@ session_dispatch_imsg(struct imsgbuf *ib bgp_fsm(p, EVNT_START); } else if (!depend_ok && p->depend_ok) { p->depend_ok = depend_ok; @@ -505,41 +806,64 @@ diff -u -p -r1.1.1.1 -r1.5 } } break; -@@ -2429,7 +2424,7 @@ session_dispatch_imsg(struct imsgbuf *ib - } +@@ -2612,29 +2646,23 @@ getpeerbydesc(const char *descr) + struct peer * + getpeerbyip(struct sockaddr *ip) + { ++ struct bgpd_addr addr; + struct peer *p, *newpeer, *loose = NULL; + u_int32_t id; - memcpy(&xmrt, imsg.data, sizeof(struct mrt)); -- if ((xmrt.fd = imsg_get_fd(ibuf)) == -1) -+ if ((xmrt.wbuf.fd = imsg.fd) == -1) - log_warnx("expected to receive fd for mrt dump " - "but didn't receive any"); - -@@ -2440,12 +2435,12 @@ session_dispatch_imsg(struct imsgbuf *ib - if (mrt == NULL) - fatal("session_dispatch_imsg"); - memcpy(mrt, &xmrt, sizeof(struct mrt)); -- TAILQ_INIT(&mrt->bufs); -+ TAILQ_INIT(&mrt->wbuf.bufs); - LIST_INSERT_HEAD(&mrthead, mrt, entry); - } else { - /* old dump reopened */ -- close(mrt->fd); -- mrt->fd = xmrt.fd; -+ close(mrt->wbuf.fd); -+ mrt->wbuf.fd = xmrt.wbuf.fd; ++ sa2addr(ip, &addr); ++ + /* we might want a more effective way to find peers by IP */ + for (p = peers; p != NULL; p = p->next) + if (!p->conf.template && +- p->conf.remote_addr.af == ip->sa_family) { +- if (p->conf.remote_addr.af == AF_INET && +- p->conf.remote_addr.v4.s_addr == +- ((struct sockaddr_in *)ip)->sin_addr.s_addr) +- return (p); +- if (p->conf.remote_addr.af == AF_INET6 && +- !bcmp(&p->conf.remote_addr.v6, +- &((struct sockaddr_in6 *)ip)->sin6_addr, +- sizeof(p->conf.remote_addr.v6))) +- return (p); +- } ++ !memcmp(&addr, &p->conf.remote_addr, sizeof(addr))) ++ return (p); + + /* try template matching */ + for (p = peers; p != NULL; p = p->next) + if (p->conf.template && +- p->conf.remote_addr.af == ip->sa_family && +- session_match_mask(p, ip)) ++ p->conf.remote_addr.aid == addr.aid && ++ session_match_mask(p, &addr)) + if (loose == NULL || loose->conf.remote_masklen < + p->conf.remote_masklen) + loose = p; +@@ -2653,21 +2681,19 @@ getpeerbyip(struct sockaddr *ip) + break; } - break; - case IMSG_MRT_CLOSE: -@@ -2667,7 +2662,7 @@ getpeerbyip(struct sockaddr *ip) - newpeer->conf.remote_masklen = 32; } - if (newpeer->conf.remote_addr.af == AF_INET6) { +- if (newpeer->conf.remote_addr.af == AF_INET) { +- newpeer->conf.remote_addr.v4.s_addr = +- ((struct sockaddr_in *)ip)->sin_addr.s_addr; ++ sa2addr(ip, &newpeer->conf.remote_addr); ++ switch (ip->sa_family) { ++ case AF_INET: + newpeer->conf.remote_masklen = 32; +- } +- if (newpeer->conf.remote_addr.af == AF_INET6) { - memcpy(&p->conf.remote_addr.v6, -+ memcpy(&newpeer->conf.remote_addr.v6, - &((struct sockaddr_in6 *)ip)->sin6_addr, - sizeof(newpeer->conf.remote_addr.v6)); +- &((struct sockaddr_in6 *)ip)->sin6_addr, +- sizeof(newpeer->conf.remote_addr.v6)); ++ break; ++ case AF_INET6: newpeer->conf.remote_masklen = 128; -@@ -2675,7 +2670,7 @@ getpeerbyip(struct sockaddr *ip) ++ break; + } newpeer->conf.template = 0; newpeer->conf.cloned = 1; newpeer->state = newpeer->prev_state = STATE_NONE; @@ -548,7 +872,141 @@ diff -u -p -r1.1.1.1 -r1.5 newpeer->rbuf = NULL; init_peer(newpeer); bgp_fsm(newpeer, EVNT_START); -@@ -2845,3 +2840,19 @@ session_demote(struct peer *p, int level +@@ -2680,40 +2706,24 @@ getpeerbyip(struct sockaddr *ip) + } + + int +-session_match_mask(struct peer *p, struct sockaddr *ip) ++session_match_mask(struct peer *p, struct bgpd_addr *a) + { +- int i; + in_addr_t v4mask; +- struct in6_addr *in; +- struct in6_addr mask; ++ struct in6_addr masked; + +- if (p->conf.remote_addr.af == AF_INET) { ++ switch (p->conf.remote_addr.aid) { ++ case AID_INET: + v4mask = htonl(prefixlen2mask(p->conf.remote_masklen)); +- if (p->conf.remote_addr.v4.s_addr == +- ((((struct sockaddr_in *)ip)->sin_addr.s_addr) & v4mask)) ++ if (p->conf.remote_addr.v4.s_addr == (a->v4.s_addr & v4mask)) + return (1); +- else +- return (0); +- } +- +- if (p->conf.remote_addr.af == AF_INET6) { +- bzero(&mask, sizeof(mask)); +- for (i = 0; i < p->conf.remote_masklen / 8; i++) +- mask.s6_addr[i] = 0xff; +- i = p->conf.remote_masklen % 8; +- if (i) +- mask.s6_addr[p->conf.remote_masklen / 8] = 0xff00 >> i; +- +- in = &((struct sockaddr_in6 *)ip)->sin6_addr; +- +- for (i = 0; i < 16; i++) +- if ((in->s6_addr[i] & mask.s6_addr[i]) != +- p->conf.remote_addr.addr8[i]) +- return (0); ++ return (0); ++ case AID_INET6: ++ inet6applymask(&masked, &a->v6, p->conf.remote_masklen); + +- return (1); ++ if (!memcmp(&masked, &p->conf.remote_addr.v6, sizeof(masked))) ++ return (1); ++ return (0); + } +- + return (0); + } + +@@ -2733,6 +2743,7 @@ getpeerbyid(u_int32_t peerid) + void + session_down(struct peer *peer) + { ++ bzero(&peer->capa.neg, sizeof(peer->capa.neg)); + peer->stats.last_updown = time(NULL); + if (imsg_compose(ibuf_rde, IMSG_SESSION_DOWN, peer->conf.id, 0, -1, + NULL, 0) == -1) +@@ -2748,35 +2759,12 @@ session_up(struct peer *p) + &p->conf, sizeof(p->conf)) == -1) + fatalx("imsg_compose error"); + +- switch (p->sa_local.ss_family) { +- case AF_INET: +- sup.local_addr.af = AF_INET; +- memcpy(&sup.local_addr.v4, +- &((struct sockaddr_in *)&p->sa_local)->sin_addr, +- sizeof(sup.local_addr.v4)); +- sup.remote_addr.af = AF_INET; +- memcpy(&sup.remote_addr.v4, +- &((struct sockaddr_in *)&p->sa_remote)->sin_addr, +- sizeof(sup.remote_addr.v4)); +- break; +- case AF_INET6: +- sup.local_addr.af = AF_INET6; +- memcpy(&sup.local_addr.v6, +- &((struct sockaddr_in6 *)&p->sa_local)->sin6_addr, +- sizeof(sup.local_addr.v6)); +- sup.remote_addr.af = AF_INET6; +- memcpy(&sup.remote_addr.v6, +- &((struct sockaddr_in6 *)&p->sa_remote)->sin6_addr, +- sizeof(sup.remote_addr.v6)); +- break; +- default: +- fatalx("session_up: unsupported address family"); +- } ++ sa2addr((struct sockaddr *)&p->sa_local, &sup.local_addr); ++ sa2addr((struct sockaddr *)&p->sa_remote, &sup.remote_addr); + + sup.remote_bgpid = p->remote_bgpid; + sup.short_as = p->short_as; +- memcpy(&sup.capa_announced, &p->capa.ann, sizeof(sup.capa_announced)); +- memcpy(&sup.capa_received, &p->capa.peer, sizeof(sup.capa_received)); ++ memcpy(&sup.capa, &p->capa.neg, sizeof(sup.capa)); + p->stats.last_updown = time(NULL); + if (imsg_compose(ibuf_rde, IMSG_SESSION_UP, p->conf.id, 0, -1, + &sup, sizeof(sup)) == -1) +@@ -2795,34 +2783,6 @@ imsg_compose_rde(int type, pid_t pid, vo + return (imsg_compose(ibuf_rde, type, 0, pid, -1, data, datalen)); + } + +-static struct sockaddr * +-addr2sa(struct bgpd_addr *addr, u_int16_t port) +-{ +- static struct sockaddr_storage ss; +- struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss; +- struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss; +- +- bzero(&ss, sizeof(ss)); +- switch (addr->af) { +- case AF_INET: +- sa_in->sin_family = AF_INET; +- sa_in->sin_len = sizeof(struct sockaddr_in); +- sa_in->sin_addr.s_addr = addr->v4.s_addr; +- sa_in->sin_port = htons(port); +- break; +- case AF_INET6: +- sa_in6->sin6_family = AF_INET6; +- sa_in6->sin6_len = sizeof(struct sockaddr_in6); +- memcpy(&sa_in6->sin6_addr, &addr->v6, +- sizeof(sa_in6->sin6_addr)); +- sa_in6->sin6_port = htons(port); +- sa_in6->sin6_scope_id = addr->scope_id; +- break; +- } +- +- return ((struct sockaddr *)&ss); +-} +- + void + session_demote(struct peer *p, int level) + { +@@ -2837,3 +2797,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 b7d84da0b6d2..2d855c2e8b3a 100644 --- a/net/openbgpd/files/patch-bgpd_session.h +++ b/net/openbgpd/files/patch-bgpd_session.h @@ -1,32 +1,43 @@ Index: bgpd/session.h =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/session.h,v -retrieving revision 1.1.1.1 -retrieving revision 1.1.1.3 -diff -u -p -r1.1.1.1 -r1.1.1.3 ---- bgpd/session.h 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/session.h 22 Oct 2009 14:24:02 -0000 1.1.1.3 +retrieving revision 1.1.1.7 +retrieving revision 1.1.1.8 +diff -u -p -r1.1.1.7 -r1.1.1.8 +--- 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 @@ -1,4 +1,4 @@ --/* $OpenBSD: session.h,v 1.98 2008/05/08 09:53:12 henning Exp $ */ -+/* $OpenBSD: session.h,v 1.101 2009/06/05 20:26:38 claudio Exp $ */ +-/* $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 $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> -@@ -171,6 +171,7 @@ enum Timer { - Timer_Hold, - Timer_IdleHold, - Timer_IdleHoldReset, -+ Timer_CarpUndemote, - Timer_Max +@@ -189,6 +189,7 @@ struct peer { + struct { + struct capabilities ann; + struct capabilities peer; ++ struct capabilities neg; + } capa; + struct { + struct bgpd_addr local_addr; +@@ -217,7 +218,7 @@ struct peer { + u_int8_t passive; }; -@@ -227,13 +228,15 @@ struct ctl_timer { +-struct peer *peers; ++extern struct peer *peers; + + struct ctl_timer { + enum Timer type; +@@ -226,16 +227,14 @@ struct ctl_timer { + + /* session.c */ void session_socket_blockmode(int, enum blockmodes); - pid_t session_main(struct bgpd_config *, struct peer *, - struct network_head *, struct filter_head *, -- struct mrt_head *, int[2], int[2], int[2], int[2]); -+ struct mrt_head *, struct rib_names *, -+ int[2], int[2], int[2], int[2]); +-pid_t session_main(struct bgpd_config *, struct peer *, +- struct network_head *, struct filter_head *, +- struct mrt_head *, struct rib_names *, +- int[2], int[2], int[2], int[2]); ++pid_t session_main(int[2], int[2], int[2], int[2], char *, char *); void bgp_fsm(struct peer *, enum session_events); int session_neighbor_rrefresh(struct peer *p); struct peer *getpeerbyaddr(struct bgpd_addr *); @@ -37,26 +48,14 @@ diff -u -p -r1.1.1.1 -r1.1.1.3 /* log.c */ char *log_fmt_peer(const struct peer_config *); -@@ -254,8 +257,8 @@ void prepare_listeners(struct bgpd_conf +@@ -255,9 +254,7 @@ int merge_config(struct bgpd_config *, + void prepare_listeners(struct bgpd_config *); /* rde.c */ - pid_t rde_main(struct bgpd_config *, struct peer *, struct network_head *, -- struct filter_head *, struct mrt_head *, int[2], int[2], int[2], -- int[2], int); -+ struct filter_head *, struct mrt_head *, struct rib_names *, -+ int[2], int[2], int[2], int[2], int); +-pid_t rde_main(struct bgpd_config *, struct peer *, struct network_head *, +- struct filter_head *, struct mrt_head *, struct rib_names *, +- int[2], int[2], int[2], int[2], int); ++pid_t rde_main(int[2], int[2], int[2], int[2], int); /* control.c */ int control_init(int, char *); -@@ -270,8 +273,9 @@ int pfkey_remove(struct peer *); - int pfkey_init(struct bgpd_sysdep *); - - /* printconf.c */ --void print_config(struct bgpd_config *, struct network_head *, struct peer *, -- struct filter_head *, struct mrt_head *); -+void print_config(struct bgpd_config *, struct rib_names *, -+ struct network_head *, struct peer *, struct filter_head *, -+ struct mrt_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 deleted file mode 100644 index f72ec2efebff..000000000000 --- a/net/openbgpd/files/patch-bgpd_timer.c +++ /dev/null @@ -1,14 +0,0 @@ -Index: bgpd/timer.c -=================================================================== -RCS file: /home/cvs/private/hrs/openbgpd/bgpd/timer.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.1.1.2 -diff -u -p -r1.1.1.1 -r1.1.1.2 ---- bgpd/timer.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/timer.c 9 Jul 2009 16:49:54 -0000 1.1.1.2 -@@ -1,4 +1,4 @@ --/* $OpenBSD: timer.c,v 1.12.2.1 2009/02/20 07:20:15 henning Exp $ */ -+/* $OpenBSD: timer.c,v 1.13 2009/01/21 20:32:53 henning Exp $ */ - - /* - * Copyright (c) 2003-2007 Henning Brauer <henning@openbsd.org> diff --git a/net/openbgpd/files/patch-bgpd_util.c b/net/openbgpd/files/patch-bgpd_util.c index 85bb12c7ccc2..4503f07a196b 100644 --- a/net/openbgpd/files/patch-bgpd_util.c +++ b/net/openbgpd/files/patch-bgpd_util.c @@ -1,14 +1,14 @@ Index: bgpd/util.c =================================================================== RCS file: /home/cvs/private/hrs/openbgpd/bgpd/util.c,v -retrieving revision 1.1.1.1 -retrieving revision 1.3 -diff -u -p -r1.1.1.1 -r1.3 ---- bgpd/util.c 30 Jun 2009 05:46:15 -0000 1.1.1.1 -+++ bgpd/util.c 9 Jul 2009 17:22:14 -0000 1.3 +retrieving revision 1.1.1.6 +retrieving revision 1.4 +diff -u -p -r1.1.1.6 -r1.4 +--- bgpd/util.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 ++++ bgpd/util.c 4 Feb 2010 16:22:23 -0000 1.4 @@ -1,4 +1,4 @@ --/* $OpenBSD: util.c,v 1.4 2008/03/17 20:40:04 henning Exp $ */ -+/* $OpenBSD: util.c,v 1.6 2009/06/12 16:42:53 claudio Exp $ */ +-/* $OpenBSD: util.c,v 1.6 2009/06/12 16:42:53 claudio Exp $ */ ++/* $OpenBSD: util.c,v 1.10 2010/01/13 06:02:37 claudio Exp $ */ /* * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org> @@ -22,42 +22,176 @@ diff -u -p -r1.1.1.1 -r1.3 #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> -@@ -143,7 +146,7 @@ aspath_snprint(char *buf, size_t size, v - UPDATE(); - } - } -- /* ensure that we have a valid C-string especially for emtpy as path */ -+ /* ensure that we have a valid C-string especially for empty as path */ - if (size > 0) - *buf = '\0'; +@@ -33,10 +36,20 @@ log_addr(const struct bgpd_addr *addr) + { + static char buf[48]; -@@ -250,3 +253,29 @@ aspath_extract(const void *seg, int pos) - memcpy(&as, ptr, sizeof(u_int32_t)); - return (ntohl(as)); +- if (inet_ntop(addr->af, &addr->ba, buf, sizeof(buf)) == NULL) +- return ("?"); +- else ++ switch (addr->aid) { ++ case AID_INET: ++ case AID_INET6: ++ if (inet_ntop(aid2af(addr->aid), &addr->ba, buf, ++ sizeof(buf)) == NULL) ++ return ("?"); ++ return (buf); ++ case AID_VPN_IPv4: ++ if (inet_ntop(AF_INET, &addr->vpn4.addr, buf, ++ sizeof(buf)) == NULL) ++ return ("?"); + return (buf); ++ } ++ return ("???"); + } + + const char * +@@ -90,6 +103,32 @@ log_as(u_int32_t as) + return (buf); + } + ++/* XXX this function does not check if the type/subtype combo is ++ * actually valid. */ ++const char * ++log_ext_subtype(u_int8_t subtype) ++{ ++ static char etype[6]; ++ ++ switch (subtype) { ++ case EXT_COMMUNITY_ROUTE_TGT: ++ return ("rt"); /* route target */ ++ case EXT_CUMMUNITY_ROUTE_ORIG: ++ return ("soo"); /* source of origin */ ++ case EXT_COMMUNITY_OSPF_DOM_ID: ++ return ("odi"); /* ospf domain id */ ++ case EXT_COMMUNITY_OSPF_RTR_TYPE: ++ return ("ort"); /* ospf route type */ ++ case EXT_COMMUNITY_OSPF_RTR_ID: ++ return ("ori"); /* ospf router id */ ++ case EXT_COMMUNITY_BGP_COLLECT: ++ return ("bdc"); /* bgp data collection */ ++ default: ++ snprintf(etype, sizeof(etype), "[%i]", (int)subtype); ++ return (etype); ++ } ++} ++ + int + aspath_snprint(char *buf, size_t size, void *data, u_int16_t len) + { +@@ -276,3 +315,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]; } + -+in_addr_t -+prefixlen2mask(u_int8_t prefixlen) ++/* address family translation functions */ ++const struct aid aid_vals[AID_MAX] = AID_VALS; ++ ++const char * ++aid2str(u_int8_t aid) ++{ ++ if (aid < AID_MAX) ++ return (aid_vals[aid].name); ++ return ("unknown AID"); ++} ++ ++int ++aid2afi(u_int8_t aid, u_int16_t *afi, u_int8_t *safi) +{ -+ if (prefixlen == 0) ++ if (aid < AID_MAX) { ++ *afi = aid_vals[aid].afi; ++ *safi = aid_vals[aid].safi; + return (0); ++ } ++ return (-1); ++} ++ ++int ++afi2aid(u_int16_t afi, u_int8_t safi, u_int8_t *aid) ++{ ++ u_int8_t i; ++ ++ for (i = 0; i < AID_MAX; i++) ++ if (aid_vals[i].afi == afi && aid_vals[i].safi == safi) { ++ *aid = i; ++ return (0); ++ } + -+ return (0xffffffff << (32 - prefixlen)); ++ return (-1); +} + -+void -+inet6applymask(struct in6_addr *dest, const struct in6_addr *src, int prefixlen) ++sa_family_t ++aid2af(u_int8_t aid) ++{ ++ if (aid < AID_MAX) ++ return (aid_vals[aid].af); ++ return (AF_UNSPEC); ++} ++ ++int ++af2aid(sa_family_t af, u_int8_t safi, u_int8_t *aid) ++{ ++ u_int8_t i; ++ ++ if (safi == 0) /* default to unicast subclass */ ++ safi = SAFI_UNICAST; ++ ++ for (i = 0; i < AID_MAX; i++) ++ if (aid_vals[i].af == af && aid_vals[i].safi == safi) { ++ *aid = i; ++ return (0); ++ } ++ ++ return (-1); ++} ++ ++struct sockaddr * ++addr2sa(struct bgpd_addr *addr, u_int16_t port) +{ -+ struct in6_addr mask; -+ int i; ++ static struct sockaddr_storage ss; ++ struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss; ++ struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss; ++ ++ if (addr->aid == AID_UNSPEC) ++ return (NULL); ++ ++ bzero(&ss, sizeof(ss)); ++ switch (addr->aid) { ++ case AID_INET: ++ sa_in->sin_family = AF_INET; ++ sa_in->sin_len = sizeof(struct sockaddr_in); ++ sa_in->sin_addr.s_addr = addr->v4.s_addr; ++ sa_in->sin_port = htons(port); ++ break; ++ case AID_INET6: ++ sa_in6->sin6_family = AF_INET6; ++ sa_in6->sin6_len = sizeof(struct sockaddr_in6); ++ memcpy(&sa_in6->sin6_addr, &addr->v6, ++ sizeof(sa_in6->sin6_addr)); ++ sa_in6->sin6_port = htons(port); ++ sa_in6->sin6_scope_id = addr->scope_id; ++ break; ++ } + -+ bzero(&mask, sizeof(mask)); -+ for (i = 0; i < prefixlen / 8; i++) -+ mask.s6_addr[i] = 0xff; -+ i = prefixlen % 8; -+ if (i) -+ mask.s6_addr[prefixlen / 8] = 0xff00 >> i; ++ return ((struct sockaddr *)&ss); ++} ++ ++void ++sa2addr(struct sockaddr *sa, struct bgpd_addr *addr) ++{ ++ struct sockaddr_in *sa_in = (struct sockaddr_in *)sa; ++ struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa; + -+ for (i = 0; i < 16; i++) -+ dest->s6_addr[i] = src->s6_addr[i] & mask.s6_addr[i]; ++ bzero(addr, sizeof(*addr)); ++ switch (sa->sa_family) { ++ case AF_INET: ++ addr->aid = AID_INET; ++ memcpy(&addr->v4, &sa_in->sin_addr, sizeof(addr->v4)); ++ break; ++ case AF_INET6: ++ addr->aid = AID_INET6; ++ memcpy(&addr->v6, &sa_in6->sin6_addr, sizeof(addr->v6)); ++ addr->scope_id = sa_in6->sin6_scope_id; /* I hate v6 */ ++ break; ++ } +} diff --git a/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h b/net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h index ab89a4aba901..1339f1f1a772 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 9 Jul 2009 17:22:14 -0000 1.3 -@@ -0,0 +1,46 @@ ++++ openbsd-compat/openbsd-compat.h 4 Feb 2010 16:22:51 -0000 1.4 +@@ -0,0 +1,87 @@ +/* -+ * $hrs: openbgpd/openbsd-compat/openbsd-compat.h,v 1.3 2009/07/09 17:22:14 hrs Exp $ ++ * $hrs: openbgpd/openbsd-compat/openbsd-compat.h,v 1.4 2010/02/04 16:22:51 hrs Exp $ + */ + +#ifndef _OPENBSD_COMPAT_H @@ -50,4 +50,45 @@ diff -N openbsd-compat/openbsd-compat.h +#define RTP_MASK 0x7f +#define RTP_DOWN 0x80 /* route/link is down */ + ++/* missing LINK_STATE_* macros in net/if.h */ ++#define LINK_STATE_INVALID LINK_STATE_UNKNOWN /* link invalid */ ++#define LINK_STATE_KALIVE_DOWN 7 /* keepalive reports down */ ++#define LINK_STATE_HALF_DUPLEX 5 /* link is up and half duplex */ ++#define LINK_STATE_FULL_DUPLEX 6 /* link is up and full duplex */ ++ ++/* ++ * Status bit descriptions for the various interface types. ++ */ ++struct if_status_description { ++ unsigned char ifs_type; ++ unsigned char ifs_state; ++ const char *ifs_string; ++}; ++ ++#define LINK_STATE_DESC_MATCH(_ifs, _t, _s) \ ++ (((_ifs)->ifs_type == (_t) || (_ifs)->ifs_type == 0) && \ ++ (_ifs)->ifs_state == (_s)) ++ ++#define LINK_STATE_DESCRIPTIONS { \ ++ { IFT_ETHER, LINK_STATE_DOWN, "no carrier" }, \ ++ \ ++ { IFT_IEEE80211, LINK_STATE_DOWN, "no network" }, \ ++ \ ++ { IFT_PPP, LINK_STATE_DOWN, "no carrier" }, \ ++ \ ++ { IFT_CARP, LINK_STATE_DOWN, "backup" }, \ ++ { IFT_CARP, LINK_STATE_UP, "master" }, \ ++ { IFT_CARP, LINK_STATE_HALF_DUPLEX, "master" }, \ ++ { IFT_CARP, LINK_STATE_FULL_DUPLEX, "master" }, \ ++ \ ++ { 0, LINK_STATE_UP, "active" }, \ ++ { 0, LINK_STATE_HALF_DUPLEX, "active" }, \ ++ { 0, LINK_STATE_FULL_DUPLEX, "active" }, \ ++ \ ++/* { 0, LINK_STATE_UNKNOWN, "unknown" }, */ \ ++ { 0, LINK_STATE_INVALID, "invalid" }, \ ++ { 0, LINK_STATE_DOWN, "down" }, \ ++ { 0, LINK_STATE_KALIVE_DOWN, "keepalive down" }, \ ++ { 0, 0, NULL } \ ++} +#endif /* _OPENBSD_COMPAT_H */ diff --git a/net/openbgpd/pkg-descr b/net/openbgpd/pkg-descr index 0a17fc34bbde..c8090fb4ab2c 100644 --- a/net/openbgpd/pkg-descr +++ b/net/openbgpd/pkg-descr @@ -2,7 +2,4 @@ OpenBGPD is a FREE implementation of the Border Gateway Protocol, Version 4. It allows ordinary machines to be used as routers exchanging routes with other systems speaking the BGP protocol. -WWW: http://www.openbgp.org/ - -- Florent Thoumie -flz@xbsd.org +WWW: http://www.openbgpd.org/ diff --git a/net/openbgpd/pkg-install b/net/openbgpd/pkg-install index 623514b0555a..f5996af787be 100644 --- a/net/openbgpd/pkg-install +++ b/net/openbgpd/pkg-install @@ -1,4 +1,5 @@ #!/bin/sh +# $FreeBSD$ case $2 in POST-INSTALL) |