diff options
Diffstat (limited to 'net/openbgpd/files/patch-bgpd_rde_attr.c')
-rw-r--r-- | net/openbgpd/files/patch-bgpd_rde_attr.c | 137 |
1 files changed, 121 insertions, 16 deletions
diff --git a/net/openbgpd/files/patch-bgpd_rde_attr.c b/net/openbgpd/files/patch-bgpd_rde_attr.c index 7aa74567837d..f62d59f083f0 100644 --- a/net/openbgpd/files/patch-bgpd_rde_attr.c +++ b/net/openbgpd/files/patch-bgpd_rde_attr.c @@ -2,13 +2,13 @@ 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.4 -diff -u -p -r1.1.1.6 -r1.4 +retrieving revision 1.5 +diff -u -p -r1.1.1.6 -r1.5 --- bgpd/rde_attr.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/rde_attr.c 4 Feb 2010 16:22:23 -0000 1.4 ++++ bgpd/rde_attr.c 10 Apr 2010 12:16:23 -0000 1.5 @@ -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.81 2009/12/18 15:51:37 claudio Exp $ */ ++/* $OpenBSD: rde_attr.c,v 1.83 2010/03/29 09:24:07 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -34,7 +34,7 @@ diff -u -p -r1.1.1.6 -r1.4 #include "bgpd.h" #include "rde.h" -@@ -971,13 +978,26 @@ aspath_match(struct aspath *a, enum as_s +@@ -971,15 +978,26 @@ aspath_match(struct aspath *a, enum as_s return (0); } @@ -42,7 +42,7 @@ diff -u -p -r1.1.1.6 -r1.4 + * Functions handling communities and extended communities. + */ + -+int community_ext_conv(struct filter_extcommunity *, u_int16_t, u_int64_t *); ++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) @@ -59,13 +59,14 @@ diff -u -p -r1.1.1.6 -r1.4 + if (a == NULL) + /* no communities, no match */ + return (0); -+ -+ len = a->len / 4; -+ p = a->data; - for (; len > 0; len--) { +- for (; len > 0; len--) { ++ p = a->data; ++ for (len = a->len / 4; len > 0; len--) { eas = *p++; -@@ -1000,7 +1020,6 @@ community_set(struct rde_aspath *asp, in + eas <<= 8; + eas |= *p++; +@@ -1000,7 +1018,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; @@ -73,7 +74,7 @@ diff -u -p -r1.1.1.6 -r1.4 attr = attr_optget(asp, ATTR_COMMUNITIES); if (attr != NULL) { -@@ -1017,7 +1036,7 @@ community_set(struct rde_aspath *asp, in +@@ -1017,7 +1034,7 @@ community_set(struct rde_aspath *asp, in p += 4; } @@ -82,7 +83,7 @@ diff -u -p -r1.1.1.6 -r1.4 /* overflow */ return (0); -@@ -1032,11 +1051,10 @@ community_set(struct rde_aspath *asp, in +@@ -1032,11 +1049,10 @@ community_set(struct rde_aspath *asp, in if (attr != NULL) { memcpy(p + 4, attr->data, attr->len); f = attr->flags; @@ -95,7 +96,7 @@ diff -u -p -r1.1.1.6 -r1.4 free(p); return (1); -@@ -1049,7 +1067,7 @@ community_delete(struct rde_aspath *asp, +@@ -1049,7 +1065,7 @@ community_delete(struct rde_aspath *asp, u_int8_t *p, *n; u_int16_t l, len = 0; u_int16_t eas, etype; @@ -104,7 +105,7 @@ diff -u -p -r1.1.1.6 -r1.4 attr = attr_optget(asp, ATTR_COMMUNITIES); if (attr == NULL) -@@ -1100,10 +1118,146 @@ community_delete(struct rde_aspath *asp, +@@ -1100,10 +1116,250 @@ community_delete(struct rde_aspath *asp, } f = attr->flags; @@ -117,6 +118,31 @@ diff -u -p -r1.1.1.6 -r1.4 +} + +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) +{ @@ -132,7 +158,7 @@ diff -u -p -r1.1.1.6 -r1.4 + attr = attr_optget(asp, ATTR_EXT_COMMUNITIES); + if (attr != NULL) { + p = attr->data; -+ ncommunities = attr->len / 8; /* 64bit per ext-community */ ++ ncommunities = attr->len / sizeof(community); + } + + /* first check if the community is not already set */ @@ -253,3 +279,82 @@ diff -u -p -r1.1.1.6 -r1.4 + + 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); ++} |