diff --git a/ChangeLog b/ChangeLog index 579e277bd..3235c43de 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2005-01-21 Dan Williams + + * Cache last-known-good wireless authentication method in + NetworkManagerInfo, and use that method first during + wireless device activation. Should speed up devices that + need Shared Key authentication method since Open System is + now the default. + + * Remove the hack to not do full activation on wired connections + that are active when we launch, it causes too many problems + with name resolution and was a hack in the first place. + + * Re-work wireless device activation again somewhat to have a + clearer chain of events and to use last-known-good + authentication method of the access point. Also provide + better status throughout activation to ensure the applet + can tell the user exactly what's going on. + + * Remove the "find wireless network" code and now simply attempt + to activate with that access point. This reduces the delay + between selecting "Other wireless Network" and actually + connecting to that network. + + * Correctly stop the device's worker thread when its removed. + 2005-01-21 Dan Williams * dhcpcd/client.c diff --git a/NetworkManager.h b/NetworkManager.h index e51e5efa9..08e4de4c2 100644 --- a/NetworkManager.h +++ b/NetworkManager.h @@ -104,6 +104,18 @@ typedef enum NMNetworkMode } NMNetworkMode; +/* + * Authentication modes + */ +typedef enum NMDeviceAuthMethod +{ + NM_DEVICE_AUTH_METHOD_UNKNOWN = 0, + NM_DEVICE_AUTH_METHOD_NONE, + NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM, + NM_DEVICE_AUTH_METHOD_SHARED_KEY +} NMDeviceAuthMethod; + + /* * Info-daemon specific preference locations */ diff --git a/info-daemon/NetworkManagerInfoDbus.c b/info-daemon/NetworkManagerInfoDbus.c index e7ad19df2..e36ca72e1 100644 --- a/info-daemon/NetworkManagerInfoDbus.c +++ b/info-daemon/NetworkManagerInfoDbus.c @@ -352,6 +352,7 @@ static DBusMessage *nmi_dbus_get_network_properties (NMIAppInfo *info, DBusMessa char *key = NULL; NMEncKeyType key_type = -1; gboolean trusted = FALSE; + NMDeviceAuthMethod auth_method = NM_DEVICE_AUTH_METHOD_UNKNOWN; g_return_val_if_fail (info != NULL, NULL); g_return_val_if_fail (message != NULL, NULL); @@ -405,6 +406,15 @@ static DBusMessage *nmi_dbus_get_network_properties (NMIAppInfo *info, DBusMessa } g_free (gconf_key); + /* Grab the network's last authentication mode, if known */ + gconf_key = g_strdup_printf ("%s/%s/auth_method", NMI_GCONF_WIRELESS_NETWORKS_PATH, escaped_network); + if ((value = gconf_client_get (info->gconf_client, gconf_key, NULL))) + { + auth_method = gconf_value_get_int (value); + gconf_value_free (value); + } + g_free (gconf_key); + /* Grab the network's trusted status */ gconf_key = g_strdup_printf ("%s/%s/trusted", NMI_GCONF_WIRELESS_NETWORKS_PATH, escaped_network); if ((value = gconf_client_get (info->gconf_client, gconf_key, NULL))) @@ -451,6 +461,7 @@ static DBusMessage *nmi_dbus_get_network_properties (NMIAppInfo *info, DBusMessa dbus_message_iter_append_int32 (&iter, timestamp); dbus_message_iter_append_string (&iter, key); dbus_message_iter_append_int32 (&iter, key_type); + dbus_message_iter_append_int32 (&iter, auth_method); dbus_message_iter_append_boolean(&iter, trusted); dbus_message_iter_append_array (&iter, &iter_array, DBUS_TYPE_STRING); @@ -487,6 +498,54 @@ static DBusMessage *nmi_dbus_get_network_properties (NMIAppInfo *info, DBusMessa } +/* + * nmi_dbus_update_network_auth_method + * + * Update a network's authentication method entry in gconf + * + */ +static DBusMessage *nmi_dbus_update_network_auth_method (NMIAppInfo *info, DBusMessage *message) +{ + DBusMessage *reply_message = NULL; + char *network = NULL; + NMDeviceAuthMethod auth_method = NM_DEVICE_AUTH_METHOD_UNKNOWN; + char *key; + GConfValue *value; + DBusError error; + char *escaped_network; + + g_return_val_if_fail (info != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + + dbus_error_init (&error); + if ( !dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &network, DBUS_TYPE_INT32, &auth_method, DBUS_TYPE_INVALID) + || (strlen (network) <= 0) + || (auth_method == NM_DEVICE_AUTH_METHOD_UNKNOWN)) + { + reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "InvalidArguments", + "NetworkManagerInfo::updateNetworkAuthMethod called with invalid arguments."); + return (reply_message); + } + + /* Ensure the access point exists in GConf */ + escaped_network = gconf_escape_key (network, strlen (network)); + key = g_strdup_printf ("%s/%s/essid", NMI_GCONF_WIRELESS_NETWORKS_PATH, escaped_network); + value = gconf_client_get (info->gconf_client, key, NULL); + g_free (key); + + if (value && (value->type == GCONF_VALUE_STRING)) + { + key = g_strdup_printf ("%s/%s/auth_method", NMI_GCONF_WIRELESS_NETWORKS_PATH, escaped_network); + gconf_client_set_int (info->gconf_client, key, auth_method, NULL); + g_free (key); + } + + g_free (escaped_network); + + return (NULL); +} + + /* * nmi_dbus_add_network_address * @@ -626,6 +685,8 @@ static DBusHandlerResult nmi_dbus_nmi_message_handler (DBusConnection *connectio reply_message = nmi_dbus_get_networks (info, message); else if (strcmp ("getNetworkProperties", method) == 0) reply_message = nmi_dbus_get_network_properties (info, message); + else if (strcmp ("updateNetworkAuthMethod", method) == 0) + nmi_dbus_update_network_auth_method (info, message); else if (strcmp ("addNetworkAddress", method) == 0) nmi_dbus_add_network_address (info, message); else diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 98a740c58..0c7dcf2ba 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -128,18 +128,11 @@ NMDevice * nm_create_device_and_add_to_list (NMData *data, const char *udi, cons nm_device_get_iface (dev), nm_device_is_wireless (dev) ? "wireless" : "wired"); data->dev_list = g_slist_append (data->dev_list, dev); - - /* We don't take down wired devices that are already set up when NetworkManager gets - * launched. Plays better with the system. - * - * FIXME: IPv6 here too - */ - if (!(data->starting_up && nm_device_is_wired (dev) && nm_device_get_ip4_address (dev))) - nm_device_deactivate (dev, TRUE); + nm_device_deactivate (dev, TRUE); nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__); - nm_data_mark_state_changed (data); + nm_policy_schedule_state_update (data); nm_dbus_signal_device_status_change (data->dbus_connection, dev, DEVICE_LIST_CHANGE); } else @@ -187,20 +180,16 @@ void nm_remove_device_from_list (NMData *data, const char *udi) data->active_device_locked = FALSE; } - if (data->user_device && (dev == data->user_device)) - { - nm_device_unref (data->user_device); - data->user_device = NULL; - } - - nm_device_activation_cancel (dev); + nm_device_set_removed (dev, TRUE); + nm_device_deactivate (dev, FALSE); + nm_device_worker_thread_stop (dev); nm_device_unref (dev); /* Remove the device entry from the device list and free its data */ data->dev_list = g_slist_remove_link (data->dev_list, element); nm_device_unref (element->data); g_slist_free (element); - nm_data_mark_state_changed (data); + nm_policy_schedule_state_update (data); nm_dbus_signal_device_status_change (data->dbus_connection, dev, DEVICE_LIST_CHANGE); break; } @@ -351,7 +340,7 @@ static void nm_hal_device_property_modified (LibHalContext *ctx, const char *udi && nm_device_is_wireless (data->active_device)) { data->active_device_locked = FALSE; - nm_data_mark_state_changed (data); + nm_policy_schedule_state_update (data); } } nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__); @@ -529,10 +518,6 @@ static NMData *nm_data_new (gboolean enable_test_devices) data->main_context = g_main_context_new (); data->main_loop = g_main_loop_new (data->main_context, FALSE); - data->wscan_ctx = g_main_context_new (); - data->wscan_loop = g_main_loop_new (data->wscan_ctx, FALSE); - data->wscan_thread_done = FALSE; - if (pipe(data->sigterm_pipe) < 0) { syslog (LOG_CRIT, "Couldn't create pipe: %s", g_strerror (errno)); @@ -556,8 +541,7 @@ static NMData *nm_data_new (gboolean enable_test_devices) /* Initialize the device list mutex to protect additions/deletions to it. */ data->dev_list_mutex = g_mutex_new (); - data->user_device_mutex = g_mutex_new (); - if (!data->dev_list_mutex || !data->user_device_mutex) + if (!data->dev_list_mutex) { nm_data_free (data); syslog (LOG_ERR, "Could not initialize data structure locks."); @@ -577,9 +561,8 @@ static NMData *nm_data_new (gboolean enable_test_devices) data->state_modified_idle_id = 0; data->enable_test_devices = enable_test_devices; - data->starting_up = TRUE; - nm_data_mark_state_changed (data); + nm_policy_schedule_state_update (data); return (data); } @@ -602,7 +585,6 @@ static void nm_data_free (NMData *data) g_slist_free (data->dev_list); g_mutex_free (data->dev_list_mutex); - g_mutex_free (data->user_device_mutex); nm_ap_list_unref (data->allowed_ap_list); nm_ap_list_unref (data->invalid_ap_list); @@ -614,30 +596,6 @@ static void nm_data_free (NMData *data) } -/* - * nm_data_mark_state_changed - * - * Queue up an idle handler to deal with state changes. - * - */ -void nm_data_mark_state_changed (NMData *data) -{ - static GStaticMutex mutex = G_STATIC_MUTEX_INIT; - - g_return_if_fail (data != NULL); - - g_static_mutex_lock (&mutex); - if (data->state_modified_idle_id == 0) - { - GSource *source = g_idle_source_new (); - - g_source_set_callback (source, nm_state_modification_monitor, data, NULL); - data->state_modified_idle_id = g_source_attach (source, data->main_context); - g_source_unref (source); - } - g_static_mutex_unlock (&mutex); -} - static void sigterm_handler (int signum) { syslog (LOG_NOTICE, "Caught SIGINT/SIGTERM"); diff --git a/src/NetworkManagerAP.c b/src/NetworkManagerAP.c index d56ba3800..5b9dc2cf3 100644 --- a/src/NetworkManagerAP.c +++ b/src/NetworkManagerAP.c @@ -48,7 +48,8 @@ struct NMAccessPoint /* Things from user prefs/NetworkManagerInfo */ gboolean trusted; char *enc_key; - NMEncKeyType enc_method; + NMEncKeyType enc_type; + NMDeviceAuthMethod auth_method; GTimeVal timestamp; GSList *user_addresses; }; @@ -71,6 +72,7 @@ NMAccessPoint * nm_ap_new (void) } ap->mode = NETWORK_MODE_INFRA; + ap->auth_method = NM_DEVICE_AUTH_METHOD_UNKNOWN; ap->refcount = 1; return (ap); @@ -207,7 +209,7 @@ char * nm_ap_get_enc_key_source (const NMAccessPoint *ap) return (ap->enc_key); } -void nm_ap_set_enc_key_source (NMAccessPoint *ap, const char * key, NMEncKeyType method) +void nm_ap_set_enc_key_source (NMAccessPoint *ap, const char * key, NMEncKeyType type) { g_return_if_fail (ap != NULL); @@ -215,7 +217,7 @@ void nm_ap_set_enc_key_source (NMAccessPoint *ap, const char * key, NMEncKeyType g_free (ap->enc_key); ap->enc_key = g_strdup (key); - ap->enc_method = method; + ap->enc_type = type; } char *nm_ap_get_enc_key_hashed (const NMAccessPoint *ap) @@ -226,7 +228,7 @@ char *nm_ap_get_enc_key_hashed (const NMAccessPoint *ap) g_return_val_if_fail (ap != NULL, NULL); source_key = nm_ap_get_enc_key_source (ap); - switch (ap->enc_method) + switch (ap->enc_type) { case (NM_ENC_TYPE_128_BIT_PASSPHRASE): if (source_key) @@ -273,6 +275,37 @@ void nm_ap_set_encrypted (NMAccessPoint *ap, gboolean encrypted) } +/* + * Return the encryption method the user specified for this access point. + * + */ +const NMEncKeyType nm_ap_get_enc_type (const NMAccessPoint *ap) +{ + g_return_val_if_fail (ap != NULL, TRUE); + + return (ap->enc_type); +} + + +/* + * Get/set functions for auth_method + * + */ +NMDeviceAuthMethod nm_ap_get_auth_method (const NMAccessPoint *ap) +{ + g_return_val_if_fail (ap != NULL, NM_DEVICE_AUTH_METHOD_UNKNOWN); + + return (ap->auth_method); +} + +void nm_ap_set_auth_method (NMAccessPoint *ap, NMDeviceAuthMethod auth_method) +{ + g_return_if_fail (ap != NULL); + + ap->auth_method = auth_method; +} + + /* * Get/set functions for address * @@ -501,18 +534,6 @@ void nm_ap_set_user_created (NMAccessPoint *ap, gboolean user_created) } -/* - * Return the encryption method the user specified for this access point. - * - */ -const NMEncKeyType nm_ap_get_enc_method (const NMAccessPoint *ap) -{ - g_return_val_if_fail (ap != NULL, TRUE); - - return (ap->enc_method); -} - - /* * Get/Set functions for user address list * @@ -569,3 +590,30 @@ void nm_ap_set_user_addresses (NMAccessPoint *ap, GSList *list) ap->user_addresses = new; } + +gboolean nm_ap_is_enc_key_valid (NMAccessPoint *ap) +{ + const char *key; + NMEncKeyType key_type; + + g_return_val_if_fail (ap != NULL, FALSE); + + key = nm_ap_get_enc_key_source (ap); + key_type = nm_ap_get_enc_type (ap); + + if (nm_is_enc_key_valid (key, key_type)) + return TRUE; + + return FALSE; +} + +gboolean nm_is_enc_key_valid (const char *key, NMEncKeyType key_type) +{ + if ( key + && strlen (key) + && (key_type != NM_ENC_TYPE_UNKNOWN) + && (key_type != NM_ENC_TYPE_NONE)) + return TRUE; + + return FALSE; +} diff --git a/src/NetworkManagerAP.h b/src/NetworkManagerAP.h index c38059aae..2d32aee43 100644 --- a/src/NetworkManagerAP.h +++ b/src/NetworkManagerAP.h @@ -43,6 +43,10 @@ void nm_ap_set_essid (NMAccessPoint *ap, const char *essid); char * nm_ap_get_enc_key_source (const NMAccessPoint *ap); char * nm_ap_get_enc_key_hashed (const NMAccessPoint *ap); void nm_ap_set_enc_key_source (NMAccessPoint *ap, const char *key, NMEncKeyType type); +const NMEncKeyType nm_ap_get_enc_type (const NMAccessPoint *ap); + +NMDeviceAuthMethod nm_ap_get_auth_method (const NMAccessPoint *ap); +void nm_ap_set_auth_method (NMAccessPoint *ap, const NMDeviceAuthMethod auth_method); gboolean nm_ap_get_encrypted (const NMAccessPoint *ap); void nm_ap_set_encrypted (NMAccessPoint *ap, gboolean encrypted); @@ -80,9 +84,11 @@ void nm_ap_set_last_seen (NMAccessPoint *ap, const GTimeVal *last_seen); gboolean nm_ap_get_user_created (const NMAccessPoint *ap); void nm_ap_set_user_created (NMAccessPoint *ap, gboolean user_created); -const NMEncKeyType nm_ap_get_enc_method (const NMAccessPoint *ap); - GSList * nm_ap_get_user_addresses (const NMAccessPoint *ap); void nm_ap_set_user_addresses (NMAccessPoint *ap, GSList *list); +/* Helper */ +gboolean nm_ap_is_enc_key_valid (NMAccessPoint *ap); +gboolean nm_is_enc_key_valid (const char *key, NMEncKeyType key_type); + #endif diff --git a/src/NetworkManagerAPList.c b/src/NetworkManagerAPList.c index 42d54c7ff..bf46dac72 100644 --- a/src/NetworkManagerAPList.c +++ b/src/NetworkManagerAPList.c @@ -312,15 +312,16 @@ void nm_ap_list_update_network_from_nmi (NMAccessPointList *list, const char *ne nm_ap_set_essid (list_ap, nm_ap_get_essid (ap)); nm_ap_set_timestamp (list_ap, nm_ap_get_timestamp (ap)); nm_ap_set_trusted (list_ap, nm_ap_get_trusted (ap)); - nm_ap_set_enc_key_source (list_ap, nm_ap_get_enc_key_source (ap), nm_ap_get_enc_method (ap)); + nm_ap_set_enc_key_source (list_ap, nm_ap_get_enc_key_source (ap), nm_ap_get_enc_type (ap)); + nm_ap_set_auth_method (list_ap, nm_ap_get_auth_method (ap)); nm_ap_set_user_addresses (list_ap, nm_ap_get_user_addresses (ap)); } else { /* New AP, just add it to the list */ nm_ap_list_append_ap (list, ap); - nm_ap_unref (ap); } + nm_ap_unref (ap); } else { @@ -387,6 +388,7 @@ gboolean nm_ap_list_merge_scanned_ap (NMAccessPointList *list, NMAccessPoint *me { /* Merge some properties on the AP that are new from scan to scan. */ nm_ap_set_encrypted (list_ap, nm_ap_get_encrypted (merge_ap)); + nm_ap_set_auth_method (list_ap, nm_ap_get_auth_method (merge_ap)); nm_ap_set_last_seen (list_ap, nm_ap_get_last_seen (merge_ap)); } else @@ -425,7 +427,17 @@ void nm_ap_list_copy_properties (NMAccessPointList *dest, NMAccessPointList *sou if ((src_ap = nm_ap_list_get_ap_by_essid (source, nm_ap_get_essid (dest_ap)))) { nm_ap_set_invalid (dest_ap, nm_ap_get_invalid (src_ap)); - nm_ap_set_enc_key_source (dest_ap, nm_ap_get_enc_key_source (src_ap), nm_ap_get_enc_method (src_ap)); + nm_ap_set_enc_key_source (dest_ap, nm_ap_get_enc_key_source (src_ap), nm_ap_get_enc_type (src_ap)); + if (nm_ap_get_auth_method (src_ap) != NM_DEVICE_AUTH_METHOD_UNKNOWN) + { + /* Ensure that we don't set the NONE auth method from the src_ap + * if the dest_ap has encryption enabled. + */ + if (nm_ap_get_encrypted (dest_ap) && (nm_ap_get_auth_method (src_ap) != NM_DEVICE_AUTH_METHOD_NONE)) + nm_ap_set_auth_method (dest_ap, nm_ap_get_auth_method (src_ap)); + else if (!nm_ap_get_encrypted (dest_ap)) + nm_ap_set_auth_method (dest_ap, NM_DEVICE_AUTH_METHOD_NONE); + } nm_ap_set_timestamp (dest_ap, nm_ap_get_timestamp (src_ap)); } } diff --git a/src/NetworkManagerDHCP.c b/src/NetworkManagerDHCP.c index ef46d982e..e9ee81c54 100644 --- a/src/NetworkManagerDHCP.c +++ b/src/NetworkManagerDHCP.c @@ -30,6 +30,7 @@ #include "NetworkManagerDevicePrivate.h" #include "NetworkManagerDHCP.h" #include "NetworkManagerSystem.h" +#include "NetworkManagerPolicy.h" #include "nm-named-manager.h" #include "../dhcpcd/client.h" @@ -344,7 +345,7 @@ gboolean nm_device_dhcp_rebind (gpointer user_data) */ nm_system_device_flush_addresses (dev); nm_device_update_ip4_address (dev); - nm_data_mark_state_changed (dev->app_data); + nm_policy_schedule_state_update (dev->app_data); return (FALSE); } else diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index a32e03425..7eb30d05a 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -33,6 +33,7 @@ #include "NetworkManagerDbus.h" #include "NetworkManagerAP.h" #include "NetworkManagerAPList.h" +#include "NetworkManagerPolicy.h" static int test_dev_num = 0; @@ -196,6 +197,12 @@ static DBusMessage *nm_dbus_nm_get_active_device (DBusConnection *connection, DB } +typedef struct NMNetNotFoundData +{ + NMData *app_data; + char *net; +} NMNetNotFoundData; + /* * nm_dbus_send_network_not_found * @@ -203,26 +210,52 @@ static DBusMessage *nm_dbus_nm_get_active_device (DBusConnection *connection, DB * not found. * */ -void nm_dbus_send_network_not_found (DBusConnection *connection, const char *network) +static gboolean nm_dbus_send_network_not_found (gpointer user_data) { + NMNetNotFoundData *cb_data = (NMNetNotFoundData *)user_data; DBusMessage *message; - g_return_if_fail (connection != NULL); - g_return_if_fail (network != NULL); + g_return_val_if_fail (cb_data != NULL, FALSE); + + if (!cb_data->app_data || !cb_data->app_data->dbus_connection || !cb_data->net) + goto out; message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "networkNotFound"); if (message == NULL) { syslog (LOG_ERR, "nm_dbus_send_network_not_found(): Couldn't allocate the dbus message"); - return; + goto out; } - dbus_message_append_args (message, DBUS_TYPE_STRING, network, DBUS_TYPE_INVALID); - if (!dbus_connection_send (connection, message, NULL)) + dbus_message_append_args (message, DBUS_TYPE_STRING, cb_data->net, DBUS_TYPE_INVALID); + if (!dbus_connection_send (cb_data->app_data->dbus_connection, message, NULL)) syslog (LOG_WARNING, "nm_dbus_send_network_not_found(): could not send dbus message"); dbus_message_unref (message); + +out: + g_free (cb_data); + return (FALSE); +} + + +void nm_dbus_schedule_network_not_found_signal (NMData *data, const char *network) +{ + NMNetNotFoundData *cb_data; + GSource *source; + + g_return_if_fail (data != NULL); + g_return_if_fail (network != NULL); + + cb_data = g_malloc0 (sizeof (NMNetNotFoundData)); + cb_data->app_data = data; + cb_data->net = g_strdup (network); + + source = g_idle_source_new (); + g_source_set_callback (source, nm_dbus_send_network_not_found, cb_data, NULL); + g_source_attach (source, data->main_context); + g_source_unref (source); } @@ -269,19 +302,18 @@ static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DB reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "InvalidArguments", "NetworkManager::setActiveDevice called with invalid arguments."); - return (reply_message); + goto out; } else syslog (LOG_INFO, "FORCE: device '%s'", dev_path); } else syslog (LOG_INFO, "FORCE: device '%s', network '%s'", dev_path, network); /* So by now we have a valid device and possibly a network as well */ dev = nm_dbus_get_device_from_object_path (data, dev_path); - dbus_free (dev_path); if (!dev || (nm_device_get_driver_support_level (dev) == NM_DRIVER_UNSUPPORTED)) { reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound", "The requested network device does not exist."); - return (reply_message); + goto out; } nm_device_ref (dev); @@ -293,37 +325,14 @@ static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DB goto out; } - if (!(reply_message = dbus_message_new_method_return (message))) - goto out; - - /* If the user specificed a wireless network too, force that as well */ - if (nm_device_is_wireless (dev) && !nm_device_find_and_use_essid (dev, network, key, key_type)) - { - nm_dbus_send_network_not_found (data->dbus_connection, network); - } - else - { - if (nm_try_acquire_mutex (data->user_device_mutex, __FUNCTION__)) - { - if (data->user_device) - nm_device_unref (data->user_device); - data->user_device = dev; - nm_device_ref (data->user_device); - nm_unlock_mutex (data->user_device_mutex, __FUNCTION__); - } - else - nm_dbus_send_network_not_found (data->dbus_connection, network); - } - - /* Have to mark our state changed since we blew away our connection trying out - * the user-requested network. - */ - nm_data_mark_state_changed (data); + data->forcing_device = TRUE; + nm_device_deactivate (dev, FALSE); + nm_device_schedule_force_use (dev, network, key, key_type); out: + dbus_free (dev_path); dbus_free (network); dbus_free (key); - nm_device_unref (dev); return (reply_message); } @@ -339,6 +348,7 @@ static DBusMessage *nm_dbus_nm_create_wireless_network (DBusConnection *connecti NMDevice *dev = NULL; DBusMessage *reply_message = NULL; char *dev_path = NULL; + NMAccessPoint *new_ap = NULL; char *network = NULL; char *key = NULL; int key_type = -1; @@ -380,37 +390,27 @@ static DBusMessage *nm_dbus_nm_create_wireless_network (DBusConnection *connecti if (!(reply_message = dbus_message_new_method_return (message))) goto out; - /* If the user specificed a wireless network too, force that as well */ - if (nm_try_acquire_mutex (data->user_device_mutex, __FUNCTION__)) + data->forcing_device = TRUE; + + new_ap = nm_ap_new (); + + /* Fill in the description of the network to create */ + nm_ap_set_essid (new_ap, network); + if (nm_is_enc_key_valid (key, key_type)) { - NMAccessPoint *ap = nm_ap_new (); - - /* Fill in the description of the network to create */ - nm_ap_set_essid (ap, network); - if (key && strlen (key)) - { - nm_ap_set_encrypted (ap, TRUE); - nm_ap_set_enc_key_source (ap, key, key_type); - } - nm_ap_set_mode (ap, NETWORK_MODE_ADHOC); - nm_ap_set_user_created (ap, TRUE); - - nm_device_set_best_ap (dev, ap); - nm_device_freeze_best_ap (dev); - nm_device_activation_cancel (dev); - - if (data->user_device) - nm_device_unref (data->user_device); - data->user_device = dev; - nm_device_ref (data->user_device); - - nm_unlock_mutex (data->user_device_mutex, __FUNCTION__); + nm_ap_set_encrypted (new_ap, TRUE); + nm_ap_set_enc_key_source (new_ap, key, key_type); + nm_ap_set_auth_method (new_ap, NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM); } + nm_ap_set_mode (new_ap, NETWORK_MODE_ADHOC); + nm_ap_set_user_created (new_ap, TRUE); - /* Have to mark our state changed since we blew away our connection trying out - * the user-requested network. - */ - nm_data_mark_state_changed (data); + nm_device_set_best_ap (dev, new_ap); + nm_device_freeze_best_ap (dev); + nm_device_activation_cancel (dev); + + /* Schedule this device to be used next. */ + nm_policy_schedule_device_switch (dev, data); out: dbus_free (network); @@ -490,6 +490,53 @@ static DBusMessage *nm_dbus_nm_get_devices (DBusConnection *connection, DBusMess /* Handler code */ /*-------------------------------------------------------------*/ +typedef struct NMStatusChangeData +{ + NMDevice *dev; + DeviceStatus status; +} NMStatusChangeData; + + +static gboolean nm_dbus_device_status_change_helper (gpointer user_data) +{ + NMStatusChangeData *data = (NMStatusChangeData *)user_data; + NMData *app_data; + + g_return_val_if_fail (data != NULL, FALSE); + + if (!data->dev || !nm_device_get_app_data (data->dev)) + goto out; + + app_data = nm_device_get_app_data (data->dev); + nm_dbus_signal_device_status_change (app_data->dbus_connection, data->dev, data->status); + +out: + g_free (data); + return FALSE; +} + +void nm_dbus_schedule_device_status_change (NMDevice *dev, DeviceStatus status) +{ + NMStatusChangeData *data = NULL; + GSource *source; + guint source_id = 0; + NMData *app_data; + + g_return_if_fail (dev != NULL); + + app_data = nm_device_get_app_data (dev); + g_return_if_fail (app_data != NULL); + + data = g_malloc0 (sizeof (NMStatusChangeData)); + data->dev = dev; + data->status = status; + + source = g_idle_source_new (); + g_source_set_callback (source, nm_dbus_device_status_change_helper, data, NULL); + source_id = g_source_attach (source, app_data->main_context); + g_source_unref (source); +} + /* * nm_dbus_signal_device_status_change @@ -525,6 +572,9 @@ void nm_dbus_signal_device_status_change (DBusConnection *connection, NMDevice * case (DEVICE_LIST_CHANGE): signal = "DevicesChanged"; break; + case (DEVICE_STATUS_CHANGE): + signal = "DeviceStatusChanged"; + break; case (DEVICE_ACTIVATION_FAILED): signal = "DeviceActivationFailed"; break; @@ -573,9 +623,11 @@ static char *nm_dbus_network_status_from_data (NMData *data) g_return_val_if_fail (data != NULL, NULL); - if (data->active_device && nm_device_is_activating (data->active_device)) + if (data->forcing_device) + status = g_strdup ("scanning"); + else if (data->active_device && nm_device_is_activating (data->active_device)) { - if (nm_device_is_wireless (data->active_device) && nm_device_is_scanning (data->active_device)) + if (nm_device_is_wireless (data->active_device) && nm_device_get_now_scanning (data->active_device)) status = g_strdup ("scanning"); else status = g_strdup ("connecting"); @@ -826,6 +878,7 @@ NMAccessPoint *nm_dbus_get_network_object (DBusConnection *connection, NMNetwork char *key = NULL; NMEncKeyType key_type = -1; gboolean trusted = FALSE; + NMDeviceAuthMethod auth_method = NM_DEVICE_AUTH_METHOD_UNKNOWN; char **addrs = NULL; gint num_addr = -1; @@ -866,6 +919,7 @@ NMAccessPoint *nm_dbus_get_network_object (DBusConnection *connection, NMNetwork DBUS_TYPE_INT32, ×tamp_secs, DBUS_TYPE_STRING, &key, DBUS_TYPE_INT32, &key_type, + DBUS_TYPE_INT32, &auth_method, DBUS_TYPE_BOOLEAN, &trusted, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &addrs, &num_addr, DBUS_TYPE_INVALID); @@ -889,6 +943,7 @@ NMAccessPoint *nm_dbus_get_network_object (DBusConnection *connection, NMNetwork nm_ap_set_enc_key_source (ap, key, key_type); else nm_ap_set_enc_key_source (ap, NULL, NM_ENC_TYPE_UNKNOWN); + nm_ap_set_auth_method (ap, auth_method); /* Get user addresses, form into a GSList, and stuff into the AP */ { @@ -923,6 +978,48 @@ out: } +/* + * nm_dbus_update_network_auth_method + * + * Tell NetworkManagerInfo the updated auth_method of the AP + * + */ +gboolean nm_dbus_update_network_auth_method (DBusConnection *connection, const char *network, const NMDeviceAuthMethod auth_method) +{ + DBusMessage *message; + DBusError error; + gboolean success = FALSE; + + g_return_val_if_fail (connection != NULL, FALSE); + g_return_val_if_fail (network != NULL, FALSE); + g_return_val_if_fail (auth_method != NM_DEVICE_AUTH_METHOD_UNKNOWN, FALSE); + + message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "updateNetworkAuthMethod"); + if (!message) + { + syslog (LOG_ERR, "nm_dbus_update_network_auth_method (): Couldn't allocate the dbus message"); + return (FALSE); + } + + dbus_message_append_args (message, DBUS_TYPE_STRING, network, + DBUS_TYPE_INT32, (int)auth_method, + DBUS_TYPE_INVALID); + + /* Send message and get trusted status back from NetworkManagerInfo */ + dbus_error_init (&error); + if (!dbus_connection_send (connection, message, NULL)) + { + syslog (LOG_ERR, "nm_dbus_update_network_auth_method (): failed to send dbus message."); + dbus_error_free (&error); + } + else + success = TRUE; + + dbus_message_unref (message); + return (success); +} + + /* * nm_dbus_add_network_address * @@ -1076,7 +1173,7 @@ static DBusHandlerResult nm_dbus_nmi_filter (DBusConnection *connection, DBusMes { data->update_ap_lists = TRUE; data->info_daemon_avail = TRUE; - nm_data_mark_state_changed (data); + nm_policy_schedule_state_update (data); } /* Don't set handled = TRUE since other filter functions on this dbus connection * may want to know about service signals. @@ -1093,7 +1190,7 @@ static DBusHandlerResult nm_dbus_nmi_filter (DBusConnection *connection, DBusMes { data->update_ap_lists = TRUE; data->info_daemon_avail = FALSE; - nm_data_mark_state_changed (data); + nm_policy_schedule_state_update (data); } /* Don't set handled = TRUE since other filter functions on this dbus connection * may want to know about service signals. @@ -1322,7 +1419,7 @@ static DBusMessage *nm_dbus_devices_handle_request (DBusConnection *connection, if (dbus_message_get_args (message, &error, DBUS_TYPE_BOOLEAN, &link, DBUS_TYPE_INVALID)) { nm_device_set_link_active (dev, link); - nm_data_mark_state_changed (data); + nm_policy_schedule_state_update (data); } } else diff --git a/src/NetworkManagerDbus.h b/src/NetworkManagerDbus.h index acecf5842..aa16d4358 100644 --- a/src/NetworkManagerDbus.h +++ b/src/NetworkManagerDbus.h @@ -35,7 +35,9 @@ typedef enum DEVICE_NO_LONGER_ACTIVE, DEVICE_ACTIVATING, DEVICE_ACTIVATION_FAILED, - DEVICE_LIST_CHANGE + DEVICE_ACTIVATION_CANCELED, + DEVICE_LIST_CHANGE, + DEVICE_STATUS_CHANGE } DeviceStatus; @@ -43,11 +45,12 @@ DBusConnection *nm_dbus_init (NMData *data); gboolean nm_dbus_is_info_daemon_running (DBusConnection *connection); +void nm_dbus_schedule_device_status_change (NMDevice *dev, DeviceStatus status); void nm_dbus_signal_device_status_change (DBusConnection *connection, NMDevice *dev, DeviceStatus status); -void nm_dbus_signal_network_status_change (DBusConnection *connection, NMData *data); +void nm_dbus_schedule_network_not_found_signal (NMData *data, const char *network); -void nm_dbus_signal_devices_changed (DBusConnection *connection); +void nm_dbus_signal_network_status_change (DBusConnection *connection, NMData *data); void nm_dbus_signal_device_ip4_address_change(DBusConnection *connection, NMDevice *dev); @@ -61,6 +64,8 @@ NMAccessPoint *nm_dbus_get_network_object (DBusConnection *connection, NMNetwo gboolean nm_dbus_add_network_address (DBusConnection *connection, NMNetworkType type, const char *network, struct ether_addr *addr); +gboolean nm_dbus_update_network_auth_method (DBusConnection *connection, const char *network, const NMDeviceAuthMethod auth_method); + char ** nm_dbus_get_networks (DBusConnection *connection, NMNetworkType type, int *num_networks); #endif diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c index 65878e10d..01cbba83c 100644 --- a/src/NetworkManagerDevice.c +++ b/src/NetworkManagerDevice.c @@ -432,6 +432,16 @@ static gpointer nm_device_worker (gpointer user_data) } +void nm_device_worker_thread_stop (NMDevice *dev) +{ + g_return_if_fail (dev != NULL); + + g_main_loop_quit (dev->loop); + while (dev->worker_done == FALSE) + g_usleep (G_USEC_PER_SEC / 2); +} + + /* * nm_device_get_app_data * @@ -444,6 +454,24 @@ NMData *nm_device_get_app_data (const NMDevice *dev) } +/* + * Get/Set for "removed" flag + */ +gboolean nm_device_get_removed (const NMDevice *dev) +{ + g_return_val_if_fail (dev != NULL, TRUE); + + return (dev->removed); +} + +void nm_device_set_removed (NMDevice *dev, const gboolean removed) +{ + g_return_if_fail (dev != NULL); + + dev->removed = removed; +} + + /* * nm_device_open_sock * @@ -579,6 +607,31 @@ void nm_device_set_link_active (NMDevice *dev, const gboolean link_active) } +/* + * Get/set functions for now_scanning + */ +gboolean nm_device_get_now_scanning (NMDevice *dev) +{ + g_return_val_if_fail (dev != NULL, FALSE); + g_return_val_if_fail (nm_device_is_wireless (dev), FALSE); + + return (dev->options.wireless.now_scanning); +} + +void nm_device_set_now_scanning (NMDevice *dev, const gboolean now_scanning) +{ + gboolean old_val; + + g_return_if_fail (dev != NULL); + g_return_if_fail (nm_device_is_wireless (dev)); + + old_val = nm_device_get_now_scanning (dev); + dev->options.wireless.now_scanning = now_scanning; + if (old_val != now_scanning) + nm_dbus_schedule_device_status_change (dev, DEVICE_STATUS_CHANGE); +} + + /* * Get function for supports_wireless_scan */ @@ -744,7 +797,7 @@ void nm_device_update_link_active (NMDevice *dev, gboolean check_mii) if (link != nm_device_get_link_active (dev)) { nm_device_set_link_active (dev, link); - nm_data_mark_state_changed (dev->app_data); + nm_policy_schedule_state_update (dev->app_data); } } @@ -1002,10 +1055,10 @@ int nm_device_get_bitrate (NMDevice *dev) * nm_device_set_bitrate * * For wireless devices, set the bitrate to broadcast/receive at. - * Rate argument should be in KHz, or 0 for automatic. + * Rate argument should be in Mbps (mega-bits per second), or 0 for automatic. * */ -void nm_device_set_bitrate (NMDevice *dev, const int KHz) +void nm_device_set_bitrate (NMDevice *dev, const int Mbps) { int sk; int err; @@ -1013,11 +1066,11 @@ void nm_device_set_bitrate (NMDevice *dev, const int KHz) g_return_if_fail (dev != NULL); g_return_if_fail (nm_device_is_wireless (dev)); - /* Test devices don't really have a frequency, they always succeed */ + /* Test devices don't really have a bitrate, they always succeed */ if (dev->test_device) return; - if (nm_device_get_bitrate (dev) == KHz) + if (nm_device_get_bitrate (dev) == Mbps) return; sk = iw_sockets_open (); @@ -1025,9 +1078,9 @@ void nm_device_set_bitrate (NMDevice *dev, const int KHz) { struct iwreq wrq; - if (KHz != 0) + if (Mbps != 0) { - wrq.u.bitrate.value = KHz * 1000; + wrq.u.bitrate.value = Mbps * 1000; wrq.u.bitrate.fixed = 1; } else @@ -1036,7 +1089,7 @@ void nm_device_set_bitrate (NMDevice *dev, const int KHz) wrq.u.bitrate.value = -1; wrq.u.bitrate.fixed = 0; } - /* Silently fail, not all drivers support this yet (ipw2x00 for example) */ + /* Silently fail as not all drivers support setting bitrate yet (ipw2x00 for example) */ iw_set_ext (sk, nm_device_get_iface (dev), SIOCSIWRATE, &wrq); close (sk); @@ -1620,7 +1673,7 @@ gboolean nm_device_set_mode (NMDevice *dev, const NMNetworkMode mode) * Schedule an idle routine in the main thread to finish the activation. * */ -void nm_device_activation_schedule_finish (NMDevice *dev, gboolean success) +void nm_device_activation_schedule_finish (NMDevice *dev, DeviceStatus activation_result) { GSource *source = NULL; guint source_id = 0; @@ -1632,7 +1685,7 @@ void nm_device_activation_schedule_finish (NMDevice *dev, gboolean success) result = g_malloc0 (sizeof (NMActivationResult)); nm_device_ref (dev); /* Ref device for idle handler */ result->dev = dev; - result->success = success; + result->result = activation_result; source = g_idle_source_new (); g_source_set_callback (source, nm_policy_activation_finish, (gpointer)result, NULL); @@ -1653,12 +1706,14 @@ void nm_device_activation_schedule_finish (NMDevice *dev, gboolean success) gboolean nm_device_activation_schedule_start (NMDevice *dev) { GError *error = NULL; - NMData *data = (NMData *)dev->app_data; + NMData *data = NULL; GSource *source = NULL; guint source_id = 0; g_return_val_if_fail (dev != NULL, FALSE); g_return_val_if_fail (!dev->activating, TRUE); /* Return if activation has already begun */ + + data = dev->app_data; g_return_val_if_fail (data != NULL, FALSE); /* Reset communication flags between worker and main thread */ @@ -1666,7 +1721,7 @@ gboolean nm_device_activation_schedule_start (NMDevice *dev) dev->quit_activation = FALSE; if (nm_device_is_wireless (dev)) { - dev->options.wireless.now_scanning = FALSE; + nm_device_set_now_scanning (dev, TRUE); dev->options.wireless.user_key_received = FALSE; } @@ -1676,20 +1731,6 @@ gboolean nm_device_activation_schedule_start (NMDevice *dev) return (FALSE); } - /* Don't attempt to actually activate if we are just starting NetworkManager and - * we are about to activate a wired device that's already configured. Plays nicer - * with the system when NM is started after a network is already set up. - * - * FIXME: IPv6 here too, and this really should not be here, it should be part of - * the policy, not the device code itself. - */ - if (data->starting_up && nm_device_is_wired (dev) && nm_device_get_ip4_address (dev)) - { - dev->activating = FALSE; - nm_device_activation_schedule_finish (dev, TRUE); - return (TRUE); - } - source = g_idle_source_new (); g_source_set_callback (source, nm_device_activate, dev, NULL); g_source_attach (source, dev->context); @@ -1716,8 +1757,8 @@ static gboolean nm_device_activation_handle_cancel (NMDevice *dev) if (dev->quit_activation) { syslog (LOG_DEBUG, "nm_device_activation_worker(%s): activation canceled.", nm_device_get_iface (dev)); - dev->activating = FALSE; - dev->quit_activation = FALSE; + if (nm_device_is_wireless (dev)) + nm_device_set_now_scanning (dev, FALSE); return (TRUE); } @@ -1799,15 +1840,17 @@ static gboolean nm_device_wireless_wait_for_link (NMDevice *dev, const char *ess * FALSE on unsuccessful activation (ie no best AP) * */ -static gboolean nm_device_set_wireless_config (NMDevice *dev, NMAccessPoint *ap, NMDeviceAuthMethod auth) +static gboolean nm_device_set_wireless_config (NMDevice *dev, NMAccessPoint *ap) { - gboolean success = FALSE; - const char *essid = NULL; + NMDeviceAuthMethod auth; + gboolean success = FALSE; + const char *essid = NULL; g_return_val_if_fail (dev != NULL, FALSE); g_return_val_if_fail (nm_device_is_wireless (dev), FALSE); g_return_val_if_fail (ap != NULL, FALSE); g_return_val_if_fail (nm_ap_get_essid (ap) != NULL, FALSE); + g_return_val_if_fail (nm_ap_get_auth_method (ap) != NM_DEVICE_AUTH_METHOD_UNKNOWN, FALSE); /* Force the card into Managed/Infrastructure mode */ nm_device_bring_down (dev); @@ -1816,10 +1859,9 @@ static gboolean nm_device_set_wireless_config (NMDevice *dev, NMAccessPoint *ap, g_usleep (G_USEC_PER_SEC * 2); nm_device_set_mode (dev, NETWORK_MODE_INFRA); - /* Disable encryption, then re-enable and set correct key on the card - * if we are going to encrypt traffic. - */ essid = nm_ap_get_essid (ap); + auth = nm_ap_get_auth_method (ap); + nm_device_set_mode (dev, nm_ap_get_mode (ap)); nm_device_set_bitrate (dev, 0); @@ -1828,17 +1870,26 @@ static gboolean nm_device_set_wireless_config (NMDevice *dev, NMAccessPoint *ap, else nm_device_set_frequency (dev, 0); /* auto */ - nm_device_set_enc_key (dev, NULL, NM_DEVICE_AUTH_METHOD_NONE); - if (nm_ap_get_encrypted (ap) && nm_ap_get_enc_key_source (ap)) + if (nm_ap_get_encrypted (ap) && nm_ap_is_enc_key_valid (ap)) { - char *hashed_key = nm_ap_get_enc_key_hashed (ap); + char *hashed_key = nm_ap_get_enc_key_hashed (ap); + + if (auth == NM_DEVICE_AUTH_METHOD_NONE) + { + nm_ap_set_auth_method (ap, NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM); + syslog (LOG_ERR, "Activation (%s/wireless): AP '%s' said it was encrypted, but had " + "'none' for authentication method. Using Open System authentication method.", + nm_device_get_iface (dev), nm_ap_get_essid (ap)); + } nm_device_set_enc_key (dev, hashed_key, auth); g_free (hashed_key); } + else + nm_device_set_enc_key (dev, NULL, NM_DEVICE_AUTH_METHOD_NONE); nm_device_set_essid (dev, essid); - syslog (LOG_INFO, "nm_device_set_wireless_config (%s) using essid '%s', with %s authentication.", + syslog (LOG_INFO, "Activation (%s/wireless): using essid '%s', with %s authentication.", nm_device_get_iface (dev), essid, (auth == NM_DEVICE_AUTH_METHOD_NONE) ? "no" : ((auth == NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM) ? "Open System" : ((auth == NM_DEVICE_AUTH_METHOD_SHARED_KEY) ? "Shared Key" : "unknown"))); @@ -1931,7 +1982,7 @@ static gboolean nm_device_activate_wireless_adhoc (NMDevice *dev, NMAccessPoint nm_ap_set_freq (ap, freq_to_use); syslog (LOG_INFO, "Will create network '%s' with frequency %f.\n", nm_ap_get_essid (ap), nm_ap_get_freq (ap)); - if ((success = nm_device_set_wireless_config (dev, ap, auth))) + if ((success = nm_device_set_wireless_config (dev, ap))) success = nm_device_activation_configure_ip (dev, TRUE); } @@ -1939,32 +1990,82 @@ static gboolean nm_device_activate_wireless_adhoc (NMDevice *dev, NMAccessPoint } -static gboolean AP_NEED_KEY (NMAccessPoint *ap) +static gboolean AP_NEED_KEY (NMDevice *dev, NMAccessPoint *ap) { - char *s; - int len = 0; - char *essid; + char *essid; + gboolean need_key = FALSE; g_return_val_if_fail (ap != NULL, FALSE); essid = nm_ap_get_essid (ap); - if ((s = nm_ap_get_enc_key_source (ap))) - len = strlen (s); - if (!nm_ap_get_encrypted (ap)) - syslog (LOG_NOTICE, "AP_NEED_KEY: access point '%s' is unencrypted, no key needed.", essid ? essid : "(null)"); + { + syslog (LOG_NOTICE, "Activation (%s/wireless): access point '%s' is unencrypted, no key needed.", + nm_device_get_iface (dev), essid ? essid : "(null)"); + } else { - if (!!nm_ap_get_enc_key_source (ap) && len) - syslog (LOG_NOTICE, "AP_NEED_KEY: access point '%s' is encrypted, and a key exists. No new key needed.", essid ? essid : "(null)"); + if (nm_ap_is_enc_key_valid (ap)) + { + syslog (LOG_NOTICE, "Activation (%s/wireless): access point '%s' is encrypted, and a key exists. No new key needed.", + nm_device_get_iface (dev), essid ? essid : "(null)"); + } else - syslog (LOG_NOTICE, "AP_NEED_KEY: access point '%s' is encrypted, but NO valid key exists. New key needed.", essid ? essid : "(null)"); + { + syslog (LOG_NOTICE, "Activation (%s/wireless): access point '%s' is encrypted, but NO valid key exists. New key needed.", + nm_device_get_iface (dev), essid ? essid : "(null)"); + need_key = TRUE; + } } - if (nm_ap_get_encrypted (ap) && (!nm_ap_get_enc_key_source (ap) || !len)) - return (TRUE); - return (FALSE); + return (need_key); +} + + +/* + * get_initial_auth_method + * + * Ensure the auth method the AP reports is valid for its encryption mode. + * + */ +static NMDeviceAuthMethod get_initial_auth_method (NMAccessPoint *ap) +{ + g_return_val_if_fail (ap != NULL, NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM); + + if (nm_ap_get_encrypted (ap)) + { + NMDeviceAuthMethod auth = nm_ap_get_auth_method (ap); + + if ( (auth == NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM) + || (auth == NM_DEVICE_AUTH_METHOD_SHARED_KEY)) + return (nm_ap_get_auth_method (ap)); + else + return (NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM); + } + + return (NM_DEVICE_AUTH_METHOD_NONE); +} + + +void invalidate_ap (NMDevice *dev, NMAccessPoint *ap) +{ + g_return_if_fail (dev != NULL); + g_return_if_fail (dev->app_data != NULL); + g_return_if_fail (ap != NULL); + + /* If its an AP the user forced, notify the user it failed. */ + /* FIXME: we dont' set ap's that are in our scan list as "artificial", + * so we won't be able to signal the user when a connection to on of them + * failed. + */ + if (nm_ap_get_artificial (ap)) + nm_dbus_schedule_network_not_found_signal (dev->app_data, nm_ap_get_essid (ap)); + + nm_ap_set_invalid (ap, TRUE); + nm_ap_list_append_ap (dev->app_data->invalid_ap_list, ap); + nm_ap_unref (ap); + nm_device_update_best_ap (dev); } @@ -1982,6 +2083,7 @@ static gboolean nm_device_activate_wireless (NMDevice *dev) gboolean success = FALSE; guint8 attempt = 1; char last_essid [50] = "\0"; + gboolean need_key = FALSE; g_return_val_if_fail (dev != NULL, FALSE); g_return_val_if_fail (dev->app_data != NULL, FALSE); @@ -2006,164 +2108,183 @@ get_ap: g_mutex_unlock (dev->options.wireless.scan_mutex); while (!(best_ap = nm_device_get_best_ap (dev))) { - dev->options.wireless.now_scanning = TRUE; + nm_device_set_now_scanning (dev, TRUE); syslog (LOG_DEBUG, "Activation (%s/wireless): waiting for an access point.", nm_device_get_iface (dev)); g_usleep (G_USEC_PER_SEC * 2); /* If we were told to quit activation, stop the thread and return */ if (nm_device_activation_handle_cancel (dev)) { - /* Wierd as it may seem, we lock here to balance the unlock in out: */ - dev->options.wireless.now_scanning = FALSE; + /* Wierd as it may seem, we lock here to balance the unlock in "out:" */ g_mutex_lock (dev->options.wireless.scan_mutex); goto out; } } + + /* Set ESSID early so that when we send out the DeviceStatusChanged signal below, + * we are able to respond correctly to queries for "getActiveNetwork" against + * our device. nm_device_get_path_for_ap() uses the /card's/ AP, not the best_ap. + */ + nm_device_set_essid (dev, nm_ap_get_essid (best_ap)); + + nm_device_set_now_scanning (dev, FALSE); g_mutex_lock (dev->options.wireless.scan_mutex); - dev->options.wireless.now_scanning = FALSE; - if (!nm_ap_get_encrypted (best_ap)) + if (nm_ap_get_artificial (best_ap)) { - nm_device_set_wireless_config (dev, best_ap, NM_DEVICE_AUTH_METHOD_NONE); - - /* If its unencrypted and we don't have a link, we can't use this AP. - * If we can't get an IP address off this AP, we can't use it either. + /* Some Cisco cards (340/350 PCMCIA) don't return non-broadcasting APs + * in their scan results, so we can't know beforehand whether or not the + * AP was encrypted. So we have to update their encryption status on the fly. */ - if (nm_ap_get_mode (best_ap) == NETWORK_MODE_ADHOC) + if (nm_ap_get_encrypted (best_ap) || nm_ap_is_enc_key_valid (best_ap)) { - success = nm_device_activation_configure_ip (dev, TRUE); + nm_ap_set_encrypted (best_ap, TRUE); + nm_ap_set_auth_method (best_ap, NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM); } - else + } + + need_key = AP_NEED_KEY (dev, best_ap); + +need_key: + if (need_key) + { + char *essid = nm_ap_get_essid (best_ap); + if (strcmp (essid, last_essid) != 0) + attempt = 1; + strncpy (&last_essid[0], essid, 49); + + /* Don't hold the mutex while waiting for a key */ + g_mutex_unlock (dev->options.wireless.scan_mutex); + + /* Get a wireless key */ + dev->options.wireless.user_key_received = FALSE; + nm_dbus_get_user_key_for_network (dev->app_data->dbus_connection, dev, best_ap, attempt); + attempt++; + need_key = FALSE; + + /* Wait for the key to come back */ + syslog (LOG_DEBUG, "Activation (%s/wireless): asking for user key.", nm_device_get_iface (dev)); + while (!dev->options.wireless.user_key_received && !dev->quit_activation) + g_usleep (G_USEC_PER_SEC / 2); + + syslog (LOG_DEBUG, "Activation (%s/wireless): user key received.", nm_device_get_iface (dev)); + + /* Done waiting, grab lock again */ + g_mutex_lock (dev->options.wireless.scan_mutex); + + /* User may have cancelled the key request, so we need to update our best AP again. */ + nm_ap_unref (best_ap); + + goto get_ap; + } + + if (nm_ap_get_mode (best_ap) == NETWORK_MODE_ADHOC) + { + /* Only do auto-ip on Ad-Hoc connections for now. We technically + * could do DHCP on them though. + */ + success = nm_device_activation_configure_ip (dev, TRUE); + goto connect_done; + } + +try_connect: + /* Initial authentication method */ + nm_ap_set_auth_method (best_ap, get_initial_auth_method (best_ap)); + + while (success == FALSE) + { + int ip_success = FALSE; + NMAccessPoint *tmp_ap = NULL; + gboolean link = FALSE; + gboolean adhoc = (nm_ap_get_mode (best_ap) == NETWORK_MODE_ADHOC); + + /* If we were told to quit activation, stop the thread and return */ + if (nm_device_activation_handle_cancel (dev)) + goto out; + + nm_device_set_wireless_config (dev, best_ap); + + link = nm_device_wireless_wait_for_link (dev, nm_ap_get_essid (best_ap)); + + /* If we were told to quit activation, stop the thread and return */ + if (nm_device_activation_handle_cancel (dev)) + goto out; + + if (!link) { - if ( nm_device_wireless_wait_for_link (dev, nm_ap_get_essid (best_ap)) - && nm_device_activation_configure_ip (dev, FALSE)) + if (nm_ap_get_auth_method (best_ap) == NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM) { - success = TRUE; + syslog (LOG_DEBUG, "Activation (%s/wireless): no hardware link to '%s' in Open System mode, trying Shared Key.", + nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); + /* Back down to Shared Key mode */ + nm_ap_set_auth_method (best_ap, NM_DEVICE_AUTH_METHOD_SHARED_KEY); + continue; + } + else if (nm_ap_get_auth_method (best_ap) == NM_DEVICE_AUTH_METHOD_SHARED_KEY) + { + /* Must be in Open System mode and it still didn't work, so + * we'll invalidate the current "best" ap and get another one */ + syslog (LOG_DEBUG, "Activation (%s/wireless): no hardware link to '%s' in Shared Key mode, trying another access point.", + nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); } else { - syslog (LOG_DEBUG, "Activation (%s/wireless): no link to '%s', or couldn't get configure interface for IP. Trying another access point.", + syslog (LOG_DEBUG, "Activation (%s/wireless): no hardware link to '%s' in non-encrypted mode.", nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); - nm_ap_set_invalid (best_ap, TRUE); - nm_ap_list_append_ap (dev->app_data->invalid_ap_list, best_ap); - nm_ap_unref (best_ap); - nm_device_update_best_ap (dev); - - /* Release scan mutex */ - g_mutex_unlock (dev->options.wireless.scan_mutex); - goto get_ap; } - } - } - else - { - NMDeviceAuthMethod auth = NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM; - gboolean need_key = AP_NEED_KEY (best_ap); - - need_key: - if (need_key) - { - char *essid = nm_ap_get_essid (best_ap); - if (strcmp (essid, last_essid) != 0) - attempt = 1; - strncpy (&last_essid[0], essid, 49); - - /* Don't hold the mutex while waiting for a key */ - g_mutex_unlock (dev->options.wireless.scan_mutex); - - /* Get a wireless key */ - dev->options.wireless.user_key_received = FALSE; - nm_dbus_get_user_key_for_network (dev->app_data->dbus_connection, dev, best_ap, attempt); - attempt++; - need_key = FALSE; - - /* Wait for the key to come back */ - syslog (LOG_DEBUG, "Activation (%s/wireless): asking for user key.", nm_device_get_iface (dev)); - while (!dev->options.wireless.user_key_received && !dev->quit_activation) - g_usleep (G_USEC_PER_SEC / 2); - - syslog (LOG_DEBUG, "Activation (%s/wireless): user key received.", nm_device_get_iface (dev)); - - /* Done waiting, grab lock again */ - g_mutex_lock (dev->options.wireless.scan_mutex); - - /* User may have cancelled the key request, so we need to update our best AP again. */ - nm_ap_unref (best_ap); + /* All applicable modes failed, invalidate current best_ap and get a new one */ + invalidate_ap (dev, best_ap); goto get_ap; } - try_connect: - while (auth != NM_DEVICE_AUTH_METHOD_NONE) + /* For those broken cards that report successful hardware link even when WEP key is wrong, + * and also for Open System mode (where you cannot know WEP key is wrong ever), we try to + * do DHCP and if that fails, fall back to next auth mode and try again. + */ + if ((success = nm_device_activation_configure_ip (dev, adhoc))) + { + /* Cache the last known good auth method in both NetworkManagerInfo and our allowed AP list */ + nm_dbus_update_network_auth_method (dev->app_data->dbus_connection, nm_ap_get_essid (best_ap), nm_ap_get_auth_method (best_ap)); + if ((tmp_ap = nm_ap_list_get_ap_by_essid (dev->app_data->allowed_ap_list, nm_ap_get_essid (best_ap)))) + nm_ap_set_auth_method (tmp_ap, nm_ap_get_auth_method (best_ap)); + } + else { - int ip_success = FALSE; - /* If we were told to quit activation, stop the thread and return */ if (nm_device_activation_handle_cancel (dev)) goto out; - nm_device_set_wireless_config (dev, best_ap, auth); - - /* Link checking and all this fallback doesn't really make sense in ad-hoc mode, - * so only do it for infrastructure mode. - */ - if (nm_ap_get_mode (best_ap) == NETWORK_MODE_ADHOC) + if ((nm_ap_get_auth_method (best_ap) == NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM) && !adhoc) { - /* Only do auto-ip on Ad-Hoc connections for now. We technically - * could do DHCP on them though. - */ - success = nm_device_activation_configure_ip (dev, TRUE); + /* Back down to Shared Key mode */ + syslog (LOG_DEBUG, "Activation (%s/wireless): could not get IP configuration info for '%s' in Open System mode, trying Shared Key.", + nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); + nm_ap_set_auth_method (best_ap, NM_DEVICE_AUTH_METHOD_SHARED_KEY); + continue; } - else if (nm_ap_get_mode (best_ap) == NETWORK_MODE_INFRA) + else if ((nm_ap_get_auth_method (best_ap) == NM_DEVICE_AUTH_METHOD_SHARED_KEY) && !adhoc) { - gboolean link = FALSE; - - link = nm_device_wireless_wait_for_link (dev, nm_ap_get_essid (best_ap)); - - if (!link && (auth == NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM)) - { - syslog (LOG_DEBUG, "Activation (%s/wireless): no hardware link to '%s' in Open System mode, trying Shared Key.", - nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); - /* Back down to Shared Key mode */ - auth = NM_DEVICE_AUTH_METHOD_SHARED_KEY; - continue; - } - else if (!link) - { - /* Must be in Open System mode and it still didn't work, so - * we'll invalidate the current "best" ap and get another one */ - syslog (LOG_DEBUG, "Activation (%s/wireless): no hardware link to '%s' in Shared Key mode, trying another access point.", - nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); - nm_ap_set_invalid (best_ap, TRUE); - nm_ap_list_append_ap (dev->app_data->invalid_ap_list, best_ap); - nm_ap_unref (best_ap); - nm_device_update_best_ap (dev); - goto get_ap; - } ip_success = nm_device_activation_configure_ip (dev, FALSE); - if (!ip_success && (auth == NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM)) - { - /* Back down to Shared Key mode */ - syslog (LOG_DEBUG, "Activation (%s/wireless): could not get IP configuration info for '%s' in Open System mode, trying Shared Key.", - nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); - auth = NM_DEVICE_AUTH_METHOD_SHARED_KEY; - continue; - } - else if (!ip_success) - { - /* Open System mode failed, we must have bad WEP key */ - syslog (LOG_DEBUG, "Activation (%s/wireless): could not get IP configuration info for '%s' in Shared Key mode, asking for new key.", - nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); - need_key = TRUE; - goto need_key; - } + /* Shared Key mode failed, we must have bad WEP key */ + syslog (LOG_DEBUG, "Activation (%s/wireless): could not get IP configuration info for '%s' in Shared Key mode, asking for new key.", + nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); + need_key = TRUE; + goto need_key; + } + else + { + /* All applicable modes failed, invalidate current best_ap and get a new one */ + invalidate_ap (dev, best_ap); + goto get_ap; } - - /* OK, we have a link and we have IP address info, we're good */ - success = TRUE; - break; } } +connect_done: + /* If we were told to quit activation, stop the thread and return */ + if (nm_device_activation_handle_cancel (dev)) + goto out; + if (success) { syslog (LOG_DEBUG, "Activation (%s/wireless): Success! Connected to access point '%s' and got an IP address.", @@ -2172,7 +2293,7 @@ get_ap: } out: - dev->options.wireless.now_scanning = FALSE; + nm_device_set_now_scanning (dev, FALSE); g_mutex_unlock (dev->options.wireless.scan_mutex); return (success); } @@ -2244,6 +2365,7 @@ static gboolean nm_device_activate (gpointer user_data) { NMDevice *dev = (NMDevice *)user_data; gboolean success = FALSE; + gboolean finished = FALSE; GMainContext *context = NULL; g_return_val_if_fail (dev != NULL, FALSE); @@ -2282,9 +2404,6 @@ static gboolean nm_device_activate (gpointer user_data) if (nm_device_activation_handle_cancel (dev)) goto out; - dev->activating = FALSE; - dev->quit_activation = FALSE; - if (success) syslog (LOG_DEBUG, "Activation (%s) IP configuration/DHCP successful!\n", nm_device_get_iface (dev)); else @@ -2294,11 +2413,7 @@ static gboolean nm_device_activate (gpointer user_data) if (nm_device_config_get_use_dhcp (dev) && dev->dhcp_iface) nm_device_dhcp_setup_timeouts (dev); - /* If we were told to quit activation, stop the thread and return */ - if (nm_device_activation_handle_cancel (dev)) - goto out; - - nm_device_activation_schedule_finish (dev, success); + finished = TRUE; out: if (dev->dhcp_iface) @@ -2308,6 +2423,11 @@ out: } syslog (LOG_DEBUG, "Activation (%s) ended.\n", nm_device_get_iface (dev)); + dev->activating = FALSE; + dev->quit_activation = FALSE; + if (finished) + nm_device_activation_schedule_finish (dev, success ? DEVICE_NOW_ACTIVE : DEVICE_ACTIVATION_FAILED); + return FALSE; } @@ -2392,12 +2512,12 @@ gboolean nm_device_deactivate (NMDevice *dev, gboolean just_added) if (nm_device_get_driver_support_level (dev) == NM_DRIVER_UNSUPPORTED) return (TRUE); - /* Take out any entries in the routing table and any IP address the old device had. */ + /* Take out any entries in the routing table and any IP address the device had. */ nm_system_device_flush_routes (dev); nm_system_device_flush_addresses (dev); dev->ip4_address = 0; - if (!just_added) + if (!just_added && (dev == dev->app_data->active_device)) nm_dbus_signal_device_status_change (dev->app_data->dbus_connection, dev, DEVICE_NO_LONGER_ACTIVE); /* Clean up stuff, don't leave the card associated */ @@ -2413,23 +2533,6 @@ gboolean nm_device_deactivate (NMDevice *dev, gboolean just_added) } -/* - * nm_device_is_scanning - * - * Returns whether the device is scanning, awaiting an access point to connect to. - * Note that this does NOT get set when the device is actually scanning, just - * when it is waiting for a valid access point to connect to. - * - */ -gboolean nm_device_is_scanning (NMDevice *dev) -{ - g_return_val_if_fail (dev != NULL, FALSE); - g_return_val_if_fail (nm_device_is_wireless (dev), FALSE); - - return (dev->options.wireless.now_scanning); -} - - /* * nm_device_set_user_key_for_network * @@ -2439,7 +2542,7 @@ gboolean nm_device_is_scanning (NMDevice *dev) */ void nm_device_set_user_key_for_network (NMDevice *dev, NMAccessPointList *invalid_list, unsigned char *network, unsigned char *key, - NMEncKeyType enc_method) + NMEncKeyType enc_type) { NMAccessPoint *best_ap; const char *cancel_message = "***canceled***"; @@ -2469,7 +2572,7 @@ void nm_device_set_user_key_for_network (NMDevice *dev, NMAccessPointList *inval * then set the new key on the access point. */ if (nm_null_safe_strcmp (network, nm_ap_get_essid (best_ap)) == 0) - nm_ap_set_enc_key_source (best_ap, key, enc_method); + nm_ap_set_enc_key_source (best_ap, key, enc_type); nm_ap_unref (best_ap); } @@ -2799,14 +2902,14 @@ void nm_device_update_best_ap (NMDevice *dev) trusted_latest_timestamp = *nm_ap_get_timestamp (tmp_ap); trusted_best_ap = scan_ap; /* Merge access point data (mainly to get updated WEP key) */ - nm_ap_set_enc_key_source (trusted_best_ap, nm_ap_get_enc_key_source (tmp_ap), nm_ap_get_enc_method (tmp_ap)); + nm_ap_set_enc_key_source (trusted_best_ap, nm_ap_get_enc_key_source (tmp_ap), nm_ap_get_enc_type (tmp_ap)); } else if (!nm_ap_get_trusted (tmp_ap) && (curtime->tv_sec > untrusted_latest_timestamp.tv_sec)) { untrusted_latest_timestamp = *nm_ap_get_timestamp (tmp_ap); untrusted_best_ap = scan_ap; /* Merge access point data (mainly to get updated WEP key) */ - nm_ap_set_enc_key_source (untrusted_best_ap, nm_ap_get_enc_key_source (tmp_ap), nm_ap_get_enc_method (tmp_ap)); + nm_ap_set_enc_key_source (untrusted_best_ap, nm_ap_get_enc_key_source (tmp_ap), nm_ap_get_enc_type (tmp_ap)); } } } @@ -2818,237 +2921,137 @@ void nm_device_update_best_ap (NMDevice *dev) } -/* - * nm_device_wireless_network_exists - * - * Tell the card to explicitly use with a particular essid, and then - * see if we can associate with some AP using that ESSID. - * Mainly for non-essid-broadcasting APs to figure out whether or not - * some random ESSID the user gave us exists or not. - * - * WARNING: will blow away any connection the card currently has. - * - */ -gboolean nm_device_wireless_network_exists (NMDevice *dev, const char *network, const char *key, NMEncKeyType key_type, - struct ether_addr *ap_addr, gboolean *encrypted) +typedef struct NMDeviceForceData { - gboolean success = FALSE; - gboolean temp_enc = FALSE; - struct ether_addr addr; - NMAccessPoint *ap = NULL; - NMDeviceAuthMethod auths[3] = { NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM, NM_DEVICE_AUTH_METHOD_SHARED_KEY, NM_DEVICE_AUTH_METHOD_NONE }; - int i; - NMNetworkMode mode = NETWORK_MODE_INFRA; - - g_return_val_if_fail (dev != NULL, FALSE); - g_return_val_if_fail (network != NULL, FALSE); - g_return_val_if_fail (ap_addr != NULL, FALSE); - g_return_val_if_fail (strlen (network), FALSE); - g_return_val_if_fail (encrypted != NULL, FALSE); - - syslog (LOG_INFO, "nm_device_wireless_network_exists () looking for network '%s'...", network); - - *encrypted = FALSE; - - nm_device_bring_up (dev); - g_usleep (G_USEC_PER_SEC * 4); - - if ((ap = nm_ap_list_get_ap_by_essid (nm_device_ap_list_get (dev), network))) - { - mode = nm_ap_get_mode (ap); - - /* If the access point we're looking for is in our list and we know its - * not encrypted, short-cut our connection fallbacks here and don't even - * try enabling encryption to see if we can connect. - */ - if (!nm_ap_get_encrypted (ap)) - { - auths[0] = NM_DEVICE_AUTH_METHOD_NONE; - auths[1] = NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM; - auths[2] = NM_DEVICE_AUTH_METHOD_SHARED_KEY; - } - } - - /* Two cases here. Ad-Hoc networks don't have an access point that authenticates or - * that you associate with, we just have to see if we know about the network and then - * set up the card. So if we know about it, we can use it. I guess if you don't have - * the right WEP key, you're kind of screwed. - */ - if (mode == NETWORK_MODE_ADHOC) - { - if (ap) - success = TRUE; - } - else if (mode == NETWORK_MODE_INFRA) - { - nm_device_set_mode (dev, mode); - - /* Loop through the auth modes */ - for (i = 0; i < 3; i++) - { - switch (auths[i]) - { - case NM_DEVICE_AUTH_METHOD_SHARED_KEY: - case NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM: - { - temp_enc = TRUE; - if ((key_type != NM_ENC_TYPE_UNKNOWN) && key && strlen (key)) - { - char *hashed_key = NULL; - switch (key_type) - { - case NM_ENC_TYPE_128_BIT_PASSPHRASE: - hashed_key = nm_wireless_128bit_key_from_passphrase (key); - break; - case NM_ENC_TYPE_ASCII_KEY: - if (strlen (key) <= 5) - hashed_key = nm_wireless_64bit_ascii_to_hex (key); - else - hashed_key = nm_wireless_128bit_ascii_to_hex (key); - break; - case NM_ENC_TYPE_HEX_KEY: - case NM_ENC_TYPE_UNKNOWN: - hashed_key = g_strdup (key); - break; - default: - break; - } - nm_device_set_enc_key (dev, hashed_key, auths[i]); - g_free (hashed_key); - } - else - { - /* We must have some encryption key to use, so fake something */ - nm_device_set_enc_key (dev, "11111111111111111111111111", auths[i]); - } - break; - } - case NM_DEVICE_AUTH_METHOD_NONE: - default: - temp_enc = FALSE; - nm_device_set_enc_key (dev, NULL, auths[i]); - break; - } - - /* Pause to allow card to associate. After we set the ESSID on the card, the card - * has to scan all channels to find our requested AP (which can take a long time - * if it is an A/B/G chipset like the Atheros 5212, for example). - * - * Also make sure to set "auto" frequency so the card doesn't think it has to - * stay locked at the one its at (Atheros cards, again). - */ - nm_device_set_frequency (dev, 0); - nm_device_set_essid (dev, network); - g_usleep (G_USEC_PER_SEC * 2); - if (nm_device_wireless_wait_for_link (dev, network)) - { - nm_device_get_ap_address (dev, ap_addr); - success = TRUE; - *encrypted = temp_enc; - break; - } - } - } - - /* If by some chance we could connect, but in the wrong encryption mode, return the - * encryption status of the access point if its in our scan, since that's more accurate. - */ - if (ap) - *encrypted = nm_ap_get_encrypted (ap); - - if (success) - syslog (LOG_INFO, " found! (%s)\n", *encrypted ? "encrypted" : "unencrypted"); - else - syslog (LOG_INFO, " not found\n"); - - return (success); -} + NMDevice *dev; + const char *net; + const char *key; + NMEncKeyType key_type; +} NMDeviceForceData; -/* - * nm_device_find_and_use_essid - * - * Given an essid, attempt to associate with that ESSID even if we can't - * see it in our scan. If we successfully find it, mark that network as - * our "best" and use it during the next activation. - * - * Returns: TRUE on success - * FALSE on failure - */ -gboolean nm_device_find_and_use_essid (NMDevice *dev, const char *essid, const char *key, NMEncKeyType key_type) +static gboolean nm_device_wireless_force_use (NMDevice *dev, const char *essid, const char *key, NMEncKeyType key_type) { struct ether_addr ap_addr; gboolean encrypted = FALSE; NMAccessPoint *ap = NULL; + NMAccessPoint *tmp_ap = NULL; gboolean success = FALSE; gboolean exists = FALSE; g_return_val_if_fail (dev != NULL, FALSE); - g_return_val_if_fail (nm_device_is_wireless (dev), FALSE); g_return_val_if_fail (dev->app_data != NULL, FALSE); - g_return_val_if_fail (essid != NULL, FALSE); + + if (!essid) + return FALSE; syslog (LOG_DEBUG, "Forcing AP '%s'", essid); - /* If the network exists, make sure it has the correct ESSID set - * (it might have been a blank ESSID up to this point) and use it. + if ( key + && strlen (key) + && (key_type != NM_ENC_TYPE_UNKNOWN) + && (key_type != NM_ENC_TYPE_NONE)) + encrypted = TRUE; + + /* Find the AP in our card's scan list first. + * If its not there, create an entirely new AP. */ - nm_device_deactivate (dev, FALSE); - g_usleep (G_USEC_PER_SEC); - - /* Grab the scanning mutex, since scanning sets some properties on the card - * that can mess our link detection up. - */ - g_mutex_lock (dev->options.wireless.scan_mutex); - - if (!(exists = nm_device_wireless_network_exists (dev, essid, key, key_type, &ap_addr, &encrypted))) - exists = nm_device_wireless_network_exists (dev, essid, key, key_type, &ap_addr, &encrypted); - - g_mutex_unlock (dev->options.wireless.scan_mutex); - - if (exists) + if (!(ap = nm_ap_list_get_ap_by_essid (nm_device_ap_list_get (dev), essid))) { - if (!(ap = nm_ap_list_get_ap_by_essid (nm_device_ap_list_get (dev), essid))) - { - if (!(ap = nm_device_ap_list_get_ap_by_address (dev, &ap_addr))) - { - /* Okay, the card didn't see it in the scan, Cisco cards sometimes do this. - * So we make a "fake" access point and add it to the scan list. - */ - ap = nm_ap_new (); - nm_ap_set_encrypted (ap, encrypted); - nm_ap_set_artificial (ap, TRUE); - nm_ap_set_address (ap, &ap_addr); - nm_ap_list_append_ap (nm_device_ap_list_get (dev), ap); - nm_ap_unref (ap); - } - nm_ap_set_essid (ap, essid); - } + /* Okay, the card didn't see it in the scan, Cisco cards sometimes do this. + * So we make a "fake" access point and add it to the scan list. + */ + ap = nm_ap_new (); + nm_ap_set_essid (ap, essid); + nm_ap_set_encrypted (ap, encrypted); + if (encrypted) + nm_ap_set_auth_method (ap, NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM); + else + nm_ap_set_auth_method (ap, NM_DEVICE_AUTH_METHOD_NONE); + nm_ap_set_artificial (ap, TRUE); + nm_ap_set_address (ap, &ap_addr); + nm_ap_list_append_ap (nm_device_ap_list_get (dev), ap); + nm_ap_unref (ap); } - /* If we found a valid access point, use it */ - if (ap) + /* Now that this AP has an essid, copy over encryption keys and whatnot */ + if ((tmp_ap = nm_ap_list_get_ap_by_essid (dev->app_data->allowed_ap_list, nm_ap_get_essid (ap)))) { - NMAccessPoint *tmp_ap; - - /* Now that this AP has an essid, copy over encryption keys and whatnot */ - if ((tmp_ap = nm_ap_list_get_ap_by_essid (dev->app_data->allowed_ap_list, nm_ap_get_essid (ap)))) - { - nm_ap_set_enc_key_source (ap, nm_ap_get_enc_key_source (tmp_ap), nm_ap_get_enc_method (tmp_ap)); - nm_ap_set_invalid (ap, nm_ap_get_invalid (tmp_ap)); - nm_ap_set_timestamp (ap, nm_ap_get_timestamp (tmp_ap)); - } - - /* Use the encryption key and type the user sent us if its valid */ - if ((key_type != NM_ENC_TYPE_UNKNOWN) && key && strlen (key)) - nm_ap_set_enc_key_source (ap, key, key_type); - nm_device_set_best_ap (dev, ap); - nm_device_freeze_best_ap (dev); - nm_device_activation_cancel (dev); - success = TRUE; + nm_ap_set_enc_key_source (ap, nm_ap_get_enc_key_source (tmp_ap), nm_ap_get_enc_type (tmp_ap)); + nm_ap_set_auth_method (ap, nm_ap_get_auth_method (tmp_ap)); + nm_ap_set_invalid (ap, nm_ap_get_invalid (tmp_ap)); + nm_ap_set_timestamp (ap, nm_ap_get_timestamp (tmp_ap)); } - return success; + /* Use the encryption key and type the user sent us if its valid */ + if (encrypted) + nm_ap_set_enc_key_source (ap, key, key_type); + + nm_device_set_best_ap (dev, ap); + nm_device_freeze_best_ap (dev); + + return TRUE; +} + + +gboolean nm_device_wired_force_use (NMDevice *dev) +{ + g_return_val_if_fail (dev != NULL, FALSE); + g_return_val_if_fail (dev->app_data != NULL, FALSE); + + return TRUE; +} + + +gboolean nm_device_force_use (gpointer user_data) +{ + NMDeviceForceData *cb_data = (NMDeviceForceData *)user_data; + NMData *app_data = NULL; + gboolean success = FALSE; + + g_return_val_if_fail (cb_data != NULL, FALSE); + + if (!cb_data->dev || !cb_data->dev->app_data) + goto out; + + app_data = cb_data->dev->app_data; + if (nm_device_is_wireless (cb_data->dev)) + success = nm_device_wireless_force_use (cb_data->dev, cb_data->net, cb_data->key, cb_data->key_type); + else if (nm_device_is_wired (cb_data->dev)) + success = nm_device_wired_force_use (cb_data->dev); + + if (success) + nm_policy_schedule_device_switch (cb_data->dev, cb_data->dev->app_data); + +out: + /* Function that scheduled us must ref the device */ + nm_device_unref (cb_data->dev); + + app_data->forcing_device = FALSE; + g_free (cb_data); + return FALSE; +} + + +void nm_device_schedule_force_use (NMDevice *dev, const char *network, const char *key, NMEncKeyType key_type) +{ + NMDeviceForceData *cb_data; + GSource *source; + + g_return_if_fail (dev != NULL); + g_return_if_fail (dev->app_data != NULL); + g_return_if_fail (dev->app_data->main_context != NULL); + + cb_data = g_malloc0 (sizeof (NMDeviceForceData)); + cb_data->dev = dev; + cb_data->net = network ? g_strdup (network) : NULL; + cb_data->key = key ? g_strdup (key) : NULL; + cb_data->key_type = key_type; + + source = g_idle_source_new (); + g_source_set_callback (source, nm_device_force_use, cb_data, NULL); + g_source_attach (source, dev->context); + g_source_unref (source); } @@ -3122,7 +3125,7 @@ static void nm_device_do_pseudo_scan (NMDevice *dev) syslog(LOG_INFO, "%s: setting AP '%s' best", nm_device_get_iface (dev), nm_ap_get_essid (ap)); nm_device_set_best_ap (dev, ap); - nm_data_mark_state_changed (dev->app_data); + nm_policy_schedule_state_update (dev->app_data); break; } } @@ -3180,7 +3183,7 @@ static void nm_device_fake_ap_list (NMDevice *dev) if ((list_ap = nm_ap_list_get_ap_by_essid (dev->app_data->allowed_ap_list, nm_ap_get_essid (nm_ap)))) { nm_ap_set_timestamp (nm_ap, nm_ap_get_timestamp (list_ap)); - nm_ap_set_enc_key_source (nm_ap, nm_ap_get_enc_key_source (list_ap), nm_ap_get_enc_method (list_ap)); + nm_ap_set_enc_key_source (nm_ap, nm_ap_get_enc_key_source (list_ap), nm_ap_get_enc_type (list_ap)); } /* Add the AP to the device's AP list */ @@ -3280,9 +3283,15 @@ static gboolean nm_device_wireless_process_scan_results (gpointer user_data) nm_ap_set_essid (nm_ap, tmp_ap->b.essid); if (tmp_ap->b.has_key && (tmp_ap->b.key_flags & IW_ENCODE_DISABLED)) + { nm_ap_set_encrypted (nm_ap, FALSE); + nm_ap_set_auth_method (nm_ap, NM_DEVICE_AUTH_METHOD_NONE); + } else + { nm_ap_set_encrypted (nm_ap, TRUE); + nm_ap_set_auth_method (nm_ap, NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM); + } if (tmp_ap->has_ap_addr) nm_ap_set_address (nm_ap, (const struct ether_addr *)(tmp_ap->ap_addr.sa_data)); @@ -3454,7 +3463,7 @@ static gboolean nm_device_wireless_scan (gpointer user_data) scan_results->scan_head.result = NULL; } else if ((err == -1) && (errno == ETIME)) - syslog (LOG_ERR, "Warning: the wireless card (%s) requires too much time for scans. It needs to be fixed.\n", nm_device_get_iface (dev)); + syslog (LOG_ERR, "Warning: the wireless card (%s) requires too much time for scans. Its driver needs to be fixed.", nm_device_get_iface (dev)); nm_device_set_mode (dev, orig_mode); /* Only set frequency if ad-hoc mode */ diff --git a/src/NetworkManagerDevice.h b/src/NetworkManagerDevice.h index 15e9a9f3a..0d648276e 100644 --- a/src/NetworkManagerDevice.h +++ b/src/NetworkManagerDevice.h @@ -27,14 +27,6 @@ #include "NetworkManager.h" #include "NetworkManagerMain.h" -typedef enum NMDeviceAuthMethod -{ - NM_DEVICE_AUTH_METHOD_UNKNOWN = 0, - NM_DEVICE_AUTH_METHOD_NONE, - NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM, - NM_DEVICE_AUTH_METHOD_SHARED_KEY -} NMDeviceAuthMethod; - typedef struct NMDevice NMDevice; @@ -43,6 +35,7 @@ NMDevice * nm_device_new (const char *iface, const char *udi, gboolean test_ void nm_device_ref (NMDevice *dev); gboolean nm_device_unref (NMDevice *dev); +void nm_device_worker_thread_stop (NMDevice *dev); int nm_device_open_sock (void); @@ -60,6 +53,9 @@ gboolean nm_device_is_wired (NMDevice *dev); NMData * nm_device_get_app_data (const NMDevice *dev); +gboolean nm_device_get_removed (const NMDevice *dev); +void nm_device_set_removed (NMDevice *dev, const gboolean removed); + gboolean nm_device_get_link_active (NMDevice *dev); void nm_device_set_link_active (NMDevice *dev, const gboolean active); void nm_device_update_link_active (NMDevice *dev, gboolean check_mii); @@ -111,13 +107,13 @@ gboolean nm_device_activation_should_cancel (NMDevice *dev); gboolean nm_device_is_activating (NMDevice *dev); gboolean nm_device_deactivate (NMDevice *dev, gboolean just_added); -gboolean nm_device_is_scanning (NMDevice *dev); +gboolean nm_device_get_now_scanning (NMDevice *dev); -gboolean nm_device_find_and_use_essid (NMDevice *dev, const char *essid, const char *key, NMEncKeyType key_type); +void nm_device_schedule_force_use (NMDevice *dev, const char *network, const char *key, NMEncKeyType key_type); void nm_device_set_user_key_for_network (NMDevice *dev, struct NMAccessPointList *invalid_list, unsigned char *network, unsigned char *key, - NMEncKeyType enc_method); + NMEncKeyType enc_type); void nm_device_bring_up (NMDevice *dev); void nm_device_bring_down (NMDevice *dev); diff --git a/src/NetworkManagerDevicePrivate.h b/src/NetworkManagerDevicePrivate.h index deb656c5c..c26d03cc2 100644 --- a/src/NetworkManagerDevicePrivate.h +++ b/src/NetworkManagerDevicePrivate.h @@ -90,6 +90,7 @@ struct NMDevice char *iface; NMDeviceType type; NMDriverSupportLevel driver_support_level; + gboolean removed; gboolean link_active; guint32 ip4_address; diff --git a/src/NetworkManagerMain.h b/src/NetworkManagerMain.h index d4ba63a1b..44f31eab2 100644 --- a/src/NetworkManagerMain.h +++ b/src/NetworkManagerMain.h @@ -46,12 +46,6 @@ typedef struct NMData GMainLoop *main_loop; gboolean info_daemon_avail; gboolean enable_test_devices; - gboolean starting_up; /* Hack for not taking down an already-set-up wired device when we launch */ - - /* Main loop for wireless scanning thread */ - GMainContext *wscan_ctx; - GMainLoop *wscan_loop; - gboolean wscan_thread_done; guint state_modified_idle_id; @@ -61,8 +55,7 @@ typedef struct NMData struct NMDevice *active_device; gboolean active_device_locked; - struct NMDevice *user_device; /* Holds a device that the user requests NM to use. */ - GMutex *user_device_mutex; + gboolean forcing_device; gboolean update_ap_lists; struct NMAccessPointList *allowed_ap_list; @@ -75,8 +68,6 @@ struct NMDevice *nm_create_device_and_add_to_list (NMData *data, const char *ud void nm_remove_device_from_list (NMData *data, const char *udi); -void nm_data_mark_state_changed (NMData *data); - void nm_schedule_status_signal_broadcast (NMData *data); #endif diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index 975e97161..13456c1d7 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -155,7 +155,7 @@ static NMDevice * nm_policy_auto_get_best_device (NMData *data) * under certain conditions. * */ -static NMDevice * nm_policy_get_best_device (NMData *data, gboolean *should_lock_on_activate) +static NMDevice * nm_policy_get_best_device (NMDevice *switch_to_dev, NMData *data, gboolean *should_lock_on_activate) { NMDevice *best_dev = NULL; @@ -168,18 +168,11 @@ static NMDevice * nm_policy_get_best_device (NMData *data, gboolean *should_lock if (should_lock_on_activate) *should_lock_on_activate = FALSE; - /* If the user told us to switch to a particular device, do it now */ - if (nm_try_acquire_mutex (data->user_device_mutex, __FUNCTION__)) + /* Prefer a device forced on us by the user */ + if (switch_to_dev && !nm_device_get_removed (switch_to_dev)) { - if (data->user_device) - { - best_dev = data->user_device; - - nm_device_unref (data->user_device); - data->user_device = NULL; - *should_lock_on_activate = TRUE; - } - nm_unlock_mutex (data->user_device_mutex, __FUNCTION__); + best_dev = switch_to_dev; + *should_lock_on_activate = TRUE; } /* Determine whether we need to clear the active device and unlock it. @@ -249,49 +242,60 @@ gboolean nm_policy_activation_finish (gpointer user_data) if (!(data = nm_device_get_app_data (dev))) goto out; - if (result->success) + switch (result->result) { - nm_dbus_signal_device_status_change (data->dbus_connection, dev, DEVICE_NOW_ACTIVE); - /* Tell NetworkManagerInfo to store the MAC address of the active device's AP */ - if (nm_device_is_wireless (dev)) - { - struct ether_addr addr; - - nm_device_get_ap_address (dev, &addr); - nm_dbus_add_network_address (data->dbus_connection, NETWORK_TYPE_ALLOWED, nm_device_get_essid (dev), &addr); - } - syslog (LOG_INFO, "Activation (%s) successful, device activated.", nm_device_get_iface (data->active_device)); - } - else - { - nm_dbus_signal_device_status_change (data->dbus_connection, dev, DEVICE_ACTIVATION_FAILED); - if (nm_device_is_wireless (dev)) - { - NMAccessPoint *ap = nm_device_get_best_ap (dev); - if (ap) + case DEVICE_NOW_ACTIVE: + nm_dbus_signal_device_status_change (data->dbus_connection, dev, result->result); + /* Tell NetworkManagerInfo to store the MAC address of the active device's AP */ + if (nm_device_is_wireless (dev)) { - /* Add the AP to the invalid list and force a best ap update (list takes ownership of ap) */ - nm_ap_list_append_ap (data->invalid_ap_list, ap); - nm_ap_unref (ap); + struct ether_addr addr; - nm_device_update_best_ap (dev); - - /* Unref because nm_device_get_best_ap() refs it before returning. */ - nm_ap_unref (ap); + nm_device_get_ap_address (dev, &addr); + nm_dbus_add_network_address (data->dbus_connection, NETWORK_TYPE_ALLOWED, nm_device_get_essid (dev), &addr); } - syslog (LOG_INFO, "Activation (%s) failed for access point (%s)", nm_device_get_iface (dev), ap ? nm_ap_get_essid (ap) : "(none)"); - } - else - syslog (LOG_INFO, "Activation (%s) failed.", nm_device_get_iface (dev)); - nm_data_mark_state_changed (data); + syslog (LOG_INFO, "Activation (%s) successful, device activated.", nm_device_get_iface (data->active_device)); + break; + + case DEVICE_ACTIVATION_FAILED: + nm_dbus_signal_device_status_change (data->dbus_connection, dev, result->result); + if (nm_device_is_wireless (dev)) + { + NMAccessPoint *ap = nm_device_get_best_ap (dev); + if (ap) + { + /* Add the AP to the invalid list and force a best ap update */ + nm_ap_list_append_ap (data->invalid_ap_list, ap); + nm_device_update_best_ap (dev); + + /* Unref because nm_device_get_best_ap() refs it before returning. */ + nm_ap_unref (ap); + } + syslog (LOG_INFO, "Activation (%s) failed for access point (%s)", nm_device_get_iface (dev), ap ? nm_ap_get_essid (ap) : "(none)"); + } + else + syslog (LOG_INFO, "Activation (%s) failed.", nm_device_get_iface (dev)); + break; + + case DEVICE_ACTIVATION_CANCELED: + default: + break; } + nm_policy_schedule_state_update (data); + out: nm_device_unref (dev); g_free (result); return FALSE; } +typedef struct NMStateUpdateData +{ + NMDevice *switch_to_dev; + NMData *app_data; +} NMStateUpdateData; + /* * nm_state_modification_monitor @@ -303,40 +307,57 @@ out: * 2) link state change of an interface * */ -gboolean nm_state_modification_monitor (gpointer user_data) +static gboolean nm_policy_state_update (gpointer user_data) { - NMData *data = (NMData *)user_data; + NMStateUpdateData *cb_data = (NMStateUpdateData *)user_data; + NMData *app_data; - g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail (cb_data != NULL, FALSE); - data->state_modified_idle_id = 0; + app_data = cb_data->app_data; + if (!app_data) + goto out; + + app_data->state_modified_idle_id = 0; /* If the info daemon is now running, get our trusted/preferred ap lists from it */ - if (data->info_daemon_avail && data->update_ap_lists) + if (app_data->info_daemon_avail && app_data->update_ap_lists) { /* Query info daemon for network lists if its now running */ - if (data->allowed_ap_list) - nm_ap_list_unref (data->allowed_ap_list); - data->allowed_ap_list = nm_ap_list_new (NETWORK_TYPE_ALLOWED); - if (data->allowed_ap_list) - nm_ap_list_populate_from_nmi (data->allowed_ap_list, data); + if (app_data->allowed_ap_list) + nm_ap_list_unref (app_data->allowed_ap_list); + app_data->allowed_ap_list = nm_ap_list_new (NETWORK_TYPE_ALLOWED); + if (app_data->allowed_ap_list) + nm_ap_list_populate_from_nmi (app_data->allowed_ap_list, app_data); - data->update_ap_lists = FALSE; + app_data->update_ap_lists = FALSE; } - if (nm_try_acquire_mutex (data->dev_list_mutex, __FUNCTION__)) + /* If we're currently waiting for a force-device operation to complete, don't try + * to change devices. We'll be notified of what device to switch to explicitly + * when the force-device operation completes. + */ + if (!cb_data->switch_to_dev && app_data->forcing_device) + goto out; + + app_data->forcing_device = FALSE; + + if (nm_try_acquire_mutex (app_data->dev_list_mutex, __FUNCTION__)) { gboolean should_lock_on_activate = FALSE; gboolean do_switch = FALSE; NMDevice *best_dev = NULL; - if ((best_dev = nm_policy_get_best_device (data, &should_lock_on_activate))) + if ((best_dev = nm_policy_get_best_device (cb_data->switch_to_dev, app_data, &should_lock_on_activate))) nm_device_ref (best_dev); /* Figure out if we need to change devices or wireless networks */ - if (best_dev != data->active_device) + if (best_dev != app_data->active_device) { - syslog (LOG_INFO, " SWITCH: best device changed"); + if (best_dev) + syslog (LOG_INFO, " SWITCH: best device changed"); + else + syslog (LOG_INFO, " SWITCH: old device no longer good, but no better device was available"); do_switch = TRUE; /* Device changed */ } else if (best_dev) @@ -356,39 +377,87 @@ gboolean nm_state_modification_monitor (gpointer user_data) if (do_switch) { /* Deactivate the old device */ - if (data->active_device) + if (app_data->active_device) { - nm_device_deactivate (data->active_device, FALSE); - nm_device_unref (data->active_device); - data->active_device = NULL; + nm_device_deactivate (app_data->active_device, FALSE); + nm_device_unref (app_data->active_device); + app_data->active_device = NULL; } if (best_dev) { /* Begin activation on the new device */ nm_device_ref (best_dev); - data->active_device = best_dev; - nm_device_activation_schedule_start (data->active_device); + app_data->active_device = best_dev; + nm_device_activation_schedule_start (app_data->active_device); /* nm_policy_get_best_device() signals us that the user forced * a device upon us and that we should lock the active device. */ if (should_lock_on_activate) - data->active_device_locked = TRUE; + app_data->active_device_locked = TRUE; } } if (best_dev) nm_device_unref (best_dev); - nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__); + nm_unlock_mutex (app_data->dev_list_mutex, __FUNCTION__); } - /* Clear the starting up flag, so we will now take over and have our way with - * any device we find out about. - */ - if (data->starting_up) - data->starting_up = FALSE; - +out: + g_free (cb_data); return (FALSE); } + + +/* + * nm_policy_schedule_state_update + * + * Queue up an idle handler to deal with state changes. + * + */ +void nm_policy_schedule_state_update (NMData *app_data) +{ + g_return_if_fail (app_data != NULL); + + nm_policy_schedule_device_switch (NULL, app_data); +} + + +/* + * nm_policy_schedule_state_update + * + * Queue up an idle handler to deal with state changes when we want + * to force a particular device to be the active device. + * + */ +void nm_policy_schedule_device_switch (NMDevice *switch_to_dev, NMData *app_data) +{ + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + + g_return_if_fail (app_data != NULL); + + g_static_mutex_lock (&mutex); + + /* Don't queue the idle handler if switch_to_dev is NULL and there's already + * an idle handler queued. Always queue the idle handler if we were passed + * a switch_to_dev. + */ + if (switch_to_dev || (app_data->state_modified_idle_id == 0)) + { + GSource *source = g_idle_source_new (); + NMStateUpdateData *cb_data = g_malloc0 (sizeof (NMStateUpdateData)); + + cb_data->switch_to_dev = switch_to_dev; + cb_data->app_data = app_data; + + g_source_set_callback (source, nm_policy_state_update, cb_data, NULL); + app_data->state_modified_idle_id = g_source_attach (source, app_data->main_context); + g_source_unref (source); + + } + + g_static_mutex_unlock (&mutex); +} + diff --git a/src/NetworkManagerPolicy.h b/src/NetworkManagerPolicy.h index 02be93f35..c1293c955 100644 --- a/src/NetworkManagerPolicy.h +++ b/src/NetworkManagerPolicy.h @@ -24,15 +24,18 @@ #include "NetworkManager.h" #include "NetworkManagerDevice.h" +#include "NetworkManagerDbus.h" typedef struct { NMDevice *dev; - gboolean success; + DeviceStatus result; } NMActivationResult; -gboolean nm_state_modification_monitor (gpointer user_data); +void nm_policy_schedule_state_update (NMData *app_data); + +void nm_policy_schedule_device_switch (NMDevice *dev, NMData *app_data); gboolean nm_policy_activation_finish (gpointer user_data);