aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorhrs <hrs@FreeBSD.org>2010-02-17 03:27:03 +0800
committerhrs <hrs@FreeBSD.org>2010-02-17 03:27:03 +0800
commitf224ddaace2eaacf1892db702cc436b93f7a1daa (patch)
tree576b460ac6fc99065dbc59b2a6a05cbd5180fea5 /net
parent1a8b352996af161adf5b34c6a6b7defb2892ff32 (diff)
downloadfreebsd-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')
-rw-r--r--net/openbgpd/Makefile4
-rw-r--r--net/openbgpd/distinfo15
-rw-r--r--net/openbgpd/files/patch-bgpctl-compat-openbsd.h6
-rw-r--r--net/openbgpd/files/patch-bgpctl_bgpctl.854
-rw-r--r--net/openbgpd/files/patch-bgpctl_bgpctl.c523
-rw-r--r--net/openbgpd/files/patch-bgpctl_fmt_scaled.c271
-rw-r--r--net/openbgpd/files/patch-bgpctl_irr_asset.c23
-rw-r--r--net/openbgpd/files/patch-bgpctl_irr_parser.c49
-rw-r--r--net/openbgpd/files/patch-bgpctl_irr_prefix.c156
-rw-r--r--net/openbgpd/files/patch-bgpctl_irrfilter.h52
-rw-r--r--net/openbgpd/files/patch-bgpctl_parser.c244
-rw-r--r--net/openbgpd/files/patch-bgpctl_parser.h36
-rw-r--r--net/openbgpd/files/patch-bgpctl_util.h122
-rw-r--r--net/openbgpd/files/patch-bgpctl_whois.c24
-rw-r--r--net/openbgpd/files/patch-bgpd_Makefile14
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.852
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.c237
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.conf.5228
-rw-r--r--net/openbgpd/files/patch-bgpd_bgpd.h590
-rw-r--r--net/openbgpd/files/patch-bgpd_buffer.c233
-rw-r--r--net/openbgpd/files/patch-bgpd_carp.c35
-rw-r--r--net/openbgpd/files/patch-bgpd_config.c45
-rw-r--r--net/openbgpd/files/patch-bgpd_control.c118
-rw-r--r--net/openbgpd/files/patch-bgpd_imsg.c263
-rw-r--r--net/openbgpd/files/patch-bgpd_imsg.h126
-rw-r--r--net/openbgpd/files/patch-bgpd_kroute.c1213
-rw-r--r--net/openbgpd/files/patch-bgpd_log.c74
-rw-r--r--net/openbgpd/files/patch-bgpd_log.h21
-rw-r--r--net/openbgpd/files/patch-bgpd_mrt.c1038
-rw-r--r--net/openbgpd/files/patch-bgpd_mrt.h211
-rw-r--r--net/openbgpd/files/patch-bgpd_name2id.c14
-rw-r--r--net/openbgpd/files/patch-bgpd_parse.y1034
-rw-r--r--net/openbgpd/files/patch-bgpd_pfkey.c171
-rw-r--r--net/openbgpd/files/patch-bgpd_pfkey_compat.c30
-rw-r--r--net/openbgpd/files/patch-bgpd_pftable.c23
-rw-r--r--net/openbgpd/files/patch-bgpd_printconf.c262
-rw-r--r--net/openbgpd/files/patch-bgpd_rde.c2505
-rw-r--r--net/openbgpd/files/patch-bgpd_rde.h386
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_attr.c256
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_decide.c112
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_filter.c179
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_prefix.c498
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_rib.c1091
-rw-r--r--net/openbgpd/files/patch-bgpd_rde_update.c706
-rw-r--r--net/openbgpd/files/patch-bgpd_session.c1062
-rw-r--r--net/openbgpd/files/patch-bgpd_session.h73
-rw-r--r--net/openbgpd/files/patch-bgpd_timer.c14
-rw-r--r--net/openbgpd/files/patch-bgpd_util.c202
-rw-r--r--net/openbgpd/files/patch-openbsd-compat_openbsd-compat.h47
-rw-r--r--net/openbgpd/pkg-descr5
-rw-r--r--net/openbgpd/pkg-install1
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)