diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2009-11-18 20:32:36 +0100 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2009-11-18 20:32:36 +0100 |
commit | 3f9b7bfe9ff050430a5886b22a5ab11b5f253048 (patch) | |
tree | d2261e130a4704bf2c84136bbdd98bdd238b2778 /proto/bgp/packets.c | |
parent | 62aa96caa28180f76c8aff0c49dd21128e396153 (diff) | |
download | bird-3f9b7bfe9ff050430a5886b22a5ab11b5f253048.tar bird-3f9b7bfe9ff050430a5886b22a5ab11b5f253048.zip |
Implements option that controls IPv6 BGP next hops when lladdr is missing.
Diffstat (limited to 'proto/bgp/packets.c')
-rw-r--r-- | proto/bgp/packets.c | 47 |
1 files changed, 32 insertions, 15 deletions
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index d126fe5..4176c9f 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -199,7 +199,7 @@ bgp_create_update(struct bgp_conn *conn, byte *buf) if (a_size < 0) { - log(L_ERR "%s: Attribute list too long, skipping corresponding route group", p->p.name); + log(L_ERR "%s: Attribute list too long, skipping corresponding routes", p->p.name); bgp_flush_prefixes(p, buck); rem_node(&buck->send_node); bgp_free_bucket(p, buck); @@ -234,9 +234,9 @@ bgp_create_update(struct bgp_conn *conn, byte *buf) { struct bgp_proto *p = conn->bgp; struct bgp_bucket *buck; - int size, second; + int size, second, rem_stored; int remains = BGP_MAX_PACKET_LENGTH - BGP_HEADER_LENGTH - 4; - byte *w, *tmp, *tstart; + byte *w, *w_stored, *tmp, *tstart; ip_addr *ipp, ip, ip_ll; ea_list *ea; eattr *nh; @@ -272,28 +272,25 @@ bgp_create_update(struct bgp_conn *conn, byte *buf) } DBG("Processing bucket %p\n", buck); - size = bgp_encode_attrs(p, w, buck->eattrs, 2048); + rem_stored = remains; + w_stored = w; + size = bgp_encode_attrs(p, w, buck->eattrs, 2048); if (size < 0) { - log(L_ERR "%s: Attribute list too long, ignoring corresponding route group", p->p.name); + log(L_ERR "%s: Attribute list too long, skipping corresponding routes", p->p.name); bgp_flush_prefixes(p, buck); rem_node(&buck->send_node); bgp_free_bucket(p, buck); continue; } - w += size; remains -= size; - tstart = tmp = bgp_attach_attr_wa(&ea, bgp_linpool, BA_MP_REACH_NLRI, remains-8); - *tmp++ = 0; - *tmp++ = BGP_AF_IPV6; - *tmp++ = 1; - nh = ea_find(buck->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP)); - ASSERT(nh); - /* We have two addresses here in 'nh'. Really. + /* We have two addresses here in NEXT_HOP eattr. Really. Unless NEXT_HOP was modified by filter */ + nh = ea_find(buck->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP)); + ASSERT(nh); second = (nh->u.ptr->length == NEXT_HOP_LENGTH); ipp = (ip_addr *) nh->u.ptr->data; ip = ipp[0]; @@ -322,12 +319,32 @@ bgp_create_update(struct bgp_conn *conn, byte *buf) ip_ll = ipp[1]; else { - ip = p->source_addr; - ip_ll = p->local_link; + switch (p->cf->missing_lladdr) + { + case MLL_SELF: + ip = p->source_addr; + ip_ll = p->local_link; + break; + case MLL_DROP: + log(L_ERR "%s: Missing link-local next hop address, skipping corresponding routes", p->p.name); + w = w_stored; + remains = rem_stored; + bgp_flush_prefixes(p, buck); + rem_node(&buck->send_node); + bgp_free_bucket(p, buck); + continue; + case MLL_IGNORE: + break; + } } } } + tstart = tmp = bgp_attach_attr_wa(&ea, bgp_linpool, BA_MP_REACH_NLRI, remains-8); + *tmp++ = 0; + *tmp++ = BGP_AF_IPV6; + *tmp++ = 1; + if (ipa_nonzero(ip_ll)) { *tmp++ = 32; |