From 993d07798e10f41c258c2a485650507c564e6990 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 14 Dec 2010 03:26:51 +0100 Subject: [PATCH] BGP: Add support for peering with link-local IPv6 addresses --- nest/iface.c | 2 +- proto/bgp/bgp.c | 13 ++++++++++++- proto/bgp/bgp.h | 1 + proto/bgp/config.Y | 3 ++- proto/bgp/packets.c | 3 +++ sysdep/bsd/krt-sock.c | 2 +- 6 files changed, 20 insertions(+), 4 deletions(-) diff --git a/nest/iface.c b/nest/iface.c index c523678..2b0b9c6 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -483,7 +483,7 @@ ifa_update(struct ifa *a) break; } - if (!(i->flags & IF_MULTIACCESS) && a->pxlen < BITS_PER_IP_ADDRESS - 2) + if (!(i->flags & IF_MULTIACCESS) && !ipa_has_link_scope(a->ip) && a->pxlen < BITS_PER_IP_ADDRESS - 2) log(L_WARN "Strange prefix length %d for point-to-point interface %s", a->pxlen, i->name); #ifndef IPV6 if ((i->flags & IF_BROADCAST) && !ipa_nonzero(a->brd)) 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..7816c1d 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; diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index 53b30ca..fc73be8 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -541,7 +541,7 @@ krt_read_addr(struct ks_msg *msg) _I0(ifa.ip) = 0xfe800000; #endif - if (iface->flags & IF_MULTIACCESS) + if ((iface->flags & IF_MULTIACCESS) || ipa_has_link_scope(ifa.ip)) { ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(masklen)); -- 1.7.3.3