From: Maria Matejka Date: Thu, 13 Nov 2025 17:04:34 +0000 (+0100) Subject: Merge commit 'd4f70a6d1' into 299-mq-bgp-async-listen X-Git-Tag: v3.2.0~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=448a745cade4c0921bef1b7ae265343d326061ab;p=thirdparty%2Fbird.git Merge commit 'd4f70a6d1' into 299-mq-bgp-async-listen --- 448a745cade4c0921bef1b7ae265343d326061ab diff --cc proto/bgp/bgp.c index bf8fced6a,47b48bc8c..f49a2ab24 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@@ -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;