diff options
Diffstat (limited to 'net/openbgpd/files/patch-bgpd_rde_attr.c')
-rw-r--r-- | net/openbgpd/files/patch-bgpd_rde_attr.c | 145 |
1 files changed, 125 insertions, 20 deletions
diff --git a/net/openbgpd/files/patch-bgpd_rde_attr.c b/net/openbgpd/files/patch-bgpd_rde_attr.c index f62d59f083f0..eccdc1e36c27 100644 --- a/net/openbgpd/files/patch-bgpd_rde_attr.c +++ b/net/openbgpd/files/patch-bgpd_rde_attr.c @@ -2,17 +2,17 @@ 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.5 -diff -u -p -r1.1.1.6 -r1.5 +retrieving revision 1.6 +diff -u -p -r1.1.1.6 -r1.6 --- bgpd/rde_attr.c 14 Feb 2010 20:19:57 -0000 1.1.1.6 -+++ bgpd/rde_attr.c 10 Apr 2010 12:16:23 -0000 1.5 ++++ bgpd/rde_attr.c 2 Jul 2011 16:06:38 -0000 1.6 @@ -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.83 2010/03/29 09:24:07 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> -@@ -17,7 +17,11 @@ +@@ -17,14 +17,22 @@ */ #include <sys/types.h> @@ -24,7 +24,8 @@ diff -u -p -r1.1.1.6 -r1.5 #include <sys/queue.h> #include <netinet/in.h> -@@ -25,6 +29,9 @@ + ++#include <limits.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -34,39 +35,143 @@ diff -u -p -r1.1.1.6 -r1.5 #include "bgpd.h" #include "rde.h" -@@ -971,15 +978,26 @@ aspath_match(struct aspath *a, enum as_s +@@ -63,7 +71,7 @@ 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]; +@@ -80,9 +88,9 @@ attr_writebuf(struct buf *buf, u_int8_t + 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 */ +@@ -405,6 +416,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 +431,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 +451,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 +@@ -972,14 +992,62 @@ aspath_match(struct aspath *a, enum as_s + } + + int +-community_match(void *data, u_int16_t len, int as, int type) ++aspath_lenmatch(struct aspath *a, enum aslen_spec type, u_int aslen) + { +- u_int8_t *p = data; +- u_int16_t eas, etype; ++ u_int8_t *seg; ++ 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 == ASLEN_MAX) { ++ if (aslen < aspath_count(a->data, a->len)) ++ return (1); ++ else ++ return (0); ++ } + +- len >>= 2; /* divide by four */ ++ /* 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; + +- for (; len > 0; len--) { ++ for (i = 0; i < seg_len; i++) { ++ /* 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) ++int +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 +1018,6 @@ community_set(struct rde_aspath *asp, in +@@ -1000,7 +1068,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; @@ -74,7 +179,7 @@ diff -u -p -r1.1.1.6 -r1.5 attr = attr_optget(asp, ATTR_COMMUNITIES); if (attr != NULL) { -@@ -1017,7 +1034,7 @@ community_set(struct rde_aspath *asp, in +@@ -1017,7 +1084,7 @@ community_set(struct rde_aspath *asp, in p += 4; } @@ -83,7 +188,7 @@ diff -u -p -r1.1.1.6 -r1.5 /* overflow */ return (0); -@@ -1032,11 +1049,10 @@ community_set(struct rde_aspath *asp, in +@@ -1032,11 +1099,10 @@ community_set(struct rde_aspath *asp, in if (attr != NULL) { memcpy(p + 4, attr->data, attr->len); f = attr->flags; @@ -96,7 +201,7 @@ diff -u -p -r1.1.1.6 -r1.5 free(p); return (1); -@@ -1049,7 +1065,7 @@ community_delete(struct rde_aspath *asp, +@@ -1049,7 +1115,7 @@ community_delete(struct rde_aspath *asp, u_int8_t *p, *n; u_int16_t l, len = 0; u_int16_t eas, etype; @@ -105,7 +210,7 @@ diff -u -p -r1.1.1.6 -r1.5 attr = attr_optget(asp, ATTR_COMMUNITIES); if (attr == NULL) -@@ -1100,10 +1116,250 @@ community_delete(struct rde_aspath *asp, +@@ -1100,10 +1166,250 @@ community_delete(struct rde_aspath *asp, } f = attr->flags; |