diff --git a/ChangeLog b/ChangeLog index 5e28427f2..abf621f2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,64 @@ +2004-08-02 Dan Williams + + * TODO + - new task: proper logging support + + * info-daemon/NetworkManagerInfo.c + - Correct spelling of "canceled" + - Correct casting of objects for g_signal_connect() + + * info-daemon/NetworkManagerInfoDbus.c + - Add defines for NetworkManager namespace and object path, and use them + - Add filter function to trap new signals from NetworkManager: + WirelessNetworkAppeared, WirelessNetworkDisappeared + + * info-daemon/passphrase.glade + - Change name of "ok" button to "Login to Network..." + - Mark invisible + + * src/NetworkManager.c + - Code and debug message cleanups + - Rename "nm_add_current_devices"->"nm_add_initial_devices" + - (nm_add_initial_devices) Check returned string array of devices + and don't try to add devices if array is NULL + - (main) Initialize libhal a bit later, make code a bit clearer + + * src/NetworkManagerAP.[ch] + - New accessor and data member "matched": used to speed up AP list + diffing + - New accessor and data member "enc_method": will be used during key + fallback to cache which passphrase->key conversion actually works + so we don't have to do it every time + + * src/NetworkManagerAPList.[ch] + - (nm_ap_list_find_ap_in_list) New: find an AP by essid in an AP list + - (nm_ap_list_diff) New: given two lists of access points, find the differences + between them, and send WirelessNetworkAppeared/Disappeared signals over + dbus in response to those differences + + * src/NetworkManagerDbus.[ch] + - (nm_dbus_get_object_path_from_ap) New: given a device and an access point, + make an object path for that access point (NOTE that we don't yet check to + make sure that access point is actually in the device's AP list yet) + - (nm_dbus_get_ap_from_object_path) Renamed from nm_dbus_get_network_from_object_path + - (nm_dbus_signal_wireless_network_appeared, nm_dbus_signal_wireless_network_disappeared) + New: signal appearance/disappearance of wireless networks + - (nm_dbus_set_user_key_for_network) Mark the network/ap as invalid if the user cancelled + key entry + + * src/NetworkManagerDevice.[ch] + - (nm_device_ap_list_clear) Use nm_ap_list_free rather than doing it ourselves + - (nm_device_ap_list_get) New: return the AP list (static function) + - (nm_device_do_normal_scan) Destroy old AP list later, so that we can diff the + new one resulting from the scan with the old one + + * src/NetworkManagerWireless.c + - (nm_wireless_is_most_prefered_ap) "invalid" access points cannot be "best" access points + + * test/nminfotest.c + - #define object paths and namespaces and use the #defines rather than static strings + - Test out user-key functionality of NetworkManagerInfo too + 2004-07-29 Dan Williams * info-daemon/NetworkManagerInfoDbus.c diff --git a/TODO b/TODO index 2a7cbd8bc..805fa4560 100644 --- a/TODO +++ b/TODO @@ -28,6 +28,10 @@ Wireless link checking could be enhanced to check the signal strength of an acce There is currently no logic to gracefully recover from a crashed/killed dbus or hal. While we don't depend as heavily on NetworkManagerInfo, we need to make sure that we can operate effectively when it's not there. There are dbus functions for notification when services come up and go away which could be used here. Remeber that when dbus dies, hal also dies at the moment. +- Proper logging support + +We need to replace NM_DEBUG_PRINT with proper logging support to syslog or something. + - Deal with blank ESSIDs Access points can be set not to broadcast their ESSIDs, which the client must know. These appear as blank ESSIDs to cards doing wireless scanning, even though the rest of the AP's information is known (channel, rate, etc). There has to be a way to deal with this as many companies do not broadcast ESSIDs for security measures. Workarounds for this practice could include brute-forcing the Allowed Networks list if no suitable wireless network is found to begin with. Obviously, there would be no way to detect if a WEP key was wrong, because unless the ESSID and WEP key are both correct, we cannot associate with the access point to see if we have a link. Code exists to do this for wireless cards that do not support wireless scanning, and this code could be adapted. diff --git a/info-daemon/NetworkManagerInfo.c b/info-daemon/NetworkManagerInfo.c index 43889911f..cc188f894 100644 --- a/info-daemon/NetworkManagerInfo.c +++ b/info-daemon/NetworkManagerInfo.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -132,7 +133,7 @@ static void cancel_button_clicked (GtkWidget *cancel_button, gpointer user_data) const char *device = g_object_get_data (G_OBJECT (dialog), "device"); const char *network = g_object_get_data (G_OBJECT (dialog), "network"); - nmi_dbus_return_user_key (info->connection, device, network, "***cancelled***"); + nmi_dbus_return_user_key (info->connection, device, network, "***canceled***"); nmi_clear_dialog (dialog, glade_xml_get_widget (info->xml, "passphrase_entry")); } } @@ -216,10 +217,10 @@ static void nmi_interface_init (NMIAppInfo *info) gtk_widget_hide (dialog); ok_button = GTK_BUTTON (glade_xml_get_widget (info->xml, "login_button")); - g_signal_connect (GTK_OBJECT (ok_button), "clicked", GTK_SIGNAL_FUNC (ok_button_clicked), info); + g_signal_connect (G_OBJECT (ok_button), "clicked", GTK_SIGNAL_FUNC (ok_button_clicked), info); gtk_widget_grab_default (GTK_WIDGET (ok_button)); cancel_button = GTK_BUTTON (glade_xml_get_widget (info->xml, "cancel_button")); - g_signal_connect (GTK_OBJECT (cancel_button), "clicked", GTK_SIGNAL_FUNC (cancel_button_clicked), info); + g_signal_connect (G_OBJECT (cancel_button), "clicked", GTK_SIGNAL_FUNC (cancel_button_clicked), info); entry = GTK_ENTRY (glade_xml_get_widget (info->xml, "passphrase_entry")); gtk_entry_set_visibility (entry, FALSE); diff --git a/info-daemon/NetworkManagerInfoDbus.c b/info-daemon/NetworkManagerInfoDbus.c index 836a6aa64..8534e862f 100644 --- a/info-daemon/NetworkManagerInfoDbus.c +++ b/info-daemon/NetworkManagerInfoDbus.c @@ -31,6 +31,8 @@ #define NMI_DBUS_NMI_OBJECT_PATH_PREFIX "/org/freedesktop/NetworkManagerInfo" #define NMI_DBUS_NMI_NAMESPACE "org.freedesktop.NetworkManagerInfo" +#define NM_DBUS_NM_OBJECT_PATH_PREFIX "/org/freedesktop/NetworkManager" +#define NM_DBUS_NM_NAMESPACE "org.freedesktop.NetworkManager" /* * nmi_dbus_create_error_message @@ -100,9 +102,9 @@ void nmi_dbus_return_user_key (DBusConnection *connection, const char *device, g_return_if_fail (network != NULL); g_return_if_fail (passphrase != NULL); - message = dbus_message_new_method_call ("org.freedesktop.NetworkManager", - "/org/freedesktop/NetworkManager", - "org.freedesktop.NetworkManager", + message = dbus_message_new_method_call (NM_DBUS_NM_NAMESPACE, + NM_DBUS_NM_OBJECT_PATH_PREFIX, + NM_DBUS_NM_NAMESPACE, "setKeyForNetwork"); if (message == NULL) { @@ -138,7 +140,7 @@ void nmi_dbus_signal_update_allowed_network (DBusConnection *connection, const c g_return_if_fail (connection != NULL); g_return_if_fail (network != NULL); - message = dbus_message_new_signal ("/org/freedesktop/NetworkManagerInfo", "org.freedesktop.NetworkManagerInfo", + message = dbus_message_new_signal (NMI_DBUS_NMI_OBJECT_PATH_PREFIX, NMI_DBUS_NMI_NAMESPACE, "AllowedNetworkUpdate"); if (!message) { @@ -428,6 +430,37 @@ void nmi_dbus_nmi_unregister_handler (DBusConnection *connection, void *user_dat } + +static DBusHandlerResult nmi_dbus_filter (DBusConnection *connection, DBusMessage *message, void *user_data) +{ + char *ap_object_path; + DBusError error; + gboolean handled = FALSE; + NMIAppInfo *info = (NMIAppInfo *) user_data; + gboolean appeared = FALSE; + gboolean disappeared = FALSE; + + g_return_val_if_fail (info != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + if (dbus_message_is_signal (message, NM_DBUS_NM_NAMESPACE, "WirelessNetworkAppeared")) + appeared = TRUE; + else if (dbus_message_is_signal (message, NM_DBUS_NM_NAMESPACE, "WirelessNetworkDisappeared")) + disappeared = TRUE; + + if (appeared || disappeared) + { + dbus_error_init (&error); + if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &ap_object_path, DBUS_TYPE_INVALID)) + { + dbus_free (ap_object_path); + handled = TRUE; + } + } + + return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); +} + + /* * nmi_dbus_service_init * @@ -453,5 +486,17 @@ int nmi_dbus_service_init (DBusConnection *dbus_connection, NMIAppInfo *info) return (-1); } + if (!dbus_connection_add_filter (dbus_connection, nmi_dbus_filter, info, NULL)) + return (-1); + + dbus_error_init (&dbus_error); + dbus_bus_add_match (dbus_connection, + "type='signal'," + "interface='"NM_DBUS_NM_NAMESPACE"'," + "sender='"NM_DBUS_NM_NAMESPACE"'," + "path='"NM_DBUS_NM_OBJECT_PATH_PREFIX"'", &dbus_error); + if (dbus_error_is_set (&dbus_error)) + return (-1); + return (0); } diff --git a/info-daemon/passphrase.glade b/info-daemon/passphrase.glade index 6217635fd..273dd0cfb 100644 --- a/info-daemon/passphrase.glade +++ b/info-daemon/passphrase.glade @@ -5,7 +5,6 @@ 6 - True GTK_WINDOW_TOPLEVEL GTK_WIN_POS_CENTER_ALWAYS @@ -47,8 +46,9 @@ True True + True True - _Login to AP + _Login to Network True GTK_RELIEF_NORMAL True @@ -147,6 +147,7 @@ A passphrase or WEP key is required to access the wireless network '%s'. True True + True True True 0 diff --git a/src/NetworkManager.c b/src/NetworkManager.c index fb0f54fff..928f6b16b 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -36,6 +37,7 @@ #include "NetworkManagerPolicy.h" #include "NetworkManagerWireless.h" #include "NetworkManagerDbus.h" +#include "NetworkManagerAP.h" #include "NetworkManagerAPList.h" @@ -72,16 +74,13 @@ NMDevice * nm_create_device_and_add_to_list (NMData *data, const char *udi) gchar *iface_name = hal_device_get_property_string (data->hal_ctx, udi, "net.interface"); /* Make sure the device is not already in the device list */ - dev = nm_get_device_by_iface (data, iface_name); - if (dev) + if ((dev = nm_get_device_by_iface (data, iface_name))) { - NM_DEBUG_PRINT_1 ("nm_create_device_and_add_to_list() device %s was already in the list\n", iface_name); hal_free_string (iface_name); return (NULL); } - dev = nm_device_new (iface_name, data); - if (dev) + if ((dev = nm_device_new (iface_name, data))) { /* Build up the device structure */ @@ -92,8 +91,8 @@ NMDevice * nm_create_device_and_add_to_list (NMData *data, const char *udi) */ if (nm_try_acquire_mutex (data->dev_list_mutex, __FUNCTION__)) { - NM_DEBUG_PRINT_3( "nm_create_device_and_add_to_list() adding udi='%s', iface='%s', iface_type=%s\n", - nm_device_get_udi (dev), nm_device_get_iface (dev), nm_device_get_iface_type (dev) == NM_IFACE_TYPE_WIRELESS_ETHERNET ? "wireless" : "wired" ); + NM_DEBUG_PRINT_2( "nm_create_device_and_add_to_list(): adding device '%s' (%s)\n", + nm_device_get_iface (dev), nm_device_is_wireless (dev) ? "wireless" : "wired" ); data->dev_list = g_slist_append (data->dev_list, dev); nm_device_deactivate (dev, TRUE); @@ -113,7 +112,7 @@ NMDevice * nm_create_device_and_add_to_list (NMData *data, const char *udi) nm_device_unref (dev); dev = NULL; } - } else NM_DEBUG_PRINT_1( "nm_create_device_and_add_to_list(): device %s does not have 'net.interface' property\n", udi ); + } return (dev); } @@ -257,12 +256,12 @@ static void nm_hal_device_property_modified (LibHalContext *ctx, const char *udi /* - * nm_add_current_devices + * nm_add_initial_devices * * Add all devices that hal knows about right now (ie not hotplug devices) * */ -static void nm_add_current_devices (NMData *data) +static void nm_add_initial_devices (NMData *data) { char **net_devices; int num_net_devices; @@ -272,8 +271,11 @@ static void nm_add_current_devices (NMData *data) /* Grab a list of network devices */ net_devices = hal_find_device_by_capability (data->hal_ctx, "net.ethernet", &num_net_devices); - for (i = 0; i < num_net_devices; i++) - nm_create_device_and_add_to_list (data, net_devices[i]); + if (net_devices) + { + for (i = 0; i < num_net_devices; i++) + nm_create_device_and_add_to_list (data, net_devices[i]); + } hal_free_string_array (net_devices); } @@ -527,7 +529,7 @@ int main( int argc, char *argv[] ) if (strcmp (opt, "help") == 0) { nm_print_usage (); - return 0; + exit (EXIT_SUCCESS); } else if (strcmp (opt, "daemon") == 0) { @@ -538,14 +540,14 @@ int main( int argc, char *argv[] ) else { nm_print_usage (); - return 1; + exit (EXIT_FAILURE); } } break; default: nm_print_usage (); - return 1; + exit (EXIT_FAILURE); break; } } @@ -557,7 +559,7 @@ int main( int argc, char *argv[] ) if (chdir ("/") < 0) { fprintf( stderr, "NetworkManager could not chdir to /. errno=%d", errno); - return 1; + return (1); } child_pid = fork (); @@ -572,7 +574,7 @@ int main( int argc, char *argv[] ) break; default: - exit (0); + exit (EXIT_SUCCESS); break; } } @@ -581,72 +583,75 @@ int main( int argc, char *argv[] ) if (!g_thread_supported ()) g_thread_init (NULL); - /* Initialize libhal. We get a connection to the hal daemon here. */ - if ((ctx = hal_initialize (&hal_functions, FALSE)) == NULL) - { - NM_DEBUG_PRINT("hal_initialize() failed, exiting... Make sure the hal daemon is running?\n"); - exit (1); - } - /* Initialize our instance data */ nm_data = nm_data_new (); if (!nm_data) { NM_DEBUG_PRINT("nm_data_new() failed... Not enough memory?\n"); - exit (1); + exit (EXIT_FAILURE); } - nm_data->hal_ctx = ctx; - hal_ctx_set_user_data (nm_data->hal_ctx, nm_data); - /* Create our dbus service */ nm_data->dbus_connection = nm_dbus_init (nm_data); - if (nm_data->dbus_connection) + if (!nm_data->dbus_connection) { - /* Initialize our list of allowed access points */ - nm_ap_list_populate (nm_data); - - /* Grab network devices that are already present and add them to our list */ - nm_add_current_devices (nm_data); - - /* Create a watch function that monitors cards for link status (hal doesn't do - * this for wireless cards yet). - */ - link_source = g_timeout_add (5000, nm_link_state_monitor, nm_data); - - /* Another watch function which handles networking state changes and applies - * the correct policy on a change. - */ - policy_source = g_timeout_add (3000, nm_state_modification_monitor, nm_data); - - /* Yet another watch function which scans for access points and - * attempts to associate with approved ones in a users' list. - */ - wireless_scan_source = g_timeout_add (10000, nm_wireless_scan_monitor, nm_data); - - /* Watch all devices that HAL knows about for state changes */ - hal_device_property_watch_all (nm_data->hal_ctx); - - /* We run dhclient when we need to, and we don't want any stray ones - * lying around upon launch. - */ - system ("killall dhclient"); - - /* Wheeee!!! */ - loop = g_main_loop_new (NULL, FALSE); - g_main_loop_run (loop); - - /* Kill the watch functions */ - g_source_remove (link_source); - g_source_remove (policy_source); - g_source_remove (wireless_scan_source); + hal_shutdown (nm_data->hal_ctx); + nm_data_free (nm_data); + exit (EXIT_FAILURE); } + /* Initialize libhal. We get a connection to the hal daemon here. */ + if ((ctx = hal_initialize (&hal_functions, FALSE)) == NULL) + { + NM_DEBUG_PRINT("hal_initialize() failed, exiting... Make sure the hal daemon is running?\n"); + exit (EXIT_FAILURE); + } + nm_data->hal_ctx = ctx; + hal_ctx_set_user_data (nm_data->hal_ctx, nm_data); + + /* Initialize our list of allowed access points */ + nm_ap_list_populate (nm_data); + + /* Grab network devices that are already present and add them to our list */ + nm_add_initial_devices (nm_data); + + /* Create a watch function that monitors cards for link status (hal doesn't do + * this for wireless cards yet). + */ + link_source = g_timeout_add (5000, nm_link_state_monitor, nm_data); + + /* Another watch function which handles networking state changes and applies + * the correct policy on a change. + */ + policy_source = g_timeout_add (3000, nm_state_modification_monitor, nm_data); + + /* Yet another watch function which scans for access points and + * attempts to associate with approved ones in a users' list. + */ + wireless_scan_source = g_timeout_add (10000, nm_wireless_scan_monitor, nm_data); + + /* Watch all devices that HAL knows about for state changes */ + hal_device_property_watch_all (nm_data->hal_ctx); + + /* We run dhclient when we need to, and we don't want any stray ones + * lying around upon launch. + */ + system ("killall dhclient"); + + /* Wheeee!!! */ + loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (loop); + + /* Kill the watch functions */ + g_source_remove (link_source); + g_source_remove (policy_source); + g_source_remove (wireless_scan_source); + /* Cleanup */ if (hal_shutdown (nm_data->hal_ctx) != 0) g_warning ("hal_shutdown() failed\n"); nm_data_free (nm_data); - return 0; + return (0); } diff --git a/src/NetworkManagerAP.c b/src/NetworkManagerAP.c index efc0ab094..4d7d9ebcb 100644 --- a/src/NetworkManagerAP.c +++ b/src/NetworkManagerAP.c @@ -38,6 +38,8 @@ struct NMAccessPoint guint16 rate; gboolean encrypted; gboolean invalid; + NMAPEncMethod enc_method; + gboolean matched; // used in ap list diffing /* Things from user prefs */ gchar *wep_key; @@ -323,3 +325,46 @@ void nm_ap_set_invalid (NMAccessPoint *ap, gboolean invalid) ap->invalid = invalid; } + + +/* + * Get/set functions for "matched", which is used by + * the ap list diffing functions to speed up the diff + * + */ +gboolean nm_ap_get_matched (NMAccessPoint *ap) +{ + g_return_val_if_fail (ap != NULL, TRUE); + + return (ap->matched); +} + +void nm_ap_set_matched (NMAccessPoint *ap, gboolean matched) +{ + g_return_if_fail (ap != NULL); + + ap->matched = matched; +} + + +/* + * Get/set functions for encryption method + * Given some sort of passphrase/wep key from the user, we try it first + * as a 104-bit passphrase->key conversion, and fall back from there. These + * functions are meant to cache which fallback succeeds so we don't have to + * do it every time. + * + */ +NMAPEncMethod nm_ap_get_enc_method (NMAccessPoint *ap) +{ + g_return_val_if_fail (ap != NULL, TRUE); + + return (ap->enc_method); +} + +void nm_ap_set_enc_method (NMAccessPoint *ap, NMAPEncMethod enc_method) +{ + g_return_if_fail (ap != NULL); + + ap->enc_method = enc_method; +} diff --git a/src/NetworkManagerAP.h b/src/NetworkManagerAP.h index 0ebf11036..beb09b811 100644 --- a/src/NetworkManagerAP.h +++ b/src/NetworkManagerAP.h @@ -29,6 +29,14 @@ typedef struct NMAccessPoint NMAccessPoint; #define NM_AP_PRIORITY_WORST 1000 +typedef enum NMAPEncMethod +{ + NM_AP_ENC_METHOD_NONE = 0, + NM_AP_ENC_METHOD_HEX_KEY, + NM_AP_ENC_METHOD_40_BIT_PASSPHRASE, + NM_AP_ENC_METHOD_104_BIT_PASSPHRASE +} NMAPEncMethod; + NMAccessPoint *nm_ap_new (void); NMAccessPoint *nm_ap_new_from_ap (NMAccessPoint *ap); @@ -63,4 +71,10 @@ void nm_ap_set_rate (NMAccessPoint *ap, guint16 rate); gboolean nm_ap_get_invalid (NMAccessPoint *ap); void nm_ap_set_invalid (NMAccessPoint *ap, gboolean invalid); +gboolean nm_ap_get_matched (NMAccessPoint *ap); +void nm_ap_set_matched (NMAccessPoint *ap, gboolean matched); + +NMAPEncMethod nm_ap_get_enc_method (NMAccessPoint *ap); +void nm_ap_set_enc_method (NMAccessPoint *ap, NMAPEncMethod enc_method); + #endif diff --git a/src/NetworkManagerAPList.c b/src/NetworkManagerAPList.c index cd16558fa..5f5d29fed 100644 --- a/src/NetworkManagerAPList.c +++ b/src/NetworkManagerAPList.c @@ -28,6 +28,38 @@ extern gboolean debug; + +/* + * nm_ap_list_find_ap_in_list + * + * Helper routine to find an AP in a list. + * + */ +static NMAccessPoint * nm_ap_list_find_ap_in_list (GSList *list, const char *network) +{ + NMAccessPoint *found_ap = NULL; + GSList *element = list; + + g_return_val_if_fail (network != NULL, NULL); + if (!list) + return (NULL); + + while (element) + { + NMAccessPoint *ap = (NMAccessPoint *)(element->data); + + if (ap && (nm_null_safe_strcmp (nm_ap_get_essid (ap), network) == 0)) + { + found_ap = ap; + break; + } + element = g_slist_next (element); + } + + return (found_ap); +} + + /* * nm_ap_list_get_ap_by_essid * @@ -44,19 +76,7 @@ NMAccessPoint *nm_ap_list_get_ap_by_essid (NMData *data, const char *network) if (nm_try_acquire_mutex (data->allowed_ap_list_mutex, __FUNCTION__)) { - GSList *element = data->allowed_ap_list; - - while (element) - { - NMAccessPoint *ap = (NMAccessPoint *)(element->data); - - if (ap && (nm_null_safe_strcmp (nm_ap_get_essid (ap), network) == 0)) - { - found_ap = ap; - break; - } - element = g_slist_next (element); - } + found_ap = nm_ap_list_find_ap_in_list (data->allowed_ap_list, network); nm_unlock_mutex (data->allowed_ap_list_mutex, __FUNCTION__); } else @@ -158,3 +178,62 @@ void nm_ap_list_free (GSList *ap_list) g_slist_free (ap_list); } + +/* + * nm_ap_list_diff + * + * Takes two ap lists and determines the differences. For each ap that is present + * in the original list, but not in the new list, a WirelessNetworkDisappeared signal is emitted + * over DBus. For each ap in the new list but not in the original, a WirelessNetworkAppeared + * signal is emitted. For each ap that is the same between the lists, the "invalid" flag is copied + * over from the old ap to the new ap to preserve "invalid" ap status (ie, user cancelled entering + * a WEP key so we cannot connect to it anyway, so why try). + * + * NOTE: it is assumed that this function is called only ONCE for each list passed into it, + * since the "matched" value on access points in the list are never cleared after the + * ap is initially created. Therefore, calling this function twice for any given ap list + * may result in undesired behavior. + * + */ +void nm_ap_list_diff (NMData *data, NMDevice *dev, GSList *old, GSList *new) +{ + GSList *element = old; + + g_return_if_fail (data != NULL); + g_return_if_fail (dev != NULL); + + /* Iterate over each item in the old list and find it in the new list */ + while (element) + { + NMAccessPoint *old_ap = (NMAccessPoint *)(element->data); + NMAccessPoint *new_ap = NULL; + + if (old_ap) + { + if ((new_ap = nm_ap_list_find_ap_in_list (new, nm_ap_get_essid (old_ap)))) + { + nm_ap_set_matched (old_ap, TRUE); + nm_ap_set_matched (new_ap, TRUE); + nm_ap_set_invalid (new_ap, nm_ap_get_invalid (old_ap)); + nm_ap_set_enc_method (new_ap, nm_ap_get_enc_method (old_ap)); + } + else + nm_dbus_signal_wireless_network_disappeared (data->dbus_connection, dev, old_ap); + } + element = g_slist_next (element); + } + + /* Iterate over the new list and compare to the old list. Items that aren't already + * matched are by definition new networks. + */ + element = new; + while (element) + { + NMAccessPoint *new_ap = (NMAccessPoint *)(element->data); + + if (new_ap && !nm_ap_get_matched (new_ap)) + nm_dbus_signal_wireless_network_appeared (data->dbus_connection, dev, new_ap); + element = g_slist_next (element); + } +} + diff --git a/src/NetworkManagerAPList.h b/src/NetworkManagerAPList.h index 0711bddd3..735ac9d40 100644 --- a/src/NetworkManagerAPList.h +++ b/src/NetworkManagerAPList.h @@ -24,6 +24,7 @@ #include #include "NetworkManager.h" +#include "NetworkManagerDevice.h" NMAccessPoint *nm_ap_list_get_ap_by_essid (NMData *data, const char *network); @@ -33,4 +34,6 @@ void nm_ap_list_populate (NMData *data); void nm_ap_list_free (GSList *ap_list); +void nm_ap_list_diff (NMData *data, NMDevice *dev, GSList *old, GSList *new); + #endif diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index 916a1093b..44f3777f8 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -20,6 +20,8 @@ */ #include +#include +#include #include #include #include @@ -67,7 +69,7 @@ static DBusMessage *nm_dbus_create_error_message (DBusMessage *message, const ch * Copies the object path for a device object into a provided buffer * */ -void nm_dbus_get_object_path_from_device (NMDevice *dev, unsigned char *buf, unsigned int buf_len) +static void nm_dbus_get_object_path_from_device (NMDevice *dev, unsigned char *buf, unsigned int buf_len) { g_return_if_fail (buf != NULL); g_return_if_fail (buf_len > 0); @@ -85,7 +87,7 @@ void nm_dbus_get_object_path_from_device (NMDevice *dev, unsigned char *buf, uns * Returns the device associated with a dbus object path * */ -NMDevice *nm_dbus_get_device_from_object_path (NMData *data, const char *path) +static NMDevice *nm_dbus_get_device_from_object_path (NMData *data, const char *path) { NMDevice *dev = NULL; @@ -125,12 +127,32 @@ NMDevice *nm_dbus_get_device_from_object_path (NMData *data, const char *path) /* - * nm_dbus_get_network_from_object_path + * nm_dbus_get_object_path_from_ap + * + * Copies the object path for a wireless network into a provided buffer + * + */ +static void nm_dbus_get_object_path_from_ap (NMDevice *dev, NMAccessPoint *ap, unsigned char *buf, unsigned int buf_len) +{ + g_return_if_fail (buf != NULL); + g_return_if_fail (buf_len > 0); + memset (buf, 0, buf_len); + + g_return_if_fail (dev != NULL); + g_return_if_fail (ap != NULL); + + /* FIXME: check to make sure the AP is actually in the device's ap_list */ + snprintf (buf, buf_len-1, "%s/%s/Networks/%s", NM_DBUS_DEVICES_OBJECT_PATH_PREFIX, nm_device_get_iface (dev), nm_ap_get_essid (ap)); +} + + +/* + * nm_dbus_get_ap_from_object_path * * Returns the network (ap) associated with a dbus object path * */ -NMAccessPoint *nm_dbus_get_network_from_object_path (const char *path, NMDevice *dev) +static NMAccessPoint *nm_dbus_get_ap_from_object_path (const char *path, NMDevice *dev) { NMAccessPoint *ap = NULL; int i = 0; @@ -356,6 +378,73 @@ void nm_dbus_signal_device_ip4_address_change (DBusConnection *connection, NMDev dbus_message_unref (message); } + +/* + * nm_dbus_signal_wireless_network_appeared + * + * Notifies the bus that a new wireless network has come into range + * + */ +void nm_dbus_signal_wireless_network_appeared (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap) +{ + DBusMessage *message; + unsigned char *object_path = g_new0 (unsigned char, 100); + + g_return_if_fail (connection != NULL); + g_return_if_fail (dev != NULL); + g_return_if_fail (ap != NULL); + + message = dbus_message_new_signal (NM_DBUS_NM_OBJECT_PATH_PREFIX, NM_DBUS_NM_NAMESPACE, "WirelessNetworkAppeared"); + if (!message) + { + NM_DEBUG_PRINT ("nm_dbus_signal_wireless_network_appeared(): Not enough memory for new dbus message!\n"); + return; + } + + nm_dbus_get_object_path_from_ap (dev, ap, object_path, 100); + dbus_message_append_args (message, DBUS_TYPE_STRING, object_path, DBUS_TYPE_INVALID); + g_free (object_path); + + if (!dbus_connection_send (connection, message, NULL)) + NM_DEBUG_PRINT ("nnm_dbus_signal_wireless_network_appeared(): Could not raise the WirelessNetworkAppeared signal!\n"); + + dbus_message_unref (message); +} + + +/* + * nm_dbus_signal_wireless_network_disappeared + * + * Notifies the bus that a new wireless network is no longer in range + * + */ +void nm_dbus_signal_wireless_network_disappeared (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap) +{ + DBusMessage *message; + unsigned char *object_path = g_new0 (unsigned char, 100); + + g_return_if_fail (connection != NULL); + g_return_if_fail (dev != NULL); + g_return_if_fail (ap != NULL); + + message = dbus_message_new_signal (NM_DBUS_NM_OBJECT_PATH_PREFIX, NM_DBUS_NM_NAMESPACE, "WirelessNetworkDisappeared"); + if (!message) + { + NM_DEBUG_PRINT ("nm_dbus_signal_wireless_network_disappeared(): Not enough memory for new dbus message!\n"); + return; + } + + nm_dbus_get_object_path_from_ap (dev, ap, object_path, 100); + dbus_message_append_args (message, DBUS_TYPE_STRING, object_path, DBUS_TYPE_INVALID); + g_free (object_path); + + if (!dbus_connection_send (connection, message, NULL)) + NM_DEBUG_PRINT ("nnm_dbus_signal_wireless_network_disappeared(): Could not raise the WirelessNetworkDisappeared signal!\n"); + + dbus_message_unref (message); +} + + #if 0 /* * nm_dbus_get_user_key_for_network_callback @@ -479,8 +568,21 @@ static void nm_dbus_set_user_key_for_network (DBusConnection *connection, DBusMe DBUS_TYPE_INVALID)) { NMDevice *dev; + const char *cancel_message = "***canceled***"; + if ((dev = nm_get_device_by_iface (data, device))) - nm_device_pending_action_set_user_key (dev, passphrase); + { + /* If the user canceled, mark the ap as invalid */ + if (strncmp (passphrase, cancel_message, strlen (cancel_message))) + { + NMAccessPoint *ap = nm_device_ap_list_get_ap_by_essid (dev, network); + + if (ap) + nm_ap_set_invalid (ap, TRUE); + } + else + nm_device_pending_action_set_user_key (dev, passphrase); + } char *key = nm_wireless_128bit_key_from_passphrase (passphrase); g_free (key); @@ -741,6 +843,7 @@ static DBusHandlerResult nm_dbus_nmi_filter (DBusConnection *connection, DBusMes g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); object_path = dbus_message_get_path (message); + if (!object_path || (strcmp (object_path, NM_DBUS_NMI_OBJECT_PATH) != 0)) return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); @@ -780,7 +883,7 @@ static DBusMessage *nm_dbus_devices_handle_networks_request (DBusConnection *con g_return_val_if_fail (request != NULL, NULL); g_return_val_if_fail (dev != NULL, NULL); - if (!(ap = nm_dbus_get_network_from_object_path (path, dev))) + if (!(ap = nm_dbus_get_ap_from_object_path (path, dev))) { reply_message = nm_dbus_create_error_message (message, NM_DBUS_NM_NAMESPACE, "NetworkNotFound", "The requested network does not exist for this device."); diff --git a/src/NetworkManagerDbus.h b/src/NetworkManagerDbus.h index 3cb4df12b..86c6b6b7e 100644 --- a/src/NetworkManagerDbus.h +++ b/src/NetworkManagerDbus.h @@ -35,24 +35,28 @@ #define NM_DBUS_NMI_NAMESPACE "org.freedesktop.NetworkManagerInfo" -DBusConnection * nm_dbus_init (NMData *data); +DBusConnection *nm_dbus_init (NMData *data); -void nm_dbus_signal_device_no_longer_active (DBusConnection *connection, NMDevice *dev); +void nm_dbus_signal_device_no_longer_active (DBusConnection *connection, NMDevice *dev); -void nm_dbus_signal_device_now_active (DBusConnection *connection, NMDevice *dev); +void nm_dbus_signal_device_now_active (DBusConnection *connection, NMDevice *dev); -void nm_dbus_signal_device_ip4_address_change(DBusConnection *connection, NMDevice *dev); +void nm_dbus_signal_device_ip4_address_change(DBusConnection *connection, NMDevice *dev); -void nm_dbus_get_user_key_for_network (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap, DBusPendingCall **pending); +void nm_dbus_signal_wireless_network_appeared (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap); -void nm_dbus_cancel_get_user_key_for_network (DBusConnection *connection); +void nm_dbus_signal_wireless_network_disappeared (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap); -char * nm_dbus_get_allowed_network_essid (DBusConnection *connection, const char *network); +void nm_dbus_get_user_key_for_network (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap, DBusPendingCall **pending); -char * nm_dbus_get_allowed_network_key (DBusConnection *connection, const char *network); +void nm_dbus_cancel_get_user_key_for_network (DBusConnection *connection); -guint nm_dbus_get_allowed_network_priority (DBusConnection *connection, const char *network); +char * nm_dbus_get_allowed_network_essid (DBusConnection *connection, const char *network); -char ** nm_dbus_get_allowed_networks (DBusConnection *connection, int *num_networks); +char * nm_dbus_get_allowed_network_key (DBusConnection *connection, const char *network); + +guint nm_dbus_get_allowed_network_priority (DBusConnection *connection, const char *network); + +char ** nm_dbus_get_allowed_networks (DBusConnection *connection, int *num_networks); #endif diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c index 1ed184430..6bf2d1cb5 100644 --- a/src/NetworkManagerDevice.c +++ b/src/NetworkManagerDevice.c @@ -33,7 +33,7 @@ #include "NetworkManagerDbus.h" #include "NetworkManagerWireless.h" #include "NetworkManagerPolicy.h" - +#include "NetworkManagerAPList.h" extern gboolean debug; @@ -1095,8 +1095,6 @@ void nm_device_ap_list_add (NMDevice *dev, NMAccessPoint *ap) */ void nm_device_ap_list_clear (NMDevice *dev) { - GSList *element; - g_return_if_fail (dev != NULL); g_return_if_fail (nm_device_is_wireless (dev)); @@ -1105,19 +1103,7 @@ void nm_device_ap_list_clear (NMDevice *dev) if (nm_try_acquire_mutex (dev->dev_options.wireless.ap_list_mutex, __FUNCTION__)) { - element = dev->dev_options.wireless.ap_list; - while (element) - { - if (element->data) - { - nm_ap_unref (element->data); - element->data = NULL; - } - - element = g_slist_next (element); - } - - g_slist_free (dev->dev_options.wireless.ap_list); + nm_ap_list_free (dev->dev_options.wireless.ap_list); dev->dev_options.wireless.ap_list = NULL; nm_unlock_mutex (dev->dev_options.wireless.ap_list_mutex, __FUNCTION__); @@ -1201,6 +1187,20 @@ NMAccessPoint *nm_device_ap_list_get_ap_by_essid (NMDevice *dev, const char *ess } +/* + * nm_device_ap_list_get + * + * Return a pointer to the AP list + * + */ +static const GSList *nm_device_ap_list_get (NMDevice *dev) +{ + g_return_val_if_fail (dev != NULL, NULL); + g_return_val_if_fail (nm_device_is_wireless (dev), NULL); + + return (dev->dev_options.wireless.ap_list); +} + /* * Get/Set functions for "best" access point * @@ -1266,9 +1266,7 @@ static void nm_device_do_normal_scan (NMDevice *dev) int err; NMAccessPoint *highest_priority_ap = NULL; int highest_priority = NM_AP_PRIORITY_WORST; - - /* Clear out the device's ap list */ - nm_device_ap_list_clear (dev); + GSList *old_ap_list = nm_device_ap_list_get (dev); err = iw_scan (iwlib_socket, nm_device_get_iface (dev), WIRELESS_EXT, &scan_results); if ((err == -1) && (errno == ENODATA)) @@ -1286,6 +1284,9 @@ static void nm_device_do_normal_scan (NMDevice *dev) } } + /* Clear out the ap list for this device in preparation for any new ones */ + dev->dev_options.wireless.ap_list = NULL; + /* Iterate over scan results and pick a "most" preferred access point. */ tmp_ap = scan_results.result; while (tmp_ap) @@ -1342,6 +1343,12 @@ static void nm_device_do_normal_scan (NMDevice *dev) nm_ap_unref (highest_priority_ap); } close (iwlib_socket); + + /* 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)); + nm_ap_list_free (old_ap_list); } else NM_DEBUG_PRINT_1 ("nm_device_do_normal_scan() could not get a control socket for the wireless card %s.\n", nm_device_get_iface (dev) ); diff --git a/src/NetworkManagerDevice.h b/src/NetworkManagerDevice.h index 944739f03..f1c0f518e 100644 --- a/src/NetworkManagerDevice.h +++ b/src/NetworkManagerDevice.h @@ -30,7 +30,7 @@ */ enum NMIfaceType { - NM_IFACE_TYPE_DONT_KNOW, + NM_IFACE_TYPE_DONT_KNOW = 0, NM_IFACE_TYPE_WIRED_ETHERNET, NM_IFACE_TYPE_WIRELESS_ETHERNET }; diff --git a/src/NetworkManagerWireless.c b/src/NetworkManagerWireless.c index 94748da49..355ee597e 100644 --- a/src/NetworkManagerWireless.c +++ b/src/NetworkManagerWireless.c @@ -90,6 +90,10 @@ gboolean nm_wireless_is_most_prefered_ap (NMData *data, NMAccessPoint *ap, int * g_return_val_if_fail (ap != NULL, FALSE); g_return_val_if_fail (highest_priority != NULL, FALSE); + /* If the AP is marked as invalid, of course its not prefered */ + if (nm_ap_get_invalid (ap)) + return (FALSE); + /* Attempt to acquire mutex for device list iteration. * If the acquire fails, just ignore the scan completely. */ diff --git a/test/nminfotest.c b/test/nminfotest.c index 9dbf60886..f5a6ad5d1 100644 --- a/test/nminfotest.c +++ b/test/nminfotest.c @@ -21,9 +21,15 @@ #include #include +#include #include #include +#define NMI_DBUS_NMI_OBJECT_PATH_PREFIX "/org/freedesktop/NetworkManagerInfo" +#define NMI_DBUS_NMI_NAMESPACE "org.freedesktop.NetworkManagerInfo" +#define NM_DBUS_NM_OBJECT_PATH_PREFIX "/org/freedesktop/NetworkManager" +#define NM_DBUS_NM_NAMESPACE "org.freedesktop.NetworkManager" + char * get_network_string_property (DBusConnection *connection, char *network, char *method) { @@ -32,10 +38,10 @@ char * get_network_string_property (DBusConnection *connection, char *network, c DBusMessageIter iter; DBusError error; - message = dbus_message_new_method_call ("org.freedesktop.NetworkManagerInfo", - "/org/freedesktop/NetworkManagerInfo", - "org.freedesktop.NetworkManagerInfo", - method); + message = dbus_message_new_method_call (NMI_DBUS_NMI_NAMESPACE, + NMI_DBUS_NMI_OBJECT_PATH_PREFIX, + NMI_DBUS_NMI_NAMESPACE, + method); if (message == NULL) { fprintf (stderr, "Couldn't allocate the dbus message\n"); @@ -89,10 +95,10 @@ int get_network_prio (DBusConnection *connection, char *network) g_return_val_if_fail (connection != NULL, -1); g_return_val_if_fail (network != NULL, -1); - message = dbus_message_new_method_call ("org.freedesktop.NetworkManagerInfo", - "/org/freedesktop/NetworkManagerInfo", - "org.freedesktop.NetworkManagerInfo", - "getAllowedNetworkPriority"); + message = dbus_message_new_method_call (NMI_DBUS_NMI_NAMESPACE, + NMI_DBUS_NMI_OBJECT_PATH_PREFIX, + NMI_DBUS_NMI_NAMESPACE, + "getAllowedNetworkPriority"); if (message == NULL) { fprintf (stderr, "Couldn't allocate the dbus message\n"); @@ -137,10 +143,10 @@ void get_allowed_networks (DBusConnection *connection) DBusMessageIter iter; DBusError error; - message = dbus_message_new_method_call ("org.freedesktop.NetworkManagerInfo", - "/org/freedesktop/NetworkManagerInfo", - "org.freedesktop.NetworkManagerInfo", - "getAllowedNetworks"); + message = dbus_message_new_method_call (NMI_DBUS_NMI_NAMESPACE, + NMI_DBUS_NMI_OBJECT_PATH_PREFIX, + NMI_DBUS_NMI_NAMESPACE, + "getAllowedNetworks"); if (message == NULL) { fprintf (stderr, "Couldn't allocate the dbus message\n"); @@ -191,13 +197,109 @@ void get_allowed_networks (DBusConnection *connection) dbus_free_string_array (networks); } +void get_user_key_for_network (DBusConnection *connection) +{ + DBusMessage *message; + + g_return_if_fail (connection != NULL); + + message = dbus_message_new_method_call (NMI_DBUS_NMI_NAMESPACE, NMI_DBUS_NMI_OBJECT_PATH_PREFIX, + NMI_DBUS_NMI_NAMESPACE, "getKeyForNetwork"); + if (message == NULL) + { + fprintf (stderr, "get_user_key_for_network(): Couldn't allocate the dbus message\n"); + return; + } + + dbus_message_append_args (message, DBUS_TYPE_STRING, "eth1", + DBUS_TYPE_STRING, "wireless-ap", + DBUS_TYPE_INVALID); + + if (!dbus_connection_send (connection, message, NULL)) + fprintf (stderr, "get_user_key_for_network(): could not send dbus message\n"); + + dbus_message_unref (message); +} + + +void set_user_key_for_network (DBusConnection *connection, DBusMessage *message, GMainLoop *loop) +{ + DBusError error; + char *device; + char *network; + char *passphrase; + + g_return_if_fail (connection != NULL); + g_return_if_fail (message != NULL); + + dbus_error_init (&error); + if (dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &device, + DBUS_TYPE_STRING, &network, + DBUS_TYPE_STRING, &passphrase, + DBUS_TYPE_INVALID)) + { + fprintf( stderr, "Device was '%s'\nNetwork was '%s'\nPassphrase was '%s'\n", device, network, passphrase); + + dbus_free (device); + dbus_free (network); + dbus_free (passphrase); + + g_main_loop_quit (loop); + } +} + + +static DBusHandlerResult nm_message_handler (DBusConnection *connection, DBusMessage *message, void *user_data) +{ + const char *method; + const char *path; + DBusMessage *reply_message = NULL; + gboolean handled = TRUE; + + g_return_val_if_fail (connection != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + method = dbus_message_get_member (message); + path = dbus_message_get_path (message); + + fprintf (stderr, "nm_dbus_nm_message_handler() got method %s for path %s\n", method, path); + + if (strcmp ("setKeyForNetwork", method) == 0) + set_user_key_for_network (connection, message, user_data); + else + handled = FALSE; + + return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); +} + + +/* + * nm_dbus_nm_unregister_handler + * + * Nothing happens here. + * + */ +void nm_unregister_handler (DBusConnection *connection, void *user_data) +{ + /* do nothing */ +} + int main( int argc, char *argv[] ) { - DBusConnection *connection; - DBusError error; + DBusConnection *connection; + DBusConnection *connection2; + DBusError error; + DBusObjectPathVTable vtable = { &nm_unregister_handler, &nm_message_handler, NULL, NULL, NULL, NULL }; + dbus_bool_t success = FALSE; + GMainLoop *loop = NULL; + + loop = g_main_loop_new (NULL, FALSE); g_type_init (); + if (!g_thread_supported ()) + g_thread_init (NULL); dbus_error_init (&error); connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); @@ -205,10 +307,29 @@ int main( int argc, char *argv[] ) { fprintf (stderr, "Error connecting to system bus: %s\n", error.message); dbus_error_free (&error); - return 1; + exit (1); + } + + dbus_connection_setup_with_g_main (connection, NULL); + dbus_error_init (&error); + dbus_bus_acquire_service (connection, NM_DBUS_NM_NAMESPACE, 0, &error); + if (dbus_error_is_set (&error)) + { + fprintf (stderr, "Could not acquire its service. dbus_bus_acquire_service() says: '%s'\n", error.message); + exit (1); + } + + success = dbus_connection_register_object_path (connection, NM_DBUS_NM_OBJECT_PATH_PREFIX, &vtable, loop); + if (!success) + { + fprintf (stderr, "Could not register a handler for NetworkManager. Not enough memory?\n"); + exit (1); } get_allowed_networks (connection); + get_user_key_for_network (connection); + + g_main_loop_run (loop); return 0; }