summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Mares <mj@ucw.cz>2000-04-21 14:25:35 +0200
committerMartin Mares <mj@ucw.cz>2000-04-21 14:25:35 +0200
commit2a9e064d7b41ae6e944dd9fbcb18b89e8fda0dba (patch)
treea4c7df02e0857276b4244eebd1b25b807c48eec0
parentf380aa60faa41872b78155f899518b25933d18b9 (diff)
downloadbird-2a9e064d7b41ae6e944dd9fbcb18b89e8fda0dba.tar
bird-2a9e064d7b41ae6e944dd9fbcb18b89e8fda0dba.zip
If no NLRI's are present in an UPDATE message, parse the attributes, but
don't check presence of mandatory attributes. [draft-09]
-rw-r--r--proto/bgp/attrs.c17
-rw-r--r--proto/bgp/bgp.h2
-rw-r--r--proto/bgp/packets.c10
3 files changed, 16 insertions, 13 deletions
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index fa2649c..f7d7b78 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -676,7 +676,7 @@ bgp_path_loopy(struct bgp_proto *p, eattr *a)
}
struct rta *
-bgp_decode_attrs(struct bgp_conn *conn, byte *attr, unsigned int len, struct linpool *pool)
+bgp_decode_attrs(struct bgp_conn *conn, byte *attr, unsigned int len, struct linpool *pool, int mandatory)
{
struct bgp_proto *bgp = conn->bgp;
rta *a = lp_alloc(pool, sizeof(struct rta));
@@ -800,13 +800,16 @@ bgp_decode_attrs(struct bgp_conn *conn, byte *attr, unsigned int len, struct lin
}
/* Check if all mandatory attributes are present */
- for(i=0; i < sizeof(bgp_mandatory_attrs)/sizeof(bgp_mandatory_attrs[0]); i++)
+ if (mandatory)
{
- code = bgp_mandatory_attrs[i];
- if (!(seen[code/8] & (1 << (code%8))))
+ for(i=0; i < sizeof(bgp_mandatory_attrs)/sizeof(bgp_mandatory_attrs[0]); i++)
{
- bgp_error(conn, 3, 3, code, 1);
- return NULL;
+ code = bgp_mandatory_attrs[i];
+ if (!(seen[code/8] & (1 << (code%8))))
+ {
+ bgp_error(conn, 3, 3, code, 1);
+ return NULL;
+ }
}
}
@@ -831,7 +834,7 @@ bgp_decode_attrs(struct bgp_conn *conn, byte *attr, unsigned int len, struct lin
neigh = neigh_find(&bgp->p, &nexthop, 0) ? : bgp->neigh;
a->gw = neigh->addr;
a->iface = neigh->iface;
- return rta_lookup(a);
+ return a;
malformed:
bgp_error(conn, 3, 1, len, 0);
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index f579ce6..b8e1abc 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -94,7 +94,7 @@ void bgp_close_conn(struct bgp_conn *c);
/* attrs.c */
-struct rta *bgp_decode_attrs(struct bgp_conn *conn, byte *a, unsigned int len, struct linpool *pool);
+struct rta *bgp_decode_attrs(struct bgp_conn *conn, byte *a, unsigned int len, struct linpool *pool, int mandatory);
int bgp_get_attr(struct eattr *e, byte *buf);
int bgp_rte_better(struct rte *, struct rte *);
void bgp_rt_notify(struct proto *, struct network *, struct rte *, struct rte *, struct ea_list *);
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index bec2e50..ccaa91c 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -305,6 +305,7 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, int len)
int withdrawn_len, attr_len, nlri_len, pxlen;
net *n;
rte e;
+ rta *a0;
rta *a = NULL;
DBG("BGP: UPDATE\n");
@@ -341,11 +342,10 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, int len)
rte_update(bgp->p.table, n, &bgp->p, NULL);
}
- if (nlri_len)
+ a0 = bgp_decode_attrs(conn, attrs, attr_len, bgp_linpool, nlri_len);
+ if (a0 && nlri_len)
{
- a = bgp_decode_attrs(conn, attrs, attr_len, bgp_linpool);
- if (!a)
- return;
+ a = rta_lookup(a0);
while (nlri_len)
{
rte *e;
@@ -357,9 +357,9 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, int len)
e->pflags = 0;
rte_update(bgp->p.table, n, &bgp->p, e);
}
- lp_flush(bgp_linpool);
rta_free(a);
}
+ lp_flush(bgp_linpool);
return;
malformed: