]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge commit 'd4f70a6d1' into 299-mq-bgp-async-listen
authorMaria Matejka <mq@ucw.cz>
Thu, 13 Nov 2025 17:04:34 +0000 (18:04 +0100)
committerMaria Matejka <mq@ucw.cz>
Thu, 13 Nov 2025 17:04:34 +0000 (18:04 +0100)
1  2 
proto/bgp/bgp.c

diff --cc proto/bgp/bgp.c
index bf8fced6a9004e121ba70301393576244006013e,47b48bc8c38bb3ddb0bb3c126e245c7039541d38..f49a2ab2446a5b688b9c8269e8f068a01d532bf2
@@@ -204,39 -167,17 +204,40 @@@ bgp_open(struct bgp_proto *p
    if (p->cf->ipatt || p->cf->c.parent)
      return 0;
  
 -  /* We assume that cf->iface is defined iff cf->local_ip is link-local */
 +  /* Set parameters of the listening socket
 +   *
 +   * If strict_bind is set, we need local_ip and maybe also iface. Mandatory if
 +   * local_ip is link-local. If strict_bind is not set, we bind to all addresses
 +   * of that family and match the local IP later when accepting the connection. */
 +
    struct bgp_listen_request *req = mb_allocz(p->p.pool, sizeof *req);
 -  req->params = (struct bgp_socket_params) {
 -    .iface = p->cf->strict_bind ? p->cf->iface : NULL,
 -    .vrf = p->p.vrf,
 -    .addr = p->cf->strict_bind && ipa_nonzero(p->cf->local_ip) ? p->cf->local_ip :
 -      (p->ipv4 ? IPA_NONE4 : IPA_NONE6),
 -    .port = p->cf->local_port,
 -    .flags = p->cf->free_bind ? SKF_FREEBIND : 0,
 -  };
 +  struct bgp_socket_params *par = &req->params;
  
 +  par->iface = p->cf->strict_bind ? p->cf->iface : NULL;
 +  par->vrf = p->p.vrf;
 +  par->addr = p->cf->strict_bind && ipa_nonzero(p->cf->local_ip) ? p->cf->local_ip :
 +    (p->ipv4 ? IPA_NONE4 : IPA_NONE6);
 +  par->port = p->cf->local_port;
 +  par->flags = p->cf->free_bind ? SKF_FREEBIND : 0;
 +
 +  /* Set parameters of the accepted socket */
 +  req->local_ip = p->cf->local_ip;
 +  req->iface = p->cf->iface;
++  req->ipatt = p->cf->ipatt;
 +  req->remote_ip = p->remote_ip;
 +  req->remote_range = p->cf->remote_range;
 +
 +  /* Initialize the incoming socket queue */
 +  init_list(&req->incoming_sockets);
 +
 +  BGP_TRACE(D_EVENTS, "Requesting listen socket at %I%J port %u", req->params.addr, req->params.iface, req->params.port);
 +
 +  if (bgp_is_dynamic(p))
 +    callback_init(&req->incoming_connection, bgp_incoming_connection_dynamic, &main_birdloop);
 +  else
 +    callback_init(&req->incoming_connection, bgp_incoming_connection_single, p->p.loop);
 +
 +  req->p = p;
    return bgp_listen_open(p, req);
  }
  
@@@ -1971,30 -1754,53 +1972,49 @@@ err2
   * @sk: TCP socket
   *
   */
 -static struct bgp_proto *
 -bgp_find_proto(sock *sk)
 +static struct bgp_listen_request *
 +bgp_find_proto(struct bgp_socket_private *bs, sock *sk)
  {
 -  struct bgp_proto *best = NULL;
 -  struct bgp_proto *p;
 +  struct bgp_listen_request *best = NULL;
  
-   /* 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);
+   /* sk->iface is valid only if src or dst address is link-local or if strict bind on interface is set */
+   bool link = ipa_is_link_local(sk->saddr) || ipa_is_link_local(sk->daddr);
  
 -  WALK_LIST(p, proto_list)
 +  struct bgp_listen_request *req; node *nxt;
 +  WALK_LIST2(req, nxt, bs->requests, sn)
    {
-     if ((ipa_equal(req->remote_ip, sk->daddr) || bgp_is_dynamic(req)) &&
-       (!req->remote_range || ipa_in_netX(sk->daddr, req->remote_range)) &&
-       (req->params.vrf == sk->vrf) &&
-       (req->params.port == sk->sport) &&
-       (!link || (req->iface == sk->iface) || req->ipatt && sk->iface && iface_patt_match(req->ipatt, sk->iface, NULL)) &&
-       (ipa_zero(req->local_ip) || ipa_equal(req->local_ip, sk->saddr)))
-     {
-       /* Non-dynamic protocol instance matched */
-       if (!bgp_is_dynamic(req))
-       return req;
 -    /* Not a BGP */
 -    if (p->p.proto != &proto_bgp)
 -      continue;
 -
+     /* Remote address configured but not the right one */
 -    if (!ipa_equal(p->remote_ip, sk->daddr) && !bgp_is_dynamic(p))
++    if (!ipa_equal(req->remote_ip, sk->daddr) && !bgp_is_dynamic(req))
+       continue;
  
-       best = req;
-     }
+     /* Remote range configured but the remote address is not in it */
 -    if (p->cf->remote_range && !ipa_in_netX(sk->daddr, p->cf->remote_range))
++    if (req->remote_range && !ipa_in_netX(sk->daddr, req->remote_range))
+       continue;
+     /* Not the right VRF */
 -    if (p->p.vrf != sk->vrf)
++    if (req->params.vrf != sk->vrf)
+       continue;
+     /* Not the right local port */
 -    if (p->cf->local_port != sk->sport)
++    if (req->params.port != sk->sport)
+       continue;
+     /* Local address set but not matching */
 -    if (!ipa_zero(p->cf->local_ip) && !ipa_equal(p->cf->local_ip, sk->saddr))
++    if (!ipa_zero(req->local_ip) && !ipa_equal(req->local_ip, sk->saddr))
+       continue;
+     /* The interface set but not matching */
 -    if ((link || p->cf->strict_bind) && p->cf->iface && (p->cf->iface != sk->iface))
++    if (link && req->iface && (req->iface != sk->iface))
+       continue;
+     /* Interface pattern configured and not matching */
 -    if ((link || p->cf->strict_bind) && p->cf->ipatt && !iface_patt_match(p->cf->ipatt, sk->iface, NULL))
++    if (link && req->ipatt && (!sk->iface || !iface_patt_match(req->ipatt, sk->iface, NULL)))
+       continue;
 -    best = p;
++    best = req;
 -    if (!bgp_is_dynamic(p))
++    if (!bgp_is_dynamic(req))
+       break;
    }
  
    return best;