diff options
author | Dan Williams <dcbw@redhat.com> | 2011-06-29 18:20:23 -0500 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2011-06-29 18:20:23 -0500 |
commit | 0997902e483093589176f24d98e9ef8a2023851c (patch) | |
tree | af08d58476e37e866dfffcde2fb12a06ea21bdc9 | |
parent | bd625c03159b3a858137ab08845855dcf2aad848 (diff) | |
parent | 6187b85052644f212d12ba6f76c60c4c14f70f79 (diff) | |
download | NetworkManager-f15.tar.gz |
Merge remote-tracking branch 'origin/master' into f15f15
-rw-r--r-- | src/nm-device-wifi.c | 144 | ||||
-rw-r--r-- | src/nm-policy.c | 47 | ||||
-rw-r--r-- | src/supplicant-manager/nm-supplicant-interface.c | 18 |
3 files changed, 128 insertions, 81 deletions
diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index b5b6d351d1..cfb30cc196 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -2462,88 +2462,86 @@ remove_link_timeout (NMDeviceWifi *self) static gboolean link_timeout_cb (gpointer user_data) { - NMDevice * dev = NM_DEVICE (user_data); - NMDeviceWifi * self = NM_DEVICE_WIFI (dev); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMActRequest * req = NULL; - NMAccessPoint * ap = NULL; - NMConnection * connection; - const char * setting_name; - gboolean auth_enforced, encrypted = FALSE; + NMDevice *dev = NM_DEVICE (user_data); - g_assert (dev); + nm_log_warn (LOGD_WIFI, "(%s): link timed out.", nm_device_get_iface (dev)); - priv->link_timeout_id = 0; - - req = nm_device_get_act_request (dev); - ap = nm_device_wifi_get_activation_ap (self); - if (req == NULL || ap == NULL) { - /* shouldn't ever happen */ - nm_log_err (LOGD_WIFI, "couldn't get activation request or activation AP."); - if (nm_device_is_activating (dev)) { - cleanup_association_attempt (self, TRUE); - nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); - } - return FALSE; - } + NM_DEVICE_WIFI_GET_PRIVATE (dev)->link_timeout_id = 0; /* Disconnect event while activated; the supplicant hasn't been able * to reassociate within the timeout period, so the connection must * fail. */ - if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) { + if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) nm_device_state_changed (dev, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT); - return FALSE; - } - /* Disconnect event during initial authentication and credentials - * ARE checked - we are likely to have wrong key. Ask the user for - * another one. + return FALSE; +} + +static gboolean +handle_authenticate_fail (NMDeviceWifi *self, guint32 new_state, guint32 old_state) +{ + NMDevice *device = NM_DEVICE (self); + NMSetting8021x *s_8021x; + NMSettingWirelessSecurity *s_wsec; + NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; + NMActRequest *req; + NMConnection *connection; + const char *setting_name = NULL; + gboolean handled = FALSE; + + g_return_val_if_fail (new_state == NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED, FALSE); + + /* Only care about ASSOCIATED -> DISCONNECTED transitions since 802.1x stuff + * happens between the ASSOCIATED and AUTHENTICATED states. */ - if (nm_device_get_state (dev) != NM_DEVICE_STATE_CONFIG) - goto time_out; + if (old_state != NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED) + return FALSE; - connection = nm_act_request_get_connection (req); - if (!connection) - goto time_out; + req = nm_device_get_act_request (NM_DEVICE (self)); + g_return_val_if_fail (req != NULL, FALSE); - auth_enforced = ap_auth_enforced (connection, ap, &encrypted); - if (!encrypted || !auth_enforced) - goto time_out; + connection = nm_act_request_get_connection (req); + g_return_val_if_fail (connection != NULL, FALSE); - /* Drivers are still just too crappy, and emit too many disassociation - * events during connection. So for now, just let the driver and supplicant - * keep trying to associate, and don't ask for new secrets when we get - * disconnected during association. + /* If it's an 802.1x or LEAP connection with "always ask"/unsaved secrets + * then we need to ask again because it might be an OTP token and the PIN + * may have changed. */ - if (0) { + s_8021x = nm_connection_get_setting_802_1x (connection); + s_wsec = nm_connection_get_setting_wireless_security (connection); + + if (s_8021x) { + nm_setting_get_secret_flags (NM_SETTING (s_8021x), + NM_SETTING_802_1X_PASSWORD, + &secret_flags, + NULL); + setting_name = NM_SETTING_802_1X_SETTING_NAME; + } else if (s_wsec) { + nm_setting_get_secret_flags (NM_SETTING (s_wsec), + NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, + &secret_flags, + NULL); + setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME; + } + + if (setting_name && (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)) { + NMSettingsGetSecretsFlags flags = NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION + | NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW; + nm_connection_clear_secrets (connection); - setting_name = nm_connection_need_secrets (connection, NULL); - if (!setting_name) - goto time_out; - /* Association/authentication failed during association, probably have a - * bad encryption key and the authenticating entity (AP, RADIUS server, etc) - * denied the association due to bad credentials. - */ nm_log_info (LOGD_DEVICE | LOGD_WIFI, "Activation (%s/wireless): disconnected during association," - " asking for new key.", nm_device_get_iface (dev)); - cleanup_association_attempt (self, TRUE); - nm_device_state_changed (dev, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); - nm_act_request_get_secrets (req, - setting_name, - NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW, - NULL, - wifi_secrets_cb, - self); + " asking for new key.", nm_device_get_iface (device)); - return FALSE; + cleanup_association_attempt (self, TRUE); + nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); + nm_act_request_get_secrets (req, setting_name, flags, NULL, wifi_secrets_cb, self); + handled = TRUE; } -time_out: - nm_log_warn (LOGD_WIFI, "(%s): link timed out.", nm_device_get_iface (dev)); - return FALSE; + return handled; } static void @@ -2612,14 +2610,20 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, break; case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED: if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) { - /* Start the link timeout so we allow some time for reauthentication, - * use a longer timeout if we are scanning since some cards take a - * while to scan. + /* Disconnect during authentication means the 802.1x password is wrong */ + if (handle_authenticate_fail (self, new_state, old_state)) + break; + } + + if (devstate == NM_DEVICE_STATE_ACTIVATED) { + /* If it's a disconnect while activated then start the link timer + * to let the supplicant reconnect for a bit and if that doesn't + * work kill the connection and try something else. Allow a bit + * more time if the card is scanning since sometimes the link will + * drop while scanning and come back when the scan is done. */ - if (!priv->link_timeout_id) { - priv->link_timeout_id = g_timeout_add_seconds (scanning ? 30 : 15, - link_timeout_cb, self); - } + if (priv->link_timeout_id == 0) + priv->link_timeout_id = g_timeout_add_seconds (scanning ? 30 : 15, link_timeout_cb, self); } break; case NM_SUPPLICANT_INTERFACE_STATE_DOWN: @@ -3583,6 +3587,10 @@ device_state_changed (NMDevice *device, } clear_aps = TRUE; break; + case NM_DEVICE_STATE_NEED_AUTH: + if (priv->supplicant.iface) + nm_supplicant_interface_disconnect (priv->supplicant.iface); + break; case NM_DEVICE_STATE_ACTIVATED: activation_success_handler (device); break; diff --git a/src/nm-policy.c b/src/nm-policy.c index f4ca93ff84..16bb0bfd92 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -66,12 +66,16 @@ struct NMPolicy { HostnameThread *lookup; + gint reset_retries_id; /* idle handler for resetting the retries count */ + char *orig_hostname; /* hostname at NM start time */ char *cur_hostname; /* hostname we want to assign */ }; #define RETRIES_TAG "autoconnect-retries" #define RETRIES_DEFAULT 4 +#define RESET_RETRIES_TIMESTAMP_TAG "reset-retries-timestamp-tag" +#define RESET_RETRIES_TIMER 300 static NMDevice * get_best_ip4_device (NMManager *manager, NMActRequest **out_req) @@ -873,6 +877,37 @@ schedule_activate_check (NMPolicy *policy, NMDevice *device, guint delay_seconds } } +static gboolean +reset_connections_retries (gpointer user_data) +{ + NMPolicy *policy = (NMPolicy *) user_data; + GSList *connections, *iter; + time_t con_stamp, min_stamp, now; + + policy->reset_retries_id = 0; + + min_stamp = now = time (NULL); + connections = nm_settings_get_connections (policy->settings); + for (iter = connections; iter; iter = g_slist_next (iter)) { + con_stamp = GPOINTER_TO_SIZE (g_object_get_data (G_OBJECT (iter->data), RESET_RETRIES_TIMESTAMP_TAG)); + if (con_stamp == 0) + continue; + if (con_stamp + RESET_RETRIES_TIMER <= now) { + set_connection_auto_retries (NM_CONNECTION (iter->data), RETRIES_DEFAULT); + g_object_set_data (G_OBJECT (iter->data), RESET_RETRIES_TIMESTAMP_TAG, GSIZE_TO_POINTER (0)); + continue; + } + if (con_stamp < min_stamp) + min_stamp = con_stamp; + } + g_slist_free (connections); + + /* Schedule the handler again if there are some stamps left */ + if (min_stamp != now) + policy->reset_retries_id = g_timeout_add_seconds (RESET_RETRIES_TIMER - (now - min_stamp), reset_connections_retries, policy); + return FALSE; +} + static NMConnection * get_device_connection (NMDevice *device) { @@ -917,8 +952,13 @@ device_state_changed (NMDevice *device, set_connection_auto_retries (connection, tries - 1); } - if (get_connection_auto_retries (connection) == 0) + if (get_connection_auto_retries (connection) == 0) { nm_log_info (LOGD_DEVICE, "Marking connection '%s' invalid.", nm_connection_get_id (connection)); + /* Schedule a handler to reset retries count */ + g_object_set_data (G_OBJECT (connection), RESET_RETRIES_TIMESTAMP_TAG, GSIZE_TO_POINTER ((gsize) time (NULL))); + if (!policy->reset_retries_id) + policy->reset_retries_id = g_timeout_add_seconds (RESET_RETRIES_TIMER, reset_connections_retries, policy); + } nm_connection_clear_secrets (connection); } schedule_activate_check (policy, device, 3); @@ -941,7 +981,7 @@ device_state_changed (NMDevice *device, update_routing_and_dns (policy, FALSE); break; case NM_DEVICE_STATE_DISCONNECTED: - /* Clear INVALID_TAG when carrier on. If cable was unplugged + /* Reset RETRIES_TAG when carrier on. If cable was unplugged * and plugged again, we should try to reconnect */ if (reason == NM_DEVICE_STATE_REASON_CARRIER && old_state == NM_DEVICE_STATE_UNAVAILABLE) reset_retries_all (policy->settings, device); @@ -1255,6 +1295,9 @@ nm_policy_destroy (NMPolicy *policy) } g_slist_free (policy->dev_ids); + if (policy->reset_retries_id) + g_source_remove (policy->reset_retries_id); + g_free (policy->orig_hostname); g_free (policy->cur_hostname); diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index e9e58f39fe..2459f589ae 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -682,12 +682,13 @@ nm_supplicant_interface_disconnect (NMSupplicantInterface * self) if (!priv->iface_proxy) return; - /* Don't try to disconnect if the supplicant interface is already disconnected */ - if ( priv->state == NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED - || priv->state == NM_SUPPLICANT_INTERFACE_STATE_INACTIVE) { - g_free (priv->net_path); - priv->net_path = NULL; - return; + /* Disconnect from the current AP */ + if ( (priv->state >= NM_SUPPLICANT_INTERFACE_STATE_SCANNING) + && (priv->state <= NM_SUPPLICANT_INTERFACE_STATE_COMPLETED)) { + dbus_g_proxy_begin_call (priv->iface_proxy, "Disconnect", + disconnect_cb, + NULL, NULL, + G_TYPE_INVALID); } /* Remove any network that was added by NetworkManager */ @@ -700,11 +701,6 @@ nm_supplicant_interface_disconnect (NMSupplicantInterface * self) g_free (priv->net_path); priv->net_path = NULL; } - - dbus_g_proxy_begin_call (priv->iface_proxy, "Disconnect", - disconnect_cb, - NULL, NULL, - G_TYPE_INVALID); } static void |