summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2011-12-08 09:00:13 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2011-12-29 21:42:44 +0100
commitec3b71ae00bfab2fcaa31425a4f9de097389f43a (patch)
treeaf86df5550298e43e5491e7f2a6b757ecf765c46
parent7e08f5ab64aaab1c40da2ce6b54c18ce791188df (diff)
downloadbird-ec3b71ae00bfab2fcaa31425a4f9de097389f43a.tar
bird-ec3b71ae00bfab2fcaa31425a4f9de097389f43a.zip
BGP: Add support for specifying interface names to allow peerings using link-local addresses
-rw-r--r--proto/bgp/bgp.c10
-rw-r--r--proto/bgp/bgp.h1
-rw-r--r--proto/bgp/config.Y4
-rw-r--r--proto/bgp/packets.c3
4 files changed, 15 insertions, 3 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 28396a5..67594c7 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -585,6 +585,11 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c
s->tos = IP_PREC_INTERNET_CONTROL;
s->password = p->cf->password;
s->tx_hook = bgp_connected;
+
+ /* Can only be NULL for multihop instances */
+ if (p->neigh && *p->cf->interface)
+ s->iface = p->neigh->iface;
+
BGP_TRACE(D_EVENTS, "Connecting to %I from local address %I", s->daddr, s->saddr);
bgp_setup_conn(p, conn);
bgp_setup_sk(conn, s);
@@ -793,7 +798,7 @@ bgp_start_locked(struct object_lock *lock)
return;
}
- p->neigh = neigh_find(&p->p, &cf->remote_ip, NEF_STICKY);
+ p->neigh = neigh_find_ifname(&p->p, &cf->remote_ip, (*cf->interface) ? cf->interface : NULL, NEF_STICKY);
if (!p->neigh || (p->neigh->scope == SCOPE_HOST))
{
log(L_ERR "%s: Invalid remote address %I", p->p.name, cf->remote_ip);
@@ -807,7 +812,7 @@ bgp_start_locked(struct object_lock *lock)
if (p->neigh->iface)
bgp_start_neighbor(p);
else
- BGP_TRACE(D_EVENTS, "Waiting for %I to become my neighbor", cf->remote_ip);
+ BGP_TRACE(D_EVENTS, "Waiting for %I to become my neighbor%s%s", cf->remote_ip, (*cf->interface) ? " on " : "", cf->interface);
}
static int
@@ -852,6 +857,7 @@ bgp_start(struct proto *P)
lock->iface = NULL;
lock->hook = bgp_start_locked;
lock->data = p;
+
olock_acquire(lock);
return PS_START;
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index 0c50583..76f0400 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -50,6 +50,7 @@ struct bgp_config {
unsigned error_delay_time_min; /* Time to wait after an error is detected */
unsigned error_delay_time_max;
unsigned disable_after_error; /* Disable the protocol when error is detected */
+ char interface[16]; /* Interface to use */
char *password; /* Password used for MD5 authentication */
struct rtable_config *igp_table; /* Table used for recursive next hop lookups */
};
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index 3ef9b29..6ec3623 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -25,7 +25,8 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
CLUSTER, ID, AS4, ADVERTISE, IPV4, CAPABILITIES, LIMIT, PASSIVE,
PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH,
INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
- TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC)
+ TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
+ INTERFACE)
CF_GRAMMAR
@@ -100,6 +101,7 @@ bgp_proto:
| bgp_proto INTERPRET COMMUNITIES bool ';' { BGP_CFG->interpret_communities = $4; }
| bgp_proto IGP TABLE rtable ';' { BGP_CFG->igp_table = $4; }
| bgp_proto TTL SECURITY bool ';' { BGP_CFG->ttl_security = $4; }
+ | bgp_proto INTERFACE TEXT ';' { strncpy(BGP_CFG->interface, $3, sizeof(BGP_CFG->interface)-1); }
;
CF_ADDTO(dynamic_attr, BGP_ORIGIN
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index c3a8673..7d78d9f 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -434,6 +434,9 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
*tmp++ = BGP_AF_IPV6;
*tmp++ = 1;
+ if (ipa_has_link_scope(ip))
+ ip = IPA_NONE;
+
if (ipa_nonzero(ip_ll))
{
*tmp++ = 32;