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.
bs->sk = sk;
bs->uc = 1;
p->sock = bs;
bs->sk = sk;
bs->uc = 1;
p->sock = bs;
add_tail(&bgp_sockets, &bs->n);
add_tail(&bgp_sockets, &bs->n);
s->tos = IP_PREC_INTERNET_CONTROL;
s->password = p->cf->password;
s->tx_hook = bgp_connected;
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);
s->saddr, ipa_is_link_local(s->saddr) ? s->iface : NULL);
bgp_setup_conn(p, conn);
bgp_setup_sk(conn, s);
+ /* 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) &&
WALK_LIST(p, proto_list)
if ((p->p.proto == &proto_bgp) &&
+ (p->sock == sk->data) &&
ipa_equal(p->cf->remote_ip, sk->daddr) &&
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)))
if (!cf->remote_as)
cf_error("Remote AS number must be set");
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)");
if (!(cf->capabilities && cf->enable_as4) && (cf->remote_as > 0xFFFF))
cf_error("Neighbor AS number out of range (AS4 not available)");
sock *t = sk_new(s->pool);
t->type = type;
sock *t = sk_new(s->pool);
t->type = type;
t->af = s->af;
t->fd = fd;
t->ttl = s->ttl;
t->af = s->af;
t->fd = fd;
t->ttl = s->ttl;