remove extended communities that have the transitive bit set from
authorbenno <benno@openbsd.org>
Tue, 30 May 2017 18:08:15 +0000 (18:08 +0000)
committerbenno <benno@openbsd.org>
Tue, 30 May 2017 18:08:15 +0000 (18:08 +0000)
routes announced to an ebgp peer (ref. rfc4360). While here remove the
pratial flag from extended and large communities.
ok claudio@

usr.sbin/bgpd/rde.h
usr.sbin/bgpd/rde_attr.c
usr.sbin/bgpd/rde_update.c

index 5debc98..5df5ff2 100644 (file)
@@ -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 *);
index 64d3aae..179849d 100644 (file)
@@ -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;
+}
index 24b4335..0fa7b50 100644 (file)
@@ -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)) {