]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BGP: Better dispatch of incoming connections
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Wed, 2 Jan 2019 15:01:21 +0000 (16:01 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Wed, 2 Jan 2019 15:01:21 +0000 (16:01 +0100)
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.

proto/bgp/bgp.c
sysdep/unix/io.c

index ceeec7270e64a080149a650a12a1b3d9bb412d27..43f9f134228a3229c5f1aaf05e7e75226eaca2d9 100644 (file)
@@ -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)");
index a511e88ede3fea5163d9fd8963eda5af6c661f39..d1d86e3b15cf70c3febc524aa377df7384fe74ca 100644 (file)
@@ -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;