diff options
| author | Michael Biebl <biebl@debian.org> | 2018-09-23 10:11:11 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-09-23 10:11:11 +0200 |
| commit | 135c3be0fb0eedb7a1b493ffde6c1ab3d23771f6 (patch) | |
| tree | 40408d2ad887437e3ca63ff7fc6334bf22ae3fe6 /src | |
| parent | 81e5928f26b40b0227604ccaf4b051fe14c9b3ef (diff) | |
| parent | e126f3e804c35480c4f075777430419d6ece23da (diff) | |
Update upstream source from tag 'upstream/1.12.4'
Update to upstream version '1.12.4' with Debian dir 650b52e60bf462f2972d0c33deec2cb171953445
Diffstat (limited to 'src')
| -rw-r--r-- | src/devices/nm-device.c | 82 | ||||
| -rw-r--r-- | src/devices/wifi/nm-device-wifi.c | 1 | ||||
| -rw-r--r-- | src/devices/wifi/nm-wifi-common.c | 2 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-client.c | 33 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-client.h | 4 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhclient.c | 8 | ||||
| -rw-r--r-- | src/dns/nm-dns-dnsmasq.c | 10 | ||||
| -rw-r--r-- | src/nm-connectivity.c | 236 | ||||
| -rw-r--r-- | src/nm-connectivity.h | 7 | ||||
| -rw-r--r-- | src/nm-ip4-config.c | 31 | ||||
| -rw-r--r-- | src/nm-ip4-config.h | 1 | ||||
| -rw-r--r-- | src/nm-ip6-config.c | 31 | ||||
| -rw-r--r-- | src/nm-ip6-config.h | 2 | ||||
| -rw-r--r-- | src/nm-manager.c | 18 | ||||
| -rw-r--r-- | src/ppp/nm-ppp-manager.c | 10 | ||||
| -rw-r--r-- | src/supplicant/nm-supplicant-interface.c | 2 | ||||
| -rw-r--r-- | src/vpn/nm-vpn-connection.c | 13 |
17 files changed, 360 insertions, 131 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 19e43762..33dd5e50 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -2615,7 +2615,6 @@ static void concheck_cb (NMConnectivity *connectivity, NMConnectivityCheckHandle *c_handle, NMConnectivityState state, - GError *error, gpointer user_data) { _nm_unused gs_unref_object NMDevice *self_keep_alive = NULL; @@ -2636,7 +2635,7 @@ concheck_cb (NMConnectivity *connectivity, handle->c_handle = NULL; self = handle->self; - if (nm_utils_error_is_cancelled (error, FALSE)) { + if (state == NM_CONNECTIVITY_CANCELLED) { /* the only place where we nm_connectivity_check_cancel(@c_handle), is * from inside concheck_handle_complete(). This is a recursive call, * nothing to do. */ @@ -2645,15 +2644,14 @@ concheck_cb (NMConnectivity *connectivity, return; } + /* we keep NMConnectivity instance alive. It cannot be disposing. */ + nm_assert (state != NM_CONNECTIVITY_DISPOSING); + self_keep_alive = g_object_ref (self); - _LOGT (LOGD_CONCHECK, "connectivity: complete check (seq:%llu, state:%s%s%s%s)", + _LOGT (LOGD_CONCHECK, "connectivity: complete check (seq:%llu, state:%s)", (long long unsigned) handle->seq, - nm_connectivity_state_to_string (state), - NM_PRINT_FMT_QUOTED (error, ", error: ", error->message, "", "")); - - /* we keep NMConnectivity instance alive. It cannot be disposing. */ - nm_assert (!nm_utils_error_is_cancelled (error, TRUE)); + nm_connectivity_state_to_string (state)); /* keep @self alive, while we invoke callbacks. */ priv = NM_DEVICE_GET_PRIVATE (self); @@ -4236,6 +4234,9 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error) } } + nm_clear_g_source (&priv->queued_ip_config_id_4); + nm_clear_g_source (&priv->queued_ip_config_id_6); + g_object_freeze_notify (G_OBJECT (self)); NM_DEVICE_GET_CLASS (self)->unrealize_notify (self); @@ -10337,10 +10338,37 @@ nm_device_reactivate_ip4_config (NMDevice *self, _set_ip_state (self, AF_INET, IP_WAIT); if (!nm_device_activate_stage3_ip4_start (self)) _LOGW (LOGD_IP4, "Failed to apply IPv4 configuration"); - } else { - if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) - _LOGW (LOGD_IP4, "Failed to reapply IPv4 configuration"); + return; + } + + if (s_ip4_old && s_ip4_new) { + gint64 metric_old, metric_new; + + /* For dynamic IP methods (DHCP, IPv4LL, WWAN) the route metric is + * set at activation/renewal time using the value from static + * configuration. To support runtime change we need to update the + * dynamic configuration in place and tell the DHCP client the new + * value to use for future renewals. + */ + metric_old = nm_setting_ip_config_get_route_metric (s_ip4_old); + metric_new = nm_setting_ip_config_get_route_metric (s_ip4_new); + + if (metric_old != metric_new) { + if (priv->dev_ip4_config.orig) { + nm_ip4_config_update_routes_metric ((NMIP4Config *) priv->dev_ip4_config.orig, + nm_device_get_route_metric (self, AF_INET)); + } + if (priv->wwan_ip_config_4.orig) { + nm_ip4_config_update_routes_metric ((NMIP4Config *) priv->wwan_ip_config_4.orig, + nm_device_get_route_metric (self, AF_INET)); + } + if (priv->dhcp4.client) + nm_dhcp_client_set_route_metric (priv->dhcp4.client, metric_new); + } } + + if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) + _LOGW (LOGD_IP4, "Failed to reapply IPv4 configuration"); } } @@ -10382,10 +10410,36 @@ nm_device_reactivate_ip6_config (NMDevice *self, _set_ip_state (self, AF_INET6, IP_WAIT); if (!nm_device_activate_stage3_ip6_start (self)) _LOGW (LOGD_IP6, "Failed to apply IPv6 configuration"); - } else { - if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) - _LOGW (LOGD_IP4, "Failed to reapply IPv6 configuration"); + return; + } + + if (s_ip6_old && s_ip6_new) { + gint64 metric_old, metric_new; + + /* See comment in nm_device_reactivate_ip6_config() */ + metric_old = nm_setting_ip_config_get_route_metric (s_ip6_old); + metric_new = nm_setting_ip_config_get_route_metric (s_ip6_new); + + if (metric_old != metric_new) { + if (priv->ac_ip6_config.orig) { + nm_ip6_config_update_routes_metric ((NMIP6Config *) priv->ac_ip6_config.orig, + nm_device_get_route_metric (self, AF_INET6)); + } + if (priv->dhcp6.ip6_config.orig) { + nm_ip6_config_update_routes_metric ((NMIP6Config *) priv->dhcp6.ip6_config.orig, + nm_device_get_route_metric (self, AF_INET6)); + } + if (priv->wwan_ip_config_6.orig) { + nm_ip6_config_update_routes_metric ((NMIP6Config *) priv->wwan_ip_config_6.orig, + nm_device_get_route_metric (self, AF_INET6)); + } + if (priv->dhcp6.client) + nm_dhcp_client_set_route_metric (priv->dhcp6.client, metric_new); + } } + + if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) + _LOGW (LOGD_IP4, "Failed to reapply IPv6 configuration"); } } diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 6bd06524..0dd6fa74 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -2557,6 +2557,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) set_current_ap (self, ap, FALSE); nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), nm_dbus_object_get_path (NM_DBUS_OBJECT (ap))); + g_object_unref (ap); return NM_ACT_STAGE_RETURN_SUCCESS; done: diff --git a/src/devices/wifi/nm-wifi-common.c b/src/devices/wifi/nm-wifi-common.c index 8e079d11..c95620e7 100644 --- a/src/devices/wifi/nm-wifi-common.c +++ b/src/devices/wifi/nm-wifi-common.c @@ -196,7 +196,7 @@ const NMDBusInterfaceInfoExtended nm_interface_info_device_wireless = { NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("PermHwAddress", "s", NM_DEVICE_PERM_HW_ADDRESS), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Mode", "u", NM_DEVICE_WIFI_MODE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("BitRate", "u", NM_DEVICE_WIFI_BITRATE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Bitrate", "u", NM_DEVICE_WIFI_BITRATE), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("AccessPoints", "ao", NM_DEVICE_WIFI_ACCESS_POINTS), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("ActiveAccessPoint", "o", NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("WirelessCapabilities", "u", NM_DEVICE_WIFI_CAPABILITIES), diff --git a/src/dhcp/nm-dhcp-client.c b/src/dhcp/nm-dhcp-client.c index 360bd367..e53c8d87 100644 --- a/src/dhcp/nm-dhcp-client.c +++ b/src/dhcp/nm-dhcp-client.c @@ -51,7 +51,7 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -NM_GOBJECT_PROPERTIES_DEFINE_BASE ( +NM_GOBJECT_PROPERTIES_DEFINE (NMDhcpClient, PROP_ADDR_FAMILY, PROP_FLAGS, PROP_HWADDR, @@ -163,6 +163,17 @@ nm_dhcp_client_get_route_table (NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE (self)->route_table; } +void +nm_dhcp_client_set_route_table (NMDhcpClient *self, guint32 route_table) +{ + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + + if (route_table != priv->route_table) { + priv->route_table = route_table; + _notify (self, PROP_ROUTE_TABLE); + } +} + guint32 nm_dhcp_client_get_route_metric (NMDhcpClient *self) { @@ -171,6 +182,17 @@ nm_dhcp_client_get_route_metric (NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE (self)->route_metric; } +void +nm_dhcp_client_set_route_metric (NMDhcpClient *self, guint32 route_metric) +{ + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + + if (route_metric != priv->route_metric) { + priv->route_metric = route_metric; + _notify (self, PROP_ROUTE_METRIC); + } +} + guint32 nm_dhcp_client_get_timeout (NMDhcpClient *self) { @@ -834,6 +856,9 @@ get_property (GObject *object, guint prop_id, case PROP_ROUTE_METRIC: g_value_set_uint (value, priv->route_metric); break; + case PROP_ROUTE_TABLE: + g_value_set_uint (value, priv->route_table); + break; case PROP_TIMEOUT: g_value_set_uint (value, priv->timeout); break; @@ -889,11 +914,9 @@ set_property (GObject *object, guint prop_id, priv->uuid = g_value_dup_string (value); break; case PROP_ROUTE_TABLE: - /* construct-only */ priv->route_table = g_value_get_uint (value); break; case PROP_ROUTE_METRIC: - /* construct-only */ priv->route_metric = g_value_get_uint (value); break; case PROP_TIMEOUT: @@ -1002,13 +1025,13 @@ nm_dhcp_client_class_init (NMDhcpClientClass *client_class) obj_properties[PROP_ROUTE_TABLE] = g_param_spec_uint (NM_DHCP_CLIENT_ROUTE_TABLE, "", "", 0, G_MAXUINT32, RT_TABLE_MAIN, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); obj_properties[PROP_ROUTE_METRIC] = g_param_spec_uint (NM_DHCP_CLIENT_ROUTE_METRIC, "", "", 0, G_MAXUINT32, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); obj_properties[PROP_TIMEOUT] = diff --git a/src/dhcp/nm-dhcp-client.h b/src/dhcp/nm-dhcp-client.h index f3d0b7d1..4c196045 100644 --- a/src/dhcp/nm-dhcp-client.h +++ b/src/dhcp/nm-dhcp-client.h @@ -131,8 +131,12 @@ GBytes *nm_dhcp_client_get_hw_addr (NMDhcpClient *self); guint32 nm_dhcp_client_get_route_table (NMDhcpClient *self); +void nm_dhcp_client_set_route_table (NMDhcpClient *self, guint32 route_table); + guint32 nm_dhcp_client_get_route_metric (NMDhcpClient *self); +void nm_dhcp_client_set_route_metric (NMDhcpClient *self, guint32 route_metric); + guint32 nm_dhcp_client_get_timeout (NMDhcpClient *self); GBytes *nm_dhcp_client_get_client_id (NMDhcpClient *self); diff --git a/src/dhcp/nm-dhcp-dhclient.c b/src/dhcp/nm-dhcp-dhclient.c index 3bd14ebe..bf93c831 100644 --- a/src/dhcp/nm-dhcp-dhclient.c +++ b/src/dhcp/nm-dhcp-dhclient.c @@ -374,11 +374,15 @@ dhclient_start (NMDhcpClient *client, if (g_file_copy (src, dst, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error)) { /* Success; use the preferred leasefile path */ g_free (priv->lease_file); - priv->lease_file = g_strdup (g_file_get_path (dst)); + priv->lease_file = g_file_get_path (dst); } else { + gs_free char *s_path = NULL; + gs_free char *d_path = NULL; + /* Failure; just use the existing leasefile */ _LOGW ("failed to copy leasefile %s to %s: %s", - g_file_get_path (src), g_file_get_path (dst), + (s_path = g_file_get_path (src)), + (d_path = g_file_get_path (dst)), error->message); g_clear_error (&error); } diff --git a/src/dns/nm-dns-dnsmasq.c b/src/dns/nm-dns-dnsmasq.c index b5b93280..91f4c55b 100644 --- a/src/dns/nm-dns-dnsmasq.c +++ b/src/dns/nm-dns-dnsmasq.c @@ -183,10 +183,12 @@ add_ip_config (NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsIPConfig domain[0] ? domain : NULL); } - for (j = 0; ip_data->domains.reverse[j]; j++) { - add_dnsmasq_nameserver (self, servers, - ip_addr_to_string_buf, - ip_data->domains.reverse[j]); + if (ip_data->domains.reverse) { + for (j = 0; ip_data->domains.reverse[j]; j++) { + add_dnsmasq_nameserver (self, servers, + ip_addr_to_string_buf, + ip_data->domains.reverse[j]); + } } } } diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 1ce6d3cf..db26218b 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -46,8 +46,10 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_state_to_string, int /*NMConnectivityState*/ NM_UTILS_LOOKUP_STR_ITEM (NM_CONNECTIVITY_PORTAL, "PORTAL"), NM_UTILS_LOOKUP_STR_ITEM (NM_CONNECTIVITY_FULL, "FULL"), - NM_UTILS_LOOKUP_STR_ITEM (NM_CONNECTIVITY_ERROR, "ERROR"), - NM_UTILS_LOOKUP_STR_ITEM (NM_CONNECTIVITY_FAKE, "FAKE"), + NM_UTILS_LOOKUP_STR_ITEM (NM_CONNECTIVITY_ERROR, "ERROR"), + NM_UTILS_LOOKUP_STR_ITEM (NM_CONNECTIVITY_FAKE, "FAKE"), + NM_UTILS_LOOKUP_STR_ITEM (NM_CONNECTIVITY_CANCELLED, "CANCELLED"), + NM_UTILS_LOOKUP_STR_ITEM (NM_CONNECTIVITY_DISPOSING, "DISPOSING"), ); const char * @@ -77,6 +79,10 @@ struct _NMConnectivityCheckHandle { } concheck; #endif + const char *completed_log_message; + char *completed_log_message_free; + NMConnectivityState completed_state; + guint timeout_id; }; @@ -90,6 +96,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { CList handles_lst_head; + CList completed_handles_lst_head; char *uri; char *response; gboolean enabled; @@ -142,60 +149,37 @@ NM_DEFINE_SINGLETON_GETTER (NMConnectivity, nm_connectivity_get, NM_TYPE_CONNECT /*****************************************************************************/ static void -cb_data_invoke_callback (NMConnectivityCheckHandle *cb_data, - NMConnectivityState state, - GError *error, - const char *log_message) +cb_data_complete (NMConnectivityCheckHandle *cb_data, + NMConnectivityState state, + const char *log_message) { - NMConnectivityCheckCallback callback; + NMConnectivity *self; nm_assert (cb_data); nm_assert (NM_IS_CONNECTIVITY (cb_data->self)); - - callback = cb_data->callback; - if (!callback) - return; - - cb_data->callback = NULL; - + nm_assert (cb_data->callback); + nm_assert (state != NM_CONNECTIVITY_UNKNOWN); nm_assert (log_message); - _LOG2D ("check completed: %s; %s", - nm_connectivity_state_to_string (state), - log_message); - - callback (cb_data->self, - cb_data, - state, - error, - cb_data->user_data); -} - -static void -cb_data_free (NMConnectivityCheckHandle *cb_data, - NMConnectivityState state, - GError *error, - const char *log_message) -{ - NMConnectivity *self; - - nm_assert (cb_data); - self = cb_data->self; - nm_assert (NM_IS_CONNECTIVITY (self)); + /* mark the handle as completing. After this point, nm_connectivity_check_cancel() + * is no longer possible. */ + cb_data->self = NULL; - c_list_unlink (&cb_data->handles_lst); + c_list_unlink_stale (&cb_data->handles_lst); #if WITH_CONCHECK if (cb_data->concheck.curl_ehandle) { NMConnectivityPrivate *priv; /* Contrary to what cURL manual claim it is *not* safe to remove - * the easy handle "at any moment"; specifically not from the - * write function. Thus here we just dissociate the cb_data from - * the easy handle and the easy handle will be cleaned up when the - * message goes to CURLMSG_DONE in _con_curl_check_connectivity(). */ + * the easy handle "at any moment"; specifically it's not safe to + * remove *any* handle from within a libcurl callback. That is + * why we queue completed handles in this case. + * + * cb_data_complete() is however only called *not* from within a + * libcurl callback. So, this is fine. */ curl_easy_setopt (cb_data->concheck.curl_ehandle, CURLOPT_WRITEFUNCTION, NULL); curl_easy_setopt (cb_data->concheck.curl_ehandle, CURLOPT_WRITEDATA, NULL); curl_easy_setopt (cb_data->concheck.curl_ehandle, CURLOPT_HEADERFUNCTION, NULL); @@ -214,7 +198,18 @@ cb_data_free (NMConnectivityCheckHandle *cb_data, nm_clear_g_source (&cb_data->timeout_id); - cb_data_invoke_callback (cb_data, state, error, log_message); + _LOG2D ("check completed: %s; %s", + nm_connectivity_state_to_string (state), + log_message); + + cb_data->callback (self, + cb_data, + state, + cb_data->user_data); + + /* Note: self might be a danling pointer at this point. It must not be used + * after this point, and all callers must either take a reference first, or + * not use the self pointer too. */ #if WITH_CONCHECK g_free (cb_data->concheck.response); @@ -222,12 +217,54 @@ cb_data_free (NMConnectivityCheckHandle *cb_data, g_string_free (cb_data->concheck.recv_msg, TRUE); #endif g_free (cb_data->ifspec); + if (cb_data->completed_log_message_free) + g_free (cb_data->completed_log_message_free); g_slice_free (NMConnectivityCheckHandle, cb_data); } /*****************************************************************************/ #if WITH_CONCHECK + +static void +cb_data_queue_completed (NMConnectivityCheckHandle *cb_data, + NMConnectivityState state, + const char *log_message_static, + char *log_message_take /* take */) +{ + nm_assert (cb_data); + nm_assert (NM_IS_CONNECTIVITY (cb_data->self)); + nm_assert (state != NM_CONNECTIVITY_UNKNOWN); + nm_assert (log_message_static || log_message_take); + nm_assert (cb_data->completed_state == NM_CONNECTIVITY_UNKNOWN); + nm_assert (!cb_data->completed_log_message); + nm_assert (c_list_contains (&NM_CONNECTIVITY_GET_PRIVATE (cb_data->self)->handles_lst_head, &cb_data->handles_lst)); + + cb_data->completed_state = state; + cb_data->completed_log_message = log_message_static ?: log_message_take; + cb_data->completed_log_message_free = log_message_take; + + c_list_unlink_stale (&cb_data->handles_lst); + c_list_link_tail (&NM_CONNECTIVITY_GET_PRIVATE (cb_data->self)->completed_handles_lst_head, &cb_data->handles_lst); +} + +static void +_complete_queued (NMConnectivity *self) +{ + NMConnectivity *self_keep_alive = NULL; + NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); + NMConnectivityCheckHandle *cb_data; + + while ((cb_data = c_list_first_entry (&priv->completed_handles_lst_head, NMConnectivityCheckHandle, handles_lst))) { + if (!self_keep_alive) + self_keep_alive = g_object_ref (self); + cb_data_complete (cb_data, + cb_data->completed_state, + cb_data->completed_log_message); + } + nm_g_object_unref (self_keep_alive); +} + static const char * _check_handle_get_response (NMConnectivityCheckHandle *cb_data) { @@ -265,29 +302,37 @@ _con_curl_check_connectivity (CURLM *mhandle, int sockfd, int ev_bitmask) continue; } - if (!cb_data->callback) { - /* callback was already invoked earlier. */ - cb_data_free (cb_data, NM_CONNECTIVITY_UNKNOWN, NULL, NULL); - } else if (msg->data.result != CURLE_OK) { - gs_free char *log_message = NULL; + nm_assert (cb_data); + nm_assert (NM_IS_CONNECTIVITY (cb_data->self)); - log_message = g_strdup_printf ("check failed with curl status %d", msg->data.result); - cb_data_free (cb_data, NM_CONNECTIVITY_LIMITED, NULL, - log_message); + if (cb_data->completed_state != NM_CONNECTIVITY_UNKNOWN) { + /* callback was already invoked earlier. Nothing to do. */ + continue; + } + + if (msg->data.result != CURLE_OK) { + cb_data_queue_completed (cb_data, + NM_CONNECTIVITY_LIMITED, + NULL, + g_strdup_printf ("check failed with curl status %d", msg->data.result)); } else if ( !((_check_handle_get_response (cb_data))[0]) && (curl_easy_getinfo (msg->easy_handle, CURLINFO_RESPONSE_CODE, &response_code) == CURLE_OK) && response_code == 204) { /* If we got a 204 response code (no content) and we actually * requested no content, report full connectivity. */ - cb_data_free (cb_data, NM_CONNECTIVITY_FULL, NULL, - "no content, as expected"); + cb_data_queue_completed (cb_data, + NM_CONNECTIVITY_FULL, + "no content, as expected", + NULL); } else { /* If we get here, it means that easy_write_cb() didn't read enough * bytes to be able to do a match, or that we were asking for no content * (204 response code) and we actually got some. Either way, that is * an indication of a captive portal */ - cb_data_free (cb_data, NM_CONNECTIVITY_PORTAL, NULL, - "unexpected short response"); + cb_data_queue_completed (cb_data, + NM_CONNECTIVITY_PORTAL, + "unexpected short response", + NULL); } } @@ -306,6 +351,7 @@ _con_curl_timeout_cb (gpointer user_data) priv->concheck.curl_timer = 0; _con_curl_check_connectivity (priv->concheck.curl_mhandle, CURL_SOCKET_TIMEOUT, 0); + _complete_queued (self); return G_SOURCE_REMOVE; } @@ -368,6 +414,8 @@ _con_curl_socketevent_cb (GIOChannel *ch, GIOCondition condition, gpointer user_ fdp->ev = 0; } + _complete_queued (self); + return success ? G_SOURCE_CONTINUE : G_SOURCE_REMOVE; } @@ -419,10 +467,17 @@ easy_header_cb (char *buffer, size_t size, size_t nitems, void *userdata) NMConnectivityCheckHandle *cb_data = userdata; size_t len = size * nitems; + if (cb_data->completed_state != NM_CONNECTIVITY_UNKNOWN) { + /* already completed. */ + return 0; + } + if ( len >= sizeof (HEADER_STATUS_ONLINE) - 1 && !g_ascii_strncasecmp (buffer, HEADER_STATUS_ONLINE, sizeof (HEADER_STATUS_ONLINE) - 1)) { - cb_data_invoke_callback (cb_data, NM_CONNECTIVITY_FULL, - NULL, "status header found"); + cb_data_queue_completed (cb_data, + NM_CONNECTIVITY_FULL, + "status header found", + NULL); return 0; } @@ -434,24 +489,33 @@ easy_write_cb (void *buffer, size_t size, size_t nmemb, void *userdata) { NMConnectivityCheckHandle *cb_data = userdata; size_t len = size * nmemb; - const char *response = _check_handle_get_response (cb_data);; + const char *response; + + if (cb_data->completed_state != NM_CONNECTIVITY_UNKNOWN) { + /* already completed. */ + return 0; + } if (!cb_data->concheck.recv_msg) cb_data->concheck.recv_msg = g_string_sized_new (len + 10); g_string_append_len (cb_data->concheck.recv_msg, buffer, len); + response = _check_handle_get_response (cb_data);; if ( response && cb_data->concheck.recv_msg->len >= strlen (response)) { /* We already have enough data -- check response */ if (g_str_has_prefix (cb_data->concheck.recv_msg->str, response)) { - cb_data_invoke_callback (cb_data, NM_CONNECTIVITY_FULL, NULL, - "expected response"); + cb_data_queue_completed (cb_data, + NM_CONNECTIVITY_FULL, + "expected response", + NULL); } else { - cb_data_invoke_callback (cb_data, NM_CONNECTIVITY_PORTAL, NULL, - "unexpected response"); + cb_data_queue_completed (cb_data, + NM_CONNECTIVITY_PORTAL, + "unexpected response", + NULL); } - return 0; } @@ -462,15 +526,11 @@ static gboolean _timeout_cb (gpointer user_data) { NMConnectivityCheckHandle *cb_data = user_data; - NMConnectivity *self; nm_assert (NM_IS_CONNECTIVITY (cb_data->self)); + nm_assert (c_list_contains (&NM_CONNECTIVITY_GET_PRIVATE (cb_data->self)->handles_lst_head, &cb_data->handles_lst)); - self = cb_data->self; - - nm_assert (c_list_contains (&NM_CONNECTIVITY_GET_PRIVATE (self)->handles_lst_head, &cb_data->handles_lst)); - - cb_data_free (cb_data, NM_CONNECTIVITY_LIMITED, NULL, "timeout"); + cb_data_complete (cb_data, NM_CONNECTIVITY_LIMITED, "timeout"); return G_SOURCE_REMOVE; } #endif @@ -490,9 +550,9 @@ _idle_cb (gpointer user_data) /* the invocation was with an invalid ifname. It is a fail. */ g_set_error (&error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, "no interface specified for connectivity check"); - cb_data_free (cb_data, NM_CONNECTIVITY_ERROR, NULL, "missing interface"); + cb_data_complete (cb_data, NM_CONNECTIVITY_ERROR, "missing interface"); } else - cb_data_free (cb_data, NM_CONNECTIVITY_FAKE, NULL, "fake result"); + cb_data_complete (cb_data, NM_CONNECTIVITY_FAKE, "fake result"); return G_SOURCE_REMOVE; } @@ -516,6 +576,7 @@ nm_connectivity_check_start (NMConnectivity *self, c_list_link_tail (&priv->handles_lst_head, &cb_data->handles_lst); cb_data->callback = callback; cb_data->user_data = user_data; + cb_data->completed_state = NM_CONNECTIVITY_UNKNOWN; if (iface) cb_data->ifspec = g_strdup_printf ("if!%s", iface); @@ -556,22 +617,13 @@ nm_connectivity_check_start (NMConnectivity *self, void nm_connectivity_check_cancel (NMConnectivityCheckHandle *cb_data) { - NMConnectivity *self; - gs_free_error GError *error = NULL; - g_return_if_fail (cb_data); + g_return_if_fail (NM_IS_CONNECTIVITY (cb_data->self)); - self = cb_data->self; - - g_return_if_fail (NM_IS_CONNECTIVITY (self)); - g_return_if_fail (!c_list_is_empty (&cb_data->handles_lst)); - g_return_if_fail (cb_data->callback); - - nm_assert (c_list_contains (&NM_CONNECTIVITY_GET_PRIVATE (self)->handles_lst_head, &cb_data->handles_lst)); + nm_assert ( c_list_contains (&NM_CONNECTIVITY_GET_PRIVATE (cb_data->self)->handles_lst_head, &cb_data->handles_lst) + || c_list_contains (&NM_CONNECTIVITY_GET_PRIVATE (cb_data->self)->completed_handles_lst_head, &cb_data->handles_lst)); - nm_utils_error_set_cancelled (&error, FALSE, "NMConnectivity"); - - cb_data_free (cb_data, NM_CONNECTIVITY_ERROR, error, "cancelled"); + cb_data_complete (cb_data, NM_CONNECTIVITY_CANCELLED, "cancelled"); } /*****************************************************************************/ @@ -684,6 +736,7 @@ nm_connectivity_init (NMConnectivity *self) NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); c_list_init (&priv->handles_lst_head); + c_list_init (&priv->completed_handles_lst_head); priv->config = g_object_ref (nm_config_get ()); g_signal_connect (G_OBJECT (priv->config), @@ -715,16 +768,13 @@ dispose (GObject *object) NMConnectivity *self = NM_CONNECTIVITY (object); NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); NMConnectivityCheckHandle *cb_data; - GError *error = NULL; - -again: - c_list_for_each_entry (cb_data, &priv->handles_lst_head, handles_lst) { - if (!error) - nm_utils_error_set_cancelled (&error, TRUE, "NMConnectivity"); - cb_data_free (cb_data, NM_CONNECTIVITY_ERROR, error, "shutting down"); - goto again; - } - g_clear_error (&error); + + nm_assert (c_list_is_empty (&priv->completed_handles_lst_head)); + + while ((cb_data = c_list_first_entry (&priv->handles_lst_head, + NMConnectivityCheckHandle, + handles_lst))) + cb_data_complete (cb_data, NM_CONNECTIVITY_DISPOSING, "shutting down"); g_clear_pointer (&priv->uri, g_free); g_clear_pointer (&priv->response, g_free); diff --git a/src/nm-connectivity.h b/src/nm-connectivity.h index df9295e0..178f27ad 100644 --- a/src/nm-connectivity.h +++ b/src/nm-connectivity.h @@ -24,8 +24,10 @@ #include "nm-dbus-interface.h" -#define NM_CONNECTIVITY_ERROR ((NMConnectivityState) -1) -#define NM_CONNECTIVITY_FAKE ((NMConnectivityState) -2) +#define NM_CONNECTIVITY_ERROR ((NMConnectivityState) -1) +#define NM_CONNECTIVITY_FAKE ((NMConnectivityState) -2) +#define NM_CONNECTIVITY_CANCELLED ((NMConnectivityState) -3) +#define NM_CONNECTIVITY_DISPOSING ((NMConnectivityState) -4) #define NM_TYPE_CONNECTIVITY (nm_connectivity_get_type ()) #define NM_CONNECTIVITY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CONNECTIVITY, NMConnectivity)) @@ -53,7 +55,6 @@ typedef struct _NMConnectivityCheckHandle NMConnectivityCheckHandle; typedef void (*NMConnectivityCheckCallback) (NMConnectivity *self, NMConnectivityCheckHandle *handle, NMConnectivityState state, - GError *error, gpointer user_data); NMConnectivityCheckHandle *nm_connectivity_check_start (NMConnectivity *self, diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 6ae81b57..657ebfc0 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -646,6 +646,37 @@ nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i } void +nm_ip4_config_update_routes_metric (NMIP4Config *self, gint64 metric) +{ + gs_free NMPlatformIP4Route *routes = NULL; + gboolean need_update = FALSE; + const NMPlatformIP4Route *r; + NMDedupMultiIter iter; + guint num = 0, i = 0; + + nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) { + if (r->metric != metric) + need_update = TRUE; + num++; + } + if (!need_update) + return; + + routes = g_new (NMPlatformIP4Route, num); + nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) { + routes[i] = *r; + routes[i].metric = metric; + i++; + } + + g_object_freeze_notify (G_OBJECT (self)); + nm_ip4_config_reset_routes (self); + for (i = 0; i < num; i++) + nm_ip4_config_add_route (self, &routes[i], NULL); + g_object_thaw_notify (G_OBJECT (self)); +} + +void nm_ip4_config_add_dependent_routes (NMIP4Config *self, guint32 route_table, guint32 route_metric, diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 78aca14e..45c1fa3f 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -223,6 +223,7 @@ const NMPlatformIP4Route *_nmtst_ip4_config_get_route (const NMIP4Config *self, const NMPlatformIP4Route *nm_ip4_config_get_direct_route_for_host (const NMIP4Config *self, in_addr_t host, guint32 route_table); +void nm_ip4_config_update_routes_metric (NMIP4Config *self, gint64 metric); void nm_ip4_config_reset_nameservers (NMIP4Config *self); void nm_ip4_config_add_nameserver (NMIP4Config *self, guint32 nameserver); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 9807d388..3869fee8 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -428,6 +428,37 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i } void +nm_ip6_config_update_routes_metric (NMIP6Config *self, gint64 metric) +{ + gs_free NMPlatformIP6Route *routes = NULL; + gboolean need_update = FALSE; + const NMPlatformIP6Route *r; + NMDedupMultiIter iter; + guint num = 0, i = 0; + + nm_ip_config_iter_ip6_route_for_each (&iter, self, &r) { + if (r->metric != metric) + need_update = TRUE; + num++; + } + if (!need_update) + return; + + routes = g_new (NMPlatformIP6Route, num); + nm_ip_config_iter_ip6_route_for_each (&iter, self, &r) { + routes[i] = *r; + routes[i].metric = metric; + i++; + } + + g_object_freeze_notify (G_OBJECT (self)); + nm_ip6_config_reset_routes (self); + for (i = 0; i < num; i++) + nm_ip6_config_add_route (self, &routes[i], NULL); + g_object_thaw_notify (G_OBJECT (self)); +} + +void nm_ip6_config_add_dependent_routes (NMIP6Config *self, guint32 route_table, guint32 route_metric) diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 9762ef48..b8e80410 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -224,4 +224,6 @@ void nm_ip6_config_reset_routes_ndisc (NMIP6Config *self, guint32 route_metric, gboolean kernel_support_rta_pref); +void nm_ip6_config_update_routes_metric (NMIP6Config *self, gint64 metric); + #endif /* __NETWORKMANAGER_IP6_CONFIG_H__ */ diff --git a/src/nm-manager.c b/src/nm-manager.c index 289dcf83..ad906169 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -3008,10 +3008,21 @@ platform_link_added (NMManager *self, continue; if (nm_device_is_real (candidate)) { - /* Ignore the link added event since there's already a realized - * device with the link's name. + /* There's already a realized device with the link's name + * and a different ifindex. */ - nm_device_update_from_platform_link (candidate, plink); + if (nm_device_get_ifindex (candidate) <= 0) + nm_device_update_from_platform_link (candidate, plink); + else { + /* The ifindex of a device can't be changed after + * initialization because it is used as a key by + * the dns-manager. + */ + _LOGD (LOGD_DEVICE, "(%s): removing old device %p after ifindex change from %d to %d", + plink->name, candidate, nm_device_get_ifindex (candidate), ifindex); + remove_device (self, candidate, FALSE, TRUE); + goto add; + } return; } else if (nm_device_realize_start (candidate, plink, @@ -3031,6 +3042,7 @@ platform_link_added (NMManager *self, /* Try next unrealized device */ } +add: /* Try registered device factories */ factory = nm_device_factory_manager_find_factory_for_link_type (plink->type); if (factory) { diff --git a/src/ppp/nm-ppp-manager.c b/src/ppp/nm-ppp-manager.c index 5e893c85..40bdea64 100644 --- a/src/ppp/nm-ppp-manager.c +++ b/src/ppp/nm-ppp-manager.c @@ -442,7 +442,7 @@ impl_ppp_manager_set_ifindex (NMDBusObject *obj, if (priv->ifindex >= 0) { _LOGW ("can't change the ifindex from %d to %d", priv->ifindex, (int) ifindex); - return; + goto out; } if (ifindex > 0) { @@ -462,7 +462,13 @@ impl_ppp_manager_set_ifindex (NMDBusObject *obj, obj_keep_alive = nmp_object_ref (NMP_OBJECT_UP_CAST (plink)); - g_signal_emit (self, signals[IFINDEX_SET], 0, ifindex, plink->name); + g_signal_emit (self, + signals[IFINDEX_SET], + 0, + ifindex, + plink ? plink->name : NULL); + +out: g_dbus_method_invocation_return_value (invocation, NULL); } diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c index 71e6a35a..e16e3130 100644 --- a/src/supplicant/nm-supplicant-interface.c +++ b/src/supplicant/nm-supplicant-interface.c @@ -111,7 +111,7 @@ typedef struct { NMSupplicantInterfaceState state; int disconnect_reason; - gboolean scanning:1; + bool scanning:1; bool scan_done_pending:1; bool scan_done_success:1; diff --git a/src/vpn/nm-vpn-connection.c b/src/vpn/nm-vpn-connection.c index ad752c4c..91acf07e 100644 --- a/src/vpn/nm-vpn-connection.c +++ b/src/vpn/nm-vpn-connection.c @@ -2686,12 +2686,16 @@ plugin_interactive_secrets_required (NMVpnConnection *self, gs_free const char **hints = NULL; gs_free char *message_hint = NULL; + if (!NM_IN_SET (priv->vpn_state, STATE_CONNECT, + STATE_NEED_AUTH)) { + _LOGD ("VPN plugin: requested secrets; state %s (%d); ignore request in current state", + vpn_state_to_string (priv->vpn_state), priv->vpn_state); + return; + } + _LOGI ("VPN plugin: requested secrets; state %s (%d)", vpn_state_to_string (priv->vpn_state), priv->vpn_state); - g_return_if_fail (priv->vpn_state == STATE_CONNECT || - priv->vpn_state == STATE_NEED_AUTH); - priv->secrets_idx = SECRETS_REQ_INTERACTIVE; _set_vpn_state (self, STATE_NEED_AUTH, NM_ACTIVE_CONNECTION_STATE_REASON_NONE, FALSE); @@ -2758,6 +2762,9 @@ dispose (GObject *object) NMVpnConnection *self = NM_VPN_CONNECTION (object); NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + if (priv->proxy) + g_signal_handlers_disconnect_by_data (priv->proxy, self); + nm_clear_g_source (&priv->start_timeout); g_clear_pointer (&priv->connect_hash, g_variant_unref); |