summaryrefslogtreecommitdiff
path: root/proto/bgp
diff options
context:
space:
mode:
Diffstat (limited to 'proto/bgp')
-rw-r--r--proto/bgp/bgp.c4
-rw-r--r--proto/bgp/bgp.h5
-rw-r--r--proto/bgp/config.Y6
-rw-r--r--proto/bgp/packets.c47
4 files changed, 46 insertions, 16 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index b38c6b13..cde02768 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -886,6 +886,10 @@ bgp_check(struct bgp_config *c)
if ((c->local_as == c->remote_as) && (c->rs_client))
cf_error("Only external neighbor can be RS client");
+
+ /* Different default based on rs_client */
+ if (c->missing_lladdr == 0)
+ c->missing_lladdr = c->rs_client ? MLL_DROP : MLL_SELF;
}
static char *bgp_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established", "Close" };
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index c487aafb..c4d03352 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -23,6 +23,7 @@ struct bgp_config {
ip_addr multihop_via; /* Multihop: address to route to */
ip_addr source_addr; /* Source address to use */
int next_hop_self; /* Always set next hop to local IP address */
+ int missing_lladdr; /* What we will do when we don' know link-local addr, see MLL_* */
int compare_path_lengths; /* Use path lengths when selecting best route */
int prefer_older; /* Prefer older routes according to RFC 5004 */
u32 default_local_pref; /* Default value for LOCAL_PREF attribute */
@@ -46,6 +47,10 @@ struct bgp_config {
char *password; /* Password used for MD5 authentication */
};
+#define MLL_SELF 1
+#define MLL_DROP 2
+#define MLL_IGNORE 3
+
struct bgp_conn {
struct bgp_proto *bgp;
struct birdsock *sk;
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index 94011750..35769466 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -22,7 +22,8 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
BGP_PATH, BGP_LOCAL_PREF, BGP_MED, BGP_ORIGIN, BGP_NEXT_HOP,
BGP_ATOMIC_AGGR, BGP_AGGREGATOR, BGP_COMMUNITY, SOURCE, ADDRESS,
PASSWORD, RR, RS, CLIENT, CLUSTER, ID, AS4, ADVERTISE, IPV4,
- CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER)
+ CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER, MISSING, LLADDR,
+ DROP, IGNORE)
CF_GRAMMAR
@@ -64,6 +65,9 @@ bgp_proto:
| bgp_proto KEEPALIVE TIME expr ';' { BGP_CFG->keepalive_time = $4; }
| bgp_proto MULTIHOP expr VIA ipa ';' { BGP_CFG->multihop = $3; BGP_CFG->multihop_via = $5; }
| bgp_proto NEXT HOP SELF ';' { BGP_CFG->next_hop_self = 1; }
+ | bgp_proto MISSING LLADDR SELF ';' { BGP_CFG->missing_lladdr = MLL_SELF; }
+ | bgp_proto MISSING LLADDR DROP ';' { BGP_CFG->missing_lladdr = MLL_DROP; }
+ | bgp_proto MISSING LLADDR IGNORE ';' { BGP_CFG->missing_lladdr = MLL_IGNORE; }
| bgp_proto PATH METRIC bool ';' { BGP_CFG->compare_path_lengths = $4; }
| bgp_proto PREFER OLDER bool ';' { BGP_CFG->prefer_older = $4; }
| bgp_proto DEFAULT BGP_MED expr ';' { BGP_CFG->default_med = $4; }
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index d126fe5f..4176c9fe 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;