diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2022-01-26 14:57:43 +0100 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2022-01-26 14:57:43 +0100 |
commit | dd4386d5c6a66943c1d1aad93bcb8025d81d8b6b (patch) | |
tree | 87c7ff104ee1f0ff4a71f281434dcbd15d2f4040 | |
parent | 62b2aa85e875d9c842f878cac896dd1fa7c5d988 (diff) | |
parent | ce0a36d20fa6a49723e8a630be3106ffe5e793fc (diff) | |
download | NetworkManager-dd4386d5c6a66943c1d1aad93bcb8025d81d8b6b.tar.gz |
merge: branch 'bg/500vlans'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1066
https://bugzilla.redhat.com/show_bug.cgi?id=2028849
-rw-r--r-- | src/core/devices/nm-device.c | 95 | ||||
-rw-r--r-- | src/core/dhcp/nm-dhcp-client.c | 124 | ||||
-rw-r--r-- | src/core/dhcp/nm-dhcp-client.h | 1 | ||||
-rw-r--r-- | src/core/dns/nm-dns-manager.c | 25 | ||||
-rw-r--r-- | src/core/nm-l3-config-data.c | 282 | ||||
-rw-r--r-- | src/core/nm-l3-config-data.h | 15 | ||||
-rw-r--r-- | src/core/nm-policy.c | 23 |
7 files changed, 408 insertions, 157 deletions
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 3786ba211f..3bb78c4b4a 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -815,8 +815,6 @@ static void _dev_ipdhcpx_set_state(NMDevice *self, int addr_family, NMDeviceIPSt static void _dev_ipdhcpx_restart(NMDevice *self, int addr_family, gboolean release); -static void _dev_ipdhcpx_handle_accept(NMDevice *self, int addr_family, const NML3ConfigData *l3cd); - static gboolean _dev_ipac6_grace_period_start(NMDevice *self, guint32 timeout_sec, gboolean force_restart); @@ -9916,63 +9914,6 @@ _dev_ipdhcpx_handle_fail(NMDevice *self, int addr_family, const char *reason) } static void -_dev_ipdhcpx_handle_accept(NMDevice *self, int addr_family, const NML3ConfigData *l3cd) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const int IS_IPv4 = NM_IS_IPv4(addr_family); - gs_free_error GError *error = NULL; - - nm_assert(NM_IS_L3_CONFIG_DATA(l3cd)); - - nm_dhcp_config_set_lease(priv->ipdhcp_data_x[IS_IPv4].config, l3cd); - _dev_l3_register_l3cds_set_one_full(self, - L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4), - l3cd, - NM_L3CFG_CONFIG_FLAGS_FORCE_ONCE, - TRUE); - - /* FIXME(l3cfg:dhcp): accept also should be handled by NMDhcpClient transparently. - * NMDhcpClient should do ACD (if enabled), and only after that passes, it exposes - * the lease to the user (NMDevice). NMDevice then may choose to configure the address. - * NMDhcpClient then checks in NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT whether the requested - * address is to be configured by NML3Cfg (here, the intent is what matters, not - * whether the address is actually visible in NMPlatform -- that is because while NML3Cfg - * configures the address (in platform), the user might delete it right away. Also, - * depending on the commit type, NML3Cfg may even choose not to configure it right now - * (which arguably will be odd). Anyway, what matters is whether the user configured - * the address in NML3Cfg (by checking the ObjStateData). - * - * If yes, then NMDhcpClient needs to accept automatically. - * - * Doing it here is wrong for two reasons: - * - * - NMDevice already has enough to do, it should not be concerned with telling - * NMDhcpClient to accept the lease, it should only configure the address. - * - * - we should only accept the lease *after* configuring the address (see n_dhcp4_client_lease_accept(). - * Currently this only works by passing commit_sync=TRUE to _dev_l3_register_l3cds_set_one(), but - * doing that is wrong (see FIXME why commit_sync needs to go away). */ - if (priv->ipdhcp_data_x[IS_IPv4].state != NM_DEVICE_IP_STATE_READY - && !nm_dhcp_client_accept(priv->ipdhcp_data_x[IS_IPv4].client, &error)) { - _LOGW(LOGD_DHCPX(IS_IPv4), "error accepting lease: %s", error->message); - _dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_FAILED); - _dev_ip_state_check_async(self, addr_family); - return; - } - - _dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_READY); - - nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_X(IS_IPv4), - self, - NULL, - NULL, - NULL, - NULL); - - _dev_ip_state_check_async(self, addr_family); -} - -static void _dev_ipdhcpx_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_data, NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); @@ -10015,8 +9956,32 @@ _dev_ipdhcpx_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_d return; } + if (notify_data->lease_update.accepted) { + _LOGT_ipdhcp(addr_family, "lease accepted"); + if (priv->ipdhcp_data_x[IS_IPv4].state != NM_DEVICE_IP_STATE_READY) { + _dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_READY); + nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_X(IS_IPv4), + self, + NULL, + NULL, + NULL, + NULL); + _dev_ip_state_check_async(self, addr_family); + } + return; + } + + /* Schedule a commit of the configuration. The DHCP client + * will accept the lease once the address is committed, and + * will send a LEASE_UPDATE notification with accepted=1. */ _LOGT_ipdhcp(addr_family, "lease update"); - _dev_ipdhcpx_handle_accept(self, addr_family, notify_data->lease_update.l3cd); + nm_dhcp_config_set_lease(priv->ipdhcp_data_x[IS_IPv4].config, + notify_data->lease_update.l3cd); + _dev_l3_register_l3cds_set_one_full(self, + L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4), + notify_data->lease_update.l3cd, + NM_L3CFG_CONFIG_FLAGS_FORCE_ONCE, + FALSE); return; } @@ -10213,8 +10178,14 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family) priv->ipdhcp_data_x[IS_IPv4].config = nm_dhcp_config_new(addr_family, previous_lease); _notify(self, PROP_DHCPX_CONFIG(IS_IPv4)); } - if (previous_lease) - _dev_ipdhcpx_handle_accept(self, addr_family, previous_lease); + if (previous_lease) { + nm_dhcp_config_set_lease(priv->ipdhcp_data_x[IS_IPv4].config, previous_lease); + _dev_l3_register_l3cds_set_one_full(self, + L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4), + previous_lease, + NM_L3CFG_CONFIG_FLAGS_FORCE_ONCE, + FALSE); + } return; diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c index f7c095fb8f..54f9ee59fd 100644 --- a/src/core/dhcp/nm-dhcp-client.c +++ b/src/core/dhcp/nm-dhcp-client.c @@ -43,12 +43,17 @@ typedef struct _NMDhcpClientPrivate { const NML3ConfigData *l3cd; GSource *no_lease_timeout_source; GSource *ipv6_lladdr_timeout_source; + GBytes *effective_client_id; pid_t pid; guint watch_id; NMDhcpState state; bool iaid_explicit : 1; bool is_stopped : 1; - GBytes *effective_client_id; + struct { + gulong id; + bool wait_dhcp_commit : 1; + bool wait_ll_address : 1; + } l3cfg_notify; } NMDhcpClientPrivate; G_DEFINE_ABSTRACT_TYPE(NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT) @@ -57,6 +62,11 @@ G_DEFINE_ABSTRACT_TYPE(NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT) /*****************************************************************************/ +static void +l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDhcpClient *self); + +/*****************************************************************************/ + /* we use pid=-1 for invalid PIDs. Ensure that pid_t can hold negative values. */ G_STATIC_ASSERT(!(((pid_t) -1) > 0)); @@ -70,6 +80,27 @@ _emit_notify(NMDhcpClient *self, const NMDhcpClientNotifyData *notify_data) /*****************************************************************************/ +static void +connect_l3cfg_notify(NMDhcpClient *self) +{ + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); + gboolean do_connect; + + do_connect = priv->l3cfg_notify.wait_dhcp_commit | priv->l3cfg_notify.wait_ll_address; + + if (!do_connect) { + nm_clear_g_signal_handler(priv->config.l3cfg, &priv->l3cfg_notify.id); + return; + } + + if (priv->l3cfg_notify.id == 0) { + priv->l3cfg_notify.id = g_signal_connect(priv->config.l3cfg, + NM_L3CFG_SIGNAL_NOTIFY, + G_CALLBACK(l3_cfg_notify_cb), + self); + } +} + pid_t nm_dhcp_client_get_pid(NMDhcpClient *self) { @@ -357,6 +388,9 @@ nm_dhcp_client_set_state(NMDhcpClient *self, NMDhcpState new_state, const NML3Co }, }; + priv->l3cfg_notify.wait_dhcp_commit = (new_state == NM_DHCP_STATE_BOUND); + connect_l3cfg_notify(self); + _emit_notify(self, ¬ify_data); } } @@ -523,14 +557,20 @@ l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDhcp nm_assert(l3cfg == priv->config.l3cfg); - if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE) { + switch (notify_data->notify_type) { + case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE: + { const NMPlatformIP6Address *addr; gs_free_error GError *error = NULL; + if (!priv->l3cfg_notify.wait_ll_address) + return; + addr = ipv6_lladdr_find(self); if (addr) { _LOGD("got IPv6LL address, starting transaction"); - g_signal_handlers_disconnect_by_func(l3cfg, l3_cfg_notify_cb, self); + priv->l3cfg_notify.wait_ll_address = FALSE; + connect_l3cfg_notify(self); nm_clear_g_source_inst(&priv->ipv6_lladdr_timeout_source); schedule_no_lease_timeout(self); @@ -543,6 +583,74 @@ l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDhcp })); } } + + break; + } + case NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT: + { + const NML3ConfigData *committed_l3cd; + NMDedupMultiIter ipconf_iter; + const NMPlatformIPAddress *lease_address; + gs_free_error GError *error = NULL; + + /* A new configuration was committed to the interface. If we previously + * got a lease, check whether we are waiting for the address to be + * configured. If the address was added, we can proceed accepting the + * lease and notifying NMDevice. */ + + if (!priv->l3cfg_notify.wait_dhcp_commit) + return; + + nm_l3_config_data_iter_ip_address_for_each (&ipconf_iter, + priv->l3cd, + priv->config.addr_family, + &lease_address) + break; + nm_assert(lease_address); + committed_l3cd = nm_l3cfg_get_combined_l3cd(l3cfg, TRUE); + + if (priv->config.addr_family == AF_INET) { + const NMPlatformIP4Address *address4 = (const NMPlatformIP4Address *) lease_address; + + if (!nm_l3_config_data_lookup_address_4(committed_l3cd, + address4->address, + address4->plen, + address4->peer_address)) + return; + } else { + const NMPlatformIP6Address *address6 = (const NMPlatformIP6Address *) lease_address; + + if (!nm_l3_config_data_lookup_address_6(committed_l3cd, &address6->address)) + return; + } + + priv->l3cfg_notify.wait_dhcp_commit = FALSE; + connect_l3cfg_notify(self); + + _LOGD("accept address"); + + if (!nm_dhcp_client_accept(self, &error)) { + gs_free char *reason = g_strdup_printf("error accepting lease: %s", error->message); + + _emit_notify(self, + &((NMDhcpClientNotifyData){ + .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD, + .it_looks_bad.reason = reason, + })); + return; + } + + _emit_notify( + self, + &((NMDhcpClientNotifyData){.notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE, + .lease_update = { + .l3cd = priv->l3cd, + .accepted = TRUE, + }})); + break; + }; + default: + /* ignore */; } } @@ -569,10 +677,8 @@ nm_dhcp_client_start_ip6(NMDhcpClient *self, GError **error) addr = ipv6_lladdr_find(self); if (!addr) { _LOGD("waiting for IPv6LL address"); - g_signal_connect(priv->config.l3cfg, - NM_L3CFG_SIGNAL_NOTIFY, - G_CALLBACK(l3_cfg_notify_cb), - self); + priv->l3cfg_notify.wait_ll_address = TRUE; + connect_l3cfg_notify(self); priv->ipv6_lladdr_timeout_source = nm_g_timeout_add_seconds_source(10, ipv6_lladdr_timeout, self); return TRUE; @@ -657,7 +763,9 @@ nm_dhcp_client_stop(NMDhcpClient *self, gboolean release) priv->is_stopped = TRUE; - g_signal_handlers_disconnect_by_func(priv->config.l3cfg, l3_cfg_notify_cb, self); + priv->l3cfg_notify.wait_dhcp_commit = FALSE; + priv->l3cfg_notify.wait_ll_address = FALSE; + connect_l3cfg_notify(self); /* Kill the DHCP client */ old_pid = priv->pid; diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h index d8f659fa4a..249bd013ff 100644 --- a/src/core/dhcp/nm-dhcp-client.h +++ b/src/core/dhcp/nm-dhcp-client.h @@ -71,6 +71,7 @@ typedef struct { * or NULL (if a previous lease timed out). It can also be the * previous lease, that was injected. */ const NML3ConfigData *l3cd; + bool accepted; } lease_update; struct { const NMPlatformIP6Address *prefix; diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index 8a8ab9eb06..efbf847b71 100644 --- a/src/core/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -1862,6 +1862,7 @@ nm_dns_manager_set_ip_config(NMDnsManager *self, gboolean changed = FALSE; NMDnsConfigIPData *ip_data = NULL; int dns_priority; + gboolean any_removed = FALSE; g_return_val_if_fail(NM_IS_DNS_MANAGER(self), FALSE); g_return_val_if_fail(!l3cd || NM_IS_L3_CONFIG_DATA(l3cd), FALSE); @@ -1919,7 +1920,16 @@ nm_dns_manager_set_ip_config(NMDnsManager *self, if (!replace_all && l3cd && ip_data_iter->l3cd != l3cd) continue; - changed = TRUE; + if (!l3cd || ip_config_type == NM_DNS_IP_CONFIG_TYPE_REMOVED + || nm_l3_config_data_cmp_full(l3cd, + ip_data_iter->l3cd, + NM_L3_CONFIG_CMP_FLAGS_DNS + | NM_L3_CONFIG_CMP_FLAGS_ROUTES_ID) + != 0) { + changed = TRUE; + } + + any_removed = TRUE; _dns_config_ip_data_free(ip_data_iter); } } @@ -1941,8 +1951,6 @@ nm_dns_manager_set_ip_config(NMDnsManager *self, goto done; } - changed = TRUE; - if (!data) { data = g_slice_new(NMDnsConfigData); *data = (NMDnsConfigData){ @@ -1956,12 +1964,17 @@ nm_dns_manager_set_ip_config(NMDnsManager *self, priv->configs_lst_need_sort = TRUE; } - if (!ip_data) + if (!ip_data) { ip_data = _dns_config_ip_data_new(data, addr_family, source_tag, l3cd, ip_config_type); - else + if (!any_removed) + changed = TRUE; + } else { ip_data->ip_config_type = ip_config_type; + changed = TRUE; + } - priv->ip_data_lst_need_sort = TRUE; + if (changed) + priv->ip_data_lst_need_sort = TRUE; nm_assert(l3cd); nm_assert(ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED); diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 8d6ac09e92..226ccd0025 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -634,7 +634,7 @@ _route_valid(int addr_family, gconstpointer r) static gboolean _NM_IS_L3_CONFIG_DATA(const NML3ConfigData *self, gboolean allow_sealed) { - nm_assert(!self || (self->ifindex > 0 && self->multi_idx && self->ref_count > 0)); + nm_assert(!self || (self->ifindex >= 0 && self->multi_idx && self->ref_count > 0)); return self && self->ref_count > 0 && (allow_sealed || !self->is_sealed); } @@ -2081,7 +2081,8 @@ static int _dedup_multi_index_cmp(const NML3ConfigData *a, const NML3ConfigData *b, NMPObjectType obj_type, - gboolean ignore_ifindex) + gboolean cmp_ifindex, + gboolean cmp_full) { const NMDedupMultiHeadEntry *h_a = nm_l3_config_data_lookup_objs(a, obj_type); const NMDedupMultiHeadEntry *h_b = nm_l3_config_data_lookup_objs(b, obj_type); @@ -2120,93 +2121,221 @@ _dedup_multi_index_cmp(const NML3ConfigData *a, have_b = nm_platform_dedup_multi_iter_next_obj(&iter_b, &obj_b, obj_type); nm_assert(have_b); - NM_CMP_RETURN(nmp_object_cmp_full(obj_a, - obj_b, - ignore_ifindex ? NMP_OBJECT_CMP_FLAGS_IGNORE_IFINDEX - : NMP_OBJECT_CMP_FLAGS_NONE)); + if (cmp_full) { + NM_CMP_RETURN(nmp_object_cmp_full(obj_a, + obj_b, + cmp_ifindex ? NMP_OBJECT_CMP_FLAGS_NONE + : NMP_OBJECT_CMP_FLAGS_IGNORE_IFINDEX)); + } else { + if (cmp_ifindex) { + NM_CMP_DIRECT(obj_a->obj_with_ifindex.ifindex, obj_b->obj_with_ifindex.ifindex); + } + + switch (obj_type) { + case NMP_OBJECT_TYPE_IP4_ADDRESS: + NM_CMP_DIRECT(obj_a->ip4_address.plen, obj_b->ip4_address.plen); + NM_CMP_DIRECT(obj_b->ip4_address.address, obj_b->ip4_address.address); + NM_CMP_DIRECT(obj_b->ip4_address.peer_address, obj_b->ip4_address.peer_address); + break; + case NMP_OBJECT_TYPE_IP6_ADDRESS: + NM_CMP_DIRECT(obj_a->ip6_address.plen, obj_b->ip6_address.plen); + NM_CMP_DIRECT_IN6ADDR(&obj_a->ip6_address.address, &obj_b->ip6_address.address); + break; + case NMP_OBJECT_TYPE_IP4_ROUTE: + { + NMPlatformIP4Route ra = obj_a->ip4_route; + NMPlatformIP4Route rb = obj_b->ip4_route; + + NM_CMP_DIRECT(ra.metric, rb.metric); + NM_CMP_DIRECT(ra.plen, rb.plen); + NM_CMP_RETURN_DIRECT( + nm_utils_ip4_address_same_prefix_cmp(ra.network, rb.network, ra.plen)); + break; + } + case NMP_OBJECT_TYPE_IP6_ROUTE: + { + NMPlatformIP6Route ra = obj_a->ip6_route; + NMPlatformIP6Route rb = obj_b->ip6_route; + + NM_CMP_DIRECT(ra.metric, rb.metric); + NM_CMP_DIRECT(ra.plen, rb.plen); + NM_CMP_RETURN_DIRECT( + nm_utils_ip6_address_same_prefix_cmp(&ra.network, &rb.network, ra.plen)); + break; + } + default: + nm_assert_not_reached(); + } + } } } +static const NML3ConfigData * +get_empty_l3cd(void) +{ + static NML3ConfigData *empty_l3cd; + + if (!empty_l3cd) { + empty_l3cd = + nm_l3_config_data_new(nm_dedup_multi_index_new(), 1, NM_IP_CONFIG_SOURCE_UNKNOWN); + empty_l3cd->ifindex = 0; + } + + return empty_l3cd; +} + int nm_l3_config_data_cmp_full(const NML3ConfigData *a, const NML3ConfigData *b, - NML3ConfigCmpFlags cmp_flags) + NML3ConfigCmpFlags flags) { - int IS_IPv4; - gboolean ignore_ifindex; + int IS_IPv4; - NM_CMP_SELF(a, b); + if (a == b) + return 0; - ignore_ifindex = NM_FLAGS_HAS(cmp_flags, NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX); + if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_ADDRESSES)) + flags |= NM_L3_CONFIG_CMP_FLAGS_ADDRESSES_ID; + if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_ROUTES)) + flags |= NM_L3_CONFIG_CMP_FLAGS_ROUTES_ID; - if (!ignore_ifindex) - NM_CMP_DIRECT(a->ifindex, b->ifindex); + if (!a) + a = get_empty_l3cd(); + if (!b) + b = get_empty_l3cd(); - NM_CMP_DIRECT(a->flags, b->flags); + if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_IFINDEX)) + NM_CMP_DIRECT(a->ifindex, b->ifindex); - NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP4_ADDRESS, ignore_ifindex)); - NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP6_ADDRESS, ignore_ifindex)); - NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP4_ROUTE, ignore_ifindex)); - NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP6_ROUTE, ignore_ifindex)); + if (NM_FLAGS_ANY(flags, + NM_L3_CONFIG_CMP_FLAGS_ADDRESSES | NM_L3_CONFIG_CMP_FLAGS_ADDRESSES_ID)) { + NM_CMP_RETURN( + _dedup_multi_index_cmp(a, + b, + NMP_OBJECT_TYPE_IP4_ADDRESS, + NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_IFINDEX), + NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_ADDRESSES))); + NM_CMP_RETURN( + _dedup_multi_index_cmp(a, + b, + NMP_OBJECT_TYPE_IP6_ADDRESS, + NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_IFINDEX), + NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_ADDRESSES))); + } + + if (NM_FLAGS_ANY(flags, NM_L3_CONFIG_CMP_FLAGS_ROUTES | NM_L3_CONFIG_CMP_FLAGS_ROUTES_ID)) { + NM_CMP_RETURN(_dedup_multi_index_cmp(a, + b, + NMP_OBJECT_TYPE_IP4_ROUTE, + NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_IFINDEX), + NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_ROUTES))); + NM_CMP_RETURN(_dedup_multi_index_cmp(a, + b, + NMP_OBJECT_TYPE_IP6_ROUTE, + NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_IFINDEX), + NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_ROUTES))); + } for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { - const int addr_family = IS_IPv4 ? AF_INET : AF_INET6; + const int addr_family = IS_IPv4 ? AF_INET : AF_INET6; + const NMPObject *def_route_a = a->best_default_route_x[IS_IPv4]; + const NMPObject *def_route_b = b->best_default_route_x[IS_IPv4]; + + NM_CMP_SELF(def_route_a, def_route_b); + + if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_ROUTES)) { + NM_CMP_RETURN(nmp_object_cmp_full(def_route_a, + def_route_b, + NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_IFINDEX) + ? NMP_OBJECT_CMP_FLAGS_NONE + : NMP_OBJECT_CMP_FLAGS_IGNORE_IFINDEX)); + } else if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_ROUTES_ID)) { + if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_IFINDEX)) { + NM_CMP_DIRECT(def_route_a->obj_with_ifindex.ifindex, + def_route_b->obj_with_ifindex.ifindex); + } - NM_CMP_RETURN(nmp_object_cmp_full(a->best_default_route_x[IS_IPv4], - b->best_default_route_x[IS_IPv4], - ignore_ifindex ? NMP_OBJECT_CMP_FLAGS_IGNORE_IFINDEX - : NMP_OBJECT_CMP_FLAGS_NONE)); + if (IS_IPv4) { + NMPlatformIP4Route ra = def_route_a->ip4_route; + NMPlatformIP4Route rb = def_route_b->ip4_route; + + NM_CMP_DIRECT(ra.metric, rb.metric); + NM_CMP_DIRECT(ra.plen, rb.plen); + NM_CMP_RETURN_DIRECT( + nm_utils_ip4_address_same_prefix_cmp(ra.network, rb.network, ra.plen)); + } else { + NMPlatformIP6Route ra = def_route_a->ip6_route; + NMPlatformIP6Route rb = def_route_b->ip6_route; + + NM_CMP_DIRECT(ra.metric, rb.metric); + NM_CMP_DIRECT(ra.plen, rb.plen); + NM_CMP_RETURN_DIRECT( + nm_utils_ip6_address_same_prefix_cmp(&ra.network, &rb.network, ra.plen)); + } + } - NM_CMP_RETURN( - _garray_inaddr_cmp(a->nameservers_x[IS_IPv4], b->nameservers_x[IS_IPv4], addr_family)); - - NM_CMP_RETURN(nm_utils_hashtable_cmp(nm_dhcp_lease_get_options(a->dhcp_lease_x[IS_IPv4]), - nm_dhcp_lease_get_options(b->dhcp_lease_x[IS_IPv4]), - TRUE, - nm_strcmp_with_data, - nm_strcmp_with_data, - NULL)); - - NM_CMP_RETURN(nm_strv_ptrarray_cmp(a->domains_x[IS_IPv4], b->domains_x[IS_IPv4])); - NM_CMP_RETURN(nm_strv_ptrarray_cmp(a->searches_x[IS_IPv4], b->searches_x[IS_IPv4])); - NM_CMP_RETURN(nm_strv_ptrarray_cmp(a->dns_options_x[IS_IPv4], b->dns_options_x[IS_IPv4])); - - if (NM_FLAGS_ANY(a->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY(IS_IPv4))) - NM_CMP_DIRECT(a->dns_priority_x[IS_IPv4], b->dns_priority_x[IS_IPv4]); - - NM_CMP_DIRECT(a->route_table_sync_x[IS_IPv4], b->route_table_sync_x[IS_IPv4]); - NM_CMP_DIRECT(a->never_default_x[IS_IPv4], b->never_default_x[IS_IPv4]); - } - - NM_CMP_RETURN(_garray_inaddr_cmp(a->wins, b->wins, AF_INET)); - NM_CMP_RETURN(_garray_inaddr_cmp(a->nis_servers, b->nis_servers, AF_INET)); - NM_CMP_DIRECT_REF_STRING(a->nis_domain, b->nis_domain); - NM_CMP_DIRECT(a->mdns, b->mdns); - NM_CMP_DIRECT(a->llmnr, b->llmnr); - NM_CMP_DIRECT(a->dns_over_tls, b->dns_over_tls); - NM_CMP_DIRECT(a->ip6_token.id, b->ip6_token.id); - NM_CMP_DIRECT(a->mtu, b->mtu); - NM_CMP_DIRECT(a->ip6_mtu, b->ip6_mtu); - NM_CMP_DIRECT_UNSAFE(a->metered, b->metered); - NM_CMP_DIRECT_UNSAFE(a->proxy_browser_only, b->proxy_browser_only); - NM_CMP_DIRECT_UNSAFE(a->proxy_method, b->proxy_method); - NM_CMP_DIRECT_REF_STRING(a->proxy_pac_url, b->proxy_pac_url); - NM_CMP_DIRECT_REF_STRING(a->proxy_pac_script, b->proxy_pac_script); - NM_CMP_DIRECT_UNSAFE(a->ip6_privacy, b->ip6_privacy); - - NM_CMP_DIRECT_UNSAFE(a->ndisc_hop_limit_set, b->ndisc_hop_limit_set); - if (a->ndisc_hop_limit_set) - NM_CMP_DIRECT(a->ndisc_hop_limit_val, b->ndisc_hop_limit_val); - - NM_CMP_DIRECT_UNSAFE(a->ndisc_reachable_time_msec_set, b->ndisc_reachable_time_msec_set); - if (a->ndisc_reachable_time_msec_set) - NM_CMP_DIRECT(a->ndisc_reachable_time_msec_val, b->ndisc_reachable_time_msec_val); - - NM_CMP_DIRECT_UNSAFE(a->ndisc_retrans_timer_msec_set, b->ndisc_retrans_timer_msec_set); - if (a->ndisc_retrans_timer_msec_set) - NM_CMP_DIRECT(a->ndisc_retrans_timer_msec_val, b->ndisc_retrans_timer_msec_val); - - NM_CMP_FIELD(a, b, source); + if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_DNS)) { + NM_CMP_RETURN(_garray_inaddr_cmp(a->nameservers_x[IS_IPv4], + b->nameservers_x[IS_IPv4], + addr_family)); + NM_CMP_RETURN(nm_strv_ptrarray_cmp(a->domains_x[IS_IPv4], b->domains_x[IS_IPv4])); + NM_CMP_RETURN(nm_strv_ptrarray_cmp(a->searches_x[IS_IPv4], b->searches_x[IS_IPv4])); + NM_CMP_RETURN( + nm_strv_ptrarray_cmp(a->dns_options_x[IS_IPv4], b->dns_options_x[IS_IPv4])); + + if (NM_FLAGS_ANY(a->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY(IS_IPv4))) + NM_CMP_DIRECT(a->dns_priority_x[IS_IPv4], b->dns_priority_x[IS_IPv4]); + } + + if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_OTHER)) { + NM_CMP_RETURN( + nm_utils_hashtable_cmp(nm_dhcp_lease_get_options(a->dhcp_lease_x[IS_IPv4]), + nm_dhcp_lease_get_options(b->dhcp_lease_x[IS_IPv4]), + TRUE, + nm_strcmp_with_data, + nm_strcmp_with_data, + NULL)); + + NM_CMP_DIRECT(a->route_table_sync_x[IS_IPv4], b->route_table_sync_x[IS_IPv4]); + NM_CMP_DIRECT(a->never_default_x[IS_IPv4], b->never_default_x[IS_IPv4]); + } + } + + if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_DNS)) { + NM_CMP_RETURN(_garray_inaddr_cmp(a->wins, b->wins, AF_INET)); + NM_CMP_RETURN(_garray_inaddr_cmp(a->nis_servers, b->nis_servers, AF_INET)); + NM_CMP_DIRECT_REF_STRING(a->nis_domain, b->nis_domain); + NM_CMP_DIRECT(a->mdns, b->mdns); + NM_CMP_DIRECT(a->llmnr, b->llmnr); + NM_CMP_DIRECT(a->dns_over_tls, b->dns_over_tls); + } + + if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_OTHER)) { + NM_CMP_DIRECT(a->flags, b->flags); + NM_CMP_DIRECT(a->ip6_token.id, b->ip6_token.id); + NM_CMP_DIRECT(a->mtu, b->mtu); + NM_CMP_DIRECT(a->ip6_mtu, b->ip6_mtu); + NM_CMP_DIRECT_UNSAFE(a->metered, b->metered); + NM_CMP_DIRECT_UNSAFE(a->proxy_browser_only, b->proxy_browser_only); + NM_CMP_DIRECT_UNSAFE(a->proxy_method, b->proxy_method); + NM_CMP_DIRECT_REF_STRING(a->proxy_pac_url, b->proxy_pac_url); + NM_CMP_DIRECT_REF_STRING(a->proxy_pac_script, b->proxy_pac_script); + NM_CMP_DIRECT_UNSAFE(a->ip6_privacy, b->ip6_privacy); + + NM_CMP_DIRECT_UNSAFE(a->ndisc_hop_limit_set, b->ndisc_hop_limit_set); + if (a->ndisc_hop_limit_set) + NM_CMP_DIRECT(a->ndisc_hop_limit_val, b->ndisc_hop_limit_val); + + NM_CMP_DIRECT_UNSAFE(a->ndisc_reachable_time_msec_set, b->ndisc_reachable_time_msec_set); + if (a->ndisc_reachable_time_msec_set) + NM_CMP_DIRECT(a->ndisc_reachable_time_msec_val, b->ndisc_reachable_time_msec_val); + + NM_CMP_DIRECT_UNSAFE(a->ndisc_retrans_timer_msec_set, b->ndisc_retrans_timer_msec_set); + if (a->ndisc_retrans_timer_msec_set) + NM_CMP_DIRECT(a->ndisc_retrans_timer_msec_val, b->ndisc_retrans_timer_msec_val); + + NM_CMP_FIELD(a, b, source); + } /* these fields are not considered by cmp(): * @@ -3180,9 +3309,10 @@ nm_l3_config_data_new_clone(const NML3ConfigData *src, int ifindex) nm_assert(nm_l3_config_data_cmp_full(src, self, - src->ifindex != ifindex - ? NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX - : NM_L3_CONFIG_CMP_FLAGS_NONE) + src->ifindex == ifindex + ? NM_L3_CONFIG_CMP_FLAGS_ALL + : NM_L3_CONFIG_CMP_FLAGS_ALL + & ~(NM_L3_CONFIG_CMP_FLAGS_IFINDEX)) == 0); nm_assert(nm_l3_config_data_get_ifindex(self) == ifindex); diff --git a/src/core/nm-l3-config-data.h b/src/core/nm-l3-config-data.h index 1c776d4edb..b7a1bb32f5 100644 --- a/src/core/nm-l3-config-data.h +++ b/src/core/nm-l3-config-data.h @@ -198,18 +198,25 @@ NMDedupMultiIndex *nm_l3_config_data_get_multi_idx(const NML3ConfigData *self); /*****************************************************************************/ typedef enum { - NM_L3_CONFIG_CMP_FLAGS_NONE, - NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX = (1LL << 0), + NM_L3_CONFIG_CMP_FLAGS_NONE = 0, + NM_L3_CONFIG_CMP_FLAGS_IFINDEX = (1LL << 0), + NM_L3_CONFIG_CMP_FLAGS_ADDRESSES_ID = (1LL << 1), + NM_L3_CONFIG_CMP_FLAGS_ADDRESSES = (1LL << 2), + NM_L3_CONFIG_CMP_FLAGS_ROUTES_ID = (1LL << 3), + NM_L3_CONFIG_CMP_FLAGS_ROUTES = (1LL << 4), + NM_L3_CONFIG_CMP_FLAGS_DNS = (1LL << 5), + NM_L3_CONFIG_CMP_FLAGS_OTHER = (1LL << 6), + NM_L3_CONFIG_CMP_FLAGS_ALL = (1LL << 7) - 1, } NML3ConfigCmpFlags; int nm_l3_config_data_cmp_full(const NML3ConfigData *a, const NML3ConfigData *b, - NML3ConfigCmpFlags cmp_flags); + NML3ConfigCmpFlags flags); static inline int nm_l3_config_data_cmp(const NML3ConfigData *a, const NML3ConfigData *b) { - return nm_l3_config_data_cmp_full(a, b, NM_L3_CONFIG_CMP_FLAGS_NONE); + return nm_l3_config_data_cmp_full(a, b, NM_L3_CONFIG_CMP_FLAGS_ALL); } static inline gboolean diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c index c4ae8e2abb..cb5b543e9d 100644 --- a/src/core/nm-policy.c +++ b/src/core/nm-policy.c @@ -1995,6 +1995,26 @@ device_state_changed(NMDevice *device, /* Reset auto retries back to default since connection was successful */ nm_settings_connection_autoconnect_retries_reset(sett_conn); } + + /* Since there is no guarantee that device_l3cd_changed() is called + * again when the device becomes ACTIVATED, we need also to update + * routing and DNS here. */ + nm_dns_manager_begin_updates(priv->dns_manager, __func__); + if (!nm_device_sys_iface_state_is_external(device)) { + nm_dns_manager_set_ip_config(priv->dns_manager, + AF_UNSPEC, + device, + nm_device_get_l3cd(device, TRUE), + NM_DNS_IP_CONFIG_TYPE_DEFAULT, + TRUE); + } + update_ip_dns(self, AF_INET, device); + update_ip_dns(self, AF_INET6, device); + update_ip4_routing(self, TRUE); + update_ip6_routing(self, TRUE); + update_system_hostname(self, "routing and dns"); + nm_dns_manager_end_updates(priv->dns_manager, __func__); + break; case NM_DEVICE_STATE_UNMANAGED: case NM_DEVICE_STATE_UNAVAILABLE: @@ -2122,7 +2142,7 @@ device_l3cd_changed(NMDevice *device, * now. */ state = nm_device_get_state(device); - if (l3cd_new && state > NM_DEVICE_STATE_DISCONNECTED && state < NM_DEVICE_STATE_DEACTIVATING) { + if (l3cd_new && state > NM_DEVICE_STATE_IP_CONFIG && state < NM_DEVICE_STATE_DEACTIVATING) { nm_dns_manager_set_ip_config(priv->dns_manager, AF_UNSPEC, device, @@ -2800,6 +2820,7 @@ constructed(GObject *object) G_OBJECT_CLASS(nm_policy_parent_class)->constructed(object); _LOGD(LOGD_DNS, "hostname-mode: %s", _hostname_mode_to_string(priv->hostname_mode)); + update_system_hostname(self, "initial hostname"); } NMPolicy * |