diff options
Diffstat (limited to 'net/openbgpd/files/patch-bgpd_rde_attr.c')
-rw-r--r-- | net/openbgpd/files/patch-bgpd_rde_attr.c | 562 |
1 files changed, 0 insertions, 562 deletions
diff --git a/net/openbgpd/files/patch-bgpd_rde_attr.c b/net/openbgpd/files/patch-bgpd_rde_attr.c deleted file mode 100644 index 2c0192abe5da..000000000000 --- a/net/openbgpd/files/patch-bgpd_rde_attr.c +++ /dev/null @@ -1,562 +0,0 @@ -Index: bgpd/rde_attr.c -=================================================================== -RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_attr.c,v -retrieving revision 1.1.1.6 -retrieving revision 1.7 -diff -u -p -r1.1.1.6 -r1.7 ---- bgpd/rde_attr.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/rde_attr.c 13 Oct 2012 18:36:00 -0000 1.7 -@@ -1,4 +1,4 @@ --/* $OpenBSD: rde_attr.c,v 1.79 2009/03/19 06:52:59 claudio Exp $ */ -+/* $OpenBSD: rde_attr.c,v 1.90 2012/04/12 17:27:20 claudio Exp $ */ - - /* - * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> -@@ -17,14 +17,22 @@ - */ - - #include <sys/types.h> -+#if defined(__FreeBSD__) /* sys/hash.h */ -+#include "hash.h" -+#else - #include <sys/hash.h> -+#endif /* defined(__FreeBSD__) */ - #include <sys/queue.h> - - #include <netinet/in.h> - -+#include <limits.h> - #include <stdlib.h> - #include <stdio.h> - #include <string.h> -+#if defined(__FreeBSD__) /* limits.h */ -+#include <limits.h> -+#endif /* defined(__FreeBSD__) */ - - #include "bgpd.h" - #include "rde.h" -@@ -36,12 +44,12 @@ attr_write(void *p, u_int16_t p_len, u_i - u_char *b = p; - u_int16_t tmp, tot_len = 2; /* attribute header (without len) */ - -+ flags &= ~ATTR_DEFMASK; - if (data_len > 255) { - tot_len += 2 + data_len; - flags |= ATTR_EXTLEN; - } else { - tot_len += 1 + data_len; -- flags &= ~ATTR_EXTLEN; - } - - if (tot_len > p_len) -@@ -63,26 +71,26 @@ attr_write(void *p, u_int16_t p_len, u_i - } - - int --attr_writebuf(struct buf *buf, u_int8_t flags, u_int8_t type, void *data, -+attr_writebuf(struct ibuf *buf, u_int8_t flags, u_int8_t type, void *data, - u_int16_t data_len) - { - u_char hdr[4]; - -+ flags &= ~ATTR_DEFMASK; - if (data_len > 255) { - flags |= ATTR_EXTLEN; - hdr[2] = (data_len >> 8) & 0xff; - hdr[3] = data_len & 0xff; - } else { -- flags &= ~ATTR_EXTLEN; - hdr[2] = data_len & 0xff; - } - - hdr[0] = flags; - hdr[1] = type; - -- if (buf_add(buf, hdr, flags & ATTR_EXTLEN ? 4 : 3) == -1) -+ if (ibuf_add(buf, hdr, flags & ATTR_EXTLEN ? 4 : 3) == -1) - return (-1); -- if (buf_add(buf, data, data_len) == -1) -+ if (ibuf_add(buf, data, data_len) == -1) - return (-1); - return (0); - } -@@ -146,8 +154,11 @@ attr_optadd(struct rde_aspath *asp, u_in - for (l = 0; l < asp->others_len; l++) { - if (asp->others[l] == NULL) - break; -- if (type == asp->others[l]->type) -+ if (type == asp->others[l]->type) { -+ if (a->refcnt == 0) -+ attr_put(a); - return (-1); -+ } - } - - /* add attribute to the table but first bump refcnt */ -@@ -318,6 +329,7 @@ attr_alloc(u_int8_t flags, u_int8_t type - fatal("attr_optadd"); - rdemem.attr_cnt++; - -+ flags &= ~ATTR_DEFMASK; /* normalize mask */ - a->flags = flags; - a->hash = hash32_buf(&flags, sizeof(flags), HASHINIT); - a->type = type; -@@ -347,6 +359,7 @@ attr_lookup(u_int8_t flags, u_int8_t typ - struct attr *a; - u_int32_t hash; - -+ flags &= ~ATTR_DEFMASK; /* normalize mask */ - hash = hash32_buf(&flags, sizeof(flags), HASHINIT); - hash = hash32_buf(&type, sizeof(type), hash); - hash = hash32_buf(&len, sizeof(len), hash); -@@ -405,6 +418,7 @@ aspath_verify(void *data, u_int16_t len, - u_int8_t *seg = data; - u_int16_t seg_size, as_size = 2; - u_int8_t seg_len, seg_type; -+ int err = 0; - - if (len & 1) - /* odd length aspath are invalid */ -@@ -419,7 +433,15 @@ aspath_verify(void *data, u_int16_t len, - seg_type = seg[0]; - seg_len = seg[1]; - -- if (seg_type != AS_SET && seg_type != AS_SEQUENCE) -+ /* -+ * BGP confederations should not show up but consider them -+ * as a soft error which invalidates the path but keeps the -+ * bgp session running. -+ */ -+ if (seg_type == AS_CONFED_SEQUENCE || seg_type == AS_CONFED_SET) -+ err = AS_ERR_SOFT; -+ if (seg_type != AS_SET && seg_type != AS_SEQUENCE && -+ seg_type != AS_CONFED_SEQUENCE && seg_type != AS_CONFED_SET) - return (AS_ERR_TYPE); - - seg_size = 2 + as_size * seg_len; -@@ -431,7 +453,7 @@ aspath_verify(void *data, u_int16_t len, - /* empty aspath segments are not allowed */ - return (AS_ERR_BAD); - } -- return (0); /* aspath is valid but probably not loop free */ -+ return (err); /* aspath is valid but probably not loop free */ - } - - void -@@ -762,15 +784,9 @@ aspath_countcopy(struct aspath *aspath, - u_int32_t - aspath_neighbor(struct aspath *aspath) - { -- /* -- * Empty aspath is OK -- internal as route. -- * But what is the neighbor? For now let's return 0. -- * That should not break anything. -- */ -- -+ /* Empty aspath is OK -- internal AS route. */ - if (aspath->len == 0) -- return (0); -- -+ return (rde_local_as()); - return (aspath_extract(aspath->data, 0)); - } - -@@ -910,76 +926,63 @@ aspath_prepend(struct aspath *asp, u_int - return (p); - } - --/* we need to be able to search more than one as */ - int --aspath_match(struct aspath *a, enum as_spec type, u_int32_t as) -+aspath_lenmatch(struct aspath *a, enum aslen_spec type, u_int aslen) - { - u_int8_t *seg; -- int final; -+ u_int32_t as, lastas = 0; -+ u_int count = 0; - u_int16_t len, seg_size; - u_int8_t i, seg_type, seg_len; - -- if (type == AS_EMPTY) { -- if (a->len == 0) -+ if (type == ASLEN_MAX) { -+ if (aslen < aspath_count(a->data, a->len)) - return (1); - else - return (0); - } - -- final = 0; -+ /* type == ASLEN_SEQ */ - seg = a->data; - for (len = a->len; len > 0; len -= seg_size, seg += seg_size) { - seg_type = seg[0]; - seg_len = seg[1]; - seg_size = 2 + sizeof(u_int32_t) * seg_len; - -- final = (len == seg_size); -- -- /* just check the first (leftmost) AS */ -- if (type == AS_PEER) { -- if (as == aspath_extract(seg, 0)) -- return (1); -- else -- return (0); -- } -- /* just check the final (rightmost) AS */ -- if (type == AS_SOURCE) { -- /* not yet in the final segment */ -- if (!final) -- continue; -- -- if (as == aspath_extract(seg, seg_len - 1)) -- return (1); -- else -- return (0); -- } -- -- /* AS_TRANSIT or AS_ALL */ - for (i = 0; i < seg_len; i++) { -- if (as == aspath_extract(seg, i)) { -- /* -- * the source (rightmost) AS is excluded from -- * AS_TRANSIT matches. -- */ -- if (final && i == seg_len - 1 && -- type == AS_TRANSIT) -- return (0); -- return (1); -- } -+ /* what should we do with AS_SET? */ -+ as = aspath_extract(seg, i); -+ if (as == lastas) { -+ if (aslen < ++count) -+ return (1); -+ } else -+ count = 1; -+ lastas = as; - } - } - return (0); - } - -+/* -+ * Functions handling communities and extended communities. -+ */ -+ -+int community_ext_matchone(struct filter_extcommunity *, u_int16_t, u_int64_t); -+ - int --community_match(void *data, u_int16_t len, int as, int type) -+community_match(struct rde_aspath *asp, int as, int type) - { -- u_int8_t *p = data; -- u_int16_t eas, etype; -+ struct attr *a; -+ u_int8_t *p; -+ u_int16_t eas, etype, len; - -- len >>= 2; /* divide by four */ -+ a = attr_optget(asp, ATTR_COMMUNITIES); -+ if (a == NULL) -+ /* no communities, no match */ -+ return (0); - -- for (; len > 0; len--) { -+ p = a->data; -+ for (len = a->len / 4; len > 0; len--) { - eas = *p++; - eas <<= 8; - eas |= *p++; -@@ -1000,7 +1003,6 @@ community_set(struct rde_aspath *asp, in - u_int8_t *p = NULL; - unsigned int i, ncommunities = 0; - u_int8_t f = ATTR_OPTIONAL|ATTR_TRANSITIVE; -- u_int8_t t = ATTR_COMMUNITIES; - - attr = attr_optget(asp, ATTR_COMMUNITIES); - if (attr != NULL) { -@@ -1017,7 +1019,7 @@ community_set(struct rde_aspath *asp, in - p += 4; - } - -- if (ncommunities++ >= 0x3fff) -+ if (ncommunities++ >= USHRT_MAX / 4) - /* overflow */ - return (0); - -@@ -1032,11 +1034,10 @@ community_set(struct rde_aspath *asp, in - if (attr != NULL) { - memcpy(p + 4, attr->data, attr->len); - f = attr->flags; -- t = attr->type; - attr_free(asp, attr); - } - -- attr_optadd(asp, f, t, p, ncommunities << 2); -+ attr_optadd(asp, f, ATTR_COMMUNITIES, p, ncommunities << 2); - - free(p); - return (1); -@@ -1049,7 +1050,7 @@ community_delete(struct rde_aspath *asp, - u_int8_t *p, *n; - u_int16_t l, len = 0; - u_int16_t eas, etype; -- u_int8_t f, t; -+ u_int8_t f; - - attr = attr_optget(asp, ATTR_COMMUNITIES); - if (attr == NULL) -@@ -1100,10 +1101,250 @@ community_delete(struct rde_aspath *asp, - } - - f = attr->flags; -- t = attr->type; - - attr_free(asp, attr); -- attr_optadd(asp, f, t, n, len); -+ attr_optadd(asp, f, ATTR_COMMUNITIES, n, len); - free(n); - } - -+int -+community_ext_match(struct rde_aspath *asp, struct filter_extcommunity *c, -+ u_int16_t neighas) -+{ -+ struct attr *attr; -+ u_int8_t *p; -+ u_int64_t ec; -+ u_int16_t len; -+ -+ attr = attr_optget(asp, ATTR_EXT_COMMUNITIES); -+ if (attr == NULL) -+ /* no communities, no match */ -+ return (0); -+ -+ p = attr->data; -+ for (len = attr->len / sizeof(ec); len > 0; len--) { -+ memcpy(&ec, p, sizeof(ec)); -+ if (community_ext_matchone(c, neighas, ec)) -+ return (1); -+ p += sizeof(ec); -+ } -+ -+ return (0); -+} -+ -+int -+community_ext_set(struct rde_aspath *asp, struct filter_extcommunity *c, -+ u_int16_t neighas) -+{ -+ struct attr *attr; -+ u_int8_t *p = NULL; -+ u_int64_t community; -+ unsigned int i, ncommunities = 0; -+ u_int8_t f = ATTR_OPTIONAL|ATTR_TRANSITIVE; -+ -+ if (community_ext_conv(c, neighas, &community)) -+ return (0); -+ -+ attr = attr_optget(asp, ATTR_EXT_COMMUNITIES); -+ if (attr != NULL) { -+ p = attr->data; -+ ncommunities = attr->len / sizeof(community); -+ } -+ -+ /* first check if the community is not already set */ -+ for (i = 0; i < ncommunities; i++) { -+ if (memcmp(&community, p, sizeof(community)) == 0) -+ /* already present, nothing todo */ -+ return (1); -+ p += sizeof(community); -+ } -+ -+ if (ncommunities++ >= USHRT_MAX / sizeof(community)) -+ /* overflow */ -+ return (0); -+ -+ if ((p = malloc(ncommunities * sizeof(community))) == NULL) -+ fatal("community_ext_set"); -+ -+ memcpy(p, &community, sizeof(community)); -+ if (attr != NULL) { -+ memcpy(p + sizeof(community), attr->data, attr->len); -+ f = attr->flags; -+ attr_free(asp, attr); -+ } -+ -+ attr_optadd(asp, f, ATTR_EXT_COMMUNITIES, p, -+ ncommunities * sizeof(community)); -+ -+ free(p); -+ return (1); -+} -+ -+void -+community_ext_delete(struct rde_aspath *asp, struct filter_extcommunity *c, -+ u_int16_t neighas) -+{ -+ struct attr *attr; -+ u_int8_t *p, *n; -+ u_int64_t community; -+ u_int16_t l, len = 0; -+ u_int8_t f; -+ -+ if (community_ext_conv(c, neighas, &community)) -+ return; -+ -+ attr = attr_optget(asp, ATTR_EXT_COMMUNITIES); -+ if (attr == NULL) -+ /* no attr nothing to do */ -+ return; -+ -+ p = attr->data; -+ for (l = 0; l < attr->len; l += sizeof(community)) { -+ if (memcmp(&community, p + l, sizeof(community)) == 0) -+ /* match */ -+ continue; -+ len += sizeof(community); -+ } -+ -+ if (len == 0) { -+ attr_free(asp, attr); -+ return; -+ } -+ -+ if ((n = malloc(len)) == NULL) -+ fatal("community_delete"); -+ -+ p = attr->data; -+ for (l = 0; l < len && p < attr->data + attr->len; -+ p += sizeof(community)) { -+ if (memcmp(&community, p, sizeof(community)) == 0) -+ /* match */ -+ continue; -+ memcpy(n + l, p, sizeof(community)); -+ l += sizeof(community); -+ } -+ -+ f = attr->flags; -+ -+ attr_free(asp, attr); -+ attr_optadd(asp, f, ATTR_EXT_COMMUNITIES, n, len); -+ free(n); -+} -+ -+int -+community_ext_conv(struct filter_extcommunity *c, u_int16_t neighas, -+ u_int64_t *community) -+{ -+ u_int64_t com; -+ u_int32_t ip; -+ -+ com = (u_int64_t)c->type << 56; -+ switch (c->type & EXT_COMMUNITY_VALUE) { -+ case EXT_COMMUNITY_TWO_AS: -+ com |= (u_int64_t)c->subtype << 48; -+ com |= (u_int64_t)c->data.ext_as.as << 32; -+ com |= c->data.ext_as.val; -+ break; -+ case EXT_COMMUNITY_IPV4: -+ com |= (u_int64_t)c->subtype << 48; -+ ip = ntohl(c->data.ext_ip.addr.s_addr); -+ com |= (u_int64_t)ip << 16; -+ com |= c->data.ext_ip.val; -+ break; -+ case EXT_COMMUNITY_FOUR_AS: -+ com |= (u_int64_t)c->subtype << 48; -+ com |= (u_int64_t)c->data.ext_as4.as4 << 16; -+ com |= c->data.ext_as4.val; -+ break; -+ case EXT_COMMUNITY_OPAQUE: -+ com |= (u_int64_t)c->subtype << 48; -+ com |= c->data.ext_opaq & EXT_COMMUNITY_OPAQUE_MAX; -+ break; -+ default: -+ com |= c->data.ext_opaq & 0xffffffffffffffULL; -+ break; -+ } -+ -+ *community = htobe64(com); -+ -+ return (0); -+} -+ -+int -+community_ext_matchone(struct filter_extcommunity *c, u_int16_t neighas, -+ u_int64_t community) -+{ -+ u_int64_t com, mask; -+ u_int32_t ip; -+ -+ community = betoh64(community); -+ -+ com = (u_int64_t)c->type << 56; -+ mask = 0xffULL << 56; -+ if ((com & mask) != (community & mask)) -+ return (0); -+ -+ switch (c->type & EXT_COMMUNITY_VALUE) { -+ case EXT_COMMUNITY_TWO_AS: -+ case EXT_COMMUNITY_IPV4: -+ case EXT_COMMUNITY_FOUR_AS: -+ case EXT_COMMUNITY_OPAQUE: -+ com = (u_int64_t)c->subtype << 48; -+ mask = 0xffULL << 48; -+ if ((com & mask) != (community & mask)) -+ return (0); -+ break; -+ default: -+ com = c->data.ext_opaq & 0xffffffffffffffULL; -+ mask = 0xffffffffffffffULL; -+ if ((com & mask) == (community & mask)) -+ return (1); -+ return (0); -+ } -+ -+ -+ switch (c->type & EXT_COMMUNITY_VALUE) { -+ case EXT_COMMUNITY_TWO_AS: -+ com = (u_int64_t)c->data.ext_as.as << 32; -+ mask = 0xffffULL << 32; -+ if ((com & mask) != (community & mask)) -+ return (0); -+ -+ com = c->data.ext_as.val; -+ mask = 0xffffffffULL; -+ if ((com & mask) == (community & mask)) -+ return (1); -+ break; -+ case EXT_COMMUNITY_IPV4: -+ ip = ntohl(c->data.ext_ip.addr.s_addr); -+ com = (u_int64_t)ip << 16; -+ mask = 0xffffffff0000ULL; -+ if ((com & mask) != (community & mask)) -+ return (0); -+ -+ com = c->data.ext_ip.val; -+ mask = 0xffff; -+ if ((com & mask) == (community & mask)) -+ return (1); -+ break; -+ case EXT_COMMUNITY_FOUR_AS: -+ com = (u_int64_t)c->data.ext_as4.as4 << 16; -+ mask = 0xffffffffULL << 16; -+ if ((com & mask) != (community & mask)) -+ return (0); -+ -+ com = c->data.ext_as4.val; -+ mask = 0xffff; -+ if ((com & mask) == (community & mask)) -+ return (1); -+ break; -+ case EXT_COMMUNITY_OPAQUE: -+ com = c->data.ext_opaq & EXT_COMMUNITY_OPAQUE_MAX; -+ mask = EXT_COMMUNITY_OPAQUE_MAX; -+ if ((com & mask) == (community & mask)) -+ return (1); -+ break; -+ } -+ -+ return (0); -+} |