This pkg includes modifications to implement 4byte (32bit) AS number extensions to BGP. the original FreeBSD port descr is appended below. -george OpenBGPD is a FREE implementation of the Border Gateway Protocol, Version 4. It allows ordinary machines to be used as routers exchanging routes with other systems speaking the BGP protocol. WWW: http://www.openbgp.org/ - Florent Thoumie flz@xbsd.org
300 lines
9.6 KiB
Text
Executable file
300 lines
9.6 KiB
Text
Executable file
--- bgpd/rde.c.orig 2007-01-11 15:02:39.000000000 +1000
|
|
+++ bgpd/rde.c 2007-01-11 16:32:45.000000000 +1000
|
|
@@ -626,6 +631,10 @@
|
|
{
|
|
struct rde_peer *peer;
|
|
struct rde_aspath *asp = NULL, *fasp;
|
|
+ struct attr *a;
|
|
+ struct attr *b;
|
|
+ struct attr tmp;
|
|
+ struct aspath *new_aspath;
|
|
u_char *p, *mpp = NULL;
|
|
int pos = 0;
|
|
u_int16_t afi, len, mplen;
|
|
@@ -633,6 +642,7 @@
|
|
u_int16_t attrpath_len;
|
|
u_int16_t nlri_len;
|
|
u_int8_t prefixlen, safi, subtype;
|
|
+ u_int32_t aggregator_as;
|
|
struct bgpd_addr prefix;
|
|
struct mpattr mpa;
|
|
|
|
@@ -668,31 +678,88 @@
|
|
|
|
if (attrpath_len != 0) { /* 0 = no NLRI information in this message */
|
|
/* parse path attributes */
|
|
+ /* allocate an empty path structure */
|
|
asp = path_get();
|
|
+ /* len is the length of the attribute set in bytes */
|
|
while (len > 0) {
|
|
- if ((pos = rde_attr_parse(p, len, peer, asp,
|
|
- &mpa)) < 0) {
|
|
+
|
|
+ if ((pos = rde_attr_parse(p, len, peer, asp, &mpa)) < 0) {
|
|
path_put(asp);
|
|
+ /****/
|
|
+ fprintf(stderr,"Attribute parse error\n") ;
|
|
+/***/
|
|
+
|
|
return (-1);
|
|
}
|
|
p += pos;
|
|
len -= pos;
|
|
}
|
|
|
|
+ /* perform an AGGREGATOR substitution */
|
|
+ /* first check that NEW_AGGREGATOR attribute was present */
|
|
+ if ((a = attr_optget(asp, ATTR_NEW_AGGREGATOR)) != NULL) {
|
|
+ /* second, check that an AGGREGATOR attribute was present */
|
|
+ if ((b = attr_optget(asp, ATTR_AGGREGATOR)) != NULL) {
|
|
+ /* then check that we are on a 2 byte to 4 byte boundary */
|
|
+ /* and the AGGREGATOR is AS_TRANS */
|
|
+ if (!(peer->capa_received.as_4bytes)) {
|
|
+ aggregator_as = as_extract(b->data,4) ;
|
|
+ if (aggregator_as == AS_TRANS) {
|
|
+ memcpy(b->data,a->data,4) ;
|
|
+ /* now re-hash the aggregator attribute by releasing it and re-adding it*/
|
|
+ tmp.flags = b->flags ;
|
|
+ tmp.type = b->flags ;
|
|
+ tmp.len = b->len ;
|
|
+ tmp.data = malloc(tmp.len) ;
|
|
+ memcpy(tmp.data,b->data,tmp.len) ;
|
|
+ attr_free(asp,b) ;
|
|
+ attr_optadd(asp,tmp.flags,tmp.type,tmp.data,tmp.len) ;
|
|
+ free(tmp.data) ;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /* now remove the NEW_AGGREGATOR attribute */
|
|
+ attr_free(asp,a) ;
|
|
+ }
|
|
+
|
|
+ /* attempt a PATH substitution */
|
|
+ /* first check that NEW_PATH attribute was present */
|
|
+ if ((a = attr_optget(asp, ATTR_NEW_ASPATH)) != NULL) {
|
|
+ /* then check that we are on a 2 byte to 4 byte boundary */
|
|
+ if (!(peer->capa_received.as_4bytes)) {
|
|
+ if ((new_aspath = aspath_translate(asp->aspath,a->data,a->len)) == NULL) {
|
|
+ rde_update_err(peer, ERR_UPDATE, ERR_UPD_NEWASPATH,
|
|
+ NULL, 0);
|
|
+ path_put(asp);
|
|
+ return (-1);
|
|
+ }
|
|
+ aspath_put(asp->aspath) ;
|
|
+ asp->aspath = new_aspath;
|
|
+ }
|
|
+ /* now remove the NEW_AS_PATH attribute */
|
|
+ attr_free(asp,a) ;
|
|
+ }
|
|
+
|
|
+
|
|
/* check for missing but necessary attributes */
|
|
- if ((subtype = rde_attr_missing(asp, peer->conf.ebgp,
|
|
- nlri_len))) {
|
|
+ if ((subtype = rde_attr_missing(asp, peer->conf.ebgp, nlri_len))) {
|
|
rde_update_err(peer, ERR_UPDATE, ERR_UPD_MISSNG_WK_ATTR,
|
|
&subtype, sizeof(u_int8_t));
|
|
path_put(asp);
|
|
+ /***/
|
|
+ fprintf(stderr,"Missing well known attributes\n");
|
|
+ /***/
|
|
return (-1);
|
|
}
|
|
|
|
/* enforce remote AS if requested */
|
|
if (asp->flags & F_ATTR_ASPATH &&
|
|
peer->conf.enforce_as == ENFORCE_AS_ON)
|
|
- if (peer->conf.remote_as !=
|
|
- aspath_neighbor(asp->aspath)) {
|
|
+ if (peer->conf.remote_as != aspath_neighbor(asp->aspath,4)) {
|
|
+ /***/
|
|
+ fprintf(stderr,"Remote AS is not equal to aspath neighbor AS\n") ;
|
|
+ fprintf(stderr,"configured remote AS is %u, Neighbor is %u\n",peer->conf.remote_as,aspath_neighbor(asp->aspath,4)) ;
|
|
+ /***/
|
|
rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH,
|
|
NULL, 0);
|
|
path_put(asp);
|
|
@@ -820,7 +887,10 @@
|
|
p += 2 + attrpath_len;
|
|
|
|
/* aspath needs to be loop free nota bene this is not a hard error */
|
|
- if (peer->conf.ebgp && !aspath_loopfree(asp->aspath, conf->as)) {
|
|
+ if (peer->conf.ebgp && !aspath_loopfree(asp->aspath, conf->as,4)) {
|
|
+ /****/
|
|
+ fprintf(stderr,"LOOP in AS PATH\n");
|
|
+/***/
|
|
path_put(asp);
|
|
return (0);
|
|
}
|
|
@@ -1012,19 +1082,26 @@
|
|
#define CHECK_FLAGS(s, t, m) \
|
|
(((s) & ~(ATTR_EXTLEN | (m))) == (t))
|
|
|
|
+/* parse update attribute set */
|
|
int
|
|
rde_attr_parse(u_char *p, u_int16_t len, struct rde_peer *peer,
|
|
struct rde_aspath *a, struct mpattr *mpa)
|
|
{
|
|
struct bgpd_addr nexthop;
|
|
u_char *op = p;
|
|
+ u_char *new_p;
|
|
u_int32_t tmp32;
|
|
u_int16_t attr_len;
|
|
+ u_int16_t new_attr_len;
|
|
u_int16_t plen = 0;
|
|
u_int8_t flags;
|
|
u_int8_t type;
|
|
u_int8_t tmp8;
|
|
|
|
+ /****/
|
|
+ fprintf(stderr,"rde_attr_parse - parse update\n") ;
|
|
+ /****/
|
|
+
|
|
if (len < 3) {
|
|
bad_len:
|
|
rde_update_err(peer, ERR_UPDATE, ERR_UPD_ATTRLEN, op, len);
|
|
@@ -1050,6 +1127,9 @@
|
|
/* adjust len to the actual attribute size including header */
|
|
len = plen + attr_len;
|
|
|
|
+/*****/
|
|
+ fprintf(stderr,"UPDATE: attribute: flags = %x, length=%u attr = %u\n",flags, attr_len,type) ;
|
|
+/*****/
|
|
switch (type) {
|
|
case ATTR_UNDEF:
|
|
rde_update_err(peer, ERR_UPDATE, ERR_UPD_UNSPECIFIC, NULL, 0);
|
|
@@ -1076,9 +1156,16 @@
|
|
a->flags |= F_ATTR_ORIGIN;
|
|
break;
|
|
case ATTR_ASPATH:
|
|
+ /****/
|
|
+ fprintf(stderr,"AS Path\n") ;
|
|
+ /****/
|
|
+
|
|
if (!CHECK_FLAGS(flags, ATTR_WELL_KNOWN, 0))
|
|
goto bad_flags;
|
|
- if (aspath_verify(p, attr_len) != 0) {
|
|
+ /****/
|
|
+ fprintf(stderr,"Received ASPATH, 4byte = %u\n",peer->capa_received.as_4bytes);
|
|
+ /****/
|
|
+ if (aspath_verify(p, attr_len, peer->capa_received.as_4bytes) < 0) {
|
|
rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH,
|
|
NULL, 0);
|
|
return (-1);
|
|
@@ -1086,9 +1173,51 @@
|
|
if (a->flags & F_ATTR_ASPATH)
|
|
goto bad_list;
|
|
a->flags |= F_ATTR_ASPATH;
|
|
- a->aspath = aspath_get(p, attr_len);
|
|
+ new_p = p ;
|
|
+ new_attr_len = attr_len ;
|
|
+ /****/
|
|
+ fprintf(stderr,"peer 4byte? = %d\n",peer->capa_received.as_4bytes) ;
|
|
+ /****/
|
|
+ if (!(peer->capa_received.as_4bytes)) {
|
|
+ /****/
|
|
+ fprintf(stderr,"inflate the as path to 4bytes\n") ;
|
|
+ /****/
|
|
+
|
|
+ if (!(new_p = aspath_inflate(p,attr_len,&new_attr_len)))
|
|
+ return(-1) ;
|
|
+ }
|
|
+ a->aspath = aspath_get(new_p, new_attr_len,4);
|
|
+ if (!(peer->capa_received.as_4bytes)) {
|
|
+ free(new_p) ;
|
|
+ }
|
|
plen += attr_len;
|
|
break;
|
|
+ case ATTR_NEW_ASPATH:
|
|
+ /****/
|
|
+ fprintf(stderr,"Received NEW_ASPATH, 4byte = %u\n",peer->capa_received.as_4bytes);
|
|
+ /****/
|
|
+
|
|
+ /* should only receive this attr from 2 byte as (old) bgp peers */
|
|
+ if (peer->capa_received.as_4bytes)
|
|
+ goto bad_flags ;
|
|
+
|
|
+ if (attr_len <= 4)
|
|
+ goto bad_len;
|
|
+
|
|
+ /* flag setting is optional (0x80) and transitive (0x40) */
|
|
+ if (!(flags & (ATTR_OPTIONAL | ATTR_TRANSITIVE)))
|
|
+ goto bad_flags;
|
|
+
|
|
+ if (aspath_verify(p, attr_len, 1) < 0) {
|
|
+ rde_update_err(peer, ERR_UPDATE, ERR_UPD_NEWASPATH,
|
|
+ NULL, 0);
|
|
+ return (-1);
|
|
+ }
|
|
+
|
|
+ /* store this attribute and perform path sustitution at the end of the
|
|
+ attribute parse block */
|
|
+ goto optattr;
|
|
+
|
|
case ATTR_NEXTHOP:
|
|
if (attr_len != 4)
|
|
goto bad_len;
|
|
@@ -1149,10 +1278,35 @@
|
|
goto bad_flags;
|
|
goto optattr;
|
|
case ATTR_AGGREGATOR:
|
|
- if (attr_len != 6)
|
|
+ if ((peer->capa_received.as_4bytes) && (attr_len != 8))
|
|
+ goto bad_len;
|
|
+ if ((!(peer->capa_received.as_4bytes)) && (attr_len != 6))
|
|
goto bad_len;
|
|
if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, 0))
|
|
goto bad_flags;
|
|
+ if (peer->capa_received.as_4bytes)
|
|
+ goto optattr;
|
|
+ new_attr_len = attr_len + 2 ;
|
|
+ if ((new_p = malloc(new_attr_len)) == NULL)
|
|
+ fatal("rde_attr_parse") ;
|
|
+ new_p[0] = 0;
|
|
+ new_p[1] = 0 ;
|
|
+ memcpy(&new_p[2],p,6);
|
|
+ if (attr_optadd(a, flags, type, new_p, new_attr_len) == -1) {
|
|
+ rde_update_err(peer, ERR_UPDATE, ERR_UPD_ATTRLIST,NULL, 0);
|
|
+ return (-1);
|
|
+ }
|
|
+ free(new_p) ;
|
|
+ plen += attr_len;
|
|
+ break;
|
|
+ case ATTR_NEW_AGGREGATOR:
|
|
+ /* should only receive this attr from 2 byte as (old) bgp peers */
|
|
+ if (peer->capa_received.as_4bytes)
|
|
+ goto bad_flags ;
|
|
+ if (attr_len != 8)
|
|
+ goto bad_len;
|
|
+ if (!(flags & (ATTR_OPTIONAL | ATTR_TRANSITIVE)))
|
|
+ goto bad_flags;
|
|
goto optattr;
|
|
case ATTR_COMMUNITIES:
|
|
if ((attr_len & 0x3) != 0)
|
|
@@ -1527,7 +1681,7 @@
|
|
|
|
for (i = 0; i <= pathtable.path_hashmask; i++) {
|
|
LIST_FOREACH(asp, &pathtable.path_hashtbl[i], path_l) {
|
|
- if (!aspath_match(asp->aspath, a->type, a->as))
|
|
+ if (!aspath_match(asp->aspath, a->type, a->as,4))
|
|
continue;
|
|
/* match found */
|
|
LIST_FOREACH(p, &asp->prefix_h, path_l)
|
|
@@ -1957,7 +2111,7 @@
|
|
/*
|
|
* generic helper function
|
|
*/
|
|
-u_int16_t
|
|
+u_int32_t
|
|
rde_local_as(void)
|
|
{
|
|
return (conf->as);
|
|
@@ -2261,7 +2415,7 @@
|
|
struct rde_peer *p;
|
|
|
|
asp = path_get();
|
|
- asp->aspath = aspath_get(NULL, 0);
|
|
+ asp->aspath = aspath_get(NULL, 0,3);
|
|
asp->origin = ORIGIN_IGP;
|
|
asp->flags = F_ATTR_ORIGIN | F_ATTR_ASPATH |
|
|
F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED;
|