From: benno Date: Tue, 30 May 2017 18:08:15 +0000 (+0000) Subject: remove extended communities that have the transitive bit set from X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=d61b7a674e5e4267d0e8a439f05afcc33af4d094;p=openbsd 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@ --- 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 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 @@ -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 @@ -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)) {