diff --git a/ChangeLog b/ChangeLog index cfc48133ad..a99601532a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,64 @@ +2004-10-13 Dan Williams + + * panel-applet/NMWirelessApplet.c + - Add function to print out applet_state in a readable + manner + + * src/NetworkManager.c + - (main): Don't segfault when nm_dbus_init() fails, we had + a left-over call to hal_shutdown() into which we passed NULL + + * src/NetworkManagerAP.c + - (nm_ap_set_essid): Allow NULL essids + + * src/NetworkManagerAPList.[ch] + - More use of nm_ap_list_[un]lock () + - (nm_ap_list_get_ap_by_essid): don't warn when looking for a NULL + network/essid, just return nothing. Also skip over NULL + essid access points in the list when searching + - (nm_ap_list_get_ap_by_address): new function + - (nm_ap_list_update_network): set the access point's key source to + NULL when the key returned from NetworkManagerInfo is NULL or + of 0 length + - nm_ap_list_update_keys() -> nm_ap_list_update_properties(), and + copy timestamp over too + - (nm_ap_list_copy_essids_by_address): new function, attempt to + find the correct ESSID for a blank-essid access point by searching + through another list and matching access point MAC addresses + - (nm_ap_list_diff): exclude blank-essid access points from the diffs + + * src/NetworkManagerDbus.c + - (nm_dbus_nm_set_active_device): deal with random networks the user + may specify. This is mainly for access points that don't + broadcast their essid. So if the user tells us to associate with + some random ESSID that's not in our access point list, we find + out if the access point does in fact exist (by attempting association + and then matching that access point's MAC address with the essid the + user gave us) and then we switch to it. + - (nm_dbus_devices_handle_request): don't add blank-essid access points + to the returned list of networks for the "getNetworks" method + + * src/NetworkManagerDevice.[ch] + - Extra debugging info for link detection + - (nm_device_ap_list_get_ap_by_address): new function, return an AP + based on MAC address + - (nm_device_get_path_for_ap): ignore blank-essid access points + - (nm_device_wireless_network_exists): new function, find out whether + a random ESSID exists by attempting to associate with it + - (nm_device_do_normal_scan): allow blank-essid access points in our + device list as long as they have an AP MAC address we can use. + Also send WirelessNetwork[Dis]Appeared signals for non-active + devices too. Lets the applet update more frequently. + + * src/backends/NetworkManagerGentoo.c + - Patch from: Robert Paskowitz + - Update backend code for Gentoo + - Implement nm_system_device_update_config_info () + + * test/nmclienttest.c + - (set_network_device): new function, takes a command-line argument + and tells NetworkManager to use that wireless network + Wed Oct 13 John (J5) Palmieri * info-daemon/NetworkManagerInfo.c (nmi_spawn_notification_icon): Stop respawning diff --git a/panel-applet/NMWirelessApplet.c b/panel-applet/NMWirelessApplet.c index da99edb369..f1a4fdbfa7 100644 --- a/panel-applet/NMWirelessApplet.c +++ b/panel-applet/NMWirelessApplet.c @@ -142,6 +142,39 @@ animation_timeout (NMWirelessApplet *applet) return TRUE; } + +inline void print_state (AppletState state) +{ + switch (state) + { + case (APPLET_STATE_NO_NM): + g_print ("State: APPLET_STATE_NO_NM\n"); + break; + case (APPLET_STATE_NO_CONNECTION): + g_print ("State: APPLET_STATE_NO_CONNECTION\n"); + break; + case (APPLET_STATE_WIRED): + g_print ("State: APPLET_STATE_WIRED\n"); + break; + case (APPLET_STATE_WIRED_CONNECTING): + g_print ("State: APPLET_STATE_WIRED_CONNECTING\n"); + break; + case (APPLET_STATE_WIRELESS): + g_print ("State: APPLET_STATE_WIRELESS\n"); + break; + case (APPLET_STATE_WIRELESS_CONNECTING): + g_print ("State: APPLET_STATE_WIRELESS_CONNECTING\n"); + break; + case (APPLET_STATE_WIRELESS_SCANNING): + g_print ("State: APPLET_STATE_WIRELESS_SCANNING\n"); + break; + default: + g_print ("State: UNKNOWN\n"); + break; + } +} + + /* * nmwa_update_state * @@ -183,6 +216,7 @@ nmwa_update_state (NMWirelessApplet *applet) } g_mutex_unlock (applet->data_mutex); +/* print_state (applet->applet_state); */ switch (applet->applet_state) { case (APPLET_STATE_NO_NM): diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 0de5cdb5ab..75b6fa338d 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -605,7 +605,7 @@ int main( int argc, char *argv[] ) nm_data = nm_data_new (enable_test_devices); if (!nm_data) { - syslog( LOG_CRIT, "nm_data_new() failed... Not enough memory?"); + syslog (LOG_CRIT, "nm_data_new() failed... Not enough memory?"); exit (EXIT_FAILURE); } @@ -613,8 +613,7 @@ int main( int argc, char *argv[] ) nm_data->dbus_connection = nm_dbus_init (nm_data); if (!nm_data->dbus_connection) { - syslog( LOG_CRIT, "nm_dbus_init() failed, exiting"); - hal_shutdown (nm_data->hal_ctx); + syslog (LOG_CRIT, "nm_dbus_init() failed, exiting. Either dbus is not running, or the NetworkManager dbus security policy was not loaded."); nm_data_free (nm_data); exit (EXIT_FAILURE); } @@ -624,7 +623,7 @@ int main( int argc, char *argv[] ) /* Initialize libhal. We get a connection to the hal daemon here. */ if ((ctx = hal_initialize (&hal_functions, FALSE)) == NULL) { - syslog( LOG_CRIT, "hal_initialize() failed, exiting... Make sure the hal daemon is running?"); + syslog (LOG_CRIT, "hal_initialize() failed, exiting... Make sure the hal daemon is running?"); exit (EXIT_FAILURE); } nm_data->hal_ctx = ctx; diff --git a/src/NetworkManagerAP.c b/src/NetworkManagerAP.c index f274d551b8..1646f5385a 100644 --- a/src/NetworkManagerAP.c +++ b/src/NetworkManagerAP.c @@ -178,9 +178,13 @@ void nm_ap_set_essid (NMAccessPoint *ap, char * essid) g_return_if_fail (ap != NULL); if (ap->essid) + { g_free (ap->essid); + ap->essid = NULL; + } - ap->essid = g_strdup (essid); + if (essid) + ap->essid = g_strdup (essid); } diff --git a/src/NetworkManagerAPList.c b/src/NetworkManagerAPList.c index f2556b44ec..c8acde0f65 100644 --- a/src/NetworkManagerAPList.c +++ b/src/NetworkManagerAPList.c @@ -140,7 +140,7 @@ void nm_ap_list_append_ap (NMAccessPointList *list, NMAccessPoint *ap) g_return_if_fail (list != NULL); g_return_if_fail (ap != NULL); - if (!nm_try_acquire_mutex (list->mutex, __FUNCTION__)) + if (!nm_ap_list_lock (list)) { syslog( LOG_ERR, "nm_ap_list_append_ap() could not acquire AP list mutex." ); return; @@ -149,7 +149,7 @@ void nm_ap_list_append_ap (NMAccessPointList *list, NMAccessPoint *ap) nm_ap_ref (ap); list->ap_list = g_slist_append (list->ap_list, ap); - nm_unlock_mutex (list->mutex, __FUNCTION__); + nm_ap_list_unlock (list); } @@ -166,7 +166,7 @@ void nm_ap_list_remove_ap (NMAccessPointList *list, NMAccessPoint *ap) g_return_if_fail (list != NULL); g_return_if_fail (ap != NULL); - if (!nm_try_acquire_mutex (list->mutex, __FUNCTION__)) + if (!nm_ap_list_lock (list)) { syslog( LOG_ERR, "nm_ap_list_append_ap() could not acquire AP list mutex." ); return; @@ -186,8 +186,7 @@ void nm_ap_list_remove_ap (NMAccessPointList *list, NMAccessPoint *ap) } element = g_slist_next (element); } - - nm_unlock_mutex (list->mutex, __FUNCTION__); + nm_ap_list_unlock (list); } @@ -204,7 +203,8 @@ NMAccessPoint *nm_ap_list_get_ap_by_essid (NMAccessPointList *list, const char * NMAccessPoint *found_ap = NULL; NMAPListIter *iter; - g_return_val_if_fail (network != NULL, NULL); + if (!network) + return (NULL); if (!list) return (NULL); @@ -214,14 +214,50 @@ NMAccessPoint *nm_ap_list_get_ap_by_essid (NMAccessPointList *list, const char * while ((ap = nm_ap_list_iter_next (iter))) { - if (nm_null_safe_strcmp (nm_ap_get_essid (ap), network) == 0) + if (nm_ap_get_essid (ap) && (nm_null_safe_strcmp (nm_ap_get_essid (ap), network) == 0)) { found_ap = ap; break; } } - nm_ap_list_iter_free (iter); + + return (found_ap); +} + + +/* + * nm_ap_list_get_ap_by_address + * + * Search through an access point list and return the access point + * that has a given AP address. + * + */ +NMAccessPoint *nm_ap_list_get_ap_by_address (NMAccessPointList *list, const struct ether_addr *addr) +{ + NMAccessPoint *ap; + NMAccessPoint *found_ap = NULL; + NMAPListIter *iter; + + if (!addr) + return (NULL); + + if (!list) + return (NULL); + + if (!(iter = nm_ap_list_iter_new (list))) + return (NULL); + + while ((ap = nm_ap_list_iter_next (iter))) + { + if (nm_ap_get_address (ap) && (memcmp (addr, nm_ap_get_address (ap), sizeof (struct ether_addr)) == 0)) + { + found_ap = ap; + break; + } + } + nm_ap_list_iter_free (iter); + return (found_ap); } @@ -258,7 +294,10 @@ void nm_ap_list_update_network (NMAccessPointList *list, const char *network, NM nm_ap_set_essid (ap, essid); nm_ap_set_timestamp (ap, timestamp); nm_ap_set_trusted (ap, trusted); - nm_ap_set_enc_key_source (ap, key, enc_method); + if (key && strlen (key)) + nm_ap_set_enc_key_source (ap, key, enc_method); + else + nm_ap_set_enc_key_source (ap, NULL, NM_AP_ENC_METHOD_UNKNOWN); } g_free (timestamp); @@ -360,14 +399,14 @@ NMAccessPointList * nm_ap_list_combine (NMAccessPointList *list1, NMAccessPointL /* - * nm_ap_list_copy_keys + * nm_ap_list_copy_properties * - * Update the keys and encryption methods in one access point list from + * Update properties (like encryption keys or timestamps) in one access point list from * access points in another list, if the APs in the first list are present * in the second. * */ -void nm_ap_list_copy_keys (NMAccessPointList *dest, NMAccessPointList *source) +void nm_ap_list_copy_properties (NMAccessPointList *dest, NMAccessPointList *source) { NMAPListIter *iter; NMAccessPoint *dest_ap; @@ -385,6 +424,40 @@ void nm_ap_list_copy_keys (NMAccessPointList *dest, NMAccessPointList *source) { 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_timestamp (dest_ap, nm_ap_get_timestamp (src_ap)); + } + } + nm_ap_list_iter_free (iter); + } +} + + +/* + * nm_ap_list_copy_essids_by_address + * + * For each blank-essid access point in the destination list, try to find + * an access point in the source list that has the same MAC address, and if + * its found, copy the source access point's essid to the dest access point. + * + */ +void nm_ap_list_copy_essids_by_address (NMAccessPointList *dest, NMAccessPointList *source) +{ + NMAPListIter *iter; + NMAccessPoint *dest_ap; + + g_return_if_fail (dest != NULL); + g_return_if_fail (source != NULL); + + if ((iter = nm_ap_list_iter_new (dest))) + { + while ((dest_ap = nm_ap_list_iter_next (iter))) + { + NMAccessPoint *src_ap = NULL; + + if (!nm_ap_get_essid (dest_ap) && (src_ap = nm_ap_list_get_ap_by_address (source, nm_ap_get_address (dest_ap)))) + { + if (nm_ap_get_essid (src_ap)) + nm_ap_set_essid (dest_ap, nm_ap_get_essid (src_ap)); } } nm_ap_list_iter_free (iter); @@ -424,13 +497,16 @@ void nm_ap_list_diff (NMData *data, NMDevice *dev, NMAccessPointList *old, NMAcc { NMAccessPoint *new_ap = NULL; - if ((new_ap = nm_ap_list_get_ap_by_essid (new, nm_ap_get_essid (old_ap)))) + if (nm_ap_get_essid (old_ap)) { - nm_ap_set_matched (old_ap, TRUE); - nm_ap_set_matched (new_ap, TRUE); + if ((new_ap = nm_ap_list_get_ap_by_essid (new, nm_ap_get_essid (old_ap)))) + { + nm_ap_set_matched (old_ap, TRUE); + nm_ap_set_matched (new_ap, TRUE); + } + else + nm_dbus_signal_wireless_network_change (data->dbus_connection, dev, old_ap, TRUE); } - else - nm_dbus_signal_wireless_network_change (data->dbus_connection, dev, old_ap, TRUE); } nm_ap_list_iter_free (iter); } @@ -442,7 +518,7 @@ void nm_ap_list_diff (NMData *data, NMDevice *dev, NMAccessPointList *old, NMAcc { while ((new_ap = nm_ap_list_iter_next (iter))) { - if (!nm_ap_get_matched (new_ap)) + if (!nm_ap_get_matched (new_ap) && nm_ap_get_essid (new_ap)) nm_dbus_signal_wireless_network_change (data->dbus_connection, dev, new_ap, FALSE); } nm_ap_list_iter_free (iter); diff --git a/src/NetworkManagerAPList.h b/src/NetworkManagerAPList.h index 980728f9e1..485793a410 100644 --- a/src/NetworkManagerAPList.h +++ b/src/NetworkManagerAPList.h @@ -47,12 +47,14 @@ 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); void nm_ap_list_update_network (NMAccessPointList *list, const char *network, NMData *data); void nm_ap_list_populate (NMAccessPointList *list, NMData *data); -void nm_ap_list_copy_keys (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); diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index f6f4fd4365..3d9bae893d 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -253,9 +253,9 @@ 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); - } else fprintf (stderr, "FORCE: device '%s'\n", dev_path); + } else syslog (LOG_INFO, "FORCE: device '%s'", dev_path); } - else fprintf (stderr, "FORCE: device '%s', network '%s'\n", dev_path, network); + 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 */ @@ -286,12 +286,35 @@ static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DB NMAccessPoint *ap; if ((ap = nm_ap_list_get_ap_by_essid (nm_device_ap_list_get (dev), network))) - { syslog (LOG_DEBUG, "Forcing AP '%s'", nm_ap_get_essid (ap)); + else + { + struct ether_addr ap_addr; + + syslog (LOG_DEBUG, "Forcing non-scanned AP '%s'", network); + /* 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. + */ + nm_device_deactivate (dev, FALSE); + if (nm_device_wireless_network_exists (dev, network, &ap_addr)) + { + if ((ap = nm_device_ap_list_get_ap_by_address (dev, &ap_addr))) + nm_ap_set_essid (ap, network); + } + } + + /* If we found a valid access point, use it */ + if (ap) + { nm_device_set_best_ap (dev, ap); nm_device_freeze_best_ap (dev); nm_device_activation_cancel (dev); } + else + { + reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NetworkNotFound", + "The requested wireless network is not in range."); + } } dbus_free (network); @@ -1170,11 +1193,14 @@ static DBusMessage *nm_dbus_devices_handle_request (DBusConnection *connection, { while ((ap = nm_ap_list_iter_next (list_iter))) { - object_path = g_strdup_printf ("%s/%s/Networks/%s", NM_DBUS_PATH_DEVICES, - nm_device_get_iface (dev), nm_ap_get_essid (ap)); - dbus_message_iter_append_string (&iter_array, object_path); - g_free (object_path); - success = TRUE; + if (nm_ap_get_essid (ap)) + { + object_path = g_strdup_printf ("%s/%s/Networks/%s", NM_DBUS_PATH_DEVICES, + nm_device_get_iface (dev), nm_ap_get_essid (ap)); + dbus_message_iter_append_string (&iter_array, object_path); + g_free (object_path); + success = TRUE; + } } nm_ap_list_iter_free (list_iter); } @@ -1449,19 +1475,22 @@ DBusConnection *nm_dbus_init (NMData *data) success = dbus_connection_register_object_path (connection, NM_DBUS_PATH, &nm_vtable, data); if (!success) { - syslog (LOG_ERR, "nm_dbus_init() could not register a handler for NetworkManager. Not enough memory?"); + syslog (LOG_CRIT, "nm_dbus_init() could not register a handler for NetworkManager. Not enough memory?"); return (NULL); } success = dbus_connection_register_fallback (connection, NM_DBUS_PATH_DEVICES, &devices_vtable, data); if (!success) { - syslog (LOG_ERR, "nm_dbus_init() could not register a handler for NetworkManager devices. Not enough memory?"); + syslog (LOG_CRIT, "nm_dbus_init() could not register a handler for NetworkManager devices. Not enough memory?"); return (NULL); } if (!dbus_connection_add_filter (connection, nm_dbus_nmi_filter, data, NULL)) + { + syslog (LOG_CRIT, "nm_dbus_init() could not attach a dbus message filter. The NetworkManager dbus security policy may not be loaded. Restart dbus?"); return (NULL); + } dbus_bus_add_match (connection, "type='signal'," diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c index 1d5cff8148..2e8e251413 100644 --- a/src/NetworkManagerDevice.c +++ b/src/NetworkManagerDevice.c @@ -1298,6 +1298,7 @@ inline gboolean HAVE_LINK (NMDevice *dev, guint32 bad_crypt_packets) g_return_val_if_fail (dev != NULL, FALSE); g_return_val_if_fail (nm_device_is_wireless (dev), FALSE); +fprintf (stderr, "HAVELINK: act=%d && (dev_crypt=%d <= prev_crypt=%d)\n", nm_device_get_link_active (dev), nm_device_get_bad_crypt_packets (dev), bad_crypt_packets); return (nm_device_get_link_active (dev) && (nm_device_get_bad_crypt_packets (dev) <= bad_crypt_packets)); } @@ -1367,6 +1368,9 @@ void nm_device_activate_wireless_wait_for_link (NMDevice *dev) || (best_ap && (nm_ap_get_encrypted (best_ap) && (!nm_ap_get_enc_key_source (best_ap) || !strlen (nm_ap_get_enc_key_source (best_ap)))))) { +fprintf (stderr, "LINK: !HAVE=%d, (best_ap=0x%X && (is_enc=%d && (!source=%d || !len_source=%d)))\n", +!HAVE_LINK (dev, bad_crypt_packets), best_ap, nm_ap_get_encrypted (best_ap), !nm_ap_get_enc_key_source (best_ap), +nm_ap_get_enc_key_source (best_ap) ? !strlen (nm_ap_get_enc_key_source (best_ap)) : 0); if ((best_ap = nm_device_get_best_ap (dev))) { dev->options.wireless.now_scanning = FALSE; @@ -1755,6 +1759,29 @@ NMAccessPoint *nm_device_ap_list_get_ap_by_essid (NMDevice *dev, const char *ess } +/* + * nm_device_ap_list_get_ap_by_address + * + * Get the access point for a specific MAC address + * + */ +NMAccessPoint *nm_device_ap_list_get_ap_by_address (NMDevice *dev, const struct ether_addr *addr) +{ + NMAccessPoint *ret_ap = NULL; + + g_return_val_if_fail (dev != NULL, NULL); + g_return_val_if_fail (nm_device_is_wireless (dev), NULL); + g_return_val_if_fail (addr != NULL, NULL); + + if (!dev->options.wireless.ap_list) + return (NULL); + + ret_ap = nm_ap_list_get_ap_by_address (dev->options.wireless.ap_list, addr); + + return (ret_ap); +} + + /* * nm_device_ap_list_get * @@ -1851,7 +1878,10 @@ char * nm_device_get_path_for_ap (NMDevice *dev, NMAccessPoint *ap) g_return_val_if_fail (dev != NULL, NULL); g_return_val_if_fail (ap != NULL, NULL); - return (g_strdup_printf ("%s/%s/Networks/%s", NM_DBUS_PATH_DEVICES, nm_device_get_iface (dev), nm_ap_get_essid (ap))); + if (nm_ap_get_essid (ap)) + return (g_strdup_printf ("%s/%s/Networks/%s", NM_DBUS_PATH_DEVICES, nm_device_get_iface (dev), nm_ap_get_essid (ap))); + else + return (NULL); } @@ -1977,6 +2007,59 @@ 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, struct ether_addr *ap_addr) +{ + struct ether_addr addr; + + 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); + + fprintf (stderr, "nm_device_wireless_network_exists () looking for network '%s'...", network); + + nm_device_bring_down (dev); + + /* Force the card into Managed/Infrastructure mode */ + nm_device_set_mode_managed (dev); + + /* Disable encryption, then re-enable and set correct key on the card + * if we are going to encrypt traffic. + */ + nm_device_set_enc_key (dev, NULL); + nm_device_set_essid (dev, network); + + /* Bring the device up and pause to allow card to associate */ + nm_device_bring_up (dev); + g_usleep (G_USEC_PER_SEC * 2); + + nm_device_update_link_active (dev, FALSE); + nm_device_get_ap_address (dev, &addr); + if (nm_ethernet_address_is_valid (&addr) && nm_device_get_essid (dev)) + { + nm_device_get_ap_address (dev, ap_addr); + fprintf (stderr, " found!\n"); + return (TRUE); + } + else + { + fprintf (stderr, " not found\n"); + return (FALSE); + } +} + + /* * nm_device_do_normal_scan * @@ -2009,6 +2092,7 @@ static void nm_device_do_normal_scan (NMDevice *dev) int err; NMAccessPointList *old_ap_list = NULL; NMAccessPointList *temp_list; + gboolean have_blank_essids = FALSE; err = iw_scan (iwlib_socket, nm_device_get_iface (dev), WIRELESS_EXT, &scan_results); if ((err == -1) && (errno == ENODATA)) @@ -2047,16 +2131,19 @@ static void nm_device_do_normal_scan (NMDevice *dev) tmp_ap = scan_results.result; while (tmp_ap) { - /* Blank essids usually indicate an AP that is not broadcasting its essid, - * but since its not broadcasting the essid, we cannot use that ap yet. - */ - if (tmp_ap->b.has_essid && tmp_ap->b.essid_on && (strlen (tmp_ap->b.essid) > 0)) + /* We need at least an ESSID or a MAC address for each access point */ + if (tmp_ap->b.has_essid || tmp_ap->has_ap_addr) { NMAccessPoint *nm_ap = nm_ap_new (); - NMAccessPoint *list_ap; /* Copy over info from scan to local structure */ - nm_ap_set_essid (nm_ap, tmp_ap->b.essid); + if (!tmp_ap->b.has_essid || (tmp_ap->b.essid && !strlen (tmp_ap->b.essid))) + { + nm_ap_set_essid (nm_ap, NULL); + have_blank_essids = TRUE; + } + else + 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); @@ -2071,12 +2158,6 @@ static void nm_device_do_normal_scan (NMDevice *dev) if (tmp_ap->b.has_freq) nm_ap_set_freq (nm_ap, tmp_ap->b.freq); - /* Merge settings from user-approved wireless networks, mainly encryption keys */ - if ((list_ap = nm_ap_list_get_ap_by_essid (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)); - } /* Add the AP to the device's AP list */ nm_ap_list_append_ap (dev->options.wireless.cached_ap_list1, nm_ap); } @@ -2085,17 +2166,24 @@ static void nm_device_do_normal_scan (NMDevice *dev) nm_dispose_scan_results (scan_results.result); close (iwlib_socket); - /* Dispose of the old list of available access points the card knows about */ - if (nm_device_ap_list_get (dev)) - nm_ap_list_unref (nm_device_ap_list_get (dev)); - /* 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. * Once we have the list, copy in any relevant information from our Allowed list. */ + 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); - nm_ap_list_copy_keys (nm_device_ap_list_get (dev), dev->app_data->allowed_ap_list); + nm_ap_list_copy_properties (nm_device_ap_list_get (dev), dev->app_data->allowed_ap_list); + + /* 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 (have_blank_essids) + nm_ap_list_copy_essids_by_address (nm_device_ap_list_get (dev), 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, dev->options.wireless.cached_ap_list4); @@ -2103,8 +2191,7 @@ static void nm_device_do_normal_scan (NMDevice *dev) /* Now do a diff of the old and new networks that we can see, and * signal any changes over dbus, but only if we are active device. */ - if (dev == dev->app_data->active_device) - nm_ap_list_diff (dev->app_data, dev, old_ap_list, nm_device_ap_list_get (dev)); + 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); } diff --git a/src/NetworkManagerDevice.h b/src/NetworkManagerDevice.h index fe83a60f54..49b543cd1d 100644 --- a/src/NetworkManagerDevice.h +++ b/src/NetworkManagerDevice.h @@ -59,6 +59,7 @@ void nm_device_get_ip6_address (NMDevice *dev); gboolean nm_device_get_supports_wireless_scan (NMDevice *dev); void nm_device_do_wireless_scan (NMDevice *dev); +gboolean nm_device_wireless_network_exists (NMDevice *dev, const char *network, struct ether_addr *addr); void nm_device_set_mode_managed (NMDevice *dev); void nm_device_set_mode_adhoc (NMDevice *dev); @@ -101,6 +102,7 @@ gboolean nm_device_is_up (NMDevice *dev); void nm_device_ap_list_clear (NMDevice *dev); struct NMAccessPointList *nm_device_ap_list_get (NMDevice *dev); NMAccessPoint *nm_device_ap_list_get_ap_by_essid (NMDevice *dev, const char *essid); +NMAccessPoint *nm_device_ap_list_get_ap_by_address(NMDevice *dev, const struct ether_addr *addr); /* System config data accessors */ gboolean nm_device_config_get_use_dhcp (NMDevice *dev); diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 3ec84e5767..0cda096f32 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -30,7 +30,7 @@ #include "NetworkManagerUtils.h" -/*#define LOCKING_DEBUG */ +/*#define LOCKING_DEBUG */ /* * nm_try_acquire_mutex @@ -59,6 +59,9 @@ gboolean nm_try_acquire_mutex (GMutex *mutex, const char *func) i++; } +#ifdef LOCKING_DEBUG + if (func) syslog (LOG_DEBUG, "MUTEX: %s FAILED to get mutex 0x%X", func, mutex); +#endif return (FALSE); } diff --git a/src/backends/NetworkManagerGentoo.c b/src/backends/NetworkManagerGentoo.c index f3edfe5f15..6b30b88633 100644 --- a/src/backends/NetworkManagerGentoo.c +++ b/src/backends/NetworkManagerGentoo.c @@ -2,6 +2,7 @@ * * Dan Williams * Dan Willemsen + * Robert Paskowitz * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,11 +20,13 @@ * * (C) Copyright 2004 Red Hat, Inc. * (C) Copyright 2004 Dan Willemsen + * (C) Copyright 2004 Robert Paskowitz */ #include #include #include +#include #include "NetworkManagerSystem.h" #include "NetworkManagerUtils.h" @@ -44,6 +47,12 @@ static GENTOOConfType nm_system_gentoo_conf_type; void nm_system_init (void) { // TODO: autodetect conf type, probably by checking if /sbin/ip exists + +/* It's not safe to assume the the iproute stuff exists, but seeing as it + * is far more convinient to flush stuff with /sbin/ip with iproute + * I think it would be acceptable to introduce the sys-apps/iproute2 + * package as a dependancy for Gentoo. +*/ nm_system_gentoo_conf_type = GENTOO_CONF_TYPE_IPROUTE; } @@ -135,6 +144,8 @@ void nm_system_device_flush_routes (NMDevice *dev) snprintf (buf, 100, "/sbin/ip route flush dev %s", nm_device_get_iface (dev)); } else if (nm_system_gentoo_conf_type == GENTOO_CONF_TYPE_IFCONFIG) { // FIXME: this command still isn't right + +/* See note above */ snprintf (buf, 100, "/sbin/route del dev %s", nm_device_get_iface (dev)); } else { snprintf (buf, 100, "/bin/false"); @@ -162,6 +173,8 @@ void nm_system_device_flush_addresses (NMDevice *dev) snprintf (buf, 100, "/sbin/ip address flush dev %s", nm_device_get_iface (dev)); } else if (nm_system_gentoo_conf_type == GENTOO_CONF_TYPE_IFCONFIG) { // FIXME: find the correct command + +/* See note above */ snprintf (buf, 100, "/bin/false"); } else { snprintf (buf, 100, "/bin/false"); @@ -275,4 +288,129 @@ void nm_system_load_device_modules (void) */ void nm_system_device_update_config_info (NMDevice *dev) { + char *cfg_file_path = NULL; + FILE *file = NULL; + char buffer[100]; + char confline[100], dhcpline[100], ipline[100]; + int ipa, ipb, ipc, ipd; + int nNext = 0, bNext = 0, count = 0; + char *confToken; + gboolean data_good = FALSE; + gboolean use_dhcp = TRUE; + guint32 ip4_address = 0; + guint32 ip4_netmask = 0; + guint32 ip4_gateway = 0; + + g_return_if_fail (dev != NULL); + + /* We use DHCP on an interface unless told not to */ + nm_device_config_set_use_dhcp (dev, TRUE); + nm_device_config_set_ip4_address (dev, 0); + nm_device_config_set_ip4_gateway (dev, 0); + nm_device_config_set_ip4_netmask (dev, 0); + + /* Gentoo systems store this information in + * /etc/conf.d/net, this is for all interfaces. + */ + + cfg_file_path = g_strdup_printf ("/etc/conf.d/net"); + if (!cfg_file_path) + return; + + if (!(file = fopen (cfg_file_path, "r"))) + { + g_free (cfg_file_path); + return; + } + sprintf(confline, "iface_%s", nm_device_get_iface (dev)); + sprintf(dhcpline, "iface_%s=\"dhcp\"", nm_device_get_iface (dev)); + while (fgets (buffer, 499, file) && !feof (file)) + { + /* Kock off newline if any */ + g_strstrip (buffer); + + if (strncmp (buffer, confline, strlen(confline)) == 0) + { + /* Make sure this config file is for this device */ + if (strncmp (&buffer[strlen(confline) - strlen(nm_device_get_iface (dev))], + nm_device_get_iface (dev), strlen(nm_device_get_iface (dev)) + ) != 0) + { + syslog (LOG_WARNING, "System config file '%s' does not define device '%s'\n", + cfg_file_path, nm_device_get_iface (dev)); + break; + } + else + data_good = TRUE; + + + + if (strncmp (buffer, dhcpline, strlen(dhcpline)) == 0) + { + use_dhcp = TRUE; + } + else + { + syslog (LOG_WARNING, "Device '%s' is setup as static, and we do not (yet) support that\n", + nm_device_get_iface (dev)); + use_dhcp = FALSE; + confToken = strtok(&buffer[strlen(confline) + 2], " "); + while (count < 3) + { + if (nNext == 1 && bNext == 1) + { + ip4_address = inet_addr (confToken); + count++; + continue; + } + if (strcmp(confToken, "netmask") == 0) + { + confToken = strtok(NULL, " "); + ip4_netmask = inet_addr (confToken); + count++; + nNext = 1; + } + else if (strcmp(confToken, "broadcast") == 0) + { + confToken = strtok(NULL, " "); + count++; + bNext = 1; + } + else + { + ip4_address = inet_addr (confToken); + count++; + } + confToken = strtok(NULL, " "); + } + } + } + /* If we aren't using dhcp, then try to get the gateway */ + if (!use_dhcp) + { + sprintf(ipline, "gateway=\"%s/", nm_device_get_iface (dev)); + if (strncmp(buffer, ipline, strlen(ipline) - 1) == 0) + { + sprintf(ipline, "gateway=\"%s/%%d.%%d.%%d.%%d\"", nm_device_get_iface (dev) ); + sscanf(buffer, ipline, &ipa, &ipb, &ipc, &ipd); + sprintf(ipline, "%d.%d.%d.%d", ipa, ipb, ipc, ipd); + ip4_gateway = inet_addr (ipline); + syslog (LOG_WARNING, "Gateway(%s): %s", nm_device_get_iface (dev), ipline); + } + } + } + fclose (file); + g_free (cfg_file_path); + + /* If successful, set values on the device */ + if (data_good) + { + nm_device_config_set_use_dhcp (dev, use_dhcp); + if (ip4_address) + nm_device_config_set_ip4_address (dev, ip4_address); + if (ip4_gateway) + nm_device_config_set_ip4_gateway (dev, ip4_gateway); + if (ip4_netmask) + nm_device_config_set_ip4_netmask (dev, ip4_netmask); + } } diff --git a/src/backends/NetworkManagerRedHat.c b/src/backends/NetworkManagerRedHat.c index b52a1d1ef7..a2fdc33e26 100644 --- a/src/backends/NetworkManagerRedHat.c +++ b/src/backends/NetworkManagerRedHat.c @@ -145,6 +145,19 @@ void nm_system_device_flush_routes (NMDevice *dev) } +/* + * nm_system_device_has_active_routes + * + * Find out whether the specified device has any routes in the routing + * table. + * + */ +gboolean nm_system_device_has_active_routes (NMDevice *dev) +{ + return (FALSE); +} + + /* * nm_system_device_flush_addresses * diff --git a/src/backends/NetworkManagerSystem.h b/src/backends/NetworkManagerSystem.h index 567cc818f1..6b85b1d641 100644 --- a/src/backends/NetworkManagerSystem.h +++ b/src/backends/NetworkManagerSystem.h @@ -34,6 +34,7 @@ gboolean nm_system_device_run_dhcp (NMDevice *dev); void nm_system_device_stop_dhcp (NMDevice *dev); +gboolean nm_system_device_has_active_routes (NMDevice *dev); void nm_system_device_flush_routes (NMDevice *dev); void nm_system_device_flush_addresses (NMDevice *dev); diff --git a/test/nmclienttest.c b/test/nmclienttest.c index 952e584379..ef9db523f5 100644 --- a/test/nmclienttest.c +++ b/test/nmclienttest.c @@ -539,6 +539,40 @@ void get_devices (DBusConnection *connection) } +void set_device_network (DBusConnection *connection, const char *path, const char *network) +{ + DBusMessage *message; + DBusMessage *reply; + DBusMessageIter iter; + DBusError error; + + message = dbus_message_new_method_call ("org.freedesktop.NetworkManager", + "/org/freedesktop/NetworkManager", + "org.freedesktop.NetworkManager", + "setActiveDevice"); + if (message == NULL) + { + fprintf (stderr, "Couldn't allocate the dbus message\n"); + return; + } + + dbus_message_append_args (message, DBUS_TYPE_STRING, path, + DBUS_TYPE_STRING, network, DBUS_TYPE_INVALID); + + dbus_error_init (&error); + reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error); + if (dbus_error_is_set (&error)) + { + fprintf (stderr, "%s raised:\n %s\n\n", error.name, error.message); + dbus_message_unref (message); + dbus_error_free (&error); + return; + } + else + fprintf (stderr, "Success!!\n"); +} + + int main( int argc, char *argv[] ) { DBusConnection *connection; @@ -561,6 +595,12 @@ int main( int argc, char *argv[] ) path = get_active_device (connection); get_device_name (connection, path); get_devices (connection); + if ((argc == 2) && (get_device_type (connection, path) == 2)) + { + fprintf (stderr, "Attempting to force AP '%s' for device '%s'\n", argv[1], path); + set_device_network (connection, path, argv[1]); + } + g_free (path); return 0;