summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2010-12-14 03:26:51 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2010-12-14 03:26:51 +0100
commit7a03ded81bf2d07331d8fb87c2c7613cb4dd518e (patch)
tree50e5ca2856f97d1e0c875c02bf2cb8887815c4ab
parente91f6960bae16314e9429719c2c2321edb484a44 (diff)
downloadbird-7a03ded81bf2d07331d8fb87c2c7613cb4dd518e.tar
bird-7a03ded81bf2d07331d8fb87c2c7613cb4dd518e.zip
BGP: Added support for peering with link-local IPv6 addresses
-rw-r--r--proto/bgp/bgp.c13
-rw-r--r--proto/bgp/bgp.h1
-rw-r--r--proto/bgp/config.Y3
-rw-r--r--proto/bgp/packets.c4
4 files changed, 18 insertions, 3 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 327292a..84c353e 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -574,6 +574,7 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c
s->saddr = p->source_addr;
s->daddr = p->cf->remote_ip;
s->dport = BGP_PORT;
+ s->iface = p->neigh->iface;
s->ttl = p->cf->multihop ? : 1;
s->rbsize = BGP_RX_BUFFER_SIZE;
s->tbsize = BGP_TX_BUFFER_SIZE;
@@ -743,6 +744,7 @@ bgp_start_locked(struct object_lock *lock)
{
struct bgp_proto *p = lock->data;
struct bgp_config *cf = p->cf;
+ struct iface *interface = NULL;
if (p->p.proto_state != PS_START)
{
@@ -759,7 +761,16 @@ bgp_start_locked(struct object_lock *lock)
return;
}
- p->neigh = neigh_find(&p->p, &cf->remote_ip, NEF_STICKY);
+ if (*cf->interface) {
+ interface = if_find_by_name(cf->interface);
+
+ if (!interface) {
+ BGP_TRACE(D_EVENTS, "Waiting for interface %s", cf->interface);
+ return;
+ }
+ }
+
+ p->neigh = neigh_find2(&p->p, &cf->remote_ip, interface, NEF_STICKY);
if (!p->neigh || (p->neigh->scope == SCOPE_HOST))
{
log(L_ERR "%s: Invalid remote address %I", p->p.name, cf->remote_ip);
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index b06f20a..c8acb25 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -47,6 +47,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 e932a7f..6ea94d6 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -25,7 +25,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
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)
+ GATEWAY, DIRECT, RECURSIVE, INTERFACE)
CF_GRAMMAR
@@ -92,6 +92,7 @@ bgp_proto:
| bgp_proto ENABLE AS4 bool ';' { BGP_CFG->enable_as4 = $4; }
| bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; }
| bgp_proto ADVERTISE IPV4 bool ';' { BGP_CFG->advertise_ipv4 = $4; }
+ | bgp_proto INTERFACE TEXT ';' { strncpy(BGP_CFG->interface, $3, sizeof(BGP_CFG->interface)-1); }
| bgp_proto PASSWORD TEXT ';' { BGP_CFG->password = $3; }
| bgp_proto ROUTE LIMIT expr ';' { BGP_CFG->route_limit = $4; }
| bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; }
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index bf98640..356d8bd 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -324,6 +324,7 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
struct bgp_proto *p = conn->bgp;
struct bgp_bucket *buck;
int size, second, rem_stored;
+ int class;
int remains = BGP_MAX_PACKET_LENGTH - BGP_HEADER_LENGTH - 4;
byte *w, *w_stored, *tmp, *tstart;
ip_addr *ipp, ip, ip_ll;
@@ -434,7 +435,8 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
*tmp++ = BGP_AF_IPV6;
*tmp++ = 1;
- if (ipa_nonzero(ip_ll))
+ class = ipa_classify(ip);
+ if (ipa_nonzero(ip_ll) && ((class & IADDR_SCOPE_MASK) != SCOPE_LINK))
{
*tmp++ = 32;
ipa_hton(ip);