-/* $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
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 *);
-/* $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>
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;
+}
-/* $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>
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,
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;
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)) {