summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd
diff options
context:
space:
mode:
authorSebastian Benoit <benno@cvs.openbsd.org>2017-05-30 18:08:16 +0000
committerSebastian Benoit <benno@cvs.openbsd.org>2017-05-30 18:08:16 +0000
commit6c065a8c1cd7572fc753466f2c6710d1633eb3f6 (patch)
treee8416f23c544eb858ff4bfcfefc9c3dd763ab9ca /usr.sbin/bgpd
parent0b96d8a8b37a3fb6d4254def172cf5b3b42232b3 (diff)
remove extended communities that have the transitive bit set from
routes announced to an ebgp peer (ref. rfc4360). While here remove the pratial flag from extended and large communities. ok claudio@
Diffstat (limited to 'usr.sbin/bgpd')
-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)) {