diff --git a/ChangeLog b/ChangeLog index a17d7c2e68..604f393559 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,49 @@ +2005-01-18 Dan Williams + + * dhcpcd/client.c + - Remove some debug messages + - Wrap others in #ifdef DEBUG/#endif + + * src/NetworkManager.c + - Remove some debug messages + - Clarify some debug messages + - Remove code related to old single-thread wireless scanning + + * src/NetworkManagerAP.[ch] + - New AP property "last_seen" to track how recently an AP was + found in a scan + - Start using 'const' more in function arguments + + * src/NetworkManagerAPList.[ch] + - (nm_ap_list_merge_scanned_ap): new, selectively update attributes + of an AP found in an AP list from a source AP, or if not found + in the list add the source AP + - (nm_ap_list_combine): remove, no longer needed + + * src/NetworkManagerDevice.c + - Each device now has a "worker" thread from start to end of its life. + Scanning for wireless devices now happens in that thread, + not in a single "wireless scanning thread" for all devices as + previously. Activation consists of adding an idle handler to the + thread's main loop/context, which gets run at the next available + opportunity. + - Wireless scanning is also simplified, there is now only one list of + access points per wireless device, and APs older than 60s are + removed from the list. Previously, we kept results for the last + 3 scans and merged whole lists, which was complicated. + - Cleaned up activation debug messages. + - Wireless activation and access-point search routines now use Open System + authentication before trying Shared Key. + - Removed some code in nm_device_update_best_ap() that could cause cards + to loose their link to the access point. + - Scanning now uses a backoff algorithm, where the inverval becomes + progressively longer between scans when the list of scanned access + points doesn't change. A change will revert to the shortest scan + interval (20s). + + * src/NetworkManagerWireless.[ch] + - Remove code related to old single-thread wireless scanning + 2005-01-18 Colin Walters * src/NetworkManagerDHCP.c (set_nameservers): Free and clear list diff --git a/dhcpcd/client.c b/dhcpcd/client.c index 695a0a88bb..9ff19aa302 100644 --- a/dhcpcd/client.c +++ b/dhcpcd/client.c @@ -422,12 +422,12 @@ int peekfd (dhcp_interface *iface, int sk, int min_data, struct timeval *end_tim * to stop with iface->cease and check our end time. */ gettimeofday (&now, NULL); - syslog (LOG_INFO, "DHCP waiting for data, overall end_time = {%ds, %dus}\n", (int)end_time->tv_sec, (int)end_time->tv_usec); +/* syslog (LOG_INFO, "DHCP waiting for data, overall end_time = {%ds, %dus}\n", (int)end_time->tv_sec, (int)end_time->tv_usec);*/ while ((timeval_subtract (&diff, end_time, &now) == 0) && !iface->cease && (recv_data_len < min_data)) { fd_set fs; struct timeval wait = {1, 0}; - syslog (LOG_INFO, "DHCP waiting for data of minimum size %d, remaining timeout = {%ds, %dus}\n", min_data, (int)diff.tv_sec, (int)diff.tv_usec); +/* syslog (LOG_INFO, "DHCP waiting for data of minimum size %d, remaining timeout = {%ds, %dus}\n", min_data, (int)diff.tv_sec, (int)diff.tv_usec);*/ FD_ZERO (&fs); FD_SET (sk, &fs); @@ -487,7 +487,9 @@ int dhcp_handle_transaction (dhcp_interface *iface, unsigned int expected_reply_ /* Send the request, then wait for the reply for a certain period of time * that increases with each failed request. Quit when we reach our end time though. */ +#ifdef DEBUG syslog (LOG_INFO, "DHCP: Starting request loop"); +#endif do { udpipMessage *udp_msg_recv = NULL; @@ -506,7 +508,9 @@ int dhcp_handle_transaction (dhcp_interface *iface, unsigned int expected_reply_ goto out; /* Send the DHCP request */ + #ifdef DEBUG syslog (LOG_INFO, "DHCP: Sending request packet..."); + #endif do { int udp_send_len = 0; @@ -524,7 +528,9 @@ int dhcp_handle_transaction (dhcp_interface *iface, unsigned int expected_reply_ err = sendto (iface->sk, udp_send, udp_send_len, MSG_DONTWAIT, (struct sockaddr *)&addr, sizeof (struct sockaddr)); if (iface->cease || ((err == -1) && (errno != EAGAIN))) { + #ifdef DEBUG syslog (LOG_INFO, "DHCP: error sending, cease = %d, err = %d, errno = %d", iface->cease, err, errno); + #endif err = iface->cease ? RET_DHCP_CEASED : RET_DHCP_ERROR; goto out; } @@ -534,11 +540,15 @@ int dhcp_handle_transaction (dhcp_interface *iface, unsigned int expected_reply_ if (timeval_subtract (&diff, &overall_end, ¤t) != 0) { err = RET_DHCP_TIMEOUT; + #ifdef DEBUG syslog (LOG_INFO, "DHCP: Send timeout"); + #endif goto out; } } while ((err == -1) && (errno == EAGAIN)); + #ifdef DEBUG syslog (LOG_INFO, "DHCP: Sent request packet."); + #endif /* Set up the future time at which point to stop waiting for data * on our socket and try the request again. If that future point is @@ -563,56 +573,71 @@ int dhcp_handle_transaction (dhcp_interface *iface, unsigned int expected_reply_ char ethPacket[ETH_FRAME_LEN]; /* Wait for some kind of data to appear on the socket */ + #ifdef DEBUG syslog (LOG_INFO, "DHCP: Waiting for reply..."); + #endif if ((err = peekfd (iface, recv_sk, min_data_len, &recv_end)) != RET_DHCP_SUCCESS) { if (err == RET_DHCP_TIMEOUT) break; goto out; } - syslog (LOG_INFO, "DHCP: Got some data to check for reply packet."); gettimeofday (¤t, NULL); /* Ok, we allegedly have the data we need, so grab it from the queue */ o = sizeof (struct sockaddr_ll); len = recvfrom (recv_sk, pkt_recv, ETH_FRAME_LEN, 0, (struct sockaddr *)&server_hw_addr, &o); - syslog (LOG_INFO, "DHCP: actual data length was %d", len); + #ifdef DEBUG + syslog (LOG_INFO, "DHCP: Got some data of length %d.", len); + #endif if (len < (sizeof (struct iphdr) + sizeof (struct udphdr))) { - syslog (LOG_INFO, "DHCP: Data length failed minimum length check (should be %d, got %d)", (sizeof (struct iphdr) + sizeof (struct udphdr)), len); + #ifdef DEBUG + syslog (LOG_INFO, "DHCP: Data length failed minimum length check (should be %d, got %d)", (sizeof (struct iphdr) + sizeof (struct udphdr)), len); + #endif continue; } ip_hdr = (struct iphdr *) pkt_recv; if (!verify_checksum (NULL, 0, ip_hdr, sizeof (struct iphdr))) { - syslog (LOG_INFO, "DHCP: Reply message had bad IP checksum, won't use it."); + #ifdef DEBUG + syslog (LOG_INFO, "DHCP: Reply message had bad IP checksum, won't use it."); + #endif continue; } if (ntohs (ip_hdr->tot_len) > len) { - syslog (LOG_INFO, "DHCP: Reply message had mismatch in length (IP header said %d, packet was really %d), won't use it.", ntohs (ip_hdr->tot_len), len); + #ifdef DEBUG + syslog (LOG_INFO, "DHCP: Reply message had mismatch in length (IP header said %d, packet was really %d), won't use it.", ntohs (ip_hdr->tot_len), len); + #endif continue; } len = ntohs (ip_hdr->tot_len); if (ip_hdr->protocol != IPPROTO_UDP) { - syslog (LOG_INFO, "DHCP: Reply message was not not UDP (ip_hdr->protocol = %d, IPPROTO_UDP = %d), won't use it.", ip_hdr->protocol, IPPROTO_UDP); + #ifdef DEBUG + syslog (LOG_INFO, "DHCP: Reply message was not not UDP (ip_hdr->protocol = %d, IPPROTO_UDP = %d), won't use it.", ip_hdr->protocol, IPPROTO_UDP); + #endif continue; } udp_hdr = (struct udphdr *) (pkt_recv + sizeof (struct iphdr)); if (ntohs (udp_hdr->source) != DHCP_SERVER_PORT) { - syslog (LOG_INFO, "DHCP: Reply message's source port was not the DHCP server port number, won't use it."); + #ifdef DEBUG + syslog (LOG_INFO, "DHCP: Reply message's source port was not the DHCP server port number, won't use it."); + #endif continue; } if (ntohs (udp_hdr->dest) != DHCP_CLIENT_PORT) { - syslog (LOG_INFO, "DHCP: Reply message's destination port was not the DHCP client port number, won't use it."); + #ifdef DEBUG + syslog (LOG_INFO, "DHCP: Reply message's destination port was not the DHCP client port number, won't use it."); + #endif continue; } @@ -624,22 +649,28 @@ int dhcp_handle_transaction (dhcp_interface *iface, unsigned int expected_reply_ if (dhcp_msg_recv->xid != iface->xid) { - syslog (LOG_INFO, "DHCP: Reply message's XID does not match expected XID (message %d, expected %d), won't use it.", dhcp_msg_recv->xid, iface->xid); + #ifdef DEBUG + syslog (LOG_INFO, "DHCP: Reply message's XID does not match expected XID (message %d, expected %d), won't use it.", dhcp_msg_recv->xid, iface->xid); + #endif free (dhcp_msg_recv); continue; } if (dhcp_msg_recv->htype != ARPHRD_ETHER) { - if (DebugFlag) - syslog (LOG_DEBUG, "DHCP: Reply message's header type was not ARPHRD_ETHER (messgae %d, expected %d), won't use it.", dhcp_msg_recv->htype, ARPHRD_ETHER); + #ifdef DEBUG + if (DebugFlag) + syslog (LOG_DEBUG, "DHCP: Reply message's header type was not ARPHRD_ETHER (messgae %d, expected %d), won't use it.", dhcp_msg_recv->htype, ARPHRD_ETHER); + #endif free (dhcp_msg_recv); continue; } if (dhcp_msg_recv->op != DHCP_BOOTREPLY) { - syslog (LOG_INFO, "DHCP: Reply message was not a bootp/DHCP reply, won't use it."); + #ifdef DEBUG + syslog (LOG_INFO, "DHCP: Reply message was not a bootp/DHCP reply, won't use it."); + #endif free (dhcp_msg_recv); continue; } @@ -668,10 +699,12 @@ int dhcp_handle_transaction (dhcp_interface *iface, unsigned int expected_reply_ if (reply_type == DHCP_NAK) { - if (iface->dhcp_options.val[dhcpMsg]) - syslog (LOG_ERR, "DHCP: DHCP_NAK response received: %s.", (char *)iface->dhcp_options.val[dhcpMsg]); - else - syslog (LOG_ERR, "DHCP: DHCP_NAK response received."); + #ifdef DEBUG + if (iface->dhcp_options.val[dhcpMsg]) + syslog (LOG_ERR, "DHCP: DHCP_NAK response received: %s.", (char *)iface->dhcp_options.val[dhcpMsg]); + else + syslog (LOG_ERR, "DHCP: DHCP_NAK response received."); + #endif err = RET_DHCP_NAK; goto out; } @@ -714,8 +747,8 @@ int dhcp_init (dhcp_interface *iface) release_dhcp_options (iface); #ifdef DEBUG - syslog (LOG_DEBUG, "ClassID = \"%s\"\n" - "ClientID = \"%u.%u.%u.%02X.%02X.%02X.%02X.%02X.%02X\"\n", iface->cls_id, + syslog (LOG_DEBUG, "ClassID = \"%s\"", iface->cls_id); + syslog (LOG_DEBUG, "ClientID = \"%u.%u.%u.%02X.%02X.%02X.%02X.%02X.%02X\"\n", iface->cli_id[0], iface->cli_id[1], iface->cli_id[2], iface->cli_id[3], iface->cli_id[4], iface->cli_id[5], iface->cli_id[6], iface->cli_id[7], iface->cli_id[8]); diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 10722a835c..98a740c58d 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -124,7 +124,7 @@ NMDevice * nm_create_device_and_add_to_list (NMData *data, const char *udi, cons */ if (nm_try_acquire_mutex (data->dev_list_mutex, __FUNCTION__)) { - syslog (LOG_INFO, "nm_create_device_and_add_to_list(): adding device '%s' (%s)", + syslog (LOG_INFO, "Adding device '%s' (%s) to our list.", nm_device_get_iface (dev), nm_device_is_wireless (dev) ? "wireless" : "wired"); data->dev_list = g_slist_append (data->dev_list, dev); @@ -202,7 +202,6 @@ void nm_remove_device_from_list (NMData *data, const char *udi) g_slist_free (element); nm_data_mark_state_changed (data); nm_dbus_signal_device_status_change (data->dbus_connection, dev, DEVICE_LIST_CHANGE); - break; } element = g_slist_next (element); @@ -238,7 +237,7 @@ static void nm_hal_device_added (LibHalContext *ctx, const char *udi) g_return_if_fail (data != NULL); - syslog( LOG_DEBUG, "nm_hal_device_added() called with udi = %s", udi ); + syslog( LOG_DEBUG, "New device added (hal udi is '%s').", udi ); /* Sometimes the device's properties (like net.interface) are not set up yet, * so this call will fail, and it will actually be added when hal sets the device's @@ -262,7 +261,7 @@ static void nm_hal_device_removed (LibHalContext *ctx, const char *udi) g_return_if_fail (data != NULL); - syslog( LOG_DEBUG, "nm_hal_device_removed() called with udi = %s", udi ); + syslog( LOG_DEBUG, "Device removed (hal udi is '%s').", udi ); nm_remove_device_from_list (data, udi); } @@ -278,7 +277,7 @@ static void nm_hal_device_new_capability (LibHalContext *ctx, const char *udi, c g_return_if_fail (data != NULL); - syslog( LOG_DEBUG, "nm_hal_device_new_capability() called with udi = %s, capability = %s", udi, capability ); + /*syslog( LOG_DEBUG, "nm_hal_device_new_capability() called with udi = %s, capability = %s", udi, capability );*/ if (capability && ((strcmp (capability, "net.80203") == 0) || (strcmp (capability, "net.80211") == 0))) { @@ -800,9 +799,7 @@ int main( int argc, char *argv[] ) /* Bring up the loopback interface. */ nm_system_enable_loopback (); - /* Create a watch function that monitors cards for link status (hal doesn't do - * this for wireless cards yet). - */ + /* Create a watch function that monitors cards for link status. */ link_source = g_timeout_source_new (5000); g_source_set_callback (link_source, nm_link_state_monitor, nm_data, NULL); link_source_id = g_source_attach (link_source, nm_data->main_context); @@ -810,7 +807,7 @@ int main( int argc, char *argv[] ) if (become_daemon && daemon (0, 0) < 0) { syslog (LOG_ERR, "NetworkManager could not daemonize. errno = %d", errno); - exit (1); + exit (EXIT_FAILURE); } if (!nm_named_manager_start (nm_data->named, &error)) @@ -819,31 +816,15 @@ int main( int argc, char *argv[] ) exit (EXIT_FAILURE); } - /* Start the wireless scanning thread and timeout */ - if (!g_thread_create (nm_wireless_scan_worker, nm_data, FALSE, &error)) - { - syslog (LOG_CRIT, "Could not start wireless scan worker thread. Exiting. (error: %s)", error ? error->message : "unknown"); - if (error) - g_error_free (error); - exit (1); - } - /* Wheeee!!! */ - syslog (LOG_NOTICE, "running mainloop..."); g_main_loop_run (nm_data->main_loop); - syslog (LOG_NOTICE, "exiting..."); /* Kill the watch functions */ g_source_remove (link_source_id); - /* Quit and wait for the scan thread */ - g_main_loop_quit (nm_data->wscan_loop); - while (nm_data->wscan_thread_done == FALSE) - g_usleep (100); - /* Cleanup */ if (hal_shutdown (nm_data->hal_ctx) != 0) - syslog (LOG_NOTICE, "libhal shutdown failed"); + syslog (LOG_NOTICE, "Error: libhal shutdown failed"); nm_data_free (nm_data); diff --git a/src/NetworkManagerAP.c b/src/NetworkManagerAP.c index b0f0cac8ca..d56ba3800c 100644 --- a/src/NetworkManagerAP.c +++ b/src/NetworkManagerAP.c @@ -37,20 +37,22 @@ struct NMAccessPoint double freq; guint16 rate; gboolean encrypted; + + /* Non-scanned attributes */ gboolean invalid; gboolean matched; /* used in ap list diffing */ - gboolean trusted; gboolean artificial; /* Whether or not the AP is from a scan */ gboolean user_created; /* Whether or not the AP was created by the user with "Create network..." */ + GTimeVal last_seen; /* Last time the AP was seen in a scan */ - /* Things from user prefs */ + /* Things from user prefs/NetworkManagerInfo */ + gboolean trusted; char *enc_key; NMEncKeyType enc_method; GTimeVal timestamp; GSList *user_addresses; }; - /* * nm_ap_new * @@ -153,7 +155,7 @@ void nm_ap_unref (NMAccessPoint *ap) * Get/set functions for timestamp * */ -const GTimeVal *nm_ap_get_timestamp (NMAccessPoint *ap) +const GTimeVal *nm_ap_get_timestamp (const NMAccessPoint *ap) { g_return_val_if_fail (ap != NULL, 0); @@ -172,7 +174,7 @@ void nm_ap_set_timestamp (NMAccessPoint *ap, const GTimeVal *timestamp) * Get/set functions for essid * */ -char * nm_ap_get_essid (NMAccessPoint *ap) +char * nm_ap_get_essid (const NMAccessPoint *ap) { g_return_val_if_fail (ap != NULL, NULL); @@ -198,7 +200,7 @@ void nm_ap_set_essid (NMAccessPoint *ap, const char * essid) * Get/set functions for encryption key * */ -char * nm_ap_get_enc_key_source (NMAccessPoint *ap) +char * nm_ap_get_enc_key_source (const NMAccessPoint *ap) { g_return_val_if_fail (ap != NULL, NULL); @@ -216,7 +218,7 @@ void nm_ap_set_enc_key_source (NMAccessPoint *ap, const char * key, NMEncKeyType ap->enc_method = method; } -char *nm_ap_get_enc_key_hashed (NMAccessPoint *ap) +char *nm_ap_get_enc_key_hashed (const NMAccessPoint *ap) { char *hashed = NULL; char *source_key; @@ -256,7 +258,7 @@ char *nm_ap_get_enc_key_hashed (NMAccessPoint *ap) * Get/set functions for encrypted flag * */ -gboolean nm_ap_get_encrypted (NMAccessPoint *ap) +gboolean nm_ap_get_encrypted (const NMAccessPoint *ap) { g_return_val_if_fail (ap != NULL, FALSE); @@ -275,7 +277,7 @@ void nm_ap_set_encrypted (NMAccessPoint *ap, gboolean encrypted) * Get/set functions for address * */ -struct ether_addr * nm_ap_get_address (NMAccessPoint *ap) +struct ether_addr * nm_ap_get_address (const NMAccessPoint *ap) { g_return_val_if_fail (ap != NULL, NULL); @@ -303,7 +305,7 @@ void nm_ap_set_address (NMAccessPoint *ap, const struct ether_addr * addr) * Get/set functions for mode (ie Ad-Hoc, Infrastructure, etc) * */ -NMNetworkMode nm_ap_get_mode (NMAccessPoint *ap) +NMNetworkMode nm_ap_get_mode (const NMAccessPoint *ap) { g_return_val_if_fail (ap != NULL, NETWORK_MODE_UNKNOWN); @@ -322,7 +324,7 @@ void nm_ap_set_mode (NMAccessPoint *ap, const NMNetworkMode mode) * Get/set functions for strength * */ -gint8 nm_ap_get_strength (NMAccessPoint *ap) +gint8 nm_ap_get_strength (const NMAccessPoint *ap) { g_return_val_if_fail (ap != NULL, 0); @@ -341,7 +343,7 @@ void nm_ap_set_strength (NMAccessPoint *ap, const gint8 strength) * Get/set functions for frequency * */ -double nm_ap_get_freq (NMAccessPoint *ap) +double nm_ap_get_freq (const NMAccessPoint *ap) { g_return_val_if_fail (ap != NULL, 0); @@ -360,7 +362,7 @@ void nm_ap_set_freq (NMAccessPoint *ap, const double freq) * Get/set functions for rate * */ -guint16 nm_ap_get_rate (NMAccessPoint *ap) +guint16 nm_ap_get_rate (const NMAccessPoint *ap) { g_return_val_if_fail (ap != NULL, 0); @@ -381,7 +383,7 @@ void nm_ap_set_rate (NMAccessPoint *ap, guint16 rate) * (by cancelling requests for WEP key, for example) * */ -gboolean nm_ap_get_invalid (NMAccessPoint *ap) +gboolean nm_ap_get_invalid (const NMAccessPoint *ap) { g_return_val_if_fail (ap != NULL, TRUE); @@ -401,7 +403,7 @@ void nm_ap_set_invalid (NMAccessPoint *ap, gboolean invalid) * the ap list diffing functions to speed up the diff * */ -gboolean nm_ap_get_matched (NMAccessPoint *ap) +gboolean nm_ap_get_matched (const NMAccessPoint *ap) { g_return_val_if_fail (ap != NULL, TRUE); @@ -421,7 +423,7 @@ void nm_ap_set_matched (NMAccessPoint *ap, gboolean matched) * 'trusted' * */ -gboolean nm_ap_get_trusted (NMAccessPoint *ap) +gboolean nm_ap_get_trusted (const NMAccessPoint *ap) { g_return_val_if_fail (ap != NULL, FALSE); @@ -442,7 +444,7 @@ void nm_ap_set_trusted (NMAccessPoint *ap, gboolean trusted) * by the card or not * */ -gboolean nm_ap_get_artificial (NMAccessPoint *ap) +gboolean nm_ap_get_artificial (const NMAccessPoint *ap) { g_return_val_if_fail (ap != NULL, FALSE); @@ -457,6 +459,26 @@ void nm_ap_set_artificial (NMAccessPoint *ap, gboolean artificial) } +/* + * Get/Set functions for how long ago the AP was last seen in a scan. + * APs older than a certain date are dropped from the list. + * + */ +const GTimeVal *nm_ap_get_last_seen (const NMAccessPoint *ap) +{ + g_return_val_if_fail (ap != NULL, FALSE); + + return (&ap->last_seen); +} + +void nm_ap_set_last_seen (NMAccessPoint *ap, const GTimeVal *last_seen) +{ + g_return_if_fail (ap != NULL); + + ap->last_seen = *last_seen; +} + + /* * Get/Set functions to indicate that an access point is * user-created, ie whether or not its a network filled with @@ -464,7 +486,7 @@ void nm_ap_set_artificial (NMAccessPoint *ap, gboolean artificial) * wireless network. * */ -gboolean nm_ap_get_user_created (NMAccessPoint *ap) +gboolean nm_ap_get_user_created (const NMAccessPoint *ap) { g_return_val_if_fail (ap != NULL, FALSE); @@ -483,7 +505,7 @@ 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 (NMAccessPoint *ap) +const NMEncKeyType nm_ap_get_enc_method (const NMAccessPoint *ap) { g_return_val_if_fail (ap != NULL, TRUE); @@ -500,7 +522,7 @@ const NMEncKeyType nm_ap_get_enc_method (NMAccessPoint *ap) * ap's actual list. * */ -GSList *nm_ap_get_user_addresses (NMAccessPoint *ap) +GSList *nm_ap_get_user_addresses (const NMAccessPoint *ap) { GSList *new = NULL; GSList *elem = NULL; diff --git a/src/NetworkManagerAP.h b/src/NetworkManagerAP.h index d4db447f3a..c38059aaec 100644 --- a/src/NetworkManagerAP.h +++ b/src/NetworkManagerAP.h @@ -34,52 +34,55 @@ NMAccessPoint * nm_ap_new_from_ap (NMAccessPoint *ap); void nm_ap_unref (NMAccessPoint *ap); void nm_ap_ref (NMAccessPoint *ap); -const GTimeVal * nm_ap_get_timestamp (NMAccessPoint *ap); +const GTimeVal * nm_ap_get_timestamp (const NMAccessPoint *ap); void nm_ap_set_timestamp (NMAccessPoint *ap, const GTimeVal *timestamp); -char * nm_ap_get_essid (NMAccessPoint *ap); +char * nm_ap_get_essid (const NMAccessPoint *ap); void nm_ap_set_essid (NMAccessPoint *ap, const char *essid); -char * nm_ap_get_enc_key_source (NMAccessPoint *ap); -char * nm_ap_get_enc_key_hashed (NMAccessPoint *ap); +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); -gboolean nm_ap_get_encrypted (NMAccessPoint *ap); +gboolean nm_ap_get_encrypted (const NMAccessPoint *ap); void nm_ap_set_encrypted (NMAccessPoint *ap, gboolean encrypted); -struct ether_addr * nm_ap_get_address (NMAccessPoint *ap); +struct ether_addr * nm_ap_get_address (const NMAccessPoint *ap); void nm_ap_set_address (NMAccessPoint *ap, const struct ether_addr *addr); -NMNetworkMode nm_ap_get_mode (NMAccessPoint *ap); +NMNetworkMode nm_ap_get_mode (const NMAccessPoint *ap); void nm_ap_set_mode (NMAccessPoint *ap, const NMNetworkMode mode); -gint8 nm_ap_get_strength (NMAccessPoint *ap); +gint8 nm_ap_get_strength (const NMAccessPoint *ap); void nm_ap_set_strength (NMAccessPoint *ap, gint8 strength); -double nm_ap_get_freq (NMAccessPoint *ap); +double nm_ap_get_freq (const NMAccessPoint *ap); void nm_ap_set_freq (NMAccessPoint *ap, double freq); -guint16 nm_ap_get_rate (NMAccessPoint *ap); +guint16 nm_ap_get_rate (const NMAccessPoint *ap); void nm_ap_set_rate (NMAccessPoint *ap, guint16 rate); -gboolean nm_ap_get_invalid (NMAccessPoint *ap); +gboolean nm_ap_get_invalid (const NMAccessPoint *ap); void nm_ap_set_invalid (NMAccessPoint *ap, gboolean invalid); -gboolean nm_ap_get_matched (NMAccessPoint *ap); +gboolean nm_ap_get_matched (const NMAccessPoint *ap); void nm_ap_set_matched (NMAccessPoint *ap, gboolean matched); -gboolean nm_ap_get_trusted (NMAccessPoint *ap); +gboolean nm_ap_get_trusted (const NMAccessPoint *ap); void nm_ap_set_trusted (NMAccessPoint *ap, gboolean trusted); -gboolean nm_ap_get_artificial (NMAccessPoint *ap); +gboolean nm_ap_get_artificial (const NMAccessPoint *ap); void nm_ap_set_artificial (NMAccessPoint *ap, gboolean artificial); -gboolean nm_ap_get_user_created (NMAccessPoint *ap); +const GTimeVal * nm_ap_get_last_seen (const NMAccessPoint *ap); +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 (NMAccessPoint *ap); +const NMEncKeyType nm_ap_get_enc_method (const NMAccessPoint *ap); -GSList * nm_ap_get_user_addresses (NMAccessPoint *ap); +GSList * nm_ap_get_user_addresses (const NMAccessPoint *ap); void nm_ap_set_user_addresses (NMAccessPoint *ap, GSList *list); #endif diff --git a/src/NetworkManagerAPList.c b/src/NetworkManagerAPList.c index 31f2365f7f..42d54c7ff7 100644 --- a/src/NetworkManagerAPList.c +++ b/src/NetworkManagerAPList.c @@ -291,12 +291,12 @@ NMAccessPoint *nm_ap_list_get_ap_by_address (NMAccessPointList *list, const stru /* - * nm_ap_list_update_network + * nm_ap_list_update_network_from_nmi * * Given a network ID, get its information from NetworkManagerInfo * */ -void nm_ap_list_update_network (NMAccessPointList *list, const char *network, NMData *data) +void nm_ap_list_update_network_from_nmi (NMAccessPointList *list, const char *network, NMData *data) { NMAccessPoint *ap = NULL; NMAccessPoint *list_ap = NULL; @@ -332,12 +332,12 @@ void nm_ap_list_update_network (NMAccessPointList *list, const char *network, NM /* - * nm_ap_list_populate + * nm_ap_list_populate_from_nmi * * Populate an initial list of allowed access points * */ -void nm_ap_list_populate (NMAccessPointList *list, NMData *data) +void nm_ap_list_populate_from_nmi (NMAccessPointList *list, NMData *data) { char **networks; int num_networks; @@ -353,7 +353,7 @@ void nm_ap_list_populate (NMAccessPointList *list, NMData *data) for (i = 0; i < num_networks; i++) { if (networks[i] && (strlen (networks[i]) > 0)) - nm_ap_list_update_network (list, networks[i], data); + nm_ap_list_update_network_from_nmi (list, networks[i], data); } dbus_free_string_array (networks); @@ -362,63 +362,41 @@ void nm_ap_list_populate (NMAccessPointList *list, NMData *data) /* - * nm_ap_list_combine + * nm_ap_list_merge_scanned_ap * - * Combine two access point lists into one. This is a simple OR operation, where each - * unique access point in either list is present in the final, combined list. + * Given an AP list and an access point, merge the access point into the list. + * If the AP is already in the list, merge just the /attributes/ together for that + * AP, if its not already in the list then just add it. This doesn't merge all + * attributes, just ones that are likely to be new from the scan. + * + * Returns: FALSE if the AP was not new and was merged + * TRUE if the ap was completely new * - * NOTE: locks NMAccessPointList arguments */ -NMAccessPointList * nm_ap_list_combine (NMAccessPointList *list1, NMAccessPointList *list2) +gboolean nm_ap_list_merge_scanned_ap (NMAccessPointList *list, NMAccessPoint *merge_ap) { - NMAccessPointList *final_list = NULL; - NMAPListIter *iter; - NMAccessPoint *ap; + NMAccessPoint *list_ap; + gboolean new = FALSE; - final_list = nm_ap_list_new (NETWORK_TYPE_DEVICE); - if (!final_list) - return (NULL); + g_return_val_if_fail (merge_ap != NULL, FALSE); - /* Add all APs in the first list */ - if (list1 && (iter = nm_ap_list_iter_new (list1))) + if (!(list_ap = nm_ap_list_get_ap_by_address (list, nm_ap_get_address (merge_ap)))) + list_ap = nm_ap_list_get_ap_by_essid (list, nm_ap_get_essid (merge_ap)); + + if (list_ap) { - while ((ap = nm_ap_list_iter_next (iter))) - { - NMAccessPoint *new_ap = nm_ap_new_from_ap (ap); - if (new_ap) - { - nm_ap_list_append_ap (final_list, new_ap); - nm_ap_unref (new_ap); - } - } - nm_ap_list_iter_free (iter); + /* 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_last_seen (list_ap, nm_ap_get_last_seen (merge_ap)); + } + else + { + /* Add the whole AP, list takes ownership. */ + nm_ap_list_append_ap (list, merge_ap); + new = TRUE; } - /* Add all APs in the second list not already added from the first */ - if (list2 && (iter = nm_ap_list_iter_new (list2))) - { - while ((ap = nm_ap_list_iter_next (iter))) - { - if (!nm_ap_list_get_ap_by_essid (final_list, nm_ap_get_essid (ap))) - { - NMAccessPoint *new_ap = nm_ap_new_from_ap (ap); - if (new_ap) - { - nm_ap_list_append_ap (final_list, new_ap); - nm_ap_unref (new_ap); - } - } - } - nm_ap_list_iter_free (iter); - } - - if (nm_ap_list_is_empty (final_list)) - { - nm_ap_list_unref (final_list); - final_list = NULL; - } - - return (final_list); + return new; } diff --git a/src/NetworkManagerAPList.h b/src/NetworkManagerAPList.h index 579e6f0d6f..e8de7b7e62 100644 --- a/src/NetworkManagerAPList.h +++ b/src/NetworkManagerAPList.h @@ -30,35 +30,36 @@ typedef struct NMAccessPointList NMAccessPointList; typedef struct NMAPListIter NMAPListIter; -NMAccessPointList * nm_ap_list_new (NMNetworkType type); -void nm_ap_list_ref (NMAccessPointList *list); -void nm_ap_list_unref (NMAccessPointList *list); +NMAccessPointList * nm_ap_list_new (NMNetworkType type); +void nm_ap_list_ref (NMAccessPointList *list); +void nm_ap_list_unref (NMAccessPointList *list); -gboolean nm_ap_list_is_empty (NMAccessPointList *list); +gboolean nm_ap_list_is_empty (NMAccessPointList *list); -void nm_ap_list_append_ap (NMAccessPointList *list, NMAccessPoint *ap); -void nm_ap_list_remove_ap (NMAccessPointList *list, NMAccessPoint *ap); +void nm_ap_list_append_ap (NMAccessPointList *list, NMAccessPoint *ap); +void nm_ap_list_remove_ap (NMAccessPointList *list, NMAccessPoint *ap); -NMAccessPoint * nm_ap_list_get_ap_by_essid (NMAccessPointList *list, const char *network); -NMAccessPoint * nm_ap_list_get_ap_by_address (NMAccessPointList *list, const struct ether_addr *addr); +NMAccessPoint * nm_ap_list_get_ap_by_essid (NMAccessPointList *list, const char *network); +NMAccessPoint * nm_ap_list_get_ap_by_address (NMAccessPointList *list, const struct ether_addr *addr); -void nm_ap_list_update_network (NMAccessPointList *list, const char *network, NMData *data); +void nm_ap_list_update_network_from_nmi (NMAccessPointList *list, const char *network, NMData *data); -void nm_ap_list_populate (NMAccessPointList *list, NMData *data); +void nm_ap_list_populate_from_nmi (NMAccessPointList *list, NMData *data); -void nm_ap_list_copy_properties (NMAccessPointList *dest, NMAccessPointList *source); +void nm_ap_list_copy_properties (NMAccessPointList *dest, NMAccessPointList *source); void nm_ap_list_copy_essids_by_address (NMAccessPointList *dest, NMAccessPointList *source); -NMAccessPointList * nm_ap_list_combine (NMAccessPointList *list1, NMAccessPointList *list2); -void nm_ap_list_diff (NMData *data, NMDevice *dev, NMAccessPointList *old, NMAccessPointList *new); -gboolean nm_ap_list_lock (NMAccessPointList *list); -void nm_ap_list_unlock (NMAccessPointList *list); +void nm_ap_list_diff (NMData *data, NMDevice *dev, NMAccessPointList *old, NMAccessPointList *new); +gboolean nm_ap_list_merge_scanned_ap (NMAccessPointList *list, NMAccessPoint *merge_ap); -NMAPListIter * nm_ap_list_iter_new (NMAccessPointList *list); -NMAccessPoint * nm_ap_list_iter_get_ap (NMAPListIter *iter); -NMAccessPoint * nm_ap_list_iter_next (NMAPListIter *iter); -void nm_ap_list_iter_free (NMAPListIter *iter); +gboolean nm_ap_list_lock (NMAccessPointList *list); +void nm_ap_list_unlock (NMAccessPointList *list); -void nm_ap_list_print_members (NMAccessPointList *list, const char *name); +NMAPListIter * nm_ap_list_iter_new (NMAccessPointList *list); +NMAccessPoint * nm_ap_list_iter_get_ap (NMAPListIter *iter); +NMAccessPoint * nm_ap_list_iter_next (NMAPListIter *iter); +void nm_ap_list_iter_free (NMAPListIter *iter); + +void nm_ap_list_print_members (NMAccessPointList *list, const char *name); #endif diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index b8901386af..a32e034258 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -1060,8 +1060,8 @@ static DBusHandlerResult nm_dbus_nmi_filter (DBusConnection *connection, DBusMes if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &network, DBUS_TYPE_INVALID)) return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - syslog (LOG_DEBUG, "NetowrkManagerInfo triggered update of wireless network '%s'", network); - nm_ap_list_update_network (data->allowed_ap_list, network, data); + syslog (LOG_DEBUG, "NetworkManagerInfo triggered update of wireless network '%s'", network); + nm_ap_list_update_network_from_nmi (data->allowed_ap_list, network, data); dbus_free (network); handled = TRUE; } diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c index 77d56265a7..65878e10d1 100644 --- a/src/NetworkManagerDevice.c +++ b/src/NetworkManagerDevice.c @@ -41,8 +41,16 @@ /* Local static prototypes */ static gboolean mii_get_link (NMDevice *dev); -static gpointer nm_device_activation_worker (gpointer user_data); +static gpointer nm_device_worker (gpointer user_data); +static gboolean nm_device_activate (gpointer user_data); static gboolean nm_device_activation_configure_ip (NMDevice *dev, gboolean do_only_autoip); +static gboolean nm_device_wireless_scan (gpointer user_data); + +typedef struct +{ + NMDevice *dev; + struct wireless_scan_head scan_head; +} NMWirelessScanResults; /******************************************************/ @@ -197,6 +205,7 @@ NMDevice *nm_get_device_by_iface (NMData *data, const char *iface) NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev, NMDeviceType test_dev_type, NMData *app_data) { NMDevice *dev; + GError *error = NULL; g_return_val_if_fail (iface != NULL, NULL); g_return_val_if_fail (strlen (iface) > 0, NULL); @@ -223,7 +232,7 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev, return (NULL); } - dev->refcount = 1; + dev->refcount = 2; /* 1 for starters, and another 1 for the worker thread */ dev->app_data = app_data; dev->iface = g_strdup (iface); dev->test_device = test_dev; @@ -247,6 +256,8 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev, iwrange range; int sk; + dev->options.wireless.scan_interval = 20; + if (!(dev->options.wireless.scan_mutex = g_mutex_new ())) { g_free (dev->iface); @@ -294,6 +305,20 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev, nm_system_device_update_config_info (dev); } + if (!g_thread_create (nm_device_worker, dev, FALSE, &error)) + { + syslog (LOG_CRIT, "nm_device_new (): could not create device worker thread. (glib said: '%s')", error->message); + g_error_free (error); + + /* When we get here, we've got a refcount of 2, one because the + * device starts off with a refcount of 1, and a second ref because + * so that it sticks around for the worker thread. So we have to unref twice. + */ + nm_device_unref (dev); + nm_device_unref (dev); + dev = NULL; + } + return (dev); } @@ -328,6 +353,8 @@ gboolean nm_device_unref (NMDevice *dev) { if (dev->loop) g_main_loop_quit (dev->loop); + while (dev->worker_done == FALSE) + g_usleep (300); if (nm_device_is_wireless (dev)) { @@ -337,13 +364,8 @@ gboolean nm_device_unref (NMDevice *dev) g_mutex_free (dev->options.wireless.scan_mutex); if (dev->options.wireless.ap_list) nm_ap_list_unref (dev->options.wireless.ap_list); - if (dev->options.wireless.cached_ap_list1) - nm_ap_list_unref (dev->options.wireless.cached_ap_list1); - if (dev->options.wireless.cached_ap_list2) - nm_ap_list_unref (dev->options.wireless.cached_ap_list2); - if (dev->options.wireless.cached_ap_list3) - nm_ap_list_unref (dev->options.wireless.cached_ap_list3); - nm_ap_unref (dev->options.wireless.best_ap); + if (dev->options.wireless.best_ap) + nm_ap_unref (dev->options.wireless.best_ap); g_mutex_free (dev->options.wireless.best_ap_mutex); } @@ -359,6 +381,57 @@ gboolean nm_device_unref (NMDevice *dev) } +/* + * nm_device_worker + * + * Main thread of the device. + * + */ +static gpointer nm_device_worker (gpointer user_data) +{ + NMDevice *dev = (NMDevice *)user_data; + + g_return_val_if_fail (dev != NULL, NULL); + + dev->context = g_main_context_new (); + dev->loop = g_main_loop_new (dev->context, FALSE); + + /* Do an initial wireless scan */ + if (nm_device_is_wireless (dev)) + { + GSource *source = g_idle_source_new (); + guint source_id = 0; + + g_source_set_callback (source, nm_device_wireless_scan, dev, NULL); + source_id = g_source_attach (source, dev->context); + g_source_unref (source); + } + + g_main_loop_run (dev->loop); + + if (nm_device_config_get_use_dhcp (dev)) + { + if (dev->renew_timeout > 0) + g_source_remove (dev->renew_timeout); + if (dev->rebind_timeout > 0) + g_source_remove (dev->rebind_timeout); + } + + g_main_loop_unref (dev->loop); + g_main_context_unref (dev->context); + + dev->loop = NULL; + dev->context = NULL; + dev->renew_timeout = 0; + dev->rebind_timeout = 0; + + dev->worker_done = TRUE; + nm_device_unref (dev); + + return NULL; +} + + /* * nm_device_get_app_data * @@ -829,6 +902,10 @@ void nm_device_set_frequency (NMDevice *dev, const double freq) int sk; int err; + /* HACK FOR NOW */ + if (freq <= 0) + return; + g_return_if_fail (dev != NULL); g_return_if_fail (nm_device_is_wireless (dev)); @@ -883,9 +960,6 @@ void nm_device_set_frequency (NMDevice *dev, const double freq) if (iw_set_ext (sk, nm_device_get_iface (dev), SIOCSIWFREQ, &wrq) != -1) success = TRUE; } - - if (!success && (errno != EOPNOTSUPP) && (errno != EINVAL) && (errno != EIO)) /* prism54 cards return EIO sometimes */ - syslog (LOG_ERR, "nm_device_set_frequency(): error setting frequency %f for device %s. errno = %d", freq, nm_device_get_iface (dev), errno); } close (sk); @@ -1568,18 +1642,20 @@ void nm_device_activation_schedule_finish (NMDevice *dev, gboolean success) /* - * nm_device_activation_begin + * nm_device_activation_schedule_start * - * Spawn a new thread to handle device activation. + * Tell the device thread to begin activation. * * Returns: TRUE on success activation beginning * FALSE on error beginning activation (bad params, couldn't create thread) * */ -gboolean nm_device_activation_begin (NMDevice *dev) +gboolean nm_device_activation_schedule_start (NMDevice *dev) { GError *error = NULL; NMData *data = (NMData *)dev->app_data; + 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 */ @@ -1614,16 +1690,10 @@ gboolean nm_device_activation_begin (NMDevice *dev) return (TRUE); } - /* Ref the device so it doesn't go away while worker function is active */ - nm_device_ref (dev); - - if (!g_thread_create (nm_device_activation_worker, dev, FALSE, &error)) - { - syslog (LOG_CRIT, "nm_device_activation_begin(): could not create activation worker thread."); - dev->activating = FALSE; - nm_device_unref (dev); - return (FALSE); - } + source = g_idle_source_new (); + g_source_set_callback (source, nm_device_activate, dev, NULL); + g_source_attach (source, dev->context); + g_source_unref (source); nm_dbus_signal_device_status_change (data->dbus_connection, dev, DEVICE_ACTIVATING); @@ -1873,19 +1943,23 @@ static gboolean AP_NEED_KEY (NMAccessPoint *ap) { char *s; int len = 0; + char *essid; + 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 is unencrypted, no key needed."); + syslog (LOG_NOTICE, "AP_NEED_KEY: access point '%s' is unencrypted, no key needed.", essid ? essid : "(null)"); else { if (!!nm_ap_get_enc_key_source (ap) && len) - syslog (LOG_NOTICE, "AP_NEED_KEY: access point is encrypted, and a key exists. No new key needed."); + syslog (LOG_NOTICE, "AP_NEED_KEY: access point '%s' is encrypted, and a key exists. No new key needed.", essid ? essid : "(null)"); else - syslog (LOG_NOTICE, "AP_NEED_KEY: access point is encrypted, but NO valid key exists. New key needed."); + syslog (LOG_NOTICE, "AP_NEED_KEY: access point '%s' is encrypted, but NO valid key exists. New key needed.", essid ? essid : "(null)"); } if (nm_ap_get_encrypted (ap) && (!nm_ap_get_enc_key_source (ap) || !len)) return (TRUE); @@ -1893,15 +1967,6 @@ static gboolean AP_NEED_KEY (NMAccessPoint *ap) return (FALSE); } -static gboolean HAVE_LINK (NMDevice *dev) -{ - g_return_val_if_fail (dev != NULL, FALSE); - g_return_val_if_fail (nm_device_is_wireless (dev), FALSE); - - syslog (LOG_NOTICE, "HAVELINK: card appears %s a link to the access point.", nm_device_get_link_active (dev) ? "to have" : "NOT to have"); - return (nm_device_get_link_active (dev)); -} - /* * nm_device_activate_wireless @@ -1942,13 +2007,14 @@ get_ap: while (!(best_ap = nm_device_get_best_ap (dev))) { dev->options.wireless.now_scanning = TRUE; - syslog (LOG_DEBUG, "nm_device_activate_wireless(%s): waiting for an access point.", nm_device_get_iface (dev)); + 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; g_mutex_lock (dev->options.wireless.scan_mutex); goto out; } @@ -1976,7 +2042,7 @@ get_ap: } else { - syslog (LOG_DEBUG, "nm_device_activate_wireless(%s): no link to '%s', or couldn't get configure interface for IP. Trying another access point.", + syslog (LOG_DEBUG, "Activation (%s/wireless): no link to '%s', or couldn't get configure interface for IP. 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); @@ -1991,7 +2057,7 @@ get_ap: } else { - NMDeviceAuthMethod auth = NM_DEVICE_AUTH_METHOD_SHARED_KEY; + NMDeviceAuthMethod auth = NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM; gboolean need_key = AP_NEED_KEY (best_ap); need_key: @@ -2012,32 +2078,23 @@ get_ap: need_key = FALSE; /* Wait for the key to come back */ - syslog (LOG_DEBUG, "nm_device_activation_worker(%s): asking for user key.", nm_device_get_iface (dev)); + 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, "nm_device_activation_worker(%s): user key received.", nm_device_get_iface (dev)); + 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); - /* If we were told to quit activation, stop the thread and return */ - if (nm_device_activation_handle_cancel (dev)) - { - nm_ap_unref (best_ap); - goto out; - } - - /* User may have cancelled the key request, so we need to update our best AP again. - * However, if they didn't, since there will now be a key, we won't get back here for - * the same access point until the key is deemed incorrect below. - */ + /* User may have cancelled the key request, so we need to update our best AP again. */ nm_ap_unref (best_ap); + goto get_ap; } try_connect: - while (auth > NM_DEVICE_AUTH_METHOD_NONE) + while (auth != NM_DEVICE_AUTH_METHOD_NONE) { int ip_success = FALSE; @@ -2063,19 +2120,19 @@ get_ap: link = nm_device_wireless_wait_for_link (dev, nm_ap_get_essid (best_ap)); - if (!link && (auth == NM_DEVICE_AUTH_METHOD_SHARED_KEY)) + if (!link && (auth == NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM)) { - syslog (LOG_DEBUG, "nm_device_activate_wireless(%s): no hardware link to '%s' in Shared Key mode, trying 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 Open System mode */ - auth--; + /* 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, "nm_device_activate_wireless(%s): no hardware link to '%s' in Open System mode, trying another access point.", + 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); @@ -2083,18 +2140,18 @@ get_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_SHARED_KEY)) + if (!ip_success && (auth == NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM)) { - /* Back down to Open System mode */ - syslog (LOG_DEBUG, "nm_device_activate_wireless(%s): could not get IP configuration info for '%s' in Shared Key mode, trying 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--; + 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, "nm_device_activate_wireless(%s): could not get IP configuration info for '%s' in Open System mode, asking for new 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; @@ -2109,7 +2166,7 @@ get_ap: if (success) { - syslog (LOG_DEBUG, "nm_device_activate_wireless(%s): Success! Connected to access point '%s' and got an IP address.", + syslog (LOG_DEBUG, "Activation (%s/wireless): Success! Connected to access point '%s' and got an IP address.", nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); nm_ap_unref (best_ap); } @@ -2178,22 +2235,21 @@ static gboolean nm_device_activation_configure_ip (NMDevice *dev, gboolean do_on /* - * nm_device_activation_worker + * nm_device_activate + * + * Activate a device, done from the device's worker thread. * - * Thread worker function to actually activate a device. We have to do it in another - * thread because things like dhclient block our main thread's event loop, and thus we - * wouldn't respond to dbus messages. */ -static gpointer nm_device_activation_worker (gpointer user_data) +static gboolean nm_device_activate (gpointer user_data) { NMDevice *dev = (NMDevice *)user_data; gboolean success = FALSE; GMainContext *context = NULL; - g_return_val_if_fail (dev != NULL, NULL); - g_return_val_if_fail (dev->app_data != NULL, NULL); + g_return_val_if_fail (dev != NULL, FALSE); + g_return_val_if_fail (dev->app_data != NULL, FALSE); - syslog (LOG_DEBUG, "nm_device_activation_worker (%s) started...", nm_device_get_iface (dev)); + syslog (LOG_DEBUG, "Activation (%s) started...", nm_device_get_iface (dev)); /* Bring the device up */ if (!nm_device_is_up (dev)); @@ -2221,23 +2277,22 @@ static gpointer nm_device_activation_worker (gpointer user_data) } else if (nm_device_is_wired (dev)) success = nm_device_activation_configure_ip (dev, FALSE); - syslog (LOG_DEBUG, "Activation (%s) IP configuration/DHCP returned = %d\n", nm_device_get_iface (dev), success); /* 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) IP configuration/DHCP unsuccessful! Ending activation...\n", nm_device_get_iface (dev)); - dev->activating = FALSE; - dev->quit_activation = FALSE; - goto out; - } - dev->activating = FALSE; dev->quit_activation = FALSE; - syslog (LOG_DEBUG, "Activation (%s) IP configuration/DHCP successful!\n", nm_device_get_iface (dev)); + + if (success) + syslog (LOG_DEBUG, "Activation (%s) IP configuration/DHCP successful!\n", nm_device_get_iface (dev)); + else + syslog (LOG_DEBUG, "Activation (%s) IP configuration/DHCP unsuccessful! Ending activation...\n", nm_device_get_iface (dev)); + + /* Setup DHCP timeouts if we need to renew/rebind at any point */ + 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)) @@ -2245,37 +2300,15 @@ static gpointer nm_device_activation_worker (gpointer user_data) nm_device_activation_schedule_finish (dev, success); - syslog (LOG_INFO, "nm_device_activation_worker(%s): device activated", nm_device_get_iface (dev)); - - /* Don't need to stick around for devices that use Static IP */ - if (!nm_device_config_get_use_dhcp (dev) || !dev->dhcp_iface) - goto out; - - /* We stick around if we need to renew the address with DHCP or something. */ - dev->context = g_main_context_new (); - dev->loop = g_main_loop_new (context, FALSE); - nm_device_dhcp_setup_timeouts (dev); - - g_main_loop_run (dev->loop); - - g_source_remove (dev->renew_timeout); - g_source_remove (dev->rebind_timeout); - g_main_loop_unref (dev->loop); - g_main_context_unref (dev->context); - out: - dev->context = NULL; - dev->loop = NULL; if (dev->dhcp_iface) { dhcp_interface_free (dev->dhcp_iface); dev->dhcp_iface = NULL; } - nm_device_unref (dev); - - syslog (LOG_DEBUG, "Activation (%s) ending thread.\n", nm_device_get_iface (dev)); - return (NULL); + syslog (LOG_DEBUG, "Activation (%s) ended.\n", nm_device_get_iface (dev)); + return FALSE; } @@ -2356,9 +2389,6 @@ gboolean nm_device_deactivate (NMDevice *dev, gboolean just_added) nm_device_activation_cancel (dev); - if (dev->loop) - g_main_loop_quit (dev->loop); - if (nm_device_get_driver_support_level (dev) == NM_DRIVER_UNSUPPORTED) return (TRUE); @@ -2376,6 +2406,7 @@ gboolean nm_device_deactivate (NMDevice *dev, gboolean just_added) nm_device_set_essid (dev, ""); nm_device_set_enc_key (dev, NULL, NM_DEVICE_AUTH_METHOD_NONE); nm_device_set_mode (dev, NETWORK_MODE_INFRA); + dev->options.wireless.scan_interval = 20; } return (TRUE); @@ -2784,13 +2815,6 @@ void nm_device_update_best_ap (NMDevice *dev) /* If the best ap is NULL, bring device down and clear out its essid and AP */ nm_device_set_best_ap (dev, best_ap); - if (!best_ap) - { - nm_device_set_frequency (dev, 0); - nm_device_set_enc_key (dev, NULL, NM_DEVICE_AUTH_METHOD_NONE); - nm_device_set_essid (dev, ""); - nm_device_bring_up (dev); - } } @@ -2812,7 +2836,7 @@ gboolean nm_device_wireless_network_exists (NMDevice *dev, const char *network, gboolean temp_enc = FALSE; struct ether_addr addr; NMAccessPoint *ap = NULL; - NMDeviceAuthMethod auths[3] = { NM_DEVICE_AUTH_METHOD_SHARED_KEY, NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM, NM_DEVICE_AUTH_METHOD_NONE }; + 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; @@ -2840,8 +2864,8 @@ gboolean nm_device_wireless_network_exists (NMDevice *dev, const char *network, if (!nm_ap_get_encrypted (ap)) { auths[0] = NM_DEVICE_AUTH_METHOD_NONE; - auths[1] = NM_DEVICE_AUTH_METHOD_SHARED_KEY; - auths[2] = NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM; + auths[1] = NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM; + auths[2] = NM_DEVICE_AUTH_METHOD_SHARED_KEY; } } @@ -2873,17 +2897,17 @@ gboolean nm_device_wireless_network_exists (NMDevice *dev, const char *network, char *hashed_key = NULL; switch (key_type) { - case (NM_ENC_TYPE_128_BIT_PASSPHRASE): + case NM_ENC_TYPE_128_BIT_PASSPHRASE: hashed_key = nm_wireless_128bit_key_from_passphrase (key); break; - case (NM_ENC_TYPE_ASCII_KEY): + 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): + case NM_ENC_TYPE_HEX_KEY: + case NM_ENC_TYPE_UNKNOWN: hashed_key = g_strdup (key); break; default: @@ -2893,7 +2917,10 @@ gboolean nm_device_wireless_network_exists (NMDevice *dev, const char *network, 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: @@ -3168,31 +3195,55 @@ static void nm_device_fake_ap_list (NMDevice *dev) /* - * nm_device_process_scan_results + * nm_device_wireless_schedule_scan * - * Process results of an iwscan() into our own AP lists + * Schedule a wireless scan in the /device's/ thread. * */ -void nm_device_process_scan_results (NMDevice *dev, wireless_scan_head *results) +static void nm_device_wireless_schedule_scan (NMDevice *dev) { - wireless_scan *tmp_ap; - NMAccessPointList *old_ap_list = NULL; - NMAccessPointList *new_scan_list = NULL; - NMAccessPointList *earliest_scan = NULL; - gboolean have_blank_essids = FALSE; - NMAPListIter *iter; - NMAccessPoint *artificial_ap; + GSource *wscan_source; + guint wscan_source_id; g_return_if_fail (dev != NULL); + g_return_if_fail (nm_device_is_wireless (dev)); - if (!results) - return; + wscan_source = g_timeout_source_new (dev->options.wireless.scan_interval * 1000); + g_source_set_callback (wscan_source, nm_device_wireless_scan, dev, NULL); + wscan_source_id = g_source_attach (wscan_source, dev->context); + g_source_unref (wscan_source); +} + + +/* + * nm_device_wireless_process_scan_results + * + * Process results of an iwscan() into our own AP lists. We're an idle function, + * but we never reschedule ourselves. + * + */ +static gboolean nm_device_wireless_process_scan_results (gpointer user_data) +{ + NMWirelessScanResults *results = (NMWirelessScanResults *)user_data; + NMDevice *dev; + wireless_scan *tmp_ap; + gboolean have_blank_essids = FALSE; + NMAPListIter *iter; + GTimeVal cur_time; + gboolean list_changed = FALSE; + + g_return_val_if_fail (results != NULL, FALSE); + + dev = results->dev; + + if (!dev || !results->scan_head.result) + return FALSE; /* Test devices get their info faked */ if (dev->test_device) { nm_device_fake_ap_list (dev); - return; + return FALSE; } /* Devices that don't support scanning have their pseudo-scanning done in @@ -3201,17 +3252,11 @@ void nm_device_process_scan_results (NMDevice *dev, wireless_scan_head *results) if (!nm_device_supports_wireless_scan (dev)) { nm_device_do_pseudo_scan (dev); - return; + return FALSE; } - /* Shift all previous cached scan results and dispose of the oldest one. */ - earliest_scan = dev->options.wireless.cached_ap_list3; - dev->options.wireless.cached_ap_list3 = dev->options.wireless.cached_ap_list2; - dev->options.wireless.cached_ap_list2 = dev->options.wireless.cached_ap_list1; - dev->options.wireless.cached_ap_list1 = nm_ap_list_new (NETWORK_TYPE_DEVICE); - - /* Iterate over scan results and pick a "most" preferred access point. */ - tmp_ap = results->result; + /* Translate iwlib scan results to NM access point list */ + tmp_ap = results->scan_head.result; while (tmp_ap) { /* We need at least an ESSID or a MAC address for each access point */ @@ -3267,90 +3312,104 @@ void nm_device_process_scan_results (NMDevice *dev, wireless_scan_head *results) if (tmp_ap->b.has_freq) nm_ap_set_freq (nm_ap, tmp_ap->b.freq); + g_get_current_time (&cur_time); + nm_ap_set_last_seen (nm_ap, &cur_time); + /* Add the AP to the device's AP list */ - nm_ap_list_append_ap (dev->options.wireless.cached_ap_list1, nm_ap); + if (nm_ap_list_merge_scanned_ap (nm_device_ap_list_get (dev), nm_ap)) + { + nm_dbus_signal_wireless_network_change (dev->app_data->dbus_connection, dev, nm_ap, FALSE); + list_changed = TRUE; + } nm_ap_unref (nm_ap); } tmp_ap = tmp_ap->next; } - /* Compose the current access point list for the card based on the past two scans. This - * is to achieve some stability in the list, since cards don't necessarily return the same - * access point list each scan even if you are standing in the same place. - */ - old_ap_list = nm_device_ap_list_get (dev); - dev->options.wireless.ap_list = nm_ap_list_combine (dev->options.wireless.cached_ap_list1, dev->options.wireless.cached_ap_list2); - - /* If any blank ESSID networks were detected in the current scan, try to match their - * AP MAC address with existing ones in previous scans, and if we get a match, copy the - * ESSID over to the newest scan list. This enures that we keep the known ESSID for that - * base station around as long as possible, which allows nm_device_update_best_ap() to do - * its job when the user wanted us to connect to a non-broadcasting network. + /* If we detected any blank-ESSID access points (ie don't broadcast their ESSID), then try to + * merge in ESSIDs that we have addresses for from user preferences/NetworkManagerInfo. */ if (have_blank_essids) - { - nm_ap_list_copy_essids_by_address (nm_device_ap_list_get (dev), old_ap_list); nm_ap_list_copy_essids_by_address (nm_device_ap_list_get (dev), dev->app_data->allowed_ap_list); - } /* Once we have the list, copy in any relevant information from our Allowed list. */ nm_ap_list_copy_properties (nm_device_ap_list_get (dev), dev->app_data->allowed_ap_list); - /* Furthermore, if we have any "artificial" access points, ie ones that exist but don't show up in - * the scan for some reason, copy those over if we are associated with that access point right now. - * Some Cisco cards don't report non-ESSID-broadcasting access points in their scans even though - * the card associates with that AP just fine. - */ - if (old_ap_list && (iter = nm_ap_list_iter_new (old_ap_list))) + /* Walk the access point list and remove any access points older than 60s */ + g_get_current_time (&cur_time); + if (nm_device_ap_list_get (dev) && (iter = nm_ap_list_iter_new (nm_device_ap_list_get (dev)))) { - char *essid = nm_device_get_essid (dev); + NMAccessPoint *outdated_ap; + GSList *outdated_list = NULL; + GSList *elem; + char *essid = nm_device_get_essid (dev); - while (essid && (artificial_ap = nm_ap_list_iter_next (iter))) + while ((outdated_ap = nm_ap_list_iter_next (iter))) { - /* Copy over the artificial AP from the old list to the new one if - * its the AP the card is currently associated with. + const GTimeVal *ap_time = nm_ap_get_last_seen (outdated_ap); + gboolean keep_around = FALSE; + + /* We don't add an "artifical" APs to the outdated list if it is the + * one the card is currently associated with. + * Some Cisco cards don't report non-ESSID-broadcasting access points + * in their scans even though the card associates with that AP just fine. */ - if ( nm_ap_get_essid (artificial_ap) - && !strcmp (essid, nm_ap_get_essid (artificial_ap)) - && nm_ap_get_artificial (artificial_ap)) - nm_ap_list_append_ap (nm_device_ap_list_get (dev), artificial_ap); + if ( nm_ap_get_essid (outdated_ap) + && !strcmp (essid, nm_ap_get_essid (outdated_ap)) + && nm_ap_get_artificial (outdated_ap)) + keep_around = TRUE; + + /* Eh, we don't care about sub-second time resolution. */ + if ((ap_time->tv_sec + 60 < cur_time.tv_sec) && !keep_around) + outdated_list = g_slist_append (outdated_list, outdated_ap); } nm_ap_list_iter_free (iter); + + /* Ok, now remove outdated ones. We have to do it after the lock + * because nm_ap_list_remove_ap() locks the list too. + */ + elem = outdated_list; + while (elem) + { + if ((outdated_ap = (NMAccessPoint *)(elem->data))) + { + nm_dbus_signal_wireless_network_change (dev->app_data->dbus_connection, dev, outdated_ap, TRUE); + nm_ap_list_remove_ap (nm_device_ap_list_get (dev), outdated_ap); + list_changed = TRUE; + } + elem = g_slist_next (elem); + } + g_slist_free (outdated_list); } - if (old_ap_list) - nm_ap_list_unref (old_ap_list); - /* Generate the "old" list from the 3rd and 4th oldest scans we've done */ - old_ap_list = nm_ap_list_combine (dev->options.wireless.cached_ap_list3, earliest_scan); + /* If the list changed, decrease our wireless scanning interval */ + if (list_changed) + dev->options.wireless.scan_interval = 20; + else + dev->options.wireless.scan_interval = MIN (60, dev->options.wireless.scan_interval + 10); - /* Don't need the 4th scan around any more */ - if (earliest_scan) - nm_ap_list_unref (earliest_scan); - - /* Now do a diff of the old and new networks that we can see, and - * signal any changes over dbus. - */ - nm_ap_list_diff (dev->app_data, dev, old_ap_list, nm_device_ap_list_get (dev)); - if (old_ap_list) - nm_ap_list_unref (old_ap_list); + return FALSE; } /* - * nm_device_do_wireless_scan + * nm_device_wireless_scan * * Get a list of access points this device can see. * */ -void nm_device_do_wireless_scan (NMDevice *dev, wireless_scan_head *results) +static gboolean nm_device_wireless_scan (gpointer user_data) { - int sk; + NMDevice *dev = (NMDevice *)(user_data); + int sk; + NMWirelessScanResults *scan_results = NULL; - g_return_if_fail (dev != NULL); + g_return_val_if_fail (dev != NULL, FALSE); + g_return_val_if_fail (dev->app_data != NULL, FALSE); /* We don't really scan on test devices or devices that don't have scanning support */ if (dev->test_device || !nm_device_supports_wireless_scan (dev)) - return; + return FALSE; /* Grab the scan mutex */ if (nm_try_acquire_mutex (dev->options.wireless.scan_mutex, __FUNCTION__)) @@ -3366,12 +3425,14 @@ void nm_device_do_wireless_scan (NMDevice *dev, wireless_scan_head *results) int err; NMNetworkMode orig_mode = NETWORK_MODE_INFRA; double orig_freq = 0; - int orig_rate; + int orig_rate = 0; orig_mode = nm_device_get_mode (dev); if (orig_mode == NETWORK_MODE_ADHOC) + { orig_freq = nm_device_get_frequency (dev); - orig_rate = nm_device_get_bitrate (dev); + orig_rate = nm_device_get_bitrate (dev); + } /* Must be in infrastructure mode during scan, otherwise we don't get a full * list of scan results. Scanning doesn't work well in Ad-Hoc mode :( @@ -3379,29 +3440,54 @@ void nm_device_do_wireless_scan (NMDevice *dev, wireless_scan_head *results) nm_device_set_mode (dev, NETWORK_MODE_INFRA); nm_device_set_frequency (dev, 0); - err = iw_scan (sk, (char *)nm_device_get_iface (dev), WIRELESS_EXT, results); + scan_results = g_malloc0 (sizeof (NMWirelessScanResults)); + err = iw_scan (sk, (char *)nm_device_get_iface (dev), WIRELESS_EXT, &(scan_results->scan_head)); if ((err == -1) && (errno == ENODATA)) { /* Card hasn't had time yet to compile full access point list. * Give it some more time and scan again. If that doesn't work - * give up. Cards that need to scan more channels (Atheros 5212 - * based cards, for example) need more time here. + * give up. */ g_usleep ((G_USEC_PER_SEC * nm_device_get_association_pause_value (dev)) / 2); - err = iw_scan (sk, (char *)nm_device_get_iface (dev), WIRELESS_EXT, results); + err = iw_scan (sk, (char *)nm_device_get_iface (dev), WIRELESS_EXT, &(scan_results->scan_head)); if (err == -1) - results->result = NULL; + 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)); + nm_device_set_mode (dev, orig_mode); /* Only set frequency if ad-hoc mode */ if (orig_mode == NETWORK_MODE_ADHOC) + { nm_device_set_frequency (dev, orig_freq); - nm_device_set_bitrate (dev, orig_rate); + nm_device_set_bitrate (dev, orig_rate); + } close (sk); } nm_unlock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__); } + + /* We run the scan processing function from the main thread, since it must deliver + * messages over DBUS. Plus, that way the main thread is the only thread that has + * to modify the device's access point list. + */ + if ((scan_results != NULL) && (scan_results->scan_head.result != NULL)) + { + guint scan_process_source_id = 0; + GSource *scan_process_source = g_idle_source_new (); + + scan_results->dev = dev; + g_source_set_callback (scan_process_source, nm_device_wireless_process_scan_results, scan_results, NULL); + scan_process_source_id = g_source_attach (scan_process_source, dev->app_data->main_context); + g_source_unref (scan_process_source); + } + + /* Make sure we reschedule ourselves so we keep scanning */ + nm_device_wireless_schedule_scan (dev); + + return FALSE; } diff --git a/src/NetworkManagerDevice.h b/src/NetworkManagerDevice.h index 8c4cb0db5c..15e9a9f3ad 100644 --- a/src/NetworkManagerDevice.h +++ b/src/NetworkManagerDevice.h @@ -80,8 +80,6 @@ void nm_device_update_hw_address (NMDevice *dev); void nm_device_get_ip6_address (NMDevice *dev); gboolean nm_device_get_supports_wireless_scan (NMDevice *dev); -void nm_device_process_scan_results (NMDevice *dev, struct wireless_scan_head *results); -void nm_device_do_wireless_scan (NMDevice *dev, struct wireless_scan_head *results); gboolean nm_device_wireless_network_exists (NMDevice *dev, const char *network, const char *key, NMEncKeyType key_type, struct ether_addr *addr, gboolean *encrypted); @@ -107,7 +105,7 @@ char * nm_device_get_path_for_ap (NMDevice *dev, NMAccessPoint *ap); /* There is no function to get the WEP key since that's a slight security risk */ void nm_device_set_enc_key (NMDevice *dev, const char *key, NMDeviceAuthMethod auth_method); -gboolean nm_device_activation_begin (NMDevice *dev); +gboolean nm_device_activation_schedule_start(NMDevice *dev); void nm_device_activation_cancel (NMDevice *dev); gboolean nm_device_activation_should_cancel (NMDevice *dev); gboolean nm_device_is_activating (NMDevice *dev); diff --git a/src/NetworkManagerDevicePrivate.h b/src/NetworkManagerDevicePrivate.h index 8a6201b672..deb656c5c0 100644 --- a/src/NetworkManagerDevicePrivate.h +++ b/src/NetworkManagerDevicePrivate.h @@ -45,16 +45,8 @@ typedef struct NMDeviceWirelessOptions struct iw_range range_info; GMutex *scan_mutex; - /* We keep a couple lists around since wireless cards - * are a bit flakey and don't report the same access - * points every time. The lists get merged and diffed - * to figure out the "real" list, but the latest_ap_list - * is always the most-current scan. - */ NMAccessPointList *ap_list; - NMAccessPointList *cached_ap_list1; - NMAccessPointList *cached_ap_list2; - NMAccessPointList *cached_ap_list3; + guint8 scan_interval; /* seconds */ NMAccessPoint *best_ap; GMutex *best_ap_mutex; @@ -110,6 +102,7 @@ struct NMDevice GMainContext *context; GMainLoop *loop; + gboolean worker_done; guint renew_timeout; guint rebind_timeout; diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index 5b55b0be9f..975e97161b 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -130,8 +130,10 @@ static NMDevice * nm_policy_auto_get_best_device (NMData *data) element = g_slist_next (element); } +#if 0 syslog (LOG_NOTICE, "AUTO: Best wired device = %s, best wireless device = %s (%s)", best_wired_dev ? nm_device_get_iface (best_wired_dev) : "(null)", best_wireless_dev ? nm_device_get_iface (best_wireless_dev) : "(null)", best_wireless_dev ? nm_device_get_essid (best_wireless_dev) : "null" ); +#endif if (best_wireless_dev || best_wired_dev) { @@ -258,7 +260,7 @@ gboolean nm_policy_activation_finish (gpointer user_data) 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, "nm_state_modification_monitor() activated device %s", nm_device_get_iface (data->active_device)); + syslog (LOG_INFO, "Activation (%s) successful, device activated.", nm_device_get_iface (data->active_device)); } else { @@ -277,16 +279,16 @@ gboolean nm_policy_activation_finish (gpointer user_data) /* Unref because nm_device_get_best_ap() refs it before returning. */ nm_ap_unref (ap); } - syslog (LOG_INFO, "nm_state_modification_monitor() failed to activate device %s (%s)", nm_device_get_iface (dev), ap ? nm_ap_get_essid (ap) : "(none)"); + 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, "nm_state_modification_monitor() failed to activate device %s", nm_device_get_iface (dev)); + syslog (LOG_INFO, "Activation (%s) failed.", nm_device_get_iface (dev)); nm_data_mark_state_changed (data); } out: - g_free (result); nm_device_unref (dev); + g_free (result); return FALSE; } @@ -317,7 +319,7 @@ gboolean nm_state_modification_monitor (gpointer user_data) 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 (data->allowed_ap_list, data); + nm_ap_list_populate_from_nmi (data->allowed_ap_list, data); data->update_ap_lists = FALSE; } @@ -364,10 +366,9 @@ gboolean nm_state_modification_monitor (gpointer user_data) if (best_dev) { /* Begin activation on the new device */ - syslog (LOG_INFO, "nm_state_modification_monitor(): beginning activation for device '%s'", nm_device_get_iface (best_dev)); nm_device_ref (best_dev); data->active_device = best_dev; - nm_device_activation_begin (data->active_device); + nm_device_activation_schedule_start (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. diff --git a/src/NetworkManagerWireless.c b/src/NetworkManagerWireless.c index 0c51b01d49..7baa419978 100644 --- a/src/NetworkManagerWireless.c +++ b/src/NetworkManagerWireless.c @@ -191,139 +191,3 @@ int nm_wireless_qual_to_percent (NMDevice *dev, const struct iw_quality *qual) return (percent); } - - -/* - * nm_wireless_process_scan_results - * - * Run from main thread to hand scan results off to each device - * for processing. - * - */ -static gboolean nm_wireless_process_scan_results (gpointer user_data) -{ - GSList *results = (GSList *)user_data; - GSList *elem = NULL; - - if (!results) - return FALSE; - - elem = results; - while (elem) - { - NMWirelessScanResults *res = (NMWirelessScanResults *)(elem->data); - - nm_device_process_scan_results (res->dev, &(res->results)); - - /* Release the scan results */ - nm_dispose_scan_results (res->results.result); - nm_device_unref (res->dev); - g_free (res); - elem->data = NULL; - - elem = g_slist_next (elem); - } - g_slist_free (results); - - return FALSE; -} - - -/* - * nm_wireless_scan_monitor - * - * Called every 10s to get a list of access points from the hardware. When its got - * the list, it schedules an idle handler in the main thread's event loop to actually - * integrate the scan results into the NMDevice's access point list. - * - */ -static gboolean nm_wireless_scan_monitor (gpointer user_data) -{ - NMData *data = (NMData *)user_data; - GSList *element; - NMDevice *dev; - GSList *scan_results = NULL; - - g_return_val_if_fail (data != NULL, TRUE); - - /* We don't want to lock the device list for the entire duration of the scanning process - * for all cards. Scanning can take quite a while. Therefore, we grab a list of the devices - * and ref each one, then release the device list lock, perform scanning, and pass that list - * to the idle handler in the main thread, along iwth the scanning results. - */ - - if (!nm_try_acquire_mutex (data->dev_list_mutex, __FUNCTION__)) - { - syslog (LOG_ERR, "nm_wireless_scan_monitor() could not acquire device list mutex." ); - return (TRUE); - } - - element = data->dev_list; - while (element) - { - if ((dev = (NMDevice *)(element->data)) && nm_device_is_wireless (dev)) - { - NMWirelessScanResults *scan_res = g_malloc0 (sizeof (NMWirelessScanResults)); - - nm_device_ref (dev); - scan_res->dev = dev; - scan_results = g_slist_append (scan_results, scan_res); - } - element = g_slist_next (element); - } - nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__); - - /* Okay, do the actual scanning now. */ - element = scan_results; - while (element) - { - NMWirelessScanResults *res = (NMWirelessScanResults *)(element->data); - nm_device_do_wireless_scan (res->dev, &(res->results)); - element = g_slist_next (element); - } - - /* Schedule an idle handler in the main thread to process the scan results */ - if (scan_results) - { - guint scan_process_source_id = 0; - GSource *scan_process_source = g_idle_source_new (); - - g_source_set_callback (scan_process_source, nm_wireless_process_scan_results, scan_results, NULL); - scan_process_source_id = g_source_attach (scan_process_source, data->main_context); - g_source_unref (scan_process_source); - } - - return (TRUE); -} - - -/* - * nm_wireless_scan_worker - * - * Worker thread main function to handle wireless scanning. - * - */ -gpointer nm_wireless_scan_worker (gpointer user_data) -{ - NMData *data = (NMData *)user_data; - guint wscan_source_id = 0; - GSource *wscan_source = NULL; - - if (!data) - return NULL; - - wscan_source = g_timeout_source_new (20000); - g_source_set_callback (wscan_source, nm_wireless_scan_monitor, data, NULL); - wscan_source_id = g_source_attach (wscan_source, data->wscan_ctx); - g_source_unref (wscan_source); - - /* Do an initial scan */ - nm_wireless_scan_monitor (user_data); - - g_main_loop_run (data->wscan_loop); - - g_source_remove (wscan_source_id); - data->wscan_thread_done = TRUE; - return NULL; -} - diff --git a/src/NetworkManagerWireless.h b/src/NetworkManagerWireless.h index f260401013..9f416edc68 100644 --- a/src/NetworkManagerWireless.h +++ b/src/NetworkManagerWireless.h @@ -28,19 +28,10 @@ #include "NetworkManagerAPList.h" -typedef struct -{ - NMDevice *dev; - struct wireless_scan_head results; -} NMWirelessScanResults; - - char * nm_wireless_64bit_ascii_to_hex (const unsigned char *ascii); char * nm_wireless_128bit_ascii_to_hex (const unsigned char *ascii); char * nm_wireless_128bit_key_from_passphrase (const char *passphrase); int nm_wireless_qual_to_percent (NMDevice *dev, const struct iw_quality *qual); -gpointer nm_wireless_scan_worker (gpointer user_data); - #endif