diff options
-rw-r--r-- | usr.sbin/bgpd/rde.h | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_attr.c | 34 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_update.c | 26 |
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)) { |