summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2019-01-02 16:01:21 +0100
committerOndrej Zajicek (work) <santiago@crfreenet.org>2019-01-02 16:01:21 +0100
commit470740f97bfa61c3c5c79d6f2d92f2014a119031 (patch)
tree9ca334919f8dd10268386693b59440f396f8f629
parente16b0aef31adf7000c22430adc3ceb9fc969ae14 (diff)
BGP: Better dispatch of incoming connections
Since v2 we have multiple listening BGP sockets, and each BGP protocol has associated one of them. Use listening socket that accepted the incoming connection as a key in the dispatch process so only BGP protocols assocaited with that listening socket can be selected. This is necesary for proper dispatch when VRFs are used.
-rw-r--r--proto/bgp/bgp.c18
-rw-r--r--sysdep/unix/io.c1
2 files changed, 13 insertions, 6 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index ceeec727..43f9f134 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -188,6 +188,7 @@ bgp_open(struct bgp_proto *p)
bs->sk = sk;
bs->uc = 1;
p->sock = bs;
+ sk->data = bs;
add_tail(&bgp_sockets, &bs->n);
@@ -1049,7 +1050,8 @@ 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;
- BGP_TRACE(D_EVENTS, "Connecting to %I%J from local address %I%J", s->daddr, p->cf->iface,
+ BGP_TRACE(D_EVENTS, "Connecting to %I%J from local address %I%J",
+ s->daddr, ipa_is_link_local(s->daddr) ? p->cf->iface : NULL,
s->saddr, ipa_is_link_local(s->saddr) ? s->iface : NULL);
bgp_setup_conn(p, conn);
bgp_setup_sk(conn, s);
@@ -1083,12 +1085,15 @@ bgp_find_proto(sock *sk)
{
struct bgp_proto *p;
+ /* sk->iface is valid only if src or dst address is link-local */
+ int link = ipa_is_link_local(sk->saddr) || ipa_is_link_local(sk->daddr);
+
WALK_LIST(p, proto_list)
if ((p->p.proto == &proto_bgp) &&
+ (p->sock == sk->data) &&
ipa_equal(p->cf->remote_ip, sk->daddr) &&
- (!p->cf->iface || (p->cf->iface == sk->iface)) &&
- (ipa_zero(p->cf->local_ip) || ipa_equal(p->cf->local_ip, sk->saddr)) &&
- (p->cf->local_port == sk->sport))
+ (!link || (p->cf->iface == sk->iface)) &&
+ (ipa_zero(p->cf->local_ip) || ipa_equal(p->cf->local_ip, sk->saddr)))
return p;
return NULL;
@@ -1765,8 +1770,9 @@ bgp_postconfig(struct proto_config *CF)
if (!cf->remote_as)
cf_error("Remote AS number must be set");
- if (ipa_is_link_local(cf->remote_ip) && !cf->iface)
- cf_error("Link-local neighbor address requires specified interface");
+ if (!cf->iface && (ipa_is_link_local(cf->local_ip) ||
+ ipa_is_link_local(cf->remote_ip)))
+ cf_error("Link-local addresses require defined interface");
if (!(cf->capabilities && cf->enable_as4) && (cf->remote_as > 0xFFFF))
cf_error("Neighbor AS number out of range (AS4 not available)");
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index a511e88e..d1d86e3b 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -1077,6 +1077,7 @@ sk_passive_connected(sock *s, int type)
sock *t = sk_new(s->pool);
t->type = type;
+ t->data = s->data;
t->af = s->af;
t->fd = fd;
t->ttl = s->ttl;