summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2011-06-29 18:20:23 -0500
committerDan Williams <dcbw@redhat.com>2011-06-29 18:20:23 -0500
commit0997902e483093589176f24d98e9ef8a2023851c (patch)
treeaf08d58476e37e866dfffcde2fb12a06ea21bdc9
parentbd625c03159b3a858137ab08845855dcf2aad848 (diff)
parent6187b85052644f212d12ba6f76c60c4c14f70f79 (diff)
downloadNetworkManager-f15.tar.gz
Merge remote-tracking branch 'origin/master' into f15f15
-rw-r--r--src/nm-device-wifi.c144
-rw-r--r--src/nm-policy.c47
-rw-r--r--src/supplicant-manager/nm-supplicant-interface.c18
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