summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpd/rde.h4
-rw-r--r--usr.sbin/bgpd/rde_attr.c34
-rw-r--r--usr.sbin/bgpd/rde_update.c26
3 files changed, 61 insertions, 3 deletions
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index 5debc98728a..5df5ff2ed8d 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.161 2017/05/28 12:21:36 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.162 2017/05/30 18:08:15 benno Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -386,6 +386,8 @@ void community_ext_delete(struct rde_aspath *,
struct filter_extcommunity *, u_int16_t);
int community_ext_conv(struct filter_extcommunity *, u_int16_t,
u_int64_t *);
+u_char *community_ext_delete_non_trans(u_char *, u_int16_t,
+ u_int16_t *);
/* rde_decide.c */
void prefix_evaluate(struct prefix *, struct rib_entry *);
diff --git a/usr.sbin/bgpd/rde_attr.c b/usr.sbin/bgpd/rde_attr.c
index 64d3aaea3d9..179849d74ae 100644
--- a/usr.sbin/bgpd/rde_attr.c
+++ b/usr.sbin/bgpd/rde_attr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_attr.c,v 1.98 2017/05/26 20:55:30 phessler Exp $ */
+/* $OpenBSD: rde_attr.c,v 1.99 2017/05/30 18:08:15 benno Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -1505,3 +1505,35 @@ community_large_delete(struct rde_aspath *asp, int64_t as, int64_t ld1,
attr_optadd(asp, f, ATTR_LARGE_COMMUNITIES, n, len);
free(n);
}
+
+
+u_char *
+community_ext_delete_non_trans(u_char *data, u_int16_t len, u_int16_t *newlen)
+{
+ u_int8_t *ext = data, *newdata;
+ u_int16_t l, nlen = 0;
+
+ for (l = 0; l < len; l += sizeof(u_int64_t)) {
+ if (!(ext[l] & EXT_COMMUNITY_TRANSITIVE))
+ nlen += sizeof(u_int64_t);
+ }
+
+ if (nlen == 0) {
+ *newlen = 0;
+ return NULL;
+ }
+
+ newdata = malloc(nlen);
+ if (newdata == NULL)
+ fatal("%s", __func__);;
+
+ for (l = 0, nlen = 0; l < len; l += sizeof(u_int64_t)) {
+ if (!(ext[l] & EXT_COMMUNITY_TRANSITIVE)) {
+ memcpy(newdata + nlen, ext + l, sizeof(u_int64_t));
+ nlen += sizeof(u_int64_t);
+ }
+ }
+
+ *newlen = nlen;
+ return newdata;
+}
diff --git a/usr.sbin/bgpd/rde_update.c b/usr.sbin/bgpd/rde_update.c
index 24b4335be5c..0fa7b50073b 100644
--- a/usr.sbin/bgpd/rde_update.c
+++ b/usr.sbin/bgpd/rde_update.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_update.c,v 1.85 2017/05/27 10:33:15 phessler Exp $ */
+/* $OpenBSD: rde_update.c,v 1.86 2017/05/30 18:08:15 benno Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -736,6 +736,8 @@ up_generate_attr(struct rde_peer *peer, struct update_attr *upa,
int flags, r, ismp = 0, neednewpath = 0;
u_int16_t len = sizeof(up_attr_buf), wlen = 0, plen;
u_int8_t l;
+ u_int16_t nlen = 0;
+ u_char *ndata = NULL;
/* origin */
if ((r = attr_write(up_attr_buf + wlen, len, ATTR_WELL_KNOWN,
@@ -849,6 +851,7 @@ up_generate_attr(struct rde_peer *peer, struct update_attr *upa,
case ATTR_COMMUNITIES:
case ATTR_ORIGINATOR_ID:
case ATTR_CLUSTER_LIST:
+ case ATTR_LARGE_COMMUNITIES:
if ((!(oa->flags & ATTR_TRANSITIVE)) &&
peer->conf.ebgp) {
r = 0;
@@ -858,6 +861,27 @@ up_generate_attr(struct rde_peer *peer, struct update_attr *upa,
oa->flags, oa->type, oa->data, oa->len)) == -1)
return (-1);
break;
+ case ATTR_EXT_COMMUNITIES:
+ /* handle (non-)transitive extended communities */
+ if (peer->conf.ebgp) {
+ ndata = community_ext_delete_non_trans(oa->data,
+ oa->len, &nlen);
+
+ if (nlen > 0) {
+ if ((r = attr_write(up_attr_buf + wlen,
+ len, oa->flags, oa->type, ndata,
+ nlen)) == -1) {
+ free(ndata);
+ return (-1);
+ }
+ } else
+ r = 0;
+ break;
+ }
+ if ((r = attr_write(up_attr_buf + wlen, len,
+ oa->flags, oa->type, oa->data, oa->len)) == -1)
+ return (-1);
+ break;
default:
/* unknown attribute */
if (!(oa->flags & ATTR_TRANSITIVE)) {