summaryrefslogtreecommitdiffstats
path: root/proto/bgp/packets.c
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2009-11-18 20:32:36 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2009-11-18 20:32:36 +0100
commit3f9b7bfe9ff050430a5886b22a5ab11b5f253048 (patch)
treed2261e130a4704bf2c84136bbdd98bdd238b2778 /proto/bgp/packets.c
parent62aa96caa28180f76c8aff0c49dd21128e396153 (diff)
downloadbird-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.c47
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;