From: Maria Matejka Date: Tue, 8 Jul 2025 18:28:03 +0000 (+0200) Subject: BGP: Fixed unnumbered connections with wildcard local IP. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ce87609da1d6a4b89b18f76c9fe6fab32854e140;p=thirdparty%2Fbird.git BGP: Fixed unnumbered connections with wildcard local IP. When the BGP was configured onlink with a neighbor range, interface range and wildcard local IP, the connections failed to establish because the inferred local IP wasn't properly propagated. --- diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index ee043036c..fb6410ab0 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -160,8 +160,11 @@ static int bgp_open(struct bgp_proto *p) { /* Interface-patterned listening sockets are created from the - * interface notifier. By default, listen to nothing. */ - if (p->cf->ipatt) + * interface notifier. By default, listen to nothing. + * + * Also dynamically spawned protocol do not need a listening socket, + * they already have their parent's one. */ + if (p->cf->ipatt || p->cf->c.parent) return 0; /* We assume that cf->iface is defined iff cf->local_ip is link-local */ @@ -169,7 +172,7 @@ bgp_open(struct bgp_proto *p) req->params = (struct bgp_socket_params) { .iface = p->cf->strict_bind ? p->cf->iface : NULL, .vrf = p->p.vrf, - .addr = p->cf->strict_bind ? p->cf->local_ip : + .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, @@ -1038,7 +1041,9 @@ bgp_spawn(struct bgp_proto *pp, sock *sk) /* Just pass remote_ip to bgp_init() */ struct bgp_config *cf = SKIP_BACK(struct bgp_config, c, sym->proto); cf->remote_ip = sk->daddr; + cf->local_ip = sk->saddr; cf->iface = sk->iface; + cf->ipatt = NULL; struct bgp_proto *p = SKIP_BACK(struct bgp_proto, p, proto_spawn(sym->proto, 0)); p->postponed_sk = sk; @@ -1909,7 +1914,7 @@ bgp_iface_update(struct bgp_proto *p, uint flags, struct iface *i) struct bgp_socket_params params = { .iface = i, .vrf = p->p.vrf, - .addr = p->cf->local_ip, + .addr = 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, }; @@ -2381,9 +2386,7 @@ bgp_init(struct proto_config *CF) p->rs_client = cf->rs_client; p->rr_client = cf->rr_client; - p->ipv4 = ipa_nonzero(cf->remote_ip) ? - ipa_is_ip4(cf->remote_ip) : - (cf->remote_range && (cf->remote_range->type == NET_IP4)); + p->ipv4 = cf->ipv4; p->remote_ip = cf->remote_ip; p->remote_as = cf->remote_as; @@ -2633,6 +2636,10 @@ bgp_postconfig(struct proto_config *CF) if (cf->check_link < 0) cf->check_link = !cf->multihop; + /* Detect IPv4 */ + cf->ipv4 = ipa_nonzero(cf->remote_ip) ? + ipa_is_ip4(cf->remote_ip) : + (cf->remote_range && (cf->remote_range->type == NET_IP4)); if (!cf->local_as) cf_error("Local AS number must be set"); diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index ad08fcd96..7e70d745b 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -105,6 +105,7 @@ struct bgp_config { u32 rr_cluster_id; /* Route reflector cluster ID, if different from local ID */ int rr_client; /* Whether neighbor is RR client of me */ int rs_client; /* Whether neighbor is RS client of me */ + int ipv4; /* Use IPv4 connection, i.e. remote_ip is IPv4 */ u32 confederation; /* Confederation ID, or zero if confeds not active */ int confederation_member; /* Whether neighbor AS is member of our confederation */ int passive; /* Do not initiate outgoing connection */