diff options
| author | Michael Biebl <biebl@debian.org> | 2025-02-27 22:37:33 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2025-02-27 22:37:33 +0100 |
| commit | b6e8711654c61e14f7058aa749911de846b54224 (patch) | |
| tree | f80a43f3daf50685fd79d9bfe80df8e3b878ddd5 /src/core/nm-l3cfg.c | |
| parent | 818258cf34b83fbc754633295e1052d4752d7b15 (diff) | |
New upstream version 1.50.3 upstream/1.50.3
Diffstat (limited to 'src/core/nm-l3cfg.c')
| -rw-r--r-- | src/core/nm-l3cfg.c | 69 |
1 files changed, 62 insertions, 7 deletions
diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c index a7189d3e..0d20bf44 100644 --- a/src/core/nm-l3cfg.c +++ b/src/core/nm-l3cfg.c @@ -370,6 +370,8 @@ G_DEFINE_TYPE(NML3Cfg, nm_l3cfg, G_TYPE_OBJECT) #define _NETNS_WATCHER_IP_ADDR_TAG(self, addr_family) \ ((gconstpointer) & (((char *) self)[1 + NM_IS_IPv4(addr_family)])) +#define _NETNS_WATCHER_MPTCP_IPV6_TAG(self) ((gconstpointer) & (((char *) self)[3])) + /*****************************************************************************/ #define _NMLOG_DOMAIN LOGD_CORE @@ -4764,7 +4766,7 @@ next: } out: - nm_netns_watcher_remove_all(self->priv.netns, TAG, FALSE); + nm_netns_watcher_remove_dirty(self->priv.netns, TAG); } /*****************************************************************************/ @@ -4777,6 +4779,30 @@ _global_tracker_mptcp_untrack(NML3Cfg *self, int addr_family) TRUE); } +static void +mptcp_ipv6_addr_cb(NMNetns *netns, + NMNetnsWatcherType watcher_type, + const NMNetnsWatcherData *watcher_data, + gconstpointer tag, + const NMNetnsWatcherEventData *event_data, + gpointer user_data) +{ + NML3Cfg *self = user_data; + + if (event_data->ip_addr.change_type == NM_PLATFORM_SIGNAL_REMOVED) + return; + + nm_assert(NMP_OBJECT_GET_TYPE(event_data->ip_addr.obj) == NMP_OBJECT_TYPE_IP6_ADDRESS); + + if (event_data->ip_addr.obj->ip6_address.n_ifa_flags & IFA_F_TENTATIVE) + return; + + /* We are inside the handler for a platform event, we should not + * perform other operations on platform synchronously. Schedule a + * commit in a idle handler. */ + nm_l3cfg_commit_on_idle_schedule(self, NM_L3_CFG_COMMIT_TYPE_AUTO); +} + static gboolean _l3_commit_mptcp_af(NML3Cfg *self, NML3CfgCommitType commit_type, @@ -4855,6 +4881,8 @@ _l3_commit_mptcp_af(NML3Cfg *self, self->priv.p->combined_l3cd_commited, addr_family, (const NMPlatformIPAddress **) &addr) { + const NMPObject *obj; + /* We want to evaluate the with-{loopback,link_local}-{4,6} flags based on the actual * ifa_scope that the address will have once we configure it. * "addr" is an address we want to configure, we expect that it will @@ -4881,6 +4909,34 @@ _l3_commit_mptcp_af(NML3Cfg *self, break; } + obj = nm_platform_ip_address_get(self->priv.platform, + addr_family, + self->priv.ifindex, + addr); + if (!obj) { + /* The address is not yet configured in platform, typically due to + * IPv4 DAD; skip it for now otherwise the kernel will try to use + * the endpoint, it will fail, and it will never try it again. */ + goto skip_addr; + } + if (!IS_IPv4 && (obj->ip6_address.n_ifa_flags & IFA_F_TENTATIVE)) { + NMNetnsWatcherData watcher_data = {}; + + /* The endpoint is not usable when the address is tentative. + * Watch the address until it becomes non-tentative and then + * schedule a new commit. */ + watcher_data.ip_addr.addr.addr_family = AF_INET6; + watcher_data.ip_addr.addr.addr.addr6 = addr->a6.address; + + nm_netns_watcher_add(self->priv.netns, + NM_NETNS_WATCHER_TYPE_IP_ADDR, + &watcher_data, + _NETNS_WATCHER_MPTCP_IPV6_TAG(self), + mptcp_ipv6_addr_cb, + self); + goto skip_addr; + } + a.addr = nm_ip_addr_init(addr_family, addr->ax.address_ptr); /* We track the address with different priorities, that depends @@ -4909,6 +4965,8 @@ skip_addr: } } + nm_netns_watcher_remove_dirty(self->priv.netns, _NETNS_WATCHER_MPTCP_IPV6_TAG(self)); + if (!any_tracked) { /* We need to make it known that this ifindex is used. Track a dummy object. */ if (nmp_global_tracker_track( @@ -5636,12 +5694,9 @@ finalize(GObject *object) gboolean changed; if (self->priv.netns) { - nm_netns_watcher_remove_all(self->priv.netns, - _NETNS_WATCHER_IP_ADDR_TAG(self, AF_INET), - TRUE); - nm_netns_watcher_remove_all(self->priv.netns, - _NETNS_WATCHER_IP_ADDR_TAG(self, AF_INET6), - TRUE); + nm_netns_watcher_remove_all(self->priv.netns, _NETNS_WATCHER_IP_ADDR_TAG(self, AF_INET)); + nm_netns_watcher_remove_all(self->priv.netns, _NETNS_WATCHER_IP_ADDR_TAG(self, AF_INET6)); + nm_netns_watcher_remove_all(self->priv.netns, _NETNS_WATCHER_MPTCP_IPV6_TAG(self)); } nm_prioq_destroy(&self->priv.p->failedobj_prioq); |