diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index fa2649c5..f7d7b788 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 f579ce66..b8e1abcf 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 bec2e501..ccaa91c1 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: