diff --git a/ChangeLog b/ChangeLog index 4f8c3af97..6db2cd0e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2006-10-13 Dan Williams + + * Huge DBus refactor: + - Create a "DBus Manager" object which manages the connection and + sends signals on NameOwnerChanged and connection/disconnection events, + handles reconnection to the bus if NM gets kicked off, and abstracts + signal handling + - Remove DBusConnection members from places where they are no + longer needed due to the refactor, like the dbus-connection + property of the named manager, and from NMData + - Reformats a bunch of the code to gnome style + (8-space tabs, braces on same line as statement, 80-col width). + Consider it open season to reformat any bits to gnome style. + style that aren't already. + 2006-10-13 Dan Williams * src/supplicant-manager/Makefile.am diff --git a/src/Makefile.am b/src/Makefile.am index 1337169fb..5f59a01ae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -27,6 +27,8 @@ NetworkManager_SOURCES = \ NetworkManagerDbusUtils.c \ NetworkManagerDialup.h \ NetworkManagerDbusUtils.h \ + nm-dbus-manager.h \ + nm-dbus-manager.c \ nm-dbus-nm.c \ nm-dbus-nm.h \ nm-dbus-device.c \ diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 54c733bd2..c9f70aca3 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -52,6 +52,10 @@ #include "nm-named-manager.h" #include "nm-vpn-act-request.h" #include "nm-dbus-vpn.h" +#include "nm-dbus-nm.h" +#include "nm-dbus-manager.h" +#include "nm-dbus-device.h" +#include "nm-dbus-net.h" #include "nm-netlink-monitor.h" #include "nm-dhcp-manager.h" #include "nm-logging.h" @@ -60,6 +64,8 @@ #define NM_DEFAULT_PID_FILE LOCALSTATEDIR"/run/NetworkManager.pid" +#define NO_HAL_MSG "Could not initialize connection to the HAL daemon." + /* * Globals */ @@ -67,6 +73,7 @@ static NMData *nm_data = NULL; static gboolean sigterm_pipe_handler (GIOChannel *src, GIOCondition condition, gpointer data); static void nm_data_free (NMData *data); +static void nm_hal_deinit (NMData *data); /* * nm_get_device_interface_from_hal @@ -208,21 +215,6 @@ NMDevice *nm_get_active_device (NMData *data) } -/* Hal doesn't really give us any way to pass a GMainContext to our - * mainloop integration function unfortunately. So we have to use - * a global. - */ -GMainContext *main_context = NULL; - -/* - * nm_hal_mainloop_integration - * - */ -static void nm_hal_mainloop_integration (LibHalContext *ctx, DBusConnection * dbus_connection) -{ - dbus_connection_setup_with_g_main (dbus_connection, main_context); -} - /* * nm_hal_device_added * @@ -348,10 +340,16 @@ void nm_add_initial_devices (NMData *data) static gboolean nm_state_change_signal_broadcast (gpointer user_data) { NMData *data = (NMData *)user_data; + NMDBusManager *dbus_mgr = NULL; + DBusConnection *dbus_connection = NULL; g_return_val_if_fail (data != NULL, FALSE); - nm_dbus_signal_state_change (data->dbus_connection, data); + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (dbus_connection) + nm_dbus_signal_state_change (dbus_connection, data); + g_object_unref (dbus_mgr); return FALSE; } @@ -413,6 +411,87 @@ nm_monitor_setup (NMData *data) return monitor; } +static gboolean +nm_hal_init (NMData *data, + DBusConnection *connection) +{ + gboolean success = FALSE; + DBusError error; + + g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail (connection != NULL, FALSE); + + /* Clean up an old context */ + if (data->hal_ctx) { + nm_warning ("a HAL context already existed. BUG."); + nm_hal_deinit (data); + } + + /* Initialize a new libhal context */ + if (!(data->hal_ctx = libhal_ctx_new ())) { + nm_warning ("Could not get connection to the HAL service."); + goto out; + } + + libhal_ctx_set_dbus_connection (data->hal_ctx, connection); + + dbus_error_init (&error); + if (!libhal_ctx_init (data->hal_ctx, &error)) { + nm_error ("libhal_ctx_init() failed: %s\n" + "Make sure the hal daemon is running?", + error.message); + goto out; + } + + libhal_ctx_set_user_data (data->hal_ctx, data->main_context); + libhal_ctx_set_device_added (data->hal_ctx, nm_hal_device_added); + libhal_ctx_set_device_removed (data->hal_ctx, nm_hal_device_removed); + libhal_ctx_set_device_new_capability (data->hal_ctx, nm_hal_device_new_capability); + + libhal_device_property_watch_all (data->hal_ctx, &error); + if (dbus_error_is_set (&error)) { + nm_error ("libhal_device_property_watch_all(): %s", error.message); + libhal_ctx_shutdown (data->hal_ctx, NULL); + goto out; + } + + /* Add any devices we know about */ + nm_add_initial_devices (data); + success = TRUE; + +out: + if (!success) { + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + if (data->hal_ctx) { + libhal_ctx_free (data->hal_ctx); + data->hal_ctx = NULL; + } + } + + return success; +} + +static void +nm_hal_deinit (NMData *data) +{ + DBusError error; + + g_return_if_fail (data != NULL); + + if (!data->hal_ctx) + return; + + dbus_error_init (&error); + libhal_ctx_shutdown (data->hal_ctx, &error); + if (dbus_error_is_set (&error)) { + nm_warning ("libhal shutdown failed - %s", error.message); + dbus_error_free (&error); + } + libhal_ctx_free (data->hal_ctx); + data->hal_ctx = NULL; +} + /* * nm_data_new @@ -524,6 +603,9 @@ static void nm_data_free (NMData *data) nm_ap_list_unref (data->allowed_ap_list); nm_ap_list_unref (data->invalid_ap_list); + nm_dbus_method_list_unref (data->nm_methods); + nm_dbus_method_list_unref (data->device_methods); + nm_vpn_manager_dispose (data->vpn_manager); nm_dhcp_manager_dispose (data->dhcp_manager); g_object_unref (data->named_manager); @@ -552,81 +634,55 @@ static gboolean sigterm_pipe_handler (GIOChannel *src, GIOCondition condition, g return FALSE; } -static LibHalContext *nm_get_hal_ctx (NMData *data) +static void +nm_name_owner_changed_handler (NMDBusManager *mgr, + DBusConnection *connection, + const char *name, + const char *old, + const char *new, + gpointer user_data) { - LibHalContext * ctx = NULL; - DBusError error; + NMData * data = (NMData *) user_data; + gboolean old_owner_good = (old && (strlen (old) > 0)); + gboolean new_owner_good = (new && (strlen (new) > 0)); - g_return_val_if_fail (data != NULL, NULL); + /* Only care about signals from HAL */ + if (strcmp (name, "org.freedesktop.Hal") != 0) + return; - /* Initialize libhal. We get a connection to the hal daemon here. */ - if ((ctx = libhal_ctx_new()) == NULL) - { - nm_error ("libhal_ctx_new() failed, exiting..."); - return NULL; - } - - nm_hal_mainloop_integration (ctx, data->dbus_connection); - libhal_ctx_set_dbus_connection (ctx, data->dbus_connection); - dbus_error_init (&error); - if(!libhal_ctx_init (ctx, &error)) - { - nm_error ("libhal_ctx_init() failed: %s\n" - "Make sure the hal daemon is running?", - error.message); - - dbus_error_free (&error); - libhal_ctx_free (ctx); - return NULL; - } - - libhal_ctx_set_user_data (ctx, data); - libhal_ctx_set_device_added (ctx, nm_hal_device_added); - libhal_ctx_set_device_removed (ctx, nm_hal_device_removed); - libhal_ctx_set_device_new_capability (ctx, nm_hal_device_new_capability); - - dbus_error_init (&error); - libhal_device_property_watch_all (ctx, &error); - if (dbus_error_is_set (&error)) - { - nm_error ("libhal_device_property_watch_all(): %s", error.message); - dbus_error_free (&error); - libhal_ctx_free (ctx); - } - - return ctx; -} - - -void nm_hal_init (NMData *data) -{ - g_return_if_fail (data != NULL); - - if ((data->hal_ctx = nm_get_hal_ctx (data))) - nm_add_initial_devices (data); -} - - -void nm_hal_deinit (NMData *data) -{ - g_return_if_fail (data != NULL); - - if (data->hal_ctx) - { - DBusError error; - - dbus_error_init (&error); - libhal_ctx_shutdown (data->hal_ctx, &error); - if (dbus_error_is_set (&error)) - { - nm_warning ("libhal shutdown failed - %s", error.message); - dbus_error_free (&error); + if (!old_owner_good && new_owner_good) { + /* HAL just appeared */ + if (!nm_hal_init (data, connection)) { + nm_error (NO_HAL_MSG); + exit (EXIT_FAILURE); } - libhal_ctx_free (data->hal_ctx); - data->hal_ctx = NULL; + } else if (old_owner_good && !new_owner_good) { + /* HAL went away. Bad HAL. */ + nm_hal_deinit (data); } } +static void +nm_dbus_connection_changed_handler (NMDBusManager *mgr, + DBusConnection *connection, + gpointer user_data) +{ + NMData *data = (NMData *) user_data; + char * owner; + + if (!connection) { + nm_hal_deinit (data); + return; + } + + if ((owner = nm_dbus_manager_get_name_owner (mgr, "org.freedesktop.Hal"))) { + if (!nm_hal_init (data, connection)) { + nm_error (NO_HAL_MSG); + exit (EXIT_FAILURE); + } + g_free (owner); + } +} static void write_pidfile (const char *pidfile) @@ -669,19 +725,30 @@ static void nm_print_usage (void) * main * */ -int main( int argc, char *argv[] ) +int +main (int argc, char *argv[]) { + GOptionContext *opt_ctx = NULL; gboolean become_daemon = FALSE; gboolean enable_test_devices = FALSE; gboolean show_usage = FALSE; - char * owner; char * pidfile = NULL; char * user_pidfile = NULL; - - if (getuid () != 0) - { + NMDBusManager * dbus_mgr; + DBusConnection *dbus_connection; + int exit_status = EXIT_FAILURE; + + GOptionEntry options[] = { + {"no-daemon", 0, 0, G_OPTION_ARG_NONE, &become_daemon, "Don't become a daemon", NULL}, + {"pid-file", 0, 0, G_OPTION_ARG_STRING, &user_pidfile, "Specify the location of a PID file", NULL}, + {"enable-test-devices", 0, 0, G_OPTION_ARG_NONE, &enable_test_devices, "Allow dummy devices to be created via DBUS methods [DEBUG]", NULL}, + {"info", 0, 0, G_OPTION_ARG_NONE, &show_usage, "Show application information", NULL}, + {NULL} + }; + + if (getuid () != 0) { g_printerr ("You must be root to run NetworkManager!\n"); - return (EXIT_FAILURE); + goto exit; } bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); @@ -689,43 +756,33 @@ int main( int argc, char *argv[] ) textdomain (GETTEXT_PACKAGE); /* Parse options */ - { - GOptionContext *opt_ctx = NULL; - GOptionEntry options[] = { - {"no-daemon", 0, 0, G_OPTION_ARG_NONE, &become_daemon, "Don't become a daemon", NULL}, - {"pid-file", 0, 0, G_OPTION_ARG_STRING, &user_pidfile, "Specify the location of a PID file", NULL}, - {"enable-test-devices", 0, 0, G_OPTION_ARG_NONE, &enable_test_devices, "Allow dummy devices to be created via DBUS methods [DEBUG]", NULL}, - {"info", 0, 0, G_OPTION_ARG_NONE, &show_usage, "Show application information", NULL}, - {NULL} - }; - opt_ctx = g_option_context_new(""); - g_option_context_add_main_entries(opt_ctx, options, NULL); - g_option_context_parse(opt_ctx, &argc, &argv, NULL); - g_option_context_free(opt_ctx); - } + opt_ctx = g_option_context_new(""); + g_option_context_add_main_entries(opt_ctx, options, NULL); + g_option_context_parse(opt_ctx, &argc, &argv, NULL); + g_option_context_free(opt_ctx); - /* Tricky: become_daemon is FALSE by default, so unless it's TRUE because of a CLI - * option, it'll become TRUE after this */ - become_daemon = !become_daemon; - if (show_usage == TRUE) - { + if (show_usage == TRUE) { nm_print_usage(); - exit (EXIT_SUCCESS); + exit_status = EXIT_SUCCESS; + goto exit; } - if (become_daemon) - { - if (daemon (0, 0) < 0) - { + pidfile = g_strdup (user_pidfile ? user_pidfile : NM_DEFAULT_PID_FILE); + + /* Tricky: become_daemon is FALSE by default, so unless it's TRUE because + * of a CLI option, it'll become TRUE after this + */ + become_daemon = !become_daemon; + if (become_daemon) { + if (daemon (0, 0) < 0) { int saved_errno; saved_errno = errno; - nm_error ("NetworkManager could not daemonize: %s [error %u]", - g_strerror (saved_errno), saved_errno); - exit (EXIT_FAILURE); + nm_error ("Could not daemonize: %s [error %u]", + g_strerror (saved_errno), + saved_errno); + goto exit; } - - pidfile = user_pidfile ? user_pidfile : NM_DEFAULT_PID_FILE; write_pidfile (pidfile); } @@ -748,46 +805,76 @@ int main( int argc, char *argv[] ) /* Initialize our instance data */ nm_data = nm_data_new (enable_test_devices); - if (!nm_data) - { - nm_error ("nm_data_new() failed... Not enough memory?"); - exit (EXIT_FAILURE); + if (!nm_data) { + nm_error ("Failed to initialize."); + goto pidfile; } - /* Create our dbus service */ - nm_data->dbus_connection = nm_dbus_init (nm_data); - if (!nm_data->dbus_connection) - { - nm_error ("nm_dbus_init() failed, exiting. " - "Either dbus is not running, or the " - "NetworkManager dbus security policy " - "was not loaded."); - exit (EXIT_FAILURE); + /* Initialize our DBus service & connection */ + dbus_mgr = nm_dbus_manager_get (nm_data->main_context); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_error ("Failed to initialize. " + "Either dbus is not running, or the " + "NetworkManager dbus security policy " + "was not loaded."); + goto done; } + g_signal_connect (G_OBJECT (dbus_mgr), "name-owner-changed", + G_CALLBACK (nm_name_owner_changed_handler), nm_data); + g_signal_connect (G_OBJECT (dbus_mgr), "dbus-connection-changed", + G_CALLBACK (nm_dbus_connection_changed_handler), nm_data); + nm_dbus_manager_register_signal_handler (dbus_mgr, + NMI_DBUS_INTERFACE, + NULL, + nm_dbus_nmi_signal_handler, + nm_data); + + /* Register DBus method handlers for the main NM objects */ + nm_data->nm_methods = nm_dbus_nm_methods_setup (nm_data); + nm_dbus_manager_register_method_list (dbus_mgr, nm_data->nm_methods); + nm_data->device_methods = nm_dbus_device_methods_setup (nm_data); + nm_dbus_manager_register_method_list (dbus_mgr, nm_data->device_methods); + nm_data->net_methods = nm_dbus_net_methods_setup (nm_data); - /* Need to happen after DBUS is initialized */ nm_data->vpn_manager = nm_vpn_manager_new (nm_data); - nm_data->dhcp_manager = nm_dhcp_manager_new (nm_data); - nm_data->named_manager = nm_named_manager_new (nm_data->dbus_connection); + if (!nm_data->vpn_manager) { + nm_warning ("Failed to start the VPN manager."); + goto done; + } + + nm_data->dhcp_manager = nm_dhcp_manager_new (nm_data, nm_data->main_context); + if (!nm_data->dhcp_manager) { + nm_warning ("Failed to start the DHCP manager."); + goto done; + } + + nm_data->named_manager = nm_named_manager_new (); + if (!nm_data->named_manager) { + nm_warning ("Failed to start the named manager."); + goto done; + } + + /* Start our DBus service */ + if (!nm_dbus_manager_start_service (dbus_mgr)) { + nm_warning ("Failed to start the named manager."); + goto done; + } + + /* If Hal is around, grab a device list from it */ + if (nm_dbus_manager_name_has_owner (dbus_mgr, "org.freedesktop.Hal")) { + if (!nm_hal_init (nm_data, dbus_connection)) { + nm_error (NO_HAL_MSG); + goto done; + } + } /* If NMI is running, grab allowed wireless network lists from it ASAP */ - if (nm_dbus_is_info_daemon_running (nm_data->dbus_connection)) - { + if (nm_dbus_manager_name_has_owner (dbus_mgr, NMI_DBUS_SERVICE)) { nm_policy_schedule_allowed_ap_list_update (nm_data); nm_dbus_vpn_schedule_vpn_connections_update (nm_data); } - /* Right before we init hal, we have to make sure our mainloop - * integration function knows about our GMainContext. HAL doesn't give - * us any way to pass that into its mainloop integration callback, so - * its got to be a global. - */ - main_context = nm_data->main_context; - - /* If Hal is around, grab a device list from it */ - if ((owner = get_name_owner (nm_data->dbus_connection, "org.freedesktop.Hal"))) - nm_hal_init (nm_data); - /* We run dhclient when we need to, and we don't want any stray ones * lying around upon launch. */ @@ -802,16 +889,23 @@ int main( int argc, char *argv[] ) /* Run the main loop */ nm_policy_schedule_device_change_check (nm_data); nm_schedule_state_change_signal_broadcast (nm_data); + exit_status = EXIT_SUCCESS; g_main_loop_run (nm_data->main_loop); +done: nm_print_open_socks (); nm_data_free (nm_data); + /* nm_data_free needs the dbus connection, so must kill the + * dbus manager after that. + */ + g_object_unref (dbus_mgr); nm_logging_shutdown (); - /* Clean up pidfile */ +pidfile: if (pidfile) unlink (pidfile); - g_free (user_pidfile); + g_free (pidfile); - exit (0); +exit: + exit (exit_status); } diff --git a/src/NetworkManagerAPList.c b/src/NetworkManagerAPList.c index 4a93d4d4d..f36c8df4a 100644 --- a/src/NetworkManagerAPList.c +++ b/src/NetworkManagerAPList.c @@ -27,6 +27,7 @@ #include "NetworkManagerUtils.h" #include "NetworkManagerDbus.h" #include "nm-utils.h" +#include "nm-dbus-manager.h" struct NMAccessPointList @@ -433,21 +434,20 @@ NMAccessPoint *nm_ap_list_get_ap_by_address (NMAccessPointList *list, const stru * TRUE if the ap was completely new * */ -gboolean nm_ap_list_merge_scanned_ap (NMDevice80211Wireless *dev, NMAccessPointList *list, NMAccessPoint *merge_ap) +gboolean +nm_ap_list_merge_scanned_ap (NMDevice80211Wireless *dev, + NMAccessPointList *list, + NMAccessPoint *merge_ap) { NMAccessPoint * list_ap = NULL; gboolean strength_changed = FALSE; gboolean new = FALSE; - NMData * app_data; const struct ether_addr * merge_bssid; g_return_val_if_fail (dev != NULL, FALSE); g_return_val_if_fail (list != NULL, FALSE); g_return_val_if_fail (merge_ap != NULL, FALSE); - app_data = nm_device_get_app_data (NM_DEVICE (dev)); - g_return_val_if_fail (app_data != NULL, FALSE); - merge_bssid = nm_ap_get_address (merge_ap); if (nm_ethernet_address_is_valid (merge_bssid) && (list_ap = nm_ap_list_get_ap_by_address (list, merge_bssid))) { @@ -464,14 +464,13 @@ gboolean nm_ap_list_merge_scanned_ap (NMDevice80211Wireless *dev, NMAccessPointL /* Did the AP's name change? */ if (!devlist_essid || !merge_essid || nm_null_safe_strcmp (devlist_essid, merge_essid)) { - nm_dbus_signal_wireless_network_change (app_data->dbus_connection, - dev, list_ap, NETWORK_STATUS_DISAPPEARED, -1); + nm_dbus_signal_wireless_network_change (dev, list_ap, + NETWORK_STATUS_DISAPPEARED, -1); new = TRUE; } nm_ap_set_capabilities (list_ap, nm_ap_get_capabilities (merge_ap)); - if (nm_ap_get_strength (merge_ap) != nm_ap_get_strength (list_ap)) - { + if (nm_ap_get_strength (merge_ap) != nm_ap_get_strength (list_ap)) { nm_ap_set_strength (list_ap, nm_ap_get_strength (merge_ap)); strength_changed = TRUE; } @@ -518,26 +517,22 @@ gboolean nm_ap_list_merge_scanned_ap (NMDevice80211Wireless *dev, NMAccessPointL * artificial, since it clearly exists somewhere. */ nm_ap_set_artificial (list_ap, FALSE); - } - else - { + } else { /* Add the merge AP to the list. */ nm_ap_list_append_ap (list, merge_ap); list_ap = merge_ap; new = TRUE; } - if (list_ap && strength_changed && !new) - { + if (list_ap && strength_changed && !new) { const int new_strength = nm_ap_get_strength (list_ap); - nm_dbus_signal_wireless_network_change (app_data->dbus_connection, - dev, list_ap, NETWORK_STATUS_STRENGTH_CHANGED, new_strength); + nm_dbus_signal_wireless_network_change (dev, list_ap, + NETWORK_STATUS_STRENGTH_CHANGED, new_strength); } - if (list_ap && new) - { - nm_dbus_signal_wireless_network_change (app_data->dbus_connection, - dev, list_ap, NETWORK_STATUS_APPEARED, -1); + if (list_ap && new) { + nm_dbus_signal_wireless_network_change (dev, list_ap, + NETWORK_STATUS_APPEARED, -1); } return TRUE; @@ -560,21 +555,21 @@ void nm_ap_list_copy_properties (NMAccessPointList *dest, NMAccessPointList *sou if (!dest || !source) return; - if ((iter = nm_ap_list_iter_new (dest))) - { - while ((dest_ap = nm_ap_list_iter_next (iter))) - { - NMAccessPoint *src_ap = NULL; + if (!(iter = nm_ap_list_iter_new (dest))) + return; - if ((src_ap = nm_ap_list_get_ap_by_essid (source, nm_ap_get_essid (dest_ap)))) - { - nm_ap_set_invalid (dest_ap, nm_ap_get_invalid (src_ap)); - nm_ap_set_security (dest_ap, nm_ap_get_security (src_ap)); - nm_ap_set_timestamp_via_timestamp (dest_ap, nm_ap_get_timestamp (src_ap)); - } + while ((dest_ap = nm_ap_list_iter_next (iter))) + { + NMAccessPoint *src_ap = NULL; + + if ((src_ap = nm_ap_list_get_ap_by_essid (source, nm_ap_get_essid (dest_ap)))) + { + nm_ap_set_invalid (dest_ap, nm_ap_get_invalid (src_ap)); + nm_ap_set_security (dest_ap, nm_ap_get_security (src_ap)); + nm_ap_set_timestamp_via_timestamp (dest_ap, nm_ap_get_timestamp (src_ap)); } - nm_ap_list_iter_free (iter); } + nm_ap_list_iter_free (iter); } @@ -586,23 +581,26 @@ void nm_ap_list_copy_properties (NMAccessPointList *dest, NMAccessPointList *sou * If one is found, copy the essid over to the original access point. * */ -void nm_ap_list_copy_one_essid_by_address (NMData *app_data, - NMDevice80211Wireless *dev, - NMAccessPoint *ap, - NMAccessPointList *search_list) +void +nm_ap_list_copy_one_essid_by_address (NMDevice80211Wireless *dev, + NMAccessPoint *ap, + NMAccessPointList *search_list) { - NMAccessPoint *found_ap; + NMAccessPoint * found_ap; if (!ap || !search_list) return; - if (!nm_ap_get_essid (ap) && (found_ap = nm_ap_list_get_ap_by_address (search_list, nm_ap_get_address (ap)))) - { - if (nm_ap_get_essid (found_ap)) - { - nm_ap_set_essid (ap, nm_ap_get_essid (found_ap)); - nm_dbus_signal_wireless_network_change (app_data->dbus_connection, dev, ap, NETWORK_STATUS_APPEARED, 0); - } + if (!nm_ap_get_essid (ap)) + return; + + found_ap = nm_ap_list_get_ap_by_address (search_list, nm_ap_get_address (ap)); + if (!found_ap) + return; + + if (nm_ap_get_essid (found_ap)) { + nm_ap_set_essid (ap, nm_ap_get_essid (found_ap)); + nm_dbus_signal_wireless_network_change (dev, ap, NETWORK_STATUS_APPEARED, 0); } } @@ -615,10 +613,10 @@ void nm_ap_list_copy_one_essid_by_address (NMData *app_data, * its found, copy the source access point's essid to the dest access point. * */ -void nm_ap_list_copy_essids_by_address (NMData *app_data, - NMDevice80211Wireless *dev, - NMAccessPointList *dest, - NMAccessPointList *source) +void +nm_ap_list_copy_essids_by_address (NMDevice80211Wireless *dev, + NMAccessPointList *dest, + NMAccessPointList *source) { NMAPListIter *iter; NMAccessPoint *dest_ap; @@ -626,13 +624,12 @@ void nm_ap_list_copy_essids_by_address (NMData *app_data, if (!dest || !source) return; - if ((iter = nm_ap_list_iter_new (dest))) - { - while ((dest_ap = nm_ap_list_iter_next (iter))) - nm_ap_list_copy_one_essid_by_address (app_data, dev, dest_ap, source); + if (!(iter = nm_ap_list_iter_new (dest))) + return; - nm_ap_list_iter_free (iter); - } + while ((dest_ap = nm_ap_list_iter_next (iter))) + nm_ap_list_copy_one_essid_by_address (dev, dest_ap, source); + nm_ap_list_iter_free (iter); } diff --git a/src/NetworkManagerAPList.h b/src/NetworkManagerAPList.h index d4e83830b..8169e4a6c 100644 --- a/src/NetworkManagerAPList.h +++ b/src/NetworkManagerAPList.h @@ -48,8 +48,8 @@ NMAccessPoint * nm_ap_list_get_ap_by_essid (NMAccessPointList *list, const char NMAccessPoint * nm_ap_list_get_ap_by_address (NMAccessPointList *list, const struct ether_addr *addr); void nm_ap_list_copy_properties (NMAccessPointList *dest, NMAccessPointList *source); -void nm_ap_list_copy_essids_by_address (NMData *app_data, NMDevice80211Wireless *dev, NMAccessPointList *dest, NMAccessPointList *source); -void nm_ap_list_copy_one_essid_by_address (NMData *app_data, NMDevice80211Wireless *dev, NMAccessPoint *ap, NMAccessPointList *search_list); +void nm_ap_list_copy_essids_by_address (NMDevice80211Wireless *dev, NMAccessPointList *dest, NMAccessPointList *source); +void nm_ap_list_copy_one_essid_by_address (NMDevice80211Wireless *dev, NMAccessPoint *ap, NMAccessPointList *search_list); gboolean nm_ap_list_merge_scanned_ap (NMDevice80211Wireless *dev, NMAccessPointList *list, NMAccessPoint *merge_ap); diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index 5fa7233bf..ede80f0aa 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -43,10 +43,13 @@ #include "nm-dbus-nmi.h" #include "nm-utils.h" #include "nm-dhcp-manager.h" +#include "nm-dbus-manager.h" +#if 0 static char *get_nmi_match_string (const char *owner); static gpointer nm_dbus_reinit (gpointer user_data); +#endif /* * nm_dbus_create_error_message @@ -54,8 +57,12 @@ static gpointer nm_dbus_reinit (gpointer user_data); * Make a DBus error message * */ -DBusMessage *nm_dbus_create_error_message (DBusMessage *message, const char *exception_namespace, - const char *exception, const char *format, ...) +DBusMessage * +nm_dbus_create_error_message (DBusMessage *message, + const char *exception_namespace, + const char *exception, + const char *format, + ...) { char *exception_text; DBusMessage *reply_message; @@ -74,6 +81,17 @@ DBusMessage *nm_dbus_create_error_message (DBusMessage *message, const char *exc } +DBusMessage * +nm_dbus_new_invalid_args_error (DBusMessage *replyto, + const char *namespace) +{ + return nm_dbus_create_error_message (replyto, + namespace, + "InvalidArguments", + "Invalid method arguments."); +} + + /* * nm_dbus_get_object_path_for_device * @@ -155,6 +173,7 @@ NMDevice *nm_dbus_get_device_from_escaped_object_path (NMData *data, const char && ((path[len] == '\0' || path[len] == '/'))) { g_free (escaped_compare_path); + g_object_ref (G_OBJECT (dev)); break; } g_free (escaped_compare_path); @@ -204,55 +223,61 @@ static DeviceStatusSignals dev_status_signals[] = * Notifies the bus that a particular device has had a status change * */ -static gboolean nm_dbus_signal_device_status_change (gpointer user_data) +static gboolean +nm_dbus_signal_device_status_change (gpointer user_data) { NMStatusChangeData *cb_data = (NMStatusChangeData *)user_data; DBusMessage * message; - char * dev_path; + char * dev_path = NULL; const char * sig = NULL; int i = 0; + NMDBusManager * dbus_mgr = NULL; + DBusConnection *dbus_connection; g_return_val_if_fail (cb_data->data, FALSE); - g_return_val_if_fail (cb_data->data->dbus_connection, FALSE); g_return_val_if_fail (cb_data->dev, FALSE); + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get the dbus connection."); + goto out; + } + while ((dev_status_signals[i].status != DEVICE_STATUS_INVALID) && (dev_status_signals[i].status != cb_data->status)) i++; if (!(sig = dev_status_signals[i].signal)) - return FALSE; + goto out; if (!(dev_path = nm_dbus_get_object_path_for_device (cb_data->dev))) - return FALSE; + goto out; - if (!(message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, sig))) - { + message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, sig); + if (!message) { nm_warning ("nm_dbus_signal_device_status_change(): Not enough memory for new dbus message!"); - g_free (dev_path); - return FALSE; + goto out; } /* If the device was wireless, attach the name of the wireless network that failed to activate */ - if (cb_data->ap) - { + if (cb_data->ap) { const char *essid = nm_ap_get_essid (cb_data->ap); if (essid) dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH, &dev_path, DBUS_TYPE_STRING, &essid, DBUS_TYPE_INVALID); nm_ap_unref (cb_data->ap); - } - else + } else { dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH, &dev_path, DBUS_TYPE_INVALID); + } - g_free (dev_path); - - if (!dbus_connection_send (cb_data->data->dbus_connection, message, NULL)) - nm_warning ("nm_dbus_signal_device_status_change(): Could not raise the signal!"); - + dbus_connection_send (dbus_connection, message, NULL); dbus_message_unref (message); g_object_unref (G_OBJECT (cb_data->dev)); g_slice_free (NMStatusChangeData, cb_data); +out: + g_object_unref (dbus_mgr); + g_free (dev_path); return FALSE; } @@ -345,25 +370,36 @@ void nm_dbus_signal_state_change (DBusConnection *connection, NMData *data) * Notifies the bus that a new wireless network has come into range * */ -void nm_dbus_signal_wireless_network_change (DBusConnection *connection, NMDevice80211Wireless *dev, NMAccessPoint *ap, NMNetworkStatus status, gint strength) +void +nm_dbus_signal_wireless_network_change (NMDevice80211Wireless *dev, + NMAccessPoint *ap, + NMNetworkStatus status, + gint strength) { + NMDBusManager * dbus_mgr = NULL; + DBusConnection *dbus_connection; DBusMessage * message; char * dev_path = NULL; char * net_path = NULL; const char * sig = NULL; - g_return_if_fail (connection != NULL); g_return_if_fail (dev != NULL); g_return_if_fail (ap != NULL); + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get the dbus connection."); + goto out; + } + if (!(dev_path = nm_dbus_get_object_path_for_device (NM_DEVICE (dev)))) goto out; if (!(net_path = nm_dbus_get_object_path_for_network (NM_DEVICE (dev), ap))) goto out; - switch (status) - { + switch (status) { case NETWORK_STATUS_DISAPPEARED: sig = "WirelessNetworkDisappeared"; break; @@ -377,483 +413,129 @@ void nm_dbus_signal_wireless_network_change (DBusConnection *connection, NMDevic break; } - if (!sig) - { - nm_warning ("nm_dbus_signal_wireless_network_change(): tried to broadcast unknown signal."); + if (!sig) { + nm_warning ("tried to broadcast unknown signal."); goto out; } - if (!(message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, sig))) - { - nm_warning ("nm_dbus_signal_wireless_network_change(): Not enough memory for new dbus message!"); + message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, sig); + if (!message) { + nm_warning ("could not allocate the dbus message."); goto out; } - dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH, &dev_path, DBUS_TYPE_OBJECT_PATH, &net_path, DBUS_TYPE_INVALID); - if (status == NETWORK_STATUS_STRENGTH_CHANGED) - dbus_message_append_args (message, DBUS_TYPE_INT32, &strength, DBUS_TYPE_INVALID); - - if (!dbus_connection_send (connection, message, NULL)) - nm_warning ("nm_dbus_signal_wireless_network_change(): Could not raise the WirelessNetwork* signal!"); + dbus_message_append_args (message, + DBUS_TYPE_OBJECT_PATH, &dev_path, + DBUS_TYPE_OBJECT_PATH, &net_path, + DBUS_TYPE_INVALID); + if (status == NETWORK_STATUS_STRENGTH_CHANGED) { + dbus_message_append_args (message, + DBUS_TYPE_INT32, &strength, + DBUS_TYPE_INVALID); + } + dbus_connection_send (dbus_connection, message, NULL); dbus_message_unref (message); out: g_free (net_path); g_free (dev_path); + g_object_unref (dbus_mgr); } -void nm_dbus_signal_device_strength_change (DBusConnection *connection, NMDevice80211Wireless *dev, gint strength) +void +nm_dbus_signal_device_strength_change (NMDevice80211Wireless *dev, + gint strength) { + NMDBusManager * dbus_mgr = NULL; + DBusConnection *dbus_connection; DBusMessage * message; char * dev_path = NULL; - g_return_if_fail (connection != NULL); g_return_if_fail (dev != NULL); + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get the dbus connection."); + goto out; + } + if (!(dev_path = nm_dbus_get_object_path_for_device (NM_DEVICE (dev)))) goto out; - if (!(message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, "DeviceStrengthChanged"))) - { - nm_warning ("nm_dbus_signal_device_strength_change(): Not enough memory for new dbus message!"); + message = dbus_message_new_signal (NM_DBUS_PATH, + NM_DBUS_INTERFACE, + "DeviceStrengthChanged"); + if (!message) { + nm_warning ("could not allocate the dbus message."); goto out; } - dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH, &dev_path, DBUS_TYPE_INT32, &strength, DBUS_TYPE_INVALID); - if (!dbus_connection_send (connection, message, NULL)) - nm_warning ("nm_dbus_signal_device_strength_change(): Could not raise the DeviceStrengthChanged signal!"); - + dbus_message_append_args (message, + DBUS_TYPE_OBJECT_PATH, &dev_path, + DBUS_TYPE_INT32, &strength, + DBUS_TYPE_INVALID); + dbus_connection_send (dbus_connection, message, NULL); dbus_message_unref (message); out: g_free (dev_path); + g_object_unref (dbus_mgr); } - -/* - * nm_dbus_signal_filter - * - * Respond to NetworkManagerInfo signals about changing Allowed Networks - * - */ -static DBusHandlerResult nm_dbus_signal_filter (DBusConnection *connection, DBusMessage *message, void *user_data) +gboolean +nm_dbus_nmi_signal_handler (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { - NMData * data = (NMData *)user_data; - const char * object_path; - const char * method; - gboolean handled = FALSE; - DBusError error; + NMData * data = (NMData *) user_data; + const char * object_path; + gboolean handled = FALSE; - g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - 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); + g_return_val_if_fail (data != NULL, FALSE); - method = dbus_message_get_member (message); if (!(object_path = dbus_message_get_path (message))) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return FALSE; - if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (strcmp (object_path, NMI_DBUS_PATH) != 0) + return FALSE; - /* nm_debug ("nm_dbus_nmi_filter() got method %s for path %s", method, object_path); */ + if (dbus_message_is_signal (message, NMI_DBUS_INTERFACE, "WirelessNetworkUpdate")) { + char *network = NULL; - dbus_error_init (&error); - - if (strcmp (object_path, NMI_DBUS_PATH) == 0) - { - if (dbus_message_is_signal (message, NMI_DBUS_INTERFACE, "WirelessNetworkUpdate")) - { - char *network = NULL; - - if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &network, DBUS_TYPE_INVALID)) - { - /* Update a single wireless network's data */ - nm_debug ("NetworkManagerInfo triggered update of wireless network '%s'", network); - nm_dbus_update_one_allowed_network (connection, network, data); - handled = TRUE; - } - } - else if (dbus_message_is_signal (message, NMI_DBUS_INTERFACE, "VPNConnectionUpdate")) - { - char *name = NULL; - - if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) - { - nm_debug ("NetworkManagerInfo triggered update of VPN connection '%s'", name); - nm_dbus_vpn_update_one_vpn_connection (data->dbus_connection, name, data); - handled = TRUE; - } - } - else if (dbus_message_is_signal (message, NMI_DBUS_INTERFACE, "UserInterfaceActivated")) - { - nm_device_802_11_wireless_set_scan_interval (data, NULL, NM_WIRELESS_SCAN_INTERVAL_ACTIVE); + if (dbus_message_get_args (message, + NULL, + DBUS_TYPE_STRING, &network, + DBUS_TYPE_INVALID)) { + /* Update a single wireless network's data */ + nm_debug ("NetworkManagerInfo triggered update of wireless network " + "'%s'", + network); + nm_dbus_update_one_allowed_network (network, data); handled = TRUE; } - } - else if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")) - { - nm_hal_deinit (data); - dbus_connection_unref (data->dbus_connection); - data->dbus_connection = NULL; - nm_dhcp_manager_dispose (data->dhcp_manager); - g_thread_create ((GThreadFunc) nm_dbus_reinit, (gpointer) data, FALSE, NULL); - handled = TRUE; - } - else if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) - { - char *service; - char *old_owner; - char *new_owner; + } else if (dbus_message_is_signal (message, NMI_DBUS_INTERFACE, "VPNConnectionUpdate")) { + char *name = NULL; - if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &service, DBUS_TYPE_STRING, &old_owner, - DBUS_TYPE_STRING, &new_owner, DBUS_TYPE_INVALID)) - { - gboolean old_owner_good = (old_owner && (strlen (old_owner) > 0)); - gboolean new_owner_good = (new_owner && (strlen (new_owner) > 0)); - - if (strcmp (service, NMI_DBUS_SERVICE) == 0) - { - if (!old_owner_good && new_owner_good) /* NMI just appeared */ - { - char *match = get_nmi_match_string (new_owner); - dbus_bus_add_match (connection, match, NULL); - nm_policy_schedule_allowed_ap_list_update (data); - nm_dbus_vpn_schedule_vpn_connections_update (data); - g_free (match); - handled = TRUE; - } - else if (old_owner_good && !new_owner_good) /* NMI went away */ - { - char *match = get_nmi_match_string (old_owner); - dbus_bus_remove_match (connection, match, NULL); - g_free (match); - } - } - else if (strcmp (service, "org.freedesktop.Hal") == 0) - { - if (!old_owner_good && new_owner_good) /* Hal just appeared */ - { - nm_hal_init (data); - handled = TRUE; - } - else if (old_owner_good && !new_owner_good) /* Hal went away */ - { - nm_hal_deinit (data); - handled = TRUE; - } - } - else if (nm_dhcp_manager_process_name_owner_changed (data->dhcp_manager, service, old_owner, new_owner) == TRUE) - handled = TRUE; - else if (nm_vpn_manager_process_name_owner_changed (data->vpn_manager, service, old_owner, new_owner) == TRUE) - handled = TRUE; - else if (nm_named_manager_process_name_owner_changed (data->named_manager, service, old_owner, new_owner) == TRUE) - handled = TRUE; + if (dbus_message_get_args (message, + NULL, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID)) { + nm_debug ("NetworkManagerInfo triggered update of VPN connection " + " '%s'", + name); + nm_dbus_vpn_update_one_vpn_connection (connection, name, data); + handled = TRUE; } - } - else if (nm_dhcp_manager_process_signal (data->dhcp_manager, message) == TRUE) - handled = TRUE; - else if (nm_vpn_manager_process_signal (data->vpn_manager, message) == TRUE) - handled = TRUE; - - if (dbus_error_is_set (&error)) - dbus_error_free (&error); - - return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); -} - - -/* - * nm_dbus_nm_message_handler - * - * Dispatch messages against our NetworkManager object - * - */ -static DBusHandlerResult nm_dbus_nm_message_handler (DBusConnection *connection, DBusMessage *message, void *user_data) -{ - NMData *data = (NMData *)user_data; - gboolean handled = TRUE; - DBusMessage *reply = NULL; - NMDbusCBData cb_data; - - g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - g_return_val_if_fail (data->nm_methods != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - 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); - - cb_data.data = data; - cb_data.dev = NULL; - handled = nm_dbus_method_dispatch (data->nm_methods, connection, message, &cb_data, &reply); - if (reply) - { - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - } - - return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); -} - - -/* - * nm_dbus_devices_message_handler - * - * Dispatch messages against individual network devices - * - */ -static DBusHandlerResult nm_dbus_devices_message_handler (DBusConnection *connection, DBusMessage *message, void *user_data) -{ - NMData *data = (NMData *)user_data; - gboolean handled = FALSE; - const char *path; - DBusMessage *reply = NULL; - NMDevice *dev; - - g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - 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); - - path = dbus_message_get_path (message); - - if (!(dev = nm_dbus_get_device_from_escaped_object_path (data, path))) - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound", "The requested network device does not exist."); - else - { - char *object_path, *escaped_object_path; - NMDbusCBData cb_data; - - cb_data.data = data; - cb_data.dev = dev; - - /* Test whether or not the _networks_ of a device were queried instead of the device itself */ - object_path = g_strdup_printf ("%s/%s/Networks/", NM_DBUS_PATH_DEVICES, nm_device_get_iface (dev)); - escaped_object_path = nm_dbus_escape_object_path (object_path); - g_free (object_path); - if (strncmp (path, escaped_object_path, strlen (escaped_object_path)) == 0) - handled = nm_dbus_method_dispatch (data->net_methods, connection, message, &cb_data, &reply); - else - handled = nm_dbus_method_dispatch (data->device_methods, connection, message, &cb_data, &reply); - g_free (escaped_object_path); - } - - if (reply) - { - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); + } else if (dbus_message_is_signal (message, NMI_DBUS_INTERFACE, "UserInterfaceActivated")) { + nm_device_802_11_wireless_set_scan_interval (data, + NULL, + NM_WIRELESS_SCAN_INTERVAL_ACTIVE); handled = TRUE; } - return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + return handled; } - -/* - * nm_dbus_vpn_message_handler - * - * Dispatch messages against our NetworkManager VPNConnections object - * - */ -static DBusHandlerResult nm_dbus_vpn_message_handler (DBusConnection *connection, DBusMessage *message, void *user_data) -{ - NMData *data = (NMData *)user_data; - gboolean handled = TRUE; - DBusMessage *reply = NULL; - NMDbusCBData cb_data; - - g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - g_return_val_if_fail (data->vpn_methods != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - 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); - - cb_data.data = data; - cb_data.dev = NULL; - handled = nm_dbus_method_dispatch (data->vpn_methods, connection, message, &cb_data, &reply); - if (reply) - { - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - } - - return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); -} - - -/* - * nm_dbus_is_info_daemon_running - * - * Ask dbus whether or not the info daemon is providing its dbus service - * - */ -gboolean nm_dbus_is_info_daemon_running (DBusConnection *connection) -{ - DBusError error; - gboolean running = FALSE; - - g_return_val_if_fail (connection != NULL, FALSE); - - dbus_error_init (&error); - running = dbus_bus_name_has_owner (connection, NMI_DBUS_SERVICE, &error); - if (dbus_error_is_set (&error)) - { - running = FALSE; - dbus_error_free (&error); - } - return running; -} - - -char *get_name_owner (DBusConnection *con, const char *name) -{ - DBusMessage * message; - DBusMessage * reply; - char * owner = NULL; - - g_return_val_if_fail (con != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - - if ((message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "GetNameOwner"))) - { - dbus_message_append_args (message, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID); - if ((reply = dbus_connection_send_with_reply_and_block (con, message, -1, NULL))) - { - const char *tmp_name = NULL; - if (dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &tmp_name, DBUS_TYPE_INVALID)) - owner = g_strdup (tmp_name); - dbus_message_unref (reply); - } - dbus_message_unref (message); - } - - return owner; -} - - -static char *get_nmi_match_string (const char *owner) -{ - g_return_val_if_fail (owner != NULL, NULL); - - return g_strdup_printf ("type='signal',interface='" NMI_DBUS_INTERFACE "',sender='%s',path='" NMI_DBUS_PATH "'", owner); -} - -/* - * nm_dbus_reinit - * - * Reconnect to the system message bus if the connection was dropped. - * - */ - -static gpointer nm_dbus_reinit (gpointer user_data) -{ - NMData *data = (NMData *) user_data; - char *owner; - - g_return_val_if_fail (data != NULL, NULL); - - while ((data->dbus_connection = nm_dbus_init (data)) == NULL) - g_usleep (G_USEC_PER_SEC * 3); - - /* if HAL was quick it is already back on the bus. Thus, we do not receive NameOwnerChanged */ - if ((owner = get_name_owner (data->dbus_connection, "org.freedesktop.Hal"))) - nm_hal_init (data); - - data->dhcp_manager = nm_dhcp_manager_new (data); - - nm_info ("Successfully reconnected to the system bus."); - - return NULL; -} - - -/* - * nm_dbus_init - * - * Connect to the system messagebus and register ourselves as a service. - * - */ -DBusConnection *nm_dbus_init (NMData *data) -{ - DBusError error; - DBusConnection * connection; - DBusObjectPathVTable nm_vtable = {NULL, &nm_dbus_nm_message_handler, NULL, NULL, NULL, NULL}; - DBusObjectPathVTable devices_vtable = {NULL, &nm_dbus_devices_message_handler, NULL, NULL, NULL, NULL}; - DBusObjectPathVTable vpn_vtable = {NULL, &nm_dbus_vpn_message_handler, NULL, NULL, NULL, NULL}; - char * owner; - int flags, ret; - - dbus_connection_set_change_sigpipe (TRUE); - - dbus_error_init (&error); - connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); - if ((connection == NULL) || dbus_error_is_set (&error)) - { - nm_warning ("nm_dbus_init() could not get the system bus. Make sure the message bus daemon is running!"); - connection = NULL; - goto out; - } - - dbus_connection_set_exit_on_disconnect (connection, FALSE); - dbus_connection_setup_with_g_main (connection, data->main_context); - - data->nm_methods = nm_dbus_nm_methods_setup (); - data->device_methods = nm_dbus_device_methods_setup (); - data->net_methods = nm_dbus_net_methods_setup (); - data->vpn_methods = nm_dbus_vpn_methods_setup (); - - if ( !dbus_connection_register_object_path (connection, NM_DBUS_PATH, &nm_vtable, data) - || !dbus_connection_register_fallback (connection, NM_DBUS_PATH_DEVICES, &devices_vtable, data) - || !dbus_connection_register_object_path (connection, NM_DBUS_PATH_VPN, &vpn_vtable, data)) - { - nm_error ("nm_dbus_init() could not register D-BUS handlers. Cannot continue."); - connection = NULL; - goto out; - } - - if (!dbus_connection_add_filter (connection, nm_dbus_signal_filter, data, NULL)) - { - nm_error ("nm_dbus_init() could not attach a dbus message filter. The NetworkManager dbus security policy may not be loaded. Restart dbus?"); - connection = NULL; - goto out; - } - - dbus_bus_add_match (connection, - "type='signal'," - "interface='" DBUS_INTERFACE_DBUS "'," - "sender='" DBUS_SERVICE_DBUS "'", - NULL); - - if ((owner = get_name_owner (connection, NMI_DBUS_SERVICE))) - { - char *match = get_nmi_match_string (owner); - - dbus_bus_add_match (connection, match, NULL); - g_free (match); - g_free (owner); - } - - dbus_error_init (&error); -#if (DBUS_VERSION_MAJOR == 0) && (DBUS_VERSION_MINOR >= 60) - flags = DBUS_NAME_FLAG_DO_NOT_QUEUE; /* Prohibit replacement is now the default */ -#else - flags = DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT; -#endif - ret = dbus_bus_request_name (connection, NM_DBUS_SERVICE, flags, &error); - if (dbus_error_is_set (&error)) - { - nm_warning ("nm_dbus_init() could not acquire the NetworkManager service.\n Message: '%s'", error.message); - connection = NULL; - goto out; - } - else if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) - { - nm_warning ("nm_dbus_init() could not acquire the NetworkManager service as it is already taken (ret=%d). Is the daemon already running?", - ret); - connection = NULL; - goto out; - } - -out: - if (dbus_error_is_set (&error)) - dbus_error_free (&error); - - return (connection); -} diff --git a/src/NetworkManagerDbus.h b/src/NetworkManagerDbus.h index 8646b66cb..9a73956cc 100644 --- a/src/NetworkManagerDbus.h +++ b/src/NetworkManagerDbus.h @@ -54,11 +54,6 @@ static inline gboolean message_is_error (DBusMessage *msg) return (dbus_message_get_type (msg) == DBUS_MESSAGE_TYPE_ERROR); } -DBusConnection *nm_dbus_init (NMData *data); - -gboolean nm_dbus_is_info_daemon_running (DBusConnection *connection); -char * get_name_owner (DBusConnection *con, const char *name); - char * nm_dbus_get_object_path_for_device (NMDevice *dev); char * nm_dbus_get_object_path_for_network (NMDevice *dev, NMAccessPoint *ap); @@ -66,8 +61,8 @@ void nm_dbus_schedule_device_status_change_signal (NMData *data, NMDevice *dev void nm_dbus_signal_state_change (DBusConnection *connection, NMData *data); -void nm_dbus_signal_wireless_network_change (DBusConnection *connection, NMDevice80211Wireless *dev, NMAccessPoint *ap, NMNetworkStatus status, gint strength); -void nm_dbus_signal_device_strength_change (DBusConnection *connection, NMDevice80211Wireless *dev, gint strength); +void nm_dbus_signal_wireless_network_change (NMDevice80211Wireless *dev, NMAccessPoint *ap, NMNetworkStatus status, gint strength); +void nm_dbus_signal_device_strength_change (NMDevice80211Wireless *dev, gint strength); NMDevice * nm_dbus_get_device_from_escaped_object_path (NMData *data, const char *path); @@ -75,4 +70,10 @@ NMState nm_get_app_state_from_data (NMData *data); DBusMessage * nm_dbus_create_error_message (DBusMessage *message, const char *exception_namespace, const char *exception, const char *format, ...); +DBusMessage * nm_dbus_new_invalid_args_error (DBusMessage *replyto, const char *namespace); + +gboolean nm_dbus_nmi_signal_handler (DBusConnection *connection, + DBusMessage *message, + gpointer user_data); + #endif diff --git a/src/NetworkManagerDbusUtils.c b/src/NetworkManagerDbusUtils.c index 7dd4430f8..a705a293d 100644 --- a/src/NetworkManagerDbusUtils.c +++ b/src/NetworkManagerDbusUtils.c @@ -20,28 +20,108 @@ */ #include +#include #include "NetworkManagerDbusUtils.h" struct NMDbusMethodList { - NMDbusMethod validate_method; - GHashTable *methods; + guint32 refcount; + GHashTable * methods; + + char * path; + gboolean is_fallback; + + DBusObjectPathMessageFunction handler_func; + gpointer user_data; + DBusFreeFunction user_data_free_func; }; -NMDbusMethodList * nm_dbus_method_list_new (NMDbusMethod validate_method) +/** + * @param path DBus object path for which the handler applies + * @param is_fallback whether the handlers should be registered as a fallback + */ +NMDbusMethodList * +nm_dbus_method_list_new (const char *path, + gboolean is_fallback, + gpointer user_data, + DBusFreeFunction user_data_free_func) { - NMDbusMethodList *list = g_slice_new0 (NMDbusMethodList); + NMDbusMethodList * list; - list->validate_method = validate_method; + g_return_val_if_fail (path != NULL, NULL); + + list = g_slice_new0 (NMDbusMethodList); + + list->refcount = 1; + list->path = g_strdup (path); + list->is_fallback = is_fallback; + list->user_data = user_data; + list->user_data_free_func = user_data_free_func; list->methods = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); return list; } +void +nm_dbus_method_list_ref (NMDbusMethodList *list) +{ + g_return_if_fail (list != NULL); -void nm_dbus_method_list_add_method (NMDbusMethodList *list, const char *method, NMDbusMethod callback) + list->refcount += 1; +} + +void +nm_dbus_method_list_unref (NMDbusMethodList *list) +{ + g_return_if_fail (list != NULL); + g_return_if_fail (list->refcount >= 1); + + list->refcount -= 1; + if (list->refcount <= 0) { + if (list->user_data && list->user_data_free_func) + (*list->user_data_free_func)(list->user_data); + g_hash_table_destroy (list->methods); + memset (list, 0, sizeof (NMDbusMethodList)); + g_slice_free (NMDbusMethodList, list); + } +} + +DBusObjectPathMessageFunction +nm_dbus_method_list_get_custom_handler_func (NMDbusMethodList *list) +{ + g_return_val_if_fail (list != NULL, NULL); + + return list->handler_func; +} + +gpointer +nm_dbus_method_list_get_user_data (NMDbusMethodList *list) +{ + g_return_val_if_fail (list != NULL, NULL); + + return list->user_data; +} + +/** + * @param handler_func NULL, or handler function which overrides the default one + */ +void +nm_dbus_method_list_set_custom_handler_func (NMDbusMethodList *list, + DBusObjectPathMessageFunction handler_func) +{ + g_return_if_fail (list != NULL); + g_return_if_fail (handler_func != NULL); + g_return_if_fail (list->handler_func == NULL); + + list->handler_func = handler_func; +} + +void +nm_dbus_method_list_add_method (NMDbusMethodList *list, + const char *method, + NMDBusHandleMessageFunc callback) { g_return_if_fail (list != NULL); g_return_if_fail (list->methods != NULL); @@ -52,46 +132,49 @@ void nm_dbus_method_list_add_method (NMDbusMethodList *list, const char *method, } -gboolean nm_dbus_method_dispatch (NMDbusMethodList *list, DBusConnection *connection, DBusMessage *message, gpointer user_data, DBusMessage **reply) +gboolean +nm_dbus_method_list_dispatch (NMDbusMethodList *list, + DBusConnection *connection, + DBusMessage *message, + gpointer user_data, + DBusMessage **reply) { - NMDbusMethod callback = NULL; - const char *method; - DBusMessage *temp_reply = NULL; - - if (reply) - *reply = NULL; + NMDBusHandleMessageFunc callback = NULL; + const char * method; g_return_val_if_fail (list != NULL, FALSE); g_return_val_if_fail (list->methods != NULL, FALSE); g_return_val_if_fail (connection != NULL, FALSE); g_return_val_if_fail (message != NULL, FALSE); + if (reply) + *reply = NULL; + if (!(method = dbus_message_get_member (message))) return FALSE; if (!(callback = g_hash_table_lookup (list->methods, method))) return FALSE; - /* Call the optional validate method first, if it returns NULL then we - * actually dispatch the call. - */ - if (list->validate_method) - temp_reply = (*(list->validate_method)) (connection, message, (NMDbusCBData *)user_data); - if (!temp_reply) - temp_reply = (*callback) (connection, message, (NMDbusCBData *)user_data); + /* Dispatch the method call */ + *reply = (*callback) (connection, message, user_data); - if (reply) - *reply = temp_reply; - - return (TRUE); + return TRUE; } - -void nm_dbus_method_list_free (NMDbusMethodList *list) +gboolean +nm_dbus_method_list_get_is_fallback (NMDbusMethodList *list) { - if (list) - { - g_hash_table_destroy (list->methods); - g_slice_free (NMDbusMethodList, list); - } + g_return_val_if_fail (list != NULL, FALSE); + + return list->is_fallback; } + +const char * +nm_dbus_method_list_get_path (NMDbusMethodList *list) +{ + g_return_val_if_fail (list != NULL, NULL); + + return list->path; +} + diff --git a/src/NetworkManagerDbusUtils.h b/src/NetworkManagerDbusUtils.h index 68d43b4b4..53b5bd0c4 100644 --- a/src/NetworkManagerDbusUtils.h +++ b/src/NetworkManagerDbusUtils.h @@ -27,27 +27,42 @@ #include #include -#include "nm-device.h" -#include "NetworkManagerMain.h" - -typedef struct NMDbusCBData -{ - NMData *data; - NMDevice *dev; - NMAccessPoint *ap; -} NMDbusCBData; - -typedef DBusMessage* (*NMDbusMethod) (DBusConnection *, DBusMessage *, NMDbusCBData *); +typedef struct NMDbusMethodList NMDbusMethodList; -NMDbusMethodList * nm_dbus_method_list_new (NMDbusMethod validate_method); +typedef DBusMessage * (* NMDBusHandleMessageFunc) (DBusConnection * connection, + DBusMessage * message, + gpointer user_data); -void nm_dbus_method_list_add_method (NMDbusMethodList *list, const char *method, NMDbusMethod callback); -gboolean nm_dbus_method_dispatch (NMDbusMethodList *list, DBusConnection *connection, DBusMessage *message, - gpointer user_data, DBusMessage **reply); +NMDbusMethodList * nm_dbus_method_list_new (const char *path, + gboolean is_fallback, + gpointer user_data, + DBusFreeFunction user_data_free_func); -void nm_dbus_method_list_free (NMDbusMethodList *list); +void nm_dbus_method_list_ref (NMDbusMethodList *list); +void nm_dbus_method_list_unref (NMDbusMethodList *list); + +DBusObjectPathMessageFunction nm_dbus_method_list_get_custom_handler_func (NMDbusMethodList *list); + +gpointer nm_dbus_method_list_get_user_data (NMDbusMethodList *list); + +void nm_dbus_method_list_set_custom_handler_func (NMDbusMethodList *list, + DBusObjectPathMessageFunction handler_func); + +void nm_dbus_method_list_add_method (NMDbusMethodList *list, + const char *method, + NMDBusHandleMessageFunc callback); + +gboolean nm_dbus_method_list_dispatch (NMDbusMethodList *list, + DBusConnection *connection, + DBusMessage *message, + gpointer user_data, + DBusMessage **reply); + +gboolean nm_dbus_method_list_get_is_fallback (NMDbusMethodList *list); + +const char * nm_dbus_method_list_get_path (NMDbusMethodList *list); #endif diff --git a/src/NetworkManagerMain.h b/src/NetworkManagerMain.h index 24b703a24..f0f72d35b 100644 --- a/src/NetworkManagerMain.h +++ b/src/NetworkManagerMain.h @@ -31,6 +31,7 @@ #include "nm-netlink-monitor.h" #include "nm-named-manager.h" #include "nm-device.h" +#include "NetworkManagerDbusUtils.h" typedef enum NMIntState @@ -45,7 +46,6 @@ typedef enum NMIntState } NMIntState; -typedef struct NMDbusMethodList NMDbusMethodList; typedef struct NMActRequest NMActRequest; typedef struct NMVPNActRequest NMVPNActRequest; typedef struct NMVPNManager NMVPNManager; @@ -67,11 +67,9 @@ typedef struct NMData NMVPNManager * vpn_manager; NMDHCPManager * dhcp_manager; - DBusConnection * dbus_connection; NMDbusMethodList * nm_methods; NMDbusMethodList * device_methods; NMDbusMethodList * net_methods; - NMDbusMethodList * vpn_methods; GMainContext * main_context; GMainLoop * main_loop; @@ -105,10 +103,6 @@ void nm_remove_device (NMData *data, NMDevice *dev); void nm_schedule_state_change_signal_broadcast (NMData *data); -void nm_hal_init (NMData *data); - -void nm_hal_deinit (NMData *data); - int nm_get_sigterm_pipe (void); #endif diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index 37bfdf472..4a68b2b00 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -38,6 +38,7 @@ #include "nm-dbus-nmi.h" #include "nm-device-802-11-wireless.h" #include "nm-device-802-3-ethernet.h" +#include "nm-dbus-manager.h" /* @@ -537,9 +538,10 @@ static gboolean allowed_list_update_pending = FALSE; * allowed wireless networks. * */ -static gboolean nm_policy_allowed_ap_list_update (gpointer user_data) +static gboolean +nm_policy_allowed_ap_list_update (gpointer user_data) { - NMData *data = (NMData *)user_data; + NMData * data = (NMData *)user_data; allowed_list_update_pending = FALSE; @@ -551,9 +553,8 @@ static gboolean nm_policy_allowed_ap_list_update (gpointer user_data) if (data->allowed_ap_list) nm_ap_list_unref (data->allowed_ap_list); if ((data->allowed_ap_list = nm_ap_list_new (NETWORK_TYPE_ALLOWED))) - nm_dbus_update_allowed_networks (data->dbus_connection, data->allowed_ap_list, data); - - return (FALSE); + nm_dbus_update_allowed_networks (data->allowed_ap_list, data); + return FALSE; } @@ -597,7 +598,8 @@ static gboolean device_list_update_pending = FALSE; * allowed wireless networks. * */ -static gboolean nm_policy_device_list_update_from_allowed_list (NMData *data) +static gboolean +nm_policy_device_list_update_from_allowed_list (NMData *data) { GSList * elt; @@ -605,27 +607,30 @@ static gboolean nm_policy_device_list_update_from_allowed_list (NMData *data) g_return_val_if_fail (data != NULL, FALSE); - for (elt = data->dev_list; elt != NULL; elt = g_slist_next (elt)) - { + for (elt = data->dev_list; elt != NULL; elt = g_slist_next (elt)) { NMDevice *dev = (NMDevice *)(elt->data); - if (nm_device_is_802_11_wireless (dev)) - { - NMDevice80211Wireless * wdev = NM_DEVICE_802_11_WIRELESS (dev); + NMDevice80211Wireless * wdev; - if (nm_device_get_capabilities (dev) & NM_DEVICE_CAP_WIRELESS_SCAN) - { - /* Once we have the list, copy in any relevant information from our Allowed list and fill - * in the ESSID of base stations that aren't broadcasting their ESSID, if we have their - * MAC address in our allowed list. - */ - nm_ap_list_copy_essids_by_address (data, wdev, nm_device_802_11_wireless_ap_list_get (wdev), data->allowed_ap_list); - nm_ap_list_copy_properties (nm_device_802_11_wireless_ap_list_get (wdev), data->allowed_ap_list); - } - else - nm_device_802_11_wireless_copy_allowed_to_dev_list (wdev, data->allowed_ap_list); + if (!nm_device_is_802_11_wireless (dev)) + continue; - nm_ap_list_remove_duplicate_essids (nm_device_802_11_wireless_ap_list_get (wdev)); + wdev = NM_DEVICE_802_11_WIRELESS (dev); + if (nm_device_get_capabilities (dev) & NM_DEVICE_CAP_WIRELESS_SCAN) { + /* Once we have the list, copy in any relevant information from our + * Allowed list and fill in the ESSID of base stations that aren't + * broadcasting their ESSID, if we have their MAC address in our + * allowed list. + */ + nm_ap_list_copy_essids_by_address (wdev, + nm_device_802_11_wireless_ap_list_get (wdev), + data->allowed_ap_list); + nm_ap_list_copy_properties (nm_device_802_11_wireless_ap_list_get (wdev), + data->allowed_ap_list); + } else { + nm_device_802_11_wireless_copy_allowed_to_dev_list (wdev, data->allowed_ap_list); } + + nm_ap_list_remove_duplicate_essids (nm_device_802_11_wireless_ap_list_get (wdev)); } nm_policy_schedule_device_change_check (data); diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c index a803bd69b..63708507e 100644 --- a/src/dhcp-manager/nm-dhcp-manager.c +++ b/src/dhcp-manager/nm-dhcp-manager.c @@ -32,32 +32,42 @@ #include "NetworkManagerSystem.h" #include "nm-activation-request.h" #include "nm-utils.h" +#include "nm-dbus-manager.h" #define NM_DHCP_TIMEOUT 45 /* DHCP timeout, in seconds */ +static gboolean nm_dhcp_manager_process_signal (DBusConnection *connection, + DBusMessage *message, + gpointer user_data); + +static void nm_dhcp_manager_name_owner_changed (NMDBusManager *dbus_mgr, + DBusConnection *connection, + const char *name, + const char *old, + const char *new, + gpointer user_data); + +static void nm_dhcp_manager_dbus_connection_changed (NMDBusManager *dbus_mgr, + DBusConnection *dbus_connection, + gpointer user_data); + struct NMDHCPManager { NMData * data; + GMainContext * main_ctx; gboolean running; size_t dhcp_sn_len; + NMDBusManager * dbus_mgr; }; -char *get_dhcp_match_string (const char *owner) -{ - g_return_val_if_fail (owner != NULL, NULL); - - return g_strdup_printf ("type='signal',interface='" DHCP_SERVICE_NAME ".state',sender='%s'", owner); -} - - static gboolean state_is_bound (guint8 state) { - if ( (state == 2) /* BOUND */ - || (state == 3) /* RENEW */ - || (state == 4) /* REBOOT */ - || (state == 5)) /* REBIND */ + if ( (state == DHCDBD_BOUND) + || (state == DHCDBD_RENEW) + || (state == DHCDBD_REBOOT) + || (state == DHCDBD_REBIND)) return TRUE; return FALSE; @@ -66,36 +76,46 @@ static gboolean state_is_bound (guint8 state) static gboolean state_is_down (guint8 state) { - if ( (state == 0) /* NBI */ - || (state == 11) /* RELEASE */ - || (state == 13) /* ABEND */ - || (state == 14)) /* END */ + if ( (state == DHCDBD_NBI) + || (state == DHCDBD_RELEASE) + || (state == DHCDBD_ABEND) + || (state == DHCDBD_END)) return TRUE; return FALSE; } -NMDHCPManager * nm_dhcp_manager_new (NMData *data) +NMDHCPManager * +nm_dhcp_manager_new (NMData *data, + GMainContext *main_ctx) { NMDHCPManager * manager; - char * owner; g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (data->dbus_connection != NULL, NULL); + g_return_val_if_fail (main_ctx != NULL, NULL); - manager = g_malloc0 (sizeof (NMDHCPManager)); + manager = g_slice_new0 (NMDHCPManager); manager->data = data; - manager->running = dbus_bus_name_has_owner (manager->data->dbus_connection, DHCP_SERVICE_NAME, NULL); + manager->main_ctx = main_ctx; + manager->dbus_mgr = nm_dbus_manager_get (NULL); + manager->running = nm_dbus_manager_name_has_owner (manager->dbus_mgr, + DHCP_SERVICE_NAME); manager->dhcp_sn_len = strlen (DHCP_SERVICE_NAME); - if (manager->running && (owner = get_name_owner (data->dbus_connection, DHCP_SERVICE_NAME))) - { - char *match = get_dhcp_match_string (owner); - dbus_bus_add_match (data->dbus_connection, match, NULL); - g_free (match); - g_free (owner); - } + nm_dbus_manager_register_signal_handler (manager->dbus_mgr, + DHCP_SERVICE_NAME ".state", + DHCP_SERVICE_NAME, + nm_dhcp_manager_process_signal, + manager); + g_signal_connect (G_OBJECT (manager->dbus_mgr), + "name-owner-changed", + G_CALLBACK (nm_dhcp_manager_name_owner_changed), + manager); + g_signal_connect (G_OBJECT (manager->dbus_mgr), + "dbus-connection-changed", + G_CALLBACK (nm_dhcp_manager_dbus_connection_changed), + manager); return manager; } @@ -105,53 +125,71 @@ void nm_dhcp_manager_dispose (NMDHCPManager *manager) { g_return_if_fail (manager != NULL); + g_object_unref (manager->dbus_mgr); memset (manager, 0, sizeof (NMDHCPManager)); - g_free (manager); + g_slice_free (NMDHCPManager, manager); } -guint32 nm_dhcp_manager_get_state_for_device (NMDHCPManager *manager, NMDevice *dev) +guint32 +nm_dhcp_manager_get_state_for_device (NMDHCPManager *manager, + NMDevice *dev) { DBusMessage * message; DBusMessage * reply; char * path; guint32 state = 0; DBusError error; + DBusConnection *dbus_connection; g_return_val_if_fail (manager != NULL, 0); g_return_val_if_fail (dev != NULL, 0); - if (!manager->running) - { + if (!manager->running) { nm_warning ("dhcdbd not running!"); return 0; } + dbus_connection = nm_dbus_manager_get_dbus_connection (manager->dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get dbus connection."); + goto out; + } + path = g_strdup_printf (DHCP_OBJECT_PATH"/%s", nm_device_get_iface (dev)); - message = dbus_message_new_method_call (DHCP_SERVICE_NAME, path, DHCP_SERVICE_NAME".dbus.get", "reason"); + message = dbus_message_new_method_call (DHCP_SERVICE_NAME, + path, + DHCP_SERVICE_NAME ".dbus.get", + "reason"); g_free (path); - if (message == NULL) - { - nm_warning ("nm_dhcp_manager_get_state_for_device(): Couldn't allocate the dbus message"); - return 0; + if (message == NULL) { + nm_warning ("couldn't allocate the dbus message."); + goto out; } dbus_error_init (&error); - reply = dbus_connection_send_with_reply_and_block (manager->data->dbus_connection, message, -1, &error); + reply = dbus_connection_send_with_reply_and_block (dbus_connection, + message, + -1, + &error); dbus_message_unref (message); - if (dbus_error_is_set (&error)) - { - if (strcmp (error.name, "org.freedesktop.DBus.Error.UnknownMethod") != 0) - nm_info ("Error from dhcdbd on 'reason' request because: name '%s', message '%s'.", error.name, error.message); + if (dbus_error_is_set (&error)) { + if (strcmp (error.name, "org.freedesktop.DBus.Error.UnknownMethod") != 0) { + nm_info ("Error from dhcdbd on 'reason' request because: name '%s'," + " message '%s'.", + error.name, + error.message); + } dbus_error_free (&error); } - else if (reply) - { + + if (reply) { if (!dbus_message_get_args (reply, NULL, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID)) state = 0; dbus_message_unref (reply); } +out: return state; } @@ -189,65 +227,86 @@ static gboolean nm_dhcp_manager_handle_timeout (NMActRequest *req) } -gboolean nm_dhcp_manager_begin_transaction (NMDHCPManager *manager, NMActRequest *req) +gboolean +nm_dhcp_manager_begin_transaction (NMDHCPManager *manager, + NMActRequest *req) { DBusError error; DBusMessage * message; DBusMessage * reply; NMDevice * dev; char * path; - const guint32 opt1 = 31; /* turns off ALL actions and dhclient-script just writes options to dhcdbd */ - const guint32 opt2 = 2; /* dhclient is run in ONE SHOT mode and releases existing leases when brought down */ + const guint32 opt1 = 31; /* turns off ALL actions and dhclient-script just writes options to dhcdbd */ + const guint32 opt2 = 2; /* dhclient is run in ONE SHOT mode and releases existing leases when brought down */ GSource * source; + DBusConnection * dbus_connection; + gboolean success = FALSE; g_return_val_if_fail (manager != NULL, FALSE); g_return_val_if_fail (req != NULL, FALSE); - if (!manager->running) - { + if (!manager->running) { nm_warning ("dhcdbd not running!"); return FALSE; } - else - { - /* Cancel any DHCP transaction already in progress */ - nm_dhcp_manager_cancel_transaction (manager, req); - /* FIXME don't sleep */ - sleep (1); + + dbus_connection = nm_dbus_manager_get_dbus_connection (manager->dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get dbus connection."); + goto out; } + /* Cancel any DHCP transaction already in progress */ + nm_dhcp_manager_cancel_transaction (manager, req); + /* FIXME don't sleep */ + sleep (1); + dev = nm_act_request_get_dev (req); g_assert (dev); - nm_info ("Activation (%s) Beginning DHCP transaction.", nm_device_get_iface (dev)); + nm_info ("Activation (%s) Beginning DHCP transaction.", + nm_device_get_iface (dev)); path = g_strdup_printf (DHCP_OBJECT_PATH"/%s", nm_device_get_iface (dev)); - message = dbus_message_new_method_call (DHCP_SERVICE_NAME, path, DHCP_SERVICE_NAME, "up"); + message = dbus_message_new_method_call (DHCP_SERVICE_NAME, + path, + DHCP_SERVICE_NAME, + "up"); g_free (path); - if (message == NULL) - { - nm_warning ("nm_dhcp_manager_begin_transaction(): Couldn't allocate the dbus message"); - return FALSE; + if (message == NULL) { + nm_warning ("couldn't allocate dbus message"); + goto out; } - dbus_message_append_args (message, DBUS_TYPE_UINT32, &opt1, DBUS_TYPE_UINT32, &opt2, DBUS_TYPE_INVALID); + dbus_message_append_args (message, + DBUS_TYPE_UINT32, &opt1, + DBUS_TYPE_UINT32, &opt2, + DBUS_TYPE_INVALID); + dbus_error_init (&error); - if ((reply = dbus_connection_send_with_reply_and_block (manager->data->dbus_connection, message, -1, &error))) + if ((reply = dbus_connection_send_with_reply_and_block (dbus_connection, message, -1, &error))) dbus_message_unref (reply); dbus_message_unref (message); - if (dbus_error_is_set (&error)) - { - nm_info ("Couldn't send DHCP 'up' message because: name '%s', message '%s'.", error.name, error.message); + if (dbus_error_is_set (&error)) { + nm_info ("Couldn't send DHCP 'up' message because: name '%s', message " + " '%s'.", + error.name, + error.message); dbus_error_free (&error); - return FALSE; + goto out; } /* Set up a timeout on the transaction to kill it after NM_DHCP_TIMEOUT seconds */ source = g_timeout_source_new (NM_DHCP_TIMEOUT * 1000); - g_source_set_callback (source, (GSourceFunc) nm_dhcp_manager_handle_timeout, req, NULL); - nm_act_request_set_dhcp_timeout (req, g_source_attach (source, manager->data->main_context)); + g_source_set_callback (source, + (GSourceFunc) nm_dhcp_manager_handle_timeout, + req, + NULL); + nm_act_request_set_dhcp_timeout (req, g_source_attach (source, manager->main_ctx)); g_source_unref (source); + success = TRUE; +out: return TRUE; } @@ -262,7 +321,7 @@ static void remove_timeout (NMDHCPManager *manager, NMActRequest *req) /* Remove any pending timeouts on the request */ if ((id = nm_act_request_get_dhcp_timeout (req)) > 0) { - GSource * source = g_main_context_find_source_by_id (manager->data->main_context, id); + GSource * source = g_main_context_find_source_by_id (manager->main_ctx, id); nm_act_request_set_dhcp_timeout (req, 0); g_source_destroy (source); } @@ -274,166 +333,236 @@ static void remove_timeout (NMDHCPManager *manager, NMActRequest *req) * Stop any in-progress DHCP transaction on a particular device. * */ -void nm_dhcp_manager_cancel_transaction (NMDHCPManager *manager, NMActRequest *req) +void +nm_dhcp_manager_cancel_transaction (NMDHCPManager *manager, + NMActRequest *req) { NMDevice *dev; + DBusMessage *message = NULL; + char *path; + DBusConnection *dbus_connection; g_return_if_fail (manager != NULL); g_return_if_fail (req != NULL); + if (!manager->running || state_is_down (nm_act_request_get_dhcp_state (req))) + return; + dev = nm_act_request_get_dev (req); g_assert (dev); - if (manager->running && !state_is_down (nm_act_request_get_dhcp_state (req))) - { - DBusMessage * message; - char * path = g_strdup_printf (DHCP_OBJECT_PATH"/%s", nm_device_get_iface (dev)); - - if ((message = dbus_message_new_method_call (DHCP_SERVICE_NAME, path, DHCP_SERVICE_NAME, "down"))) - { - dbus_connection_send (manager->data->dbus_connection, message, NULL); - dbus_message_unref (message); - - /* Give dhcdbd/dhclient some time to send out a RELEASE if they like */ - /* FIXME: we should really monitor the interface's DHCP state by waiting - * for dhcdbd to tell us the device is "down" rather than sleeping here. - */ - if (!manager->data->asleep) - sleep (1); - } - g_free (path); - - remove_timeout (manager, req); + dbus_connection = nm_dbus_manager_get_dbus_connection (manager->dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get dbus connection."); + goto out; } + + path = g_strdup_printf (DHCP_OBJECT_PATH"/%s", nm_device_get_iface (dev)); + message = dbus_message_new_method_call (DHCP_SERVICE_NAME, + path, + DHCP_SERVICE_NAME, + "down"); + g_free (path); + if (!message) { + nm_warning ("could not allocate dbus message."); + goto out; + } + + dbus_connection_send (dbus_connection, message, NULL); + dbus_message_unref (message); + + /* Give dhcdbd/dhclient some time to send out a RELEASE if they like */ + /* FIXME: we should really monitor the interface's DHCP state by waiting + * for dhcdbd to tell us the device is "down" rather than sleeping here. + */ + if (!manager->data->asleep) + sleep (1); + + remove_timeout (manager, req); + +out: + return; } -static gboolean get_ip4_uint32s (NMDHCPManager *manager, NMDevice *dev, const char *item, - guint32 **ip4_uint32, guint32 *num_items, gboolean ignore_error) +static gboolean +get_ip4_uint32s (NMDHCPManager *manager, + NMDevice *dev, + const char *item, + guint32 **ip4_uint32, + guint32 *num_items, + gboolean ignore_error) { DBusMessage * message = NULL; DBusMessage * reply = NULL; char * path; gboolean success = FALSE; + DBusConnection *dbus_connection; + DBusError error; + GArray * buffer; + DBusMessageIter iter; + g_return_val_if_fail (manager != NULL, FALSE); g_return_val_if_fail (dev != NULL, FALSE); g_return_val_if_fail (ip4_uint32 != NULL, FALSE); g_return_val_if_fail (num_items != NULL, FALSE); + dbus_connection = nm_dbus_manager_get_dbus_connection (manager->dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get dbus connection."); + goto out; + } + *ip4_uint32 = NULL; *num_items = 0; path = g_strdup_printf (DHCP_OBJECT_PATH"/%s", nm_device_get_iface (dev)); - if ((message = dbus_message_new_method_call (DHCP_SERVICE_NAME, path, DHCP_SERVICE_NAME".dbus.get", item))) - { - DBusError error; - - dbus_error_init (&error); - reply = dbus_connection_send_with_reply_and_block (manager->data->dbus_connection, message, -1, &error); - if (reply) - { - GArray *buffer; - DBusMessageIter iter; - - dbus_message_iter_init (reply, &iter); - - buffer = g_array_new (TRUE, TRUE, sizeof (guint32)); - while (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_UINT32) - { - guint32 value; - - dbus_message_iter_get_basic (&iter, &value); - g_array_append_val (buffer, value); - dbus_message_iter_next (&iter); - success = TRUE; - } - - if (success) - { - *ip4_uint32 = (guint32 *)(buffer->data); - *num_items = buffer->len; - } - g_array_free (buffer, FALSE); - dbus_message_unref (reply); - } - - if (dbus_error_is_set (&error)) - { - if (!ignore_error) - nm_warning ("get_ip4_uint32s(): error calling '%s', DHCP daemon returned error '%s', message '%s'.", - item, error.name, error.message); - dbus_error_free (&error); - } - dbus_message_unref (message); - } + message = dbus_message_new_method_call (DHCP_SERVICE_NAME, + path, + DHCP_SERVICE_NAME".dbus.get", + item); g_free (path); + if (!message) { + nm_warning ("could not allocate dbus message."); + goto out; + } + dbus_error_init (&error); + reply = dbus_connection_send_with_reply_and_block (dbus_connection, + message, + -1, + &error); + dbus_message_unref (message); + if (dbus_error_is_set (&error)) { + if (!ignore_error) { + nm_warning ("error calling '%s', DHCP daemon returned error '%s', " + "message '%s'.", + item, + error.name, + error.message); + } + dbus_error_free (&error); + goto out; + } + + if (!reply) { + nm_warning ("error calling '%s', DHCP daemon did not respond.", item); + goto out; + } + + dbus_message_iter_init (reply, &iter); + + buffer = g_array_new (TRUE, TRUE, sizeof (guint32)); + while (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_UINT32) { + guint32 uint32_value; + + dbus_message_iter_get_basic (&iter, &uint32_value); + g_array_append_val (buffer, uint32_value); + dbus_message_iter_next (&iter); + success = TRUE; + } + + if (success) { + *ip4_uint32 = (guint32 *)(buffer->data); + *num_items = buffer->len; + } + g_array_free (buffer, FALSE); + dbus_message_unref (reply); + +out: return success; } -static gboolean get_ip4_string (NMDHCPManager *manager, NMDevice *dev, const char *item, - char **string, gboolean ignore_error) +static gboolean +get_ip4_string (NMDHCPManager *manager, + NMDevice *dev, + const char *item, + char **string, + gboolean ignore_error) { DBusMessage * message = NULL; DBusMessage * reply = NULL; char * path; gboolean success = FALSE; + DBusError error; + DBusConnection *dbus_connection; + DBusMessageIter iter; g_return_val_if_fail (manager != NULL, FALSE); g_return_val_if_fail (dev != NULL, FALSE); g_return_val_if_fail (string != NULL, FALSE); + dbus_connection = nm_dbus_manager_get_dbus_connection (manager->dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get dbus connection."); + goto out; + } + *string = NULL; path = g_strdup_printf (DHCP_OBJECT_PATH"/%s", nm_device_get_iface (dev)); - if ((message = dbus_message_new_method_call (DHCP_SERVICE_NAME, path, DHCP_SERVICE_NAME".dbus.get", item))) - { - DBusError error; + message = dbus_message_new_method_call (DHCP_SERVICE_NAME, + path, + DHCP_SERVICE_NAME".dbus.get", + item); + g_free (path); + if (!message) { + nm_warning ("could not allocate dbus message."); + goto out; + } + + dbus_error_init (&error); + reply = dbus_connection_send_with_reply_and_block (dbus_connection, + message, + -1, + &error); + dbus_message_unref (message); + if (dbus_error_is_set (&error)) { + if (!ignore_error) { + nm_warning ("error calling '%s', DHCP daemon returned error '%s', " + "message '%s'.", + item, + error.name, + error.message); + } + dbus_error_free (&error); + *string = NULL; + goto out; + } + + if (!reply) { + nm_warning ("error calling '%s', DHCP daemon did not respond.", item); + goto out; + } + + dbus_message_iter_init (reply, &iter); + if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING) { + char *dbus_string; dbus_error_init (&error); - if ((reply = dbus_connection_send_with_reply_and_block (manager->data->dbus_connection, message, -1, &error))) - { - DBusMessageIter iter; - - dbus_message_iter_init (reply, &iter); - if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING) - { - char *dbus_string; - - dbus_error_init (&error); - if (dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &dbus_string, DBUS_TYPE_INVALID)) - { - *string = g_strdup (dbus_string); - success = TRUE; - } - } - else if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY) - { - char *byte_array = NULL; - int len = 0; - - dbus_error_init (&error); - if (dbus_message_get_args (reply, &error, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &byte_array, &len, DBUS_TYPE_INVALID)) - { - byte_array[len] = '\0'; - *string = g_strdup (byte_array); - success = TRUE; - } - } + if (dbus_message_get_args (reply, + &error, + DBUS_TYPE_STRING, &dbus_string, + DBUS_TYPE_INVALID)) { + *string = g_strdup (dbus_string); + success = TRUE; } + } else if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY) { + char *byte_array = NULL; + int len = 0; - if (dbus_error_is_set (&error)) - { - if (!ignore_error) - nm_warning ("get_ip4_string(): error calling '%s', DHCP daemon returned error '%s', message '%s'.", - item, error.name, error.message); - dbus_error_free (&error); - *string = NULL; + dbus_error_init (&error); + if (dbus_message_get_args (reply, + &error, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &byte_array, &len, + DBUS_TYPE_INVALID)) { + byte_array[len] = '\0'; + *string = g_strdup (byte_array); + success = TRUE; } - dbus_message_unref (message); } - g_free (path); +out: return success; } @@ -627,8 +756,12 @@ static inline const char * state_to_string (guint8 state) * active DHCP daemon, if any. Return TRUE if processed, FALSE if not. * */ -gboolean nm_dhcp_manager_process_signal (NMDHCPManager *manager, DBusMessage *message) +static gboolean +nm_dhcp_manager_process_signal (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { + NMDHCPManager * manager = (NMDHCPManager *) user_data; const char * object_path; const char * member; const char * interface; @@ -648,6 +781,7 @@ gboolean nm_dhcp_manager_process_signal (NMDHCPManager *manager, DBusMessage *me return FALSE; if (!(interface = dbus_message_get_interface (message))) return FALSE; + /* Ignore non-DHCP related messages */ if (strncmp (interface, DHCP_SERVICE_NAME, manager->dhcp_sn_len)) return FALSE; @@ -702,7 +836,7 @@ gboolean nm_dhcp_manager_process_signal (NMDHCPManager *manager, DBusMessage *me case DHCDBD_FAIL: /* all attempts to contact server timed out, sleeping */ case DHCDBD_ABEND: /* dhclient exited abnormally */ -// case DHCDBD_END: /* dhclient exited normally */ + case DHCDBD_END: /* dhclient exited normally */ if (nm_act_request_get_stage (req) == NM_ACT_STAGE_IP_CONFIG_START) { nm_policy_schedule_activation_failed (req); @@ -726,43 +860,44 @@ out: * Respond to "service created"/"service deleted" signals from dbus for the active DHCP daemon. * */ -gboolean nm_dhcp_manager_process_name_owner_changed (NMDHCPManager *manager, const char *changed_service_name, const char *old_owner, const char *new_owner) +static void +nm_dhcp_manager_name_owner_changed (NMDBusManager *dbus_mgr, + DBusConnection *connection, + const char *name, + const char *old, + const char *new, + gpointer user_data) { - gboolean handled = FALSE; - gboolean old_owner_good = (old_owner && strlen (old_owner)); - gboolean new_owner_good = (new_owner && strlen (new_owner)); + NMDHCPManager * self = (NMDHCPManager *) user_data; + gboolean old_owner_good = (old && strlen (old)); + gboolean new_owner_good = (new && strlen (new)); - g_return_val_if_fail (manager != NULL, FALSE); - g_return_val_if_fail (changed_service_name != NULL, FALSE); + g_return_if_fail (self != NULL); + g_return_if_fail (name != NULL); /* Can't handle the signal if its not from the DHCP service */ - if (strcmp (DHCP_SERVICE_NAME, changed_service_name) != 0) - return FALSE; + if (strcmp (DHCP_SERVICE_NAME, name) != 0) + return; - if (!old_owner_good && new_owner_good) - { - char *match = get_dhcp_match_string (new_owner); - - /* DHCP service got created */ - dbus_bus_add_match (manager->data->dbus_connection, match, NULL); - g_free (match); - - manager->running = TRUE; - handled = TRUE; + if (!old_owner_good && new_owner_good) { + self->running = TRUE; + } else if (old_owner_good && !new_owner_good) { + self->running = FALSE; } - else if (old_owner_good && !new_owner_good) - { - char *match = get_dhcp_match_string (old_owner); - - /* DHCP service went away */ - dbus_bus_remove_match (manager->data->dbus_connection, match, NULL); - g_free (match); - - manager->running = FALSE; - handled = TRUE; - } - - return handled; } +static void +nm_dhcp_manager_dbus_connection_changed (NMDBusManager *dbus_mgr, + DBusConnection *dbus_connection, + gpointer user_data) +{ + NMDHCPManager * self = (NMDHCPManager *) user_data; + + if (dbus_connection) { + if (nm_dbus_manager_name_has_owner (dbus_mgr, DHCP_SERVICE_NAME)) + self->running = TRUE; + } else { + self->running = FALSE; + } +} diff --git a/src/dhcp-manager/nm-dhcp-manager.h b/src/dhcp-manager/nm-dhcp-manager.h index 2746713be..5d6503ca1 100644 --- a/src/dhcp-manager/nm-dhcp-manager.h +++ b/src/dhcp-manager/nm-dhcp-manager.h @@ -49,9 +49,7 @@ enum dhcdbd_state DHCDBD_END_OPTIONS, /* last option in subscription sent */ }; -char * get_dhcp_match_string (const char *owner); - -NMDHCPManager * nm_dhcp_manager_new (NMData *data); +NMDHCPManager * nm_dhcp_manager_new (NMData *data, GMainContext *main_ctx); void nm_dhcp_manager_dispose (NMDHCPManager *manager); gboolean nm_dhcp_manager_begin_transaction (NMDHCPManager *manager, NMActRequest *req); @@ -59,9 +57,6 @@ void nm_dhcp_manager_cancel_transaction (NMDHCPManager *manager, NMActReque NMIP4Config * nm_dhcp_manager_get_ip4_config (NMDHCPManager *manager, NMActRequest *req); -gboolean nm_dhcp_manager_process_signal (NMDHCPManager *manager, DBusMessage *message); -gboolean nm_dhcp_manager_process_name_owner_changed (NMDHCPManager *manager, const char *changed_service_name, const char *old_owner, const char *new_owner); - guint32 nm_dhcp_manager_get_state_for_device (NMDHCPManager *manager, NMDevice *dev); #endif diff --git a/src/named-manager/nm-named-manager.c b/src/named-manager/nm-named-manager.c index 8b3755076..88582254c 100644 --- a/src/named-manager/nm-named-manager.c +++ b/src/named-manager/nm-named-manager.c @@ -39,6 +39,7 @@ #include "nm-ip4-config.h" #include "nm-utils.h" #include "NetworkManagerSystem.h" +#include "nm-dbus-manager.h" #ifdef HAVE_SELINUX #include @@ -54,26 +55,11 @@ #define NAMED_DBUS_PATH "/com/redhat/named" #endif -enum -{ - PROP_0, - PROP_DBUS_CONNECTION -}; - G_DEFINE_TYPE(NMNamedManager, nm_named_manager, G_TYPE_OBJECT) -static void nm_named_manager_finalize (GObject *object); -static void nm_named_manager_dispose (GObject *object); -static GObject *nm_named_manager_constructor (GType type, guint n_construct_properties, - GObjectConstructParam *construct_properties); -static void nm_named_manager_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void nm_named_manager_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); +#define NM_NAMED_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + NM_TYPE_NAMED_MANAGER, \ + NMNamedManagerPrivate)) static NMIP4Config *get_last_default_domain (NMNamedManager *mgr); @@ -83,139 +69,15 @@ static gboolean rewrite_resolv_conf (NMNamedManager *mgr, NMIP4Config *config, G static gboolean remove_ip4_config_from_named (NMNamedManager *mgr, NMIP4Config *config); -struct NMNamedManagerPrivate -{ - gboolean use_named; - DBusConnection *connection; +struct NMNamedManagerPrivate { + gboolean use_named; + NMDBusManager * dbus_mgr; GSList * configs; gboolean disposed; }; -static void -nm_named_manager_class_init (NMNamedManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = nm_named_manager_dispose; - object_class->finalize = nm_named_manager_finalize; - object_class->constructor = nm_named_manager_constructor; - object_class->set_property = nm_named_manager_set_property; - object_class->get_property = nm_named_manager_get_property; - - g_object_class_install_property (object_class, - PROP_DBUS_CONNECTION, - g_param_spec_pointer ("dbus-connection", - "DBusConnection", - "dbus connection", - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); -} - -static void -nm_named_manager_init (NMNamedManager *mgr) -{ - mgr->priv = g_new0 (NMNamedManagerPrivate, 1); - - mgr->priv->use_named = FALSE; -} - -static void -nm_named_manager_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - NMNamedManager *mgr = NM_NAMED_MANAGER (object); - - switch (prop_id) - { - case PROP_DBUS_CONNECTION: - mgr->priv->connection = g_value_get_pointer (value); - mgr->priv->use_named = (gboolean) dbus_bus_name_has_owner (mgr->priv->connection, - NAMED_DBUS_SERVICE, NULL); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_named_manager_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - NMNamedManager *mgr = NM_NAMED_MANAGER (object); - - switch (prop_id) - { - case PROP_DBUS_CONNECTION: - g_value_set_pointer (value, mgr->priv->connection); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_named_manager_dispose (GObject *object) -{ - NMNamedManager *mgr = NM_NAMED_MANAGER (object); - GSList *elt; - - if (mgr->priv->disposed) - return; - mgr->priv->disposed = TRUE; - - for (elt = mgr->priv->configs; elt; elt = g_slist_next (elt)) - remove_ip4_config_from_named (mgr, (NMIP4Config *)(elt->data)); -} - -static void -nm_named_manager_finalize (GObject *object) -{ - NMNamedManager *mgr = NM_NAMED_MANAGER (object); - - g_return_if_fail (mgr->priv != NULL); - - g_slist_foreach (mgr->priv->configs, (GFunc) nm_ip4_config_unref, NULL); - g_slist_free (mgr->priv->configs); - - g_free (mgr->priv); - - G_OBJECT_CLASS (nm_named_manager_parent_class)->finalize (object); -} - -static GObject * -nm_named_manager_constructor (GType type, guint n_construct_properties, - GObjectConstructParam *construct_properties) -{ - NMNamedManager *mgr; - NMNamedManagerClass *klass; - GObjectClass *parent_class; - - klass = NM_NAMED_MANAGER_CLASS (g_type_class_peek (NM_TYPE_NAMED_MANAGER)); - - parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); - - mgr = NM_NAMED_MANAGER (parent_class->constructor (type, n_construct_properties, - construct_properties)); - - - return G_OBJECT (mgr); -} - -NMNamedManager * -nm_named_manager_new (DBusConnection *connection) -{ - return NM_NAMED_MANAGER (g_object_new (NM_TYPE_NAMED_MANAGER, - "dbus-connection", - connection, - NULL)); -} GQuark nm_named_manager_error_quark (void) @@ -234,49 +96,78 @@ nm_named_manager_error_quark (void) * Respond to "service created"/"service deleted" signals from dbus for named. * */ -gboolean -nm_named_manager_process_name_owner_changed (NMNamedManager *mgr, - const char *changed_service_name, - const char *old_owner, const char *new_owner) +static void +nm_named_manager_name_owner_changed (NMDBusManager *dbus_mgr, + DBusConnection *connection, + const char *name, + const char *old, + const char *new, + gpointer user_data) { + NMNamedManager *mgr = (NMNamedManager *) user_data; gboolean handled = FALSE; - gboolean old_owner_good = (old_owner && strlen (old_owner)); - gboolean new_owner_good = (new_owner && strlen (new_owner)); + gboolean old_owner_good = (old && strlen (old)); + gboolean new_owner_good = (new && strlen (new)); - g_return_val_if_fail (mgr != NULL, FALSE); - g_return_val_if_fail (changed_service_name != NULL, FALSE); + g_return_if_fail (mgr != NULL); + g_return_if_fail (name != NULL); /* Ensure signal is for named's service */ - if (strcmp (NAMED_DBUS_SERVICE, changed_service_name) != 0) - return FALSE; + if (strcmp (NAMED_DBUS_SERVICE, name) != 0) + return; - if (!old_owner_good && new_owner_good) - { + if (!old_owner_good && new_owner_good) { mgr->priv->use_named = TRUE; if (!add_all_ip4_configs_to_named (mgr)) nm_warning ("Could not set fowarders in named."); handled = TRUE; - } - else if (old_owner_good && !new_owner_good) - { + } else if (old_owner_good && !new_owner_good) { mgr->priv->use_named = FALSE; - /* FIXME: change resolv.conf */ handled = TRUE; } - if (handled) - { + if (handled) { GError *error = NULL; - if (!rewrite_resolv_conf (mgr, get_last_default_domain (mgr), &error)) - { - nm_warning ("Could not write resolv.conf. Error: '%s'", error ? error->message : "(none)"); + if (!rewrite_resolv_conf (mgr, get_last_default_domain (mgr), &error)) { + nm_warning ("Could not write resolv.conf. Error: '%s'", + error ? error->message : "(none)"); g_error_free (error); } } +} - return handled; +static void +nm_named_manager_dbus_connection_changed (NMDBusManager *dbus_mgr, + DBusConnection *dbus_connection, + gpointer user_data) +{ + NMNamedManager *mgr = (NMNamedManager *) user_data; + gboolean handled = FALSE; + + g_return_if_fail (mgr != NULL); + + if (dbus_connection) { + if (nm_dbus_manager_name_has_owner (dbus_mgr, NAMED_DBUS_SERVICE)) { + mgr->priv->use_named = TRUE; + if (!add_all_ip4_configs_to_named (mgr)) + nm_warning ("Could not set fowarders in named."); + handled = TRUE; + } + } else { + mgr->priv->use_named = FALSE; + handled = TRUE; + } + + if (handled) { + GError *error = NULL; + if (!rewrite_resolv_conf (mgr, get_last_default_domain (mgr), &error)) { + nm_warning ("Could not write resolv.conf. Error: '%s'", + error ? error->message : "(none)"); + g_error_free (error); + } + } } static char * @@ -439,64 +330,88 @@ add_ip4_config_to_named (NMNamedManager *mgr, NMIP4Config *config) { const char *domain; int i, num_nameservers; + gboolean success = FALSE; DBusMessage * message; - DBusMessage * reply; + DBusMessage * reply = NULL; DBusError error; gboolean dflt = FALSE; + DBusConnection *dbus_connection; g_return_val_if_fail (mgr != NULL, FALSE); g_return_val_if_fail (config != NULL, FALSE); + dbus_error_init (&error); + + dbus_connection = nm_dbus_manager_get_dbus_connection (mgr->priv->dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get dbus connection."); + goto out; + } + if (!(domain = get_domain_for_config (config, &dflt))) - return FALSE; + goto out; - if (!(message = dbus_message_new_method_call (NAMED_DBUS_SERVICE, NAMED_DBUS_PATH, NAMED_DBUS_INTERFACE, "SetForwarders"))) - return FALSE; + message = dbus_message_new_method_call (NAMED_DBUS_SERVICE, + NAMED_DBUS_PATH, + NAMED_DBUS_INTERFACE, + "SetForwarders"); + if (!message) { + nm_warning ("could not allocate dbus message."); + goto out; + } - dbus_message_append_args (message, DBUS_TYPE_STRING, &domain, DBUS_TYPE_INVALID); + dbus_message_append_args (message, + DBUS_TYPE_STRING, &domain, + DBUS_TYPE_INVALID); num_nameservers = nm_ip4_config_get_num_nameservers (config); - for (i = 0; i < num_nameservers; i++) - { + for (i = 0; i < num_nameservers; i++) { dbus_uint32_t server = nm_ip4_config_get_nameserver (config, i); dbus_uint16_t port = htons (53); /* default DNS port */ char fwd_policy = dflt ? 1 : 2; /* 'first' : 'only' */ - dbus_message_append_args (message, DBUS_TYPE_UINT32, &server, - DBUS_TYPE_UINT16, &port, - DBUS_TYPE_BYTE, &fwd_policy, - DBUS_TYPE_INVALID); + dbus_message_append_args (message, + DBUS_TYPE_UINT32, &server, + DBUS_TYPE_UINT16, &port, + DBUS_TYPE_BYTE, &fwd_policy, + DBUS_TYPE_INVALID); } - dbus_error_init (&error); - reply = dbus_connection_send_with_reply_and_block (mgr->priv->connection, message, -1, &error); + reply = dbus_connection_send_with_reply_and_block (dbus_connection, + message, -1, &error); dbus_message_unref (message); - - if (dbus_error_is_set (&error)) - { - nm_warning ("Could not set forwarders for zone '%s'. Error: '%s'.", domain, error.message); - dbus_error_free (&error); - return FALSE; + if (dbus_error_is_set (&error)) { + nm_warning ("Could not set forwarders for zone '%s'. Error: '%s'.", + domain, + error.message); + goto out; } - if (!reply) - { - nm_warning ("Could not set forwarders for zone '%s', did not receive a reply from named.", domain); - dbus_error_free (&error); - return FALSE; + if (!reply) { + nm_warning ("Could not set forwarders for zone '%s', did not receive " + "a reply from named.", + domain); + goto out; } - if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) - { + if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) { const char *err_msg = NULL; - dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &err_msg, DBUS_TYPE_INVALID); - nm_warning ("Could not set forwarders for zone '%s'. Named replied: '%s'", domain, err_msg); - dbus_message_unref (reply); - return FALSE; + dbus_message_get_args (reply, + NULL, + DBUS_TYPE_STRING, &err_msg, + DBUS_TYPE_INVALID); + nm_warning ("Could not set forwarders for zone '%s'. " + "Named replied: '%s'", + domain, + err_msg); } - dbus_message_unref (reply); + success = TRUE; - return TRUE; +out: + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + dbus_message_unref (reply); + return success; } static gboolean @@ -515,47 +430,76 @@ add_all_ip4_configs_to_named (NMNamedManager *mgr) static gboolean remove_one_zone_from_named (NMNamedManager *mgr, const char *zone) { - DBusMessage * message; - DBusMessage * reply; + gboolean success = FALSE; + DBusMessage * message = NULL; + DBusMessage * reply = NULL; DBusError error; + DBusConnection *dbus_connection; g_return_val_if_fail (mgr != NULL, FALSE); g_return_val_if_fail (zone != NULL, FALSE); - if (!(message = dbus_message_new_method_call (NAMED_DBUS_SERVICE, NAMED_DBUS_PATH, NAMED_DBUS_INTERFACE, "SetForwarders"))) - return FALSE; - - dbus_message_append_args (message, DBUS_TYPE_STRING, &zone, DBUS_TYPE_INVALID); - dbus_error_init (&error); - reply = dbus_connection_send_with_reply_and_block (mgr->priv->connection, message, -1, &error); + + dbus_connection = nm_dbus_manager_get_dbus_connection (mgr->priv->dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get dbus connection."); + goto out; + } + + message = dbus_message_new_method_call (NAMED_DBUS_SERVICE, + NAMED_DBUS_PATH, + NAMED_DBUS_INTERFACE, + "SetForwarders"); + if (!message) { + nm_warning ("could not allocate dbus message."); + goto out; + } + + dbus_message_append_args (message, + DBUS_TYPE_STRING, &zone, + DBUS_TYPE_INVALID); + + reply = dbus_connection_send_with_reply_and_block (dbus_connection, + message, + -1, + &error); dbus_message_unref (message); - if (dbus_error_is_set (&error)) - { - nm_warning ("Could not remove forwarders for zone '%s'. Error: '%s'.", zone, error.message); - dbus_error_free (&error); - return FALSE; + if (dbus_error_is_set (&error)) { + nm_warning ("Could not remove forwarders for zone '%s'. " + "Error: '%s'.", + zone, + error.message); + goto out; } - if (!reply) - { - nm_warning ("Could not remove forwarders for zone '%s', did not receive a reply from named.", zone); - dbus_error_free (&error); - return FALSE; + if (!reply) { + nm_warning ("Could not remove forwarders for zone '%s', did not " + " receive a reply from named.", + zone); + goto out; } - if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) - { + if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) { const char *err_msg = NULL; - dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &err_msg, DBUS_TYPE_INVALID); - nm_warning ("Could not remove forwarders for zone '%s'. Named replied: '%s'", zone, err_msg); - dbus_message_unref (reply); - return FALSE; + dbus_message_get_args (reply, + NULL, + DBUS_TYPE_STRING, &err_msg, + DBUS_TYPE_INVALID); + nm_warning ("Could not remove forwarders for zone '%s'. " + "Named replied: '%s'", + zone, + err_msg); + goto out; } - dbus_message_unref (reply); + success = TRUE; - return TRUE; +out: + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + dbus_message_unref (reply); + return success; } static gboolean @@ -576,59 +520,75 @@ static void remove_all_zones_from_named (NMNamedManager *mgr) { DBusMessage * message; - DBusMessage * reply; + DBusMessage * reply = NULL; DBusError error; DBusMessageIter iter; GSList * zones = NULL; GSList * elt = NULL; + DBusConnection * dbus_connection; g_return_if_fail (mgr != NULL); if (!mgr->priv->use_named) return; - if (!(message = dbus_message_new_method_call (NAMED_DBUS_SERVICE, NAMED_DBUS_PATH, NAMED_DBUS_INTERFACE, "GetForwarders"))) - return; + dbus_connection = nm_dbus_manager_get_dbus_connection (mgr->priv->dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get dbus connection."); + goto out; + } + + message = dbus_message_new_method_call (NAMED_DBUS_SERVICE, + NAMED_DBUS_PATH, + NAMED_DBUS_INTERFACE, + "GetForwarders"); + if (!message) { + nm_warning ("could not allocate dbus message."); + goto out; + } dbus_error_init (&error); - reply = dbus_connection_send_with_reply_and_block (mgr->priv->connection, message, -1, &error); + reply = dbus_connection_send_with_reply_and_block (dbus_connection, + message, + -1, + &error); dbus_message_unref (message); - if (dbus_error_is_set (&error)) - { - nm_warning ("Could not get forwarder list from named. Error: '%s'.", error.message); - dbus_error_free (&error); - return; + if (dbus_error_is_set (&error)) { + nm_warning ("Could not get forwarder list from named. Error: '%s'.", + error.message); + goto out; } - if (!reply) - { - nm_warning ("Could not get forarder list from named, did not receive a reply from named."); - dbus_error_free (&error); - return; + if (!reply) { + nm_warning ("Could not get forarder list from named, did not receive " + " a reply from named."); + goto out; } - if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) - { + if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) { const char *err_msg = NULL; - dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &err_msg, DBUS_TYPE_INVALID); - nm_warning ("Could not get forwarder list from named. Named replied: '%s'", err_msg); - dbus_message_unref (reply); - return; + dbus_message_get_args (reply, + NULL, + DBUS_TYPE_STRING, &err_msg, + DBUS_TYPE_INVALID); + nm_warning ("Could not get forwarder list from named. " + "Named replied: '%s'", + err_msg); + goto out; } dbus_message_iter_init (reply, &iter); - do - { - /* We depend on zones being the only strings in what named returns obviously */ - if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING) - { + do { + /* We depend on zones being the only strings in what + * named returns (obviously) + */ + if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING) { char *zone = NULL; dbus_message_iter_get_basic (&iter, &zone); zones = g_slist_append (zones, g_strdup (zone)); } } while (dbus_message_iter_next (&iter)); - dbus_message_unref (reply); /* Remove all the zones from named */ for (elt = zones; elt; elt = g_slist_next (elt)) @@ -636,6 +596,11 @@ remove_all_zones_from_named (NMNamedManager *mgr) g_slist_foreach (zones, (GFunc) g_free, NULL); g_slist_free (zones); + +out: + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + dbus_message_unref (reply); } gboolean @@ -735,3 +700,66 @@ nm_named_manager_remove_ip4_config (NMNamedManager *mgr, NMIP4Config *config) return TRUE; } + +static void +nm_named_manager_init (NMNamedManager *mgr) +{ + mgr->priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr); + mgr->priv->use_named = FALSE; + mgr->priv->dbus_mgr = nm_dbus_manager_get (NULL); + g_signal_connect (G_OBJECT (mgr->priv->dbus_mgr), + "name-owner-changed", + G_CALLBACK (nm_named_manager_name_owner_changed), + mgr); + g_signal_connect (G_OBJECT (mgr->priv->dbus_mgr), + "dbus-connection-changed", + G_CALLBACK (nm_named_manager_dbus_connection_changed), + mgr); +} + +static void +nm_named_manager_dispose (GObject *object) +{ + NMNamedManager *mgr = NM_NAMED_MANAGER (object); + GSList *elt; + + if (mgr->priv->disposed) + return; + mgr->priv->disposed = TRUE; + + for (elt = mgr->priv->configs; elt; elt = g_slist_next (elt)) + remove_ip4_config_from_named (mgr, (NMIP4Config *)(elt->data)); +} + +static void +nm_named_manager_finalize (GObject *object) +{ + NMNamedManager *mgr = NM_NAMED_MANAGER (object); + + g_return_if_fail (mgr->priv != NULL); + + g_slist_foreach (mgr->priv->configs, (GFunc) nm_ip4_config_unref, NULL); + g_slist_free (mgr->priv->configs); + + g_object_unref (mgr->priv->dbus_mgr); + + G_OBJECT_CLASS (nm_named_manager_parent_class)->finalize (object); +} + +NMNamedManager * +nm_named_manager_new (void) +{ + return NM_NAMED_MANAGER (g_object_new (NM_TYPE_NAMED_MANAGER, NULL)); +} + +static void +nm_named_manager_class_init (NMNamedManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = nm_named_manager_dispose; + object_class->finalize = nm_named_manager_finalize; + + g_type_class_add_private (object_class, sizeof (NMNamedManagerPrivate)); +} + diff --git a/src/named-manager/nm-named-manager.h b/src/named-manager/nm-named-manager.h index c49600049..1ca6af734 100644 --- a/src/named-manager/nm-named-manager.h +++ b/src/named-manager/nm-named-manager.h @@ -50,26 +50,19 @@ G_BEGIN_DECLS typedef struct NMNamedManagerPrivate NMNamedManagerPrivate; -typedef struct -{ +typedef struct { GObject parent; NMNamedManagerPrivate *priv; } NMNamedManager; -typedef struct -{ +typedef struct { GObjectClass parent; - } NMNamedManagerClass; GType nm_named_manager_get_type (void); -NMNamedManager * nm_named_manager_new (DBusConnection *connection); - -gboolean nm_named_manager_process_name_owner_changed (NMNamedManager *mgr, - const char *changed_service_name, - const char *old_owner, const char *new_owner); +NMNamedManager * nm_named_manager_new (void); gboolean nm_named_manager_add_ip4_config (NMNamedManager *mgr, NMIP4Config *config); diff --git a/src/nm-activation-request.c b/src/nm-activation-request.c index d589e1171..0c7cee3ae 100644 --- a/src/nm-activation-request.c +++ b/src/nm-activation-request.c @@ -27,6 +27,7 @@ #include "nm-device.h" #include "NetworkManagerDbus.h" #include "nm-dhcp-manager.h" +#include "nm-dbus-manager.h" #include "nm-utils.h" @@ -170,7 +171,9 @@ NMActStage nm_act_request_get_stage (NMActRequest *req) void nm_act_request_set_stage (NMActRequest *req, NMActStage stage) { DBusMessage * message; - char * dev_path; + char * dev_path = NULL; + NMDBusManager * dbus_mgr = NULL; + DBusConnection *dbus_connection; g_return_if_fail (req != NULL); @@ -179,23 +182,34 @@ void nm_act_request_set_stage (NMActRequest *req, NMActStage stage) g_return_if_fail (req->data); g_return_if_fail (req->dev); - if (!(dev_path = nm_dbus_get_object_path_for_device (req->dev))) - return; - - if (!(message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, "DeviceActivationStage"))) - { - nm_warning ("nm_act_request_set_stage(): Not enough memory for new dbus message!"); - g_free (dev_path); - return; + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_warning ("couldn't get the dbus connection."); + goto out; } - dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH, &dev_path, DBUS_TYPE_UINT32, &stage, DBUS_TYPE_INVALID); - g_free (dev_path); + if (!(dev_path = nm_dbus_get_object_path_for_device (req->dev))) + goto out; - if (!dbus_connection_send (req->data->dbus_connection, message, NULL)) - nm_warning ("nm_act_request_set_stage(): Could not raise the signal!"); + message = dbus_message_new_signal (NM_DBUS_PATH, + NM_DBUS_INTERFACE, + "DeviceActivationStage"); + if (!message) { + nm_warning ("couldn't allocate the dbus message."); + goto out; + } + dbus_message_append_args (message, + DBUS_TYPE_OBJECT_PATH, &dev_path, + DBUS_TYPE_UINT32, &stage, + DBUS_TYPE_INVALID); + dbus_connection_send (dbus_connection, message, NULL); dbus_message_unref (message); + +out: + g_free (dev_path); + g_object_unref (dbus_mgr); } DBusPendingCall * nm_act_request_get_user_key_pending_call (NMActRequest *req) diff --git a/src/nm-dbus-device.c b/src/nm-dbus-device.c index 87879a04d..896262e89 100644 --- a/src/nm-dbus-device.c +++ b/src/nm-dbus-device.c @@ -36,474 +36,677 @@ #include "nm-dbus-device.h" #include "nm-device-802-3-ethernet.h" #include "nm-device-802-11-wireless.h" +#include "nm-device-private.h" +#include "nm-dbus-net.h" -static DBusMessage *nm_dbus_device_get_name (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +new_invalid_device_type_error (DBusMessage *replyto) { - DBusMessage *reply = NULL; - NMDevice *dev; - - g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL); - - dev = data->dev; - if ((reply = dbus_message_new_method_return (message))) { - const char *iface; - iface = nm_device_get_iface (dev); - dbus_message_append_args (reply, DBUS_TYPE_STRING, &iface, DBUS_TYPE_INVALID); - } - - return reply; + return nm_dbus_create_error_message (replyto, + NM_DBUS_INTERFACE, + "InvalidDeviceType", + "Invalid device type for this" + "request."); } -static DBusMessage *nm_dbus_device_get_type (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) + +static DBusMessage * +nm_dbus_device_get_name (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { + NMDbusCBData *data = (NMDbusCBData *) user_data; DBusMessage *reply = NULL; - NMDevice *dev; + const char *iface; - g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->dev != NULL, NULL); - dev = data->dev; - if ((reply = dbus_message_new_method_return (message))) - { - dbus_int32_t type; - type = nm_device_get_device_type (dev); - dbus_message_append_args (reply, DBUS_TYPE_INT32, &type, DBUS_TYPE_INVALID); + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; } - return reply; -} - -static DBusMessage *nm_dbus_device_get_hal_udi (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) -{ - DBusMessage *reply = NULL; - NMDevice *dev; - - g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL); - - dev = data->dev; - if ((reply = dbus_message_new_method_return (message))) { - const char *udi; - udi = nm_device_get_udi (dev); - dbus_message_append_args (reply, DBUS_TYPE_STRING, &udi, DBUS_TYPE_INVALID); - } + iface = nm_device_get_iface (data->dev); + dbus_message_append_args (reply, DBUS_TYPE_STRING, &iface, DBUS_TYPE_INVALID); return reply; } -static DBusMessage *nm_dbus_device_get_ip4_address (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_device_get_type (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { + NMDbusCBData *data = (NMDbusCBData *) user_data; DBusMessage *reply = NULL; - NMDevice *dev; + dbus_int32_t type; - g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->dev != NULL, NULL); - dev = data->dev; - if ((reply = dbus_message_new_method_return (message))) { - dbus_uint32_t address; + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; + } + + type = nm_device_get_device_type (data->dev); + dbus_message_append_args (reply, DBUS_TYPE_INT32, &type, DBUS_TYPE_INVALID); + + return reply; +} + +static DBusMessage * +nm_dbus_device_get_hal_udi (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) +{ + NMDbusCBData *data = (NMDbusCBData *) user_data; + DBusMessage *reply = NULL; + const char *udi; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->dev != NULL, NULL); + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; + } + + udi = nm_device_get_udi (data->dev); + dbus_message_append_args (reply, DBUS_TYPE_STRING, &udi, DBUS_TYPE_INVALID); + + return reply; +} + +static DBusMessage * +nm_dbus_device_get_ip4_address (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) +{ + NMDbusCBData *data = (NMDbusCBData *) user_data; + DBusMessage *reply = NULL; + dbus_uint32_t address; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->dev != NULL, NULL); + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; + } - address = nm_device_get_ip4_address (dev); - dbus_message_append_args (reply, DBUS_TYPE_UINT32, &address, DBUS_TYPE_INVALID); - } + address = nm_device_get_ip4_address (data->dev); + dbus_message_append_args (reply, DBUS_TYPE_UINT32, &address, DBUS_TYPE_INVALID); return reply; } -static DBusMessage *nm_dbus_device_get_hw_address (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_device_get_hw_address (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { + NMDbusCBData *data = (NMDbusCBData *) user_data; DBusMessage *reply = NULL; - NMDevice *dev; + struct ether_addr addr; + char char_addr[20]; + char * ptr = &char_addr[0]; - g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->dev != NULL, NULL); - dev = data->dev; - if ((reply = dbus_message_new_method_return (message))) - { - struct ether_addr addr; - char char_addr[20]; - char * ptr = &char_addr[0]; - - memset (&addr, 0, sizeof (struct ether_addr)); - if (nm_device_is_802_3_ethernet (dev)) - nm_device_802_3_ethernet_get_address (NM_DEVICE_802_3_ETHERNET (dev), &addr); - else if (nm_device_is_802_11_wireless (dev)) - nm_device_802_11_wireless_get_address (NM_DEVICE_802_11_WIRELESS (dev), &addr); - memset (char_addr, 0, 20); - iw_ether_ntop (&addr, char_addr); - dbus_message_append_args (reply, DBUS_TYPE_STRING, &ptr, DBUS_TYPE_INVALID); + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; } + memset (&addr, 0, sizeof (struct ether_addr)); + if (nm_device_is_802_3_ethernet (data->dev)) { + nm_device_802_3_ethernet_get_address (NM_DEVICE_802_3_ETHERNET (data->dev), &addr); + } else if (nm_device_is_802_11_wireless (data->dev)) { + nm_device_802_11_wireless_get_address (NM_DEVICE_802_11_WIRELESS (data->dev), &addr); + } + memset (char_addr, 0, 20); + iw_ether_ntop (&addr, char_addr); + dbus_message_append_args (reply, DBUS_TYPE_STRING, &ptr, DBUS_TYPE_INVALID); + return reply; } -static DBusMessage *nm_dbus_device_get_mode (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_device_get_mode (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { + NMDbusCBData *data = (NMDbusCBData *) user_data; DBusMessage *reply = NULL; - NMDevice *dev; + dbus_int32_t mode; - g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->dev != NULL, NULL); - dev = data->dev; - if (!nm_device_is_802_11_wireless (dev)) - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotWireless", - "Wired devices cannot see wireless networks."); + if (!nm_device_is_802_11_wireless (data->dev)) { + reply = new_invalid_device_type_error (message); + goto out; } - else if ((reply = dbus_message_new_method_return (message))) - { - dbus_int32_t mode = (dbus_int32_t) nm_device_802_11_wireless_get_mode (NM_DEVICE_802_11_WIRELESS (dev)); - dbus_message_append_args (reply, DBUS_TYPE_INT32, &mode, DBUS_TYPE_INVALID); + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + goto out; } + mode = (dbus_int32_t) nm_device_802_11_wireless_get_mode (NM_DEVICE_802_11_WIRELESS (data->dev)); + dbus_message_append_args (reply, DBUS_TYPE_INT32, &mode, DBUS_TYPE_INVALID); + +out: + return reply; +} + +static DBusMessage * +nm_dbus_device_get_link_active (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) +{ + NMDbusCBData *data = (NMDbusCBData *) user_data; + DBusMessage *reply = NULL; + dbus_bool_t is_active; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->dev != NULL, NULL); + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; + } + + is_active = nm_device_has_active_link (data->dev); + dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &is_active, DBUS_TYPE_INVALID); + return reply; } -static DBusMessage *nm_dbus_device_get_link_active (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) -{ - DBusMessage *reply = NULL; - NMDevice *dev; - - g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL); - - dev = data->dev; - if ((reply = dbus_message_new_method_return (message))) - { - dbus_bool_t is_active; - - is_active = nm_device_has_active_link (dev); - dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &is_active, DBUS_TYPE_INVALID); - } - - return reply; -} - -static DBusMessage *nm_dbus_device_get_active_network (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_device_get_active_network (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { + NMDbusCBData *data = (NMDbusCBData *) user_data; DBusMessage *reply = NULL; + NMDevice * dev; gboolean success = FALSE; - NMDevice *dev; + NMActRequest * req; + NMAccessPoint * ap; - g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->dev != NULL, NULL); /* Only wireless devices have an active network */ dev = data->dev; if (!nm_device_is_802_11_wireless (dev)) { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotWireless", - "Wired devices cannot have active networks."); + reply = new_invalid_device_type_error (message); + goto out; } - else if ((reply = dbus_message_new_method_return (message))) + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + goto out; + } + + req = nm_device_get_act_request (dev); + if (req && (ap = nm_act_request_get_ap (req))) { + NMAccessPoint *tmp_ap; + char * object_path = NULL; + + tmp_ap = nm_device_802_11_wireless_ap_list_get_ap_by_essid (NM_DEVICE_802_11_WIRELESS (dev), nm_ap_get_essid (ap)); + if (tmp_ap && (object_path = nm_dbus_get_object_path_for_network (dev, tmp_ap))) { + dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID); + g_free (object_path); + success = TRUE; + } + } + + if (!success) { + dbus_message_unref (reply); + reply = nm_dbus_create_error_message (message, + NM_DBUS_INTERFACE, + "NoActiveNetwork", + "The device is not associated " + " with any networks at this time."); + } + +out: + return reply; +} + +static DBusMessage * +nm_dbus_device_get_networks (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) +{ + NMDbusCBData *data = (NMDbusCBData *) user_data; + DBusMessage * reply = NULL; + NMDevice * dev; + DBusMessageIter iter; + DBusMessageIter iter_array; + NMAccessPoint * ap = NULL; + gboolean success = FALSE; + NMAccessPointList * ap_list; + NMAPListIter * list_iter; + char * escaped_object_path; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->dev != NULL, NULL); + + if (!nm_device_is_802_11_wireless (data->dev)) { + reply = new_invalid_device_type_error (message); + goto out; + } + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + goto out; + } + + dbus_message_iter_init_append (reply, &iter); + dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter_array); + + dev = data->dev; + if ((ap_list = nm_device_802_11_wireless_ap_list_get (NM_DEVICE_802_11_WIRELESS (dev)))) { + if ((list_iter = nm_ap_list_iter_new (ap_list))) { + while ((ap = nm_ap_list_iter_next (list_iter))) { + if (nm_ap_get_essid (ap)) { + escaped_object_path = nm_dbus_get_object_path_for_network (dev, ap); + dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_OBJECT_PATH, &escaped_object_path); + g_free (escaped_object_path); + success = TRUE; + } + } + nm_ap_list_iter_free (list_iter); + } + } + dbus_message_iter_close_container (&iter, &iter_array); + + if (!success) { + dbus_message_unref (reply); + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NoNetworks", + "The device cannot see any wireless networks."); + } + +out: + return reply; +} + +static DBusMessage * +nm_dbus_device_get_capabilities (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) +{ + NMDbusCBData *data = (NMDbusCBData *) user_data; + DBusMessage *reply = NULL; + dbus_uint32_t capabilities; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->dev != NULL, NULL); + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; + } + + capabilities = nm_device_get_capabilities (data->dev); + dbus_message_append_args (reply, DBUS_TYPE_UINT32, &capabilities, DBUS_TYPE_INVALID); + + return reply; +} + +static DBusMessage * +nm_dbus_device_get_driver (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) +{ + NMDbusCBData *data = (NMDbusCBData *) user_data; + DBusMessage *reply = NULL; + const char * driver; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->dev != NULL, NULL); + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; + } + + driver = nm_device_get_driver (data->dev); + if (!driver) + driver = ""; + dbus_message_append_args (reply, DBUS_TYPE_STRING, &driver, DBUS_TYPE_INVALID); + + return reply; +} + +static DBusMessage * +nm_dbus_device_set_link_active (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) +{ + NMDbusCBData *data = (NMDbusCBData *) user_data; + DBusMessage *reply = NULL; + gboolean have_link; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->dev != NULL, NULL); + g_return_val_if_fail (data->data != NULL, NULL); + + /* Can only set link status for test devices */ + if (!nm_device_is_test_device (data->dev)) { + reply = nm_dbus_create_error_message (message, + NM_DBUS_INTERFACE, + "NotTestDevice", + "Only test devices can have their" + " link status set manually."); + goto out; + } + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + goto out; + } + + if (!dbus_message_get_args (message, NULL, + DBUS_TYPE_BOOLEAN, &have_link, + DBUS_TYPE_INVALID)) { + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE); + goto out; + } + + nm_device_set_active_link (data->dev, have_link); + nm_policy_schedule_device_change_check (data->data); + +out: + return reply; +} + +static DBusMessage * +nm_dbus_device_get_properties (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) +{ + NMDbusCBData * data = (NMDbusCBData *) user_data; + DBusMessage * reply = NULL; + NMDevice * dev; + char * op; + const char * iface; + dbus_uint32_t type; + const char * udi; + gchar * ip4_address; + gchar * broadcast; + gchar * subnetmask; + gchar * route; + gchar * primary_dns; + gchar * secondary_dns; + struct ether_addr hw_addr; + char hw_addr_buf[20]; + char * hw_addr_buf_ptr = &hw_addr_buf[0]; + dbus_int32_t mode = -1; + dbus_int32_t strength = -1; + dbus_int32_t speed = 0; + char * active_network_path = NULL; + dbus_bool_t link_active; + dbus_uint32_t capabilities; + dbus_uint32_t type_capabilities; + char ** networks = NULL; + int num_networks = 0; + dbus_bool_t active; + NMActStage act_stage; + NMIP4Config * ip4config; + guint32 broadcast_addr = 0; + guint32 subnetmask_addr = 0; + guint32 route_addr = 0; + guint32 primary_dns_addr = 0; + guint32 secondary_dns_addr = 0; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->dev != NULL, NULL); + g_return_val_if_fail (data->data != NULL, NULL); + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + goto out; + } + + dev = data->dev; + op = nm_dbus_get_object_path_for_device (dev); + iface = nm_device_get_iface (dev); + type = nm_device_get_device_type (dev); + udi = nm_device_get_udi (dev); + link_active = (dbus_bool_t) nm_device_has_active_link (dev); + capabilities = (dbus_uint32_t) nm_device_get_capabilities (dev); + type_capabilities = (dbus_uint32_t) nm_device_get_type_capabilities (dev); + active = nm_device_get_act_request (dev) ? TRUE : FALSE; + act_stage = active ? nm_act_request_get_stage (nm_device_get_act_request (dev)) : NM_ACT_STAGE_UNKNOWN; + + memset (hw_addr_buf, 0, 20); + if (nm_device_is_802_3_ethernet (dev)) + nm_device_802_3_ethernet_get_address (NM_DEVICE_802_3_ETHERNET (dev), &hw_addr); + else if (nm_device_is_802_11_wireless (dev)) + nm_device_802_11_wireless_get_address (NM_DEVICE_802_11_WIRELESS (dev), &hw_addr); + iw_ether_ntop (&hw_addr, hw_addr_buf); + + ip4config = nm_device_get_ip4_config (dev); + if (ip4config) { + guint32 nr_nameservers; + + broadcast_addr = nm_ip4_config_get_broadcast (ip4config); + subnetmask_addr = nm_ip4_config_get_netmask (ip4config); + route_addr = nm_ip4_config_get_gateway (ip4config); + + nr_nameservers = nm_ip4_config_get_num_nameservers (ip4config); + if (nr_nameservers > 1) + secondary_dns_addr = nm_ip4_config_get_nameserver (ip4config, 1); + if (nr_nameservers > 0) + primary_dns_addr = nm_ip4_config_get_nameserver (ip4config, 0); + } + ip4_address = nm_utils_inet_ip4_address_as_string (nm_device_get_ip4_address (dev)); + broadcast = nm_utils_inet_ip4_address_as_string (broadcast_addr); + subnetmask = nm_utils_inet_ip4_address_as_string (subnetmask_addr); + route = nm_utils_inet_ip4_address_as_string (route_addr); + primary_dns = nm_utils_inet_ip4_address_as_string (primary_dns_addr); + secondary_dns = nm_utils_inet_ip4_address_as_string (secondary_dns_addr); + + if (nm_device_is_802_11_wireless (dev)) { + NMDevice80211Wireless * wdev = NM_DEVICE_802_11_WIRELESS (dev); NMActRequest * req = nm_device_get_act_request (dev); NMAccessPoint * ap; + NMAccessPointList * ap_list; + NMAPListIter * iter; - if (req && (ap = nm_act_request_get_ap (req))) - { - NMAccessPoint *tmp_ap; - char * object_path = NULL; + strength = nm_device_802_11_wireless_get_signal_strength (wdev); + mode = nm_device_802_11_wireless_get_mode (wdev); + speed = nm_device_802_11_wireless_get_bitrate (wdev); - tmp_ap = nm_device_802_11_wireless_ap_list_get_ap_by_essid (NM_DEVICE_802_11_WIRELESS (dev), nm_ap_get_essid (ap)); - if (tmp_ap && (object_path = nm_dbus_get_object_path_for_network (dev, tmp_ap))) - { - dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID); - g_free (object_path); - success = TRUE; - } + if (req && (ap = nm_act_request_get_ap (req))) { + NMAccessPoint *tmp_ap; + + if ((tmp_ap = nm_device_802_11_wireless_ap_list_get_ap_by_essid (wdev, nm_ap_get_essid (ap)))) + active_network_path = nm_dbus_get_object_path_for_network (dev, tmp_ap); } - if (!success) - { - dbus_message_unref (reply); - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NoActiveNetwork", - "The device is not associated with any networks at this time."); - } - } - return reply; -} + ap_list = nm_device_802_11_wireless_ap_list_get (wdev); + if (ap_list && (num_networks = nm_ap_list_size (ap_list))) { + if ((iter = nm_ap_list_iter_new (ap_list))) { + int i = 0; -static DBusMessage *nm_dbus_device_get_networks (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) -{ - DBusMessage *reply = NULL; - NMDevice *dev; - - g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL); - - /* Only wireless devices have networks */ - dev = data->dev; - if (!nm_device_is_802_11_wireless (dev)) - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotWireless", - "Wired devices cannot see wireless networks."); - } - else if ((reply = dbus_message_new_method_return (message))) - { - DBusMessageIter iter; - DBusMessageIter iter_array; - NMAccessPoint *ap = NULL; - gboolean success = FALSE; - NMAccessPointList *ap_list; - NMAPListIter *list_iter; - char *escaped_object_path; - - dbus_message_iter_init_append (reply, &iter); - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter_array); - - if ((ap_list = nm_device_802_11_wireless_ap_list_get (NM_DEVICE_802_11_WIRELESS (dev)))) - { - if ((list_iter = nm_ap_list_iter_new (ap_list))) - { - while ((ap = nm_ap_list_iter_next (list_iter))) - { - if (nm_ap_get_essid (ap)) - { - escaped_object_path = nm_dbus_get_object_path_for_network (dev, ap); - dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_OBJECT_PATH, &escaped_object_path); - g_free (escaped_object_path); - success = TRUE; - } + networks = g_malloc0 (sizeof (char *) * (num_networks + 1)); + while ((ap = nm_ap_list_iter_next (iter))) { + char *ap_op = nm_dbus_get_object_path_for_network (dev, ap); + if (ap_op) + networks[i++] = ap_op; } - nm_ap_list_iter_free (list_iter); + num_networks = i; /* # actually added to array, since we can have NULL essid access points */ + + nm_ap_list_iter_free (iter); } } - - dbus_message_iter_close_container (&iter, &iter_array); - - if (!success) - { - dbus_message_unref (reply); - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NoNetworks", - "The device cannot see any wireless networks."); - } + } else { + speed = nm_device_802_3_ethernet_get_speed (NM_DEVICE_802_3_ETHERNET (dev)); } + if (!active_network_path) + active_network_path = g_strdup (""); + + dbus_message_append_args (reply, + DBUS_TYPE_OBJECT_PATH, &op, + DBUS_TYPE_STRING, &iface, + DBUS_TYPE_UINT32, &type, + DBUS_TYPE_STRING, &udi, + DBUS_TYPE_BOOLEAN,&active, + DBUS_TYPE_UINT32, &act_stage, + DBUS_TYPE_STRING, &ip4_address, + DBUS_TYPE_STRING, &subnetmask, + DBUS_TYPE_STRING, &broadcast, + DBUS_TYPE_STRING, &hw_addr_buf_ptr, + DBUS_TYPE_STRING, &route, + DBUS_TYPE_STRING, &primary_dns, + DBUS_TYPE_STRING, &secondary_dns, + DBUS_TYPE_INT32, &mode, + DBUS_TYPE_INT32, &strength, + DBUS_TYPE_BOOLEAN,&link_active, + DBUS_TYPE_INT32, &speed, + DBUS_TYPE_UINT32, &capabilities, + DBUS_TYPE_UINT32, &type_capabilities, + DBUS_TYPE_STRING, &active_network_path, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &networks, num_networks, + DBUS_TYPE_INVALID); + g_free (op); + g_free (active_network_path); + g_strfreev (networks); + g_free (route); + g_free (ip4_address); + g_free (broadcast); + g_free (subnetmask); + +out: return reply; } -static DBusMessage *nm_dbus_device_get_capabilities (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) + +/* + * nm_dbus_devices_message_handler + * + * Dispatch messages against individual network devices + * + */ +static DBusHandlerResult +nm_dbus_device_message_handler (DBusConnection *connection, + DBusMessage *message, + void *user_data) { - DBusMessage *reply = NULL; - NMDevice *dev; + NMData * data = (NMData *)user_data; + gboolean handled = FALSE; + const char * path; + DBusMessage * reply = NULL; + NMDevice * dev; + char * object_path; + char * escaped_object_path; + NMDbusCBData * cb_data; - g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL); + 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); + g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - dev = data->dev; - if ((reply = dbus_message_new_method_return (message))) - { - dbus_uint32_t capabilities = nm_device_get_capabilities (dev); - dbus_message_append_args (reply, DBUS_TYPE_UINT32, &capabilities, DBUS_TYPE_INVALID); + path = dbus_message_get_path (message); + if (!(dev = nm_dbus_get_device_from_escaped_object_path (data, path))) { + reply = nm_dbus_create_error_message (message, + NM_DBUS_INTERFACE, + "DeviceNotFound", + "The requested device does not " + " exist."); + goto out; } - return reply; + /* Test whether or not the _networks_ of a device were queried instead of the device itself */ + object_path = g_strdup_printf ("%s/%s/Networks/", + NM_DBUS_PATH_DEVICES, + nm_device_get_iface (dev)); + escaped_object_path = nm_dbus_escape_object_path (object_path); + g_free (object_path); + + cb_data = g_slice_new0 (NMDbusCBData); + cb_data->data = data; + cb_data->dev = dev; + + if (strncmp (path, escaped_object_path, strlen (escaped_object_path)) == 0) { + handled = nm_dbus_net_methods_dispatch (data->net_methods, + connection, + message, + cb_data, + &reply); + } else { + handled = nm_dbus_method_list_dispatch (data->device_methods, + connection, + message, + cb_data, + &reply); + } + g_object_unref (G_OBJECT (cb_data->dev)); + g_slice_free (NMDbusCBData, cb_data); + g_free (escaped_object_path); + +out: + if (reply) + { + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + handled = TRUE; + } + + return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); } -static DBusMessage *nm_dbus_device_get_driver (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) -{ - DBusMessage *reply = NULL; - NMDevice *dev; - - g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL); - - dev = data->dev; - if ((reply = dbus_message_new_method_return (message))) - { - const char * driver = nm_device_get_driver (dev); - if (!driver) - driver = ""; - dbus_message_append_args (reply, DBUS_TYPE_STRING, &driver, DBUS_TYPE_INVALID); - } - - return reply; -} - -static DBusMessage *nm_dbus_device_set_link_active (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) -{ - DBusMessage *reply = NULL; - NMDevice *dev; - - g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL); - - /* Can only set link status for active devices */ - dev = data->dev; - if (!nm_device_is_test_device (dev)) - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NotTestDevice", - "Only test devices can have their link status set manually."); - } - else if ((reply = dbus_message_new_method_return (message))) - { - DBusError error; - gboolean have_link; - - dbus_error_init (&error); - if (dbus_message_get_args (message, &error, DBUS_TYPE_BOOLEAN, &have_link, DBUS_TYPE_INVALID)) - { - nm_device_set_active_link (dev, have_link); - nm_policy_schedule_device_change_check (data->data); - } - } - - return reply; -} - -static DBusMessage *nm_dbus_device_get_properties (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) -{ - DBusMessage *reply = NULL; - NMDevice *dev; - - g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL); - - dev = data->dev; - if ((reply = dbus_message_new_method_return (message))) - { - char * op = nm_dbus_get_object_path_for_device (dev); - const char * iface = nm_device_get_iface (dev); - dbus_uint32_t type = nm_device_get_device_type (dev); - const char * udi = nm_device_get_udi (dev); - gchar * ip4_address; - gchar * broadcast; - gchar * subnetmask; - gchar * route; - gchar * primary_dns; - gchar * secondary_dns; - struct ether_addr hw_addr; - char hw_addr_buf[20]; - char * hw_addr_buf_ptr = &hw_addr_buf[0]; - dbus_int32_t mode = -1; - dbus_int32_t strength = -1; - dbus_int32_t speed = 0; - char * active_network_path = NULL; - dbus_bool_t link_active = (dbus_bool_t) nm_device_has_active_link (dev); - dbus_uint32_t capabilities = (dbus_uint32_t) nm_device_get_capabilities (dev); - dbus_uint32_t type_capabilities = (dbus_uint32_t) nm_device_get_type_capabilities (dev); - char ** networks = NULL; - int num_networks = 0; - dbus_bool_t active = nm_device_get_act_request (dev) ? TRUE : FALSE; - NMActStage act_stage = active ? nm_act_request_get_stage (nm_device_get_act_request (dev)) : NM_ACT_STAGE_UNKNOWN; - NMIP4Config * ip4config; - guint32 broadcast_addr = 0; - guint32 subnetmask_addr = 0; - guint32 route_addr = 0; - guint32 primary_dns_addr = 0; - guint32 secondary_dns_addr = 0; - - memset (hw_addr_buf, 0, 20); - if (nm_device_is_802_3_ethernet (dev)) - nm_device_802_3_ethernet_get_address (NM_DEVICE_802_3_ETHERNET (dev), &hw_addr); - else if (nm_device_is_802_11_wireless (dev)) - nm_device_802_11_wireless_get_address (NM_DEVICE_802_11_WIRELESS (dev), &hw_addr); - iw_ether_ntop (&hw_addr, hw_addr_buf); - - ip4config = nm_device_get_ip4_config (dev); - if (ip4config) - { - guint32 nr_nameservers; - - broadcast_addr = nm_ip4_config_get_broadcast (ip4config); - subnetmask_addr = nm_ip4_config_get_netmask (ip4config); - route_addr = nm_ip4_config_get_gateway (ip4config); - - nr_nameservers = nm_ip4_config_get_num_nameservers (ip4config); - if (nr_nameservers > 1) - secondary_dns_addr = nm_ip4_config_get_nameserver (ip4config, 1); - if (nr_nameservers > 0) - primary_dns_addr = nm_ip4_config_get_nameserver (ip4config, 0); - } - ip4_address = nm_utils_inet_ip4_address_as_string (nm_device_get_ip4_address (dev)); - broadcast = nm_utils_inet_ip4_address_as_string (broadcast_addr); - subnetmask = nm_utils_inet_ip4_address_as_string (subnetmask_addr); - route = nm_utils_inet_ip4_address_as_string (route_addr); - primary_dns = nm_utils_inet_ip4_address_as_string (primary_dns_addr); - secondary_dns = nm_utils_inet_ip4_address_as_string (secondary_dns_addr); - - if (nm_device_is_802_11_wireless (dev)) - { - NMDevice80211Wireless * wdev = NM_DEVICE_802_11_WIRELESS (dev); - NMActRequest * req = nm_device_get_act_request (dev); - NMAccessPoint * ap; - NMAccessPointList * ap_list; - NMAPListIter * iter; - - strength = nm_device_802_11_wireless_get_signal_strength (wdev); - mode = nm_device_802_11_wireless_get_mode (wdev); - speed = nm_device_802_11_wireless_get_bitrate (wdev); - - if (req && (ap = nm_act_request_get_ap (req))) - { - NMAccessPoint *tmp_ap; - - if ((tmp_ap = nm_device_802_11_wireless_ap_list_get_ap_by_essid (wdev, nm_ap_get_essid (ap)))) - active_network_path = nm_dbus_get_object_path_for_network (dev, tmp_ap); - } - - ap_list = nm_device_802_11_wireless_ap_list_get (wdev); - if (ap_list && (num_networks = nm_ap_list_size (ap_list))) - { - if ((iter = nm_ap_list_iter_new (ap_list))) - { - int i = 0; - - networks = g_malloc0 (sizeof (char *) * (num_networks + 1)); - while ((ap = nm_ap_list_iter_next (iter))) - { - char *ap_op = nm_dbus_get_object_path_for_network (dev, ap); - if (ap_op) - networks[i++] = ap_op; - } - num_networks = i; /* # actually added to array, since we can have NULL essid access points */ - - nm_ap_list_iter_free (iter); - } - } - } - else - speed = nm_device_802_3_ethernet_get_speed (NM_DEVICE_802_3_ETHERNET (dev)); - - if (!active_network_path) - active_network_path = g_strdup (""); - - dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &op, - DBUS_TYPE_STRING, &iface, - DBUS_TYPE_UINT32, &type, - DBUS_TYPE_STRING, &udi, - DBUS_TYPE_BOOLEAN,&active, - DBUS_TYPE_UINT32, &act_stage, - DBUS_TYPE_STRING, &ip4_address, - DBUS_TYPE_STRING, &subnetmask, - DBUS_TYPE_STRING, &broadcast, - DBUS_TYPE_STRING, &hw_addr_buf_ptr, - DBUS_TYPE_STRING, &route, - DBUS_TYPE_STRING, &primary_dns, - DBUS_TYPE_STRING, &secondary_dns, - DBUS_TYPE_INT32, &mode, - DBUS_TYPE_INT32, &strength, - DBUS_TYPE_BOOLEAN,&link_active, - DBUS_TYPE_INT32, &speed, - DBUS_TYPE_UINT32, &capabilities, - DBUS_TYPE_UINT32, &type_capabilities, - DBUS_TYPE_STRING, &active_network_path, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &networks, num_networks, - DBUS_TYPE_INVALID); - g_free (op); - g_free (active_network_path); - g_strfreev (networks); - g_free (route); - g_free (ip4_address); - g_free (broadcast); - g_free (subnetmask); - } - - return reply; -} - - /* * nm_dbus_device_methods_setup * * Register handlers for dbus methods on the org.freedesktop.NetworkManager.Devices object. * */ -NMDbusMethodList *nm_dbus_device_methods_setup (void) +NMDbusMethodList *nm_dbus_device_methods_setup (NMData *data) { - NMDbusMethodList *list = nm_dbus_method_list_new (NULL); + NMDbusMethodList * list; + + g_return_val_if_fail (data != NULL, NULL); + + list = nm_dbus_method_list_new (NM_DBUS_PATH_DEVICES, TRUE, data, NULL); + nm_dbus_method_list_set_custom_handler_func (list, nm_dbus_device_message_handler); nm_dbus_method_list_add_method (list, "getProperties", nm_dbus_device_get_properties); nm_dbus_method_list_add_method (list, "getName", nm_dbus_device_get_name); diff --git a/src/nm-dbus-device.h b/src/nm-dbus-device.h index a3d452706..1130e32ab 100644 --- a/src/nm-dbus-device.h +++ b/src/nm-dbus-device.h @@ -23,7 +23,7 @@ #define NM_DBUS_DEVICE_H -NMDbusMethodList *nm_dbus_device_methods_setup (void); +NMDbusMethodList *nm_dbus_device_methods_setup (NMData *data); #endif diff --git a/src/nm-dbus-manager.c b/src/nm-dbus-manager.c new file mode 100644 index 000000000..2493bb0e5 --- /dev/null +++ b/src/nm-dbus-manager.c @@ -0,0 +1,822 @@ +/* + * Copyright (C) 2006 Red Hat, Inc. + * + * Written by Dan Williams + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" +#include "NetworkManager.h" +#include "nm-dbus-manager.h" +#include "nm-marshal.h" + +#include +#include +#include +#include +#include "nm-utils.h" + +static gboolean nm_dbus_manager_init_bus (NMDBusManager *self); +static void nm_dbus_manager_cleanup (NMDBusManager *self); +static void free_signal_handler_data (gpointer data); +static void start_reconnection_timeout (NMDBusManager *self); + +enum { + PROP_0, + PROP_MAIN_CONTEXT, + PROP_DBUS_CONNECTION +}; + +enum { + DBUS_CONNECTION_CHANGED = 0, + NAME_OWNER_CHANGED, + NUMBER_OF_SIGNALS +}; +static guint nm_dbus_manager_signals[NUMBER_OF_SIGNALS]; + + +G_DEFINE_TYPE(NMDBusManager, nm_dbus_manager, G_TYPE_OBJECT) + +#define NM_DBUS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + NM_TYPE_DBUS_MANAGER, \ + NMDBusManagerPrivate)) + + +typedef struct SignalHandlerData { + NMDBusSignalHandlerFunc func; + char * sender; + gpointer user_data; + gboolean enabled; +} SignalHandlerData; + +typedef struct MethodHandlerData { + NMDbusMethodList * list; + NMDBusManager * self; +} MethodHandlerData; + +struct _NMDBusManagerPrivate { + DBusConnection *connection; + GMainContext * main_ctx; + GSList * msg_handlers; + GHashTable * signal_handlers; + gboolean started; + gboolean disposed; +}; + +NMDBusManager * +nm_dbus_manager_get (GMainContext *ctx) +{ + static NMDBusManager *singleton = NULL; + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + + /* Ensure that if singleton is NULL, that ctx is non-NULL */ + g_return_val_if_fail (singleton ? TRUE : (ctx ? TRUE : FALSE), NULL); + + g_static_mutex_lock (&mutex); + if (!singleton) { + singleton = NM_DBUS_MANAGER (g_object_new (NM_TYPE_DBUS_MANAGER, + "main-context", ctx, + NULL)); + if (!nm_dbus_manager_init_bus (singleton)) + start_reconnection_timeout (singleton); + } else { + g_object_ref (singleton); + } + g_static_mutex_unlock (&mutex); + + g_assert (singleton); + return singleton; +} + +static void +nm_dbus_manager_init (NMDBusManager *self) +{ + self->priv = NM_DBUS_MANAGER_GET_PRIVATE (self); + + self->priv->signal_handlers = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + free_signal_handler_data); +} + +static void +nm_dbus_manager_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + NMDBusManager *self = NM_DBUS_MANAGER (object); + + switch (prop_id) { + case PROP_MAIN_CONTEXT: + if (!self->priv->main_ctx) { + self->priv->main_ctx = g_value_get_pointer (value); + g_main_context_ref (self->priv->main_ctx); + } else { + nm_warning ("already have a valid main context."); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_dbus_manager_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDBusManager *self = NM_DBUS_MANAGER (object); + + switch (prop_id) { + case PROP_DBUS_CONNECTION: + g_value_set_pointer (value, self->priv->connection); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_dbus_manager_dispose (GObject *object) +{ + NMDBusManager *self = NM_DBUS_MANAGER (object); + + if (self->priv->disposed) + return; + self->priv->disposed = TRUE; +} + +static void +cleanup_handler_data (gpointer item, gpointer user_data) +{ + MethodHandlerData * data = (MethodHandlerData *) item; + + nm_dbus_method_list_unref (data->list); + g_slice_free (MethodHandlerData, item); +} + +static void +nm_dbus_manager_finalize (GObject *object) +{ + NMDBusManager * self = NM_DBUS_MANAGER (object); + + g_return_if_fail (self->priv != NULL); + + nm_dbus_manager_cleanup (self); + g_main_context_unref (self->priv->main_ctx); + g_slist_foreach (self->priv->msg_handlers, cleanup_handler_data, NULL); + g_slist_free (self->priv->msg_handlers); + g_hash_table_destroy (self->priv->signal_handlers); + + G_OBJECT_CLASS (nm_dbus_manager_parent_class)->finalize (object); +} + +static void +nm_dbus_manager_class_init (NMDBusManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = nm_dbus_manager_dispose; + object_class->finalize = nm_dbus_manager_finalize; + object_class->get_property = nm_dbus_manager_get_property; + object_class->set_property = nm_dbus_manager_set_property; + + g_object_class_install_property (object_class, + PROP_MAIN_CONTEXT, + g_param_spec_pointer ("main-context", + "GMainContext", + "The mainloop context.", + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY) + ); + + g_object_class_install_property (object_class, + PROP_DBUS_CONNECTION, + g_param_spec_pointer ("dbus-connection", + "DBusConnection", + "The application's dbus connection.", + G_PARAM_READABLE) + ); + + nm_dbus_manager_signals[DBUS_CONNECTION_CHANGED] = + g_signal_new ("dbus-connection-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMDBusManagerClass, dbus_connection_changed), + NULL, NULL, nm_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + klass->dbus_connection_changed = NULL; + + nm_dbus_manager_signals[NAME_OWNER_CHANGED] = + g_signal_new ("name-owner-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMDBusManagerClass, name_owner_changed), + NULL, NULL, nm_marshal_VOID__POINTER_STRING_STRING_STRING, + G_TYPE_NONE, 4, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + klass->name_owner_changed = NULL; + + g_type_class_add_private (klass, sizeof (NMDBusManagerPrivate)); +} + + +/* Only cleanup a specific dbus connection, not all our private data */ +static void +nm_dbus_manager_cleanup (NMDBusManager *self) +{ + if (self->priv->connection) { + dbus_connection_close (self->priv->connection); + self->priv->connection = NULL; + } + self->priv->started = FALSE; +} + +static gboolean +nm_dbus_manager_reconnect (gpointer user_data) +{ + NMDBusManager *self = NM_DBUS_MANAGER (user_data); + gboolean success = FALSE; + + g_assert (self != NULL); + + if (nm_dbus_manager_init_bus (self)) { + if (nm_dbus_manager_start_service (self)) { + nm_info ("reconnected to the system bus."); + g_signal_emit (G_OBJECT (self), + nm_dbus_manager_signals[DBUS_CONNECTION_CHANGED], + 0, self->priv->connection); + success = TRUE; + } + } + + if (!success) { + nm_dbus_manager_cleanup (self); + } + + /* Remove the source only if reconnection was successful */ + return success ? FALSE : TRUE; +} + +static char * +get_match_for (const char *interface, const char *sender) +{ + return g_strdup_printf ("type='signal',interface='%s',sender='%s'", + interface, sender); +} + +static gboolean +add_match_helper (NMDBusManager *self, + const char *interface, + const char *sender) +{ + gboolean success = FALSE; + DBusError error; + char * match; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (interface != NULL, FALSE); + g_return_val_if_fail (sender != NULL, FALSE); + + match = get_match_for (interface, sender); + dbus_error_init (&error); + dbus_bus_add_match (self->priv->connection, match, &error); + if (dbus_error_is_set (&error)) { + nm_warning ("failed to add signal match for '%s'.", interface); + dbus_error_free (&error); + } else { + success = TRUE; + } + g_free (match); + return success; +} + +static void +start_reconnection_timeout (NMDBusManager *self) +{ + GSource * source; + + /* Schedule timeout for reconnection attempts */ + source = g_timeout_source_new (3000); + g_source_set_callback (source, + (GSourceFunc) nm_dbus_manager_reconnect, + self, + NULL); + g_source_attach (source, self->priv->main_ctx); + g_source_unref (source); +} + +static DBusHandlerResult +nm_dbus_manager_signal_handler (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + NMDBusManager * self = NM_DBUS_MANAGER (user_data); + gboolean handled = FALSE; + + 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); + g_return_val_if_fail (self != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (0) { + const char * interface = dbus_message_get_interface (message); + const char * path = dbus_message_get_path (message); + const char * member = dbus_message_get_member (message); + const char * sig = dbus_message_get_signature (message); + nm_info ("(signal) iface: %s, path: %s, member: %s, sig: %s", + interface, path, member, sig); + } + + if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) { + gboolean success; + const char * name; + const char * old_owner; + const char * new_owner; + + success = dbus_message_get_args (message, NULL, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &old_owner, + DBUS_TYPE_STRING, &new_owner, + DBUS_TYPE_INVALID); + if (success) { + SignalHandlerData * sig_data; + gboolean old_owner_good = (old_owner && strlen (old_owner)); + gboolean new_owner_good = (new_owner && strlen (new_owner)); + + sig_data = g_hash_table_lookup (self->priv->signal_handlers, + name); + + if (!old_owner_good && new_owner_good) { + /* Add any matches registered with us */ + if (sig_data) { + sig_data->enabled = add_match_helper (self, + name, + sig_data->sender); + } + } else if (old_owner_good && !new_owner_good) { + /* Mark any matches for services that have gone away as disabled. */ + if (sig_data) + sig_data->enabled = FALSE; + } + + g_signal_emit (G_OBJECT (self), + nm_dbus_manager_signals[NAME_OWNER_CHANGED], + 0, connection, name, old_owner, new_owner); + handled = TRUE; + } + } else if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")) { + /* Clean up existing connection */ + nm_info ("disconnected by the system bus."); + nm_dbus_manager_cleanup (self); + g_signal_emit (G_OBJECT (self), + nm_dbus_manager_signals[DBUS_CONNECTION_CHANGED], + 0, NULL); + + start_reconnection_timeout (self); + + handled = TRUE; + } else { + SignalHandlerData * cb_data; + const char * interface; + + interface = dbus_message_get_interface (message); + if (interface) { + if ((cb_data = g_hash_table_lookup (self->priv->signal_handlers, + interface))) { + handled = (*cb_data->func) (connection, + message, + cb_data->user_data); + } + } + } + + return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); +} + +char * +nm_dbus_manager_get_name_owner (NMDBusManager *self, + const char *name) +{ + DBusError error; + DBusMessage * message; + DBusMessage * reply = NULL; + char * owner = NULL; + + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (name != NULL, NULL); + + message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "GetNameOwner"); + if (!message) { + nm_warning ("Not enough memory for DBus message."); + goto out; + } + + dbus_message_append_args (message, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID); + + dbus_error_init (&error); + reply = dbus_connection_send_with_reply_and_block (self->priv->connection, + message, 2000, &error); + if (dbus_error_is_set (&error)) { + nm_warning ("Did not get reply from DBus. Message: %s", error.message); + dbus_error_free (&error); + goto out; + } + + if (reply) { + const char *tmp_name = NULL; + if (dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, + &tmp_name, DBUS_TYPE_INVALID)) + owner = g_strdup (tmp_name); + } + +out: + if (reply) + dbus_message_unref (reply); + if (message) + dbus_message_unref (message); + return owner; +} + +gboolean +nm_dbus_manager_name_has_owner (NMDBusManager *self, + const char *name) +{ + DBusError error; + gboolean running = FALSE; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (name != NULL, FALSE); + + if (!self->priv->connection) { + nm_warning ("Called when manager had no dbus connection."); + return FALSE; + } + + dbus_error_init (&error); + running = dbus_bus_name_has_owner (self->priv->connection, name, &error); + if (dbus_error_is_set (&error)) { + running = FALSE; + dbus_error_free (&error); + } + return running; +} + +static DBusHandlerResult +nm_dbus_manager_message_handler (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + MethodHandlerData * data = (MethodHandlerData *) user_data; + NMDBusManager * self = data->self; + NMDbusMethodList * list = data->list; + DBusObjectPathMessageFunction custom_handler_func; + gboolean handled = FALSE; + DBusMessage * reply = NULL; + void * hdlr_user_data; + + g_return_val_if_fail (self != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + g_return_val_if_fail (list != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + hdlr_user_data = nm_dbus_method_list_get_user_data (list); + + /* Try the method lists' custom handler first */ + custom_handler_func = nm_dbus_method_list_get_custom_handler_func (list); + if (custom_handler_func) { + handled = (*custom_handler_func) (connection, message, hdlr_user_data); + } else { + /* Generic handler for lists that don't specify a custom handler */ + handled = nm_dbus_method_list_dispatch (list, connection, message, + hdlr_user_data, &reply); + if (reply) { + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + } + } + + return handled ? DBUS_HANDLER_RESULT_HANDLED + : DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static gboolean +nm_dbus_manager_init_bus (NMDBusManager *self) +{ + DBusError error; + gboolean success = FALSE; + + g_return_val_if_fail (self->priv->main_ctx, FALSE); + + if (self->priv->connection) { + nm_warning ("DBus Manager already has a valid connection."); + return FALSE; + } + + dbus_connection_set_change_sigpipe (TRUE); + + dbus_error_init (&error); + self->priv->connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if (dbus_error_is_set (&error)) { + nm_warning ("Could not get the system bus. Make sure " + "the message bus daemon is running! Message: %s", + error.message); + dbus_error_free (&error); + goto out; + } + + dbus_connection_set_exit_on_disconnect (self->priv->connection, FALSE); + dbus_connection_setup_with_g_main (self->priv->connection, + self->priv->main_ctx); + + if (!dbus_connection_add_filter (self->priv->connection, + nm_dbus_manager_signal_handler, + self, + NULL)) { + nm_warning ("Could not register a dbus message filter. The " + "NetworkManager dbus security policy may not be loaded. " + "Restart dbus?"); + goto out; + } + success = TRUE; + + /* Monitor DBus signals for service start/stop announcements */ + dbus_error_init (&error); + dbus_bus_add_match (self->priv->connection, + "type='signal'," + "interface='" DBUS_INTERFACE_DBUS "'," + "sender='" DBUS_SERVICE_DBUS "'", + &error); + if (dbus_error_is_set (&error)) { + nm_warning ("Could not monitor DBus signals. Message: %s", + error.message); + dbus_error_free (&error); + goto out; + } + success = TRUE; + +out: + if (!success) + nm_dbus_manager_cleanup (self); + return success; +} + +static gboolean +nm_dbus_manager_register_method_handlers (NMDBusManager *self) +{ + gboolean success = FALSE; + GSList * elt; + + g_return_val_if_fail (self != NULL, FALSE); + + for (elt = self->priv->msg_handlers; elt; elt = g_slist_next (elt)) { + MethodHandlerData * data = (MethodHandlerData *) elt->data; + DBusObjectPathVTable vtable = {NULL, &nm_dbus_manager_message_handler, + NULL, NULL, NULL, NULL}; + dbus_bool_t ret = FALSE; + const char * path; + + if (!nm_dbus_method_list_get_path (data->list)) { + nm_warning ("DBus message handler had no path."); + continue; + } + + /* If the method list object specifies a custom handler, use that + * instead of our default built-in one. + */ + path = nm_dbus_method_list_get_path (data->list); + if (nm_dbus_method_list_get_is_fallback (data->list)) { + ret = dbus_connection_register_fallback (self->priv->connection, + path, &vtable, data); + } else { + ret = dbus_connection_register_object_path (self->priv->connection, + path, &vtable, data); + } + + if (ret == FALSE) { + nm_warning ("Could not register DBus message handler for path %s.", + path); + goto out; + } + } + success = TRUE; + +out: + return success; +} + +static void +register_signal_handler (gpointer key, + gpointer value, + gpointer user_data) +{ + NMDBusManager *self = NM_DBUS_MANAGER (user_data); + SignalHandlerData * cb_data = (SignalHandlerData *) value; + + if (nm_dbus_manager_name_has_owner (self, key)) + add_match_helper (self, key, cb_data->sender); +} + +static gboolean +nm_dbus_manager_register_signal_handlers (NMDBusManager *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + + g_hash_table_foreach (self->priv->signal_handlers, + register_signal_handler, + self); + return TRUE; +} + +/* Register our service on the bus; shouldn't be called until + * all necessary message handlers have been registered, because + * when we register on the bus, clients may start to call. + */ +gboolean +nm_dbus_manager_start_service (NMDBusManager *self) +{ + DBusError error; + gboolean success = FALSE; + int flags, ret; + + g_return_val_if_fail (self != NULL, FALSE); + + if (self->priv->started) { + nm_warning ("Service has already started."); + return FALSE; + } + + /* Register our method handlers */ + if (!nm_dbus_manager_register_method_handlers (self)) + goto out; + + /* And our signal handlers */ + if (!nm_dbus_manager_register_signal_handlers (self)) + goto out; + + dbus_error_init (&error); +#if (DBUS_VERSION_MAJOR == 0) && (DBUS_VERSION_MINOR >= 60) + flags = DBUS_NAME_FLAG_DO_NOT_QUEUE; +#else + flags = DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT; +#endif + ret = dbus_bus_request_name (self->priv->connection, NM_DBUS_SERVICE, + flags, &error); + if (dbus_error_is_set (&error)) { + nm_warning ("Could not acquire the NetworkManager service.\n" + " Message: '%s'", error.message); + dbus_error_free (&error); + goto out; + } + + if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + nm_warning ("Could not acquire the NetworkManager service as it is " + " already taken. Return: %d", ret); + goto out; + } + + self->priv->started = TRUE; + success = TRUE; + +out: + if (!success) + nm_dbus_manager_cleanup (self); + return success; +} + +void +nm_dbus_manager_register_method_list (NMDBusManager *self, + NMDbusMethodList *list) +{ + MethodHandlerData * data; + + g_return_if_fail (self != NULL); + g_return_if_fail (list != NULL); + + if (self->priv->started) { + nm_warning ("DBus Manager object already started!"); + return; + } + + if (self->priv->connection == NULL) { + nm_warning ("DBus Manager object not yet initialized!"); + return; + } + + if (g_slist_find (self->priv->msg_handlers, list)) { + nm_warning ("Handler already registered."); + return; + } + + data = g_slice_new0 (MethodHandlerData); + if (!data) { + nm_warning ("Not enough memory to register the handler."); + return; + } + + nm_dbus_method_list_ref (list); + data->list = list; + data->self = self; + self->priv->msg_handlers = g_slist_append (self->priv->msg_handlers, data); +} + +static void +free_signal_handler_data (gpointer data) +{ + SignalHandlerData * cb_data = (SignalHandlerData *) data; + + g_return_if_fail (cb_data != NULL); + + g_free (cb_data->sender); + g_slice_free (SignalHandlerData, cb_data); +} + +void +nm_dbus_manager_register_signal_handler (NMDBusManager *self, + const char *interface, + const char *sender, + NMDBusSignalHandlerFunc callback, + gpointer user_data) +{ + SignalHandlerData * cb_data; + + g_return_if_fail (self != NULL); + g_return_if_fail (interface != NULL); + g_return_if_fail (callback != NULL); + + if (!(cb_data = g_slice_new0 (SignalHandlerData))) + return; + cb_data->sender = sender ? g_strdup (sender) : g_strdup (interface); + cb_data->func = callback; + cb_data->user_data = user_data; + g_hash_table_insert (self->priv->signal_handlers, + g_strdup (interface), + cb_data); + + if (nm_dbus_manager_name_has_owner (self, cb_data->sender)) + cb_data->enabled = add_match_helper (self, interface, cb_data->sender); +} + +void +nm_dbus_manager_remove_signal_handler (NMDBusManager *self, + const char *interface) +{ + SignalHandlerData * cb_data; + DBusError error; + char * match; + + g_return_if_fail (self != NULL); + g_return_if_fail (interface != NULL); + + cb_data = g_hash_table_lookup (self->priv->signal_handlers, interface); + if (!cb_data) + return; + + if (cb_data->enabled == FALSE) + goto out; + if (nm_dbus_manager_name_has_owner (self, cb_data->sender)) + goto out; + + match = get_match_for (interface, cb_data->sender); + dbus_error_init (&error); + dbus_bus_remove_match (self->priv->connection, match, &error); + if (dbus_error_is_set (&error)) { + nm_warning ("failed to remove signal match for '%s'.", interface); + dbus_error_free (&error); + } + g_free (match); + +out: + g_hash_table_remove (self->priv->signal_handlers, interface); +} + +DBusConnection * +nm_dbus_manager_get_dbus_connection (NMDBusManager *self) +{ + GValue value = {0,}; + + g_return_val_if_fail (self != NULL, NULL); + + g_value_init (&value, G_TYPE_POINTER); + g_object_get_property (G_OBJECT (self), "dbus-connection", &value); + return g_value_get_pointer (&value); +} diff --git a/src/nm-dbus-manager.h b/src/nm-dbus-manager.h new file mode 100644 index 000000000..a987c36e0 --- /dev/null +++ b/src/nm-dbus-manager.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2006 Red Hat, Inc. + * + * Written by Dan Williams + * + * 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 the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __NM_DBUS_MANAGER_H__ +#define __NM_DBUS_MANAGER_H__ + +#include "config.h" +#include "NetworkManagerDbusUtils.h" +#include +#include + +G_BEGIN_DECLS + +typedef gboolean (* NMDBusSignalHandlerFunc) (DBusConnection * connection, + DBusMessage * message, + gpointer user_data); + +#define NM_TYPE_DBUS_MANAGER (nm_dbus_manager_get_type ()) +#define NM_DBUS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NM_TYPE_DBUS_MANAGER, NMDBusManager)) +#define NM_DBUS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NM_TYPE_DBUS_MANAGER, NMDBusManagerClass)) +#define NM_IS_DBUS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NM_TYPE_DBUS_MANAGER)) +#define NM_IS_DBUS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NM_TYPE_DBUS_MANAGER)) +#define NM_DBUS_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NM_TYPE_DBUS_MANAGER, NMDBusManagerClass)) + +typedef struct _NMDBusManager NMDBusManager; +typedef struct _NMDBusManagerClass NMDBusManagerClass; +typedef struct _NMDBusManagerPrivate NMDBusManagerPrivate; + +struct _NMDBusManager { + GObject parent; + + /*< private >*/ + NMDBusManagerPrivate *priv; +}; + +struct _NMDBusManagerClass { + GObjectClass parent; + + /* Signals */ + void (*dbus_connection_changed) (NMDBusManager *mgr, + DBusConnection *connection); + + void (*name_owner_changed) (NMDBusManager *mgr, + DBusConnection *connection, + const char *name, + const char *old_owner, + const char *new_owner); +}; + +GType nm_dbus_manager_get_type (void); + +NMDBusManager * nm_dbus_manager_get (GMainContext *ctx); + +char * nm_dbus_manager_get_name_owner (NMDBusManager *self, + const char *name); + +gboolean nm_dbus_manager_start_service (NMDBusManager *self); + +void nm_dbus_manager_register_method_list (NMDBusManager *self, + NMDbusMethodList *list); + +gboolean nm_dbus_manager_name_has_owner (NMDBusManager *self, + const char *name); + +void nm_dbus_manager_register_signal_handler (NMDBusManager *self, + const char *interface, + const char *sender, + NMDBusSignalHandlerFunc callback, + gpointer user_data); + +void nm_dbus_manager_remove_signal_handler (NMDBusManager *self, + const char *interface); + +DBusConnection * nm_dbus_manager_get_dbus_connection (NMDBusManager *self); + +G_END_DECLS + +#endif /* __NM_DBUS_MANAGER_H__ */ diff --git a/src/nm-dbus-net.c b/src/nm-dbus-net.c index 4c01f2eca..cfcd02b49 100644 --- a/src/nm-dbus-net.c +++ b/src/nm-dbus-net.c @@ -27,6 +27,8 @@ #include "NetworkManagerUtils.h" #include "nm-dbus-net.h" #include "nm-utils.h" +#include "nm-device-private.h" + /* * nm_dbus_get_ap_from_object_path @@ -34,25 +36,27 @@ * Returns the network (ap) associated with a dbus object path * */ -static NMAccessPoint *nm_dbus_get_ap_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; - NMAccessPointList *ap_list; - NMAPListIter *iter; - char compare_path[100], *escaped_compare_path; + NMAccessPoint * ap = NULL; + NMAccessPointList * ap_list; + NMAPListIter * iter; + char compare_path[100]; + char * escaped_compare_path; g_return_val_if_fail (path != NULL, NULL); g_return_val_if_fail (dev != NULL, NULL); ap_list = nm_device_802_11_wireless_ap_list_get (NM_DEVICE_802_11_WIRELESS (dev)); if (!ap_list) - return (NULL); + return NULL; if (!(iter = nm_ap_list_iter_new (ap_list))) - return (NULL); + return NULL; - while ((ap = nm_ap_list_iter_next (iter))) - { + while ((ap = nm_ap_list_iter_next (iter))) { int len; snprintf (compare_path, 100, "%s/%s/Networks/%s", NM_DBUS_PATH_DEVICES, @@ -60,214 +64,316 @@ static NMAccessPoint *nm_dbus_get_ap_from_object_path (const char *path, NMDevic escaped_compare_path = nm_dbus_escape_object_path (compare_path); len = strlen(escaped_compare_path); - if (strncmp (path, escaped_compare_path, len) == 0) - { + if (strncmp (path, escaped_compare_path, len) == 0) { /* Differentiate between 'foo' and 'foo-a' */ - if (path[len] == '\0' || path[len] == '/') - { + if (path[len] == '\0' || path[len] == '/') { g_free (escaped_compare_path); break; } } g_free (escaped_compare_path); } - nm_ap_list_iter_free (iter); - return (ap); + + return ap; } -static DBusMessage *nm_dbus_net_validate (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_net_get_name (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { + NMDbusCBData * data = (NMDbusCBData *) user_data; DBusMessage *reply = NULL; - NMAccessPoint *ap; - const char *path; + const char *essid; - g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->ap != NULL, NULL); - path = dbus_message_get_path (message); - if ((ap = nm_dbus_get_ap_from_object_path (path, data->dev))) - data->ap = ap; - else - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NetworkNotFound", - "The requested network does not exist for this device."); + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; } + essid = nm_ap_get_essid (data->ap); + dbus_message_append_args (reply, DBUS_TYPE_STRING, &essid, DBUS_TYPE_INVALID); + return reply; } -static DBusMessage *nm_dbus_net_get_name (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_net_get_address (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { - DBusMessage *reply = NULL; + NMDbusCBData * data = (NMDbusCBData *) user_data; + DBusMessage * reply = NULL; + char buf[20]; - g_return_val_if_fail (data && data->data && data->dev && data->ap && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->ap != NULL, NULL); - if ((reply = dbus_message_new_method_return (message))) - { - const char *essid = nm_ap_get_essid (data->ap); - dbus_message_append_args (reply, DBUS_TYPE_STRING, &essid, DBUS_TYPE_INVALID); + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; } + memset (&buf[0], 0, 20); + iw_ether_ntop((const struct ether_addr *) (nm_ap_get_address (data->ap)), &buf[0]); + dbus_message_append_args (reply, DBUS_TYPE_STRING, &buf, DBUS_TYPE_INVALID); + return reply; } -static DBusMessage *nm_dbus_net_get_address (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_net_get_strength (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { - DBusMessage *reply = NULL; + NMDbusCBData * data = (NMDbusCBData *) user_data; + DBusMessage * reply = NULL; + NMAccessPoint * tmp_ap = NULL; + NMAccessPointList * ap_list; + NMAPListIter * iter; + int best_strength; - g_return_val_if_fail (data && data->data && data->dev && data->ap && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->ap != NULL, NULL); - if ((reply = dbus_message_new_method_return (message))) - { - char buf[20]; - - memset (&buf[0], 0, 20); - iw_ether_ntop((const struct ether_addr *) (nm_ap_get_address (data->ap)), &buf[0]); - dbus_message_append_args (reply, DBUS_TYPE_STRING, &buf, DBUS_TYPE_INVALID); + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; } - return reply; -} - -static DBusMessage *nm_dbus_net_get_strength (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) -{ - DBusMessage *reply = NULL; - - g_return_val_if_fail (data && data->data && data->dev && data->ap && connection && message, NULL); - /* We iterate over the device list and return the best strength for all * APs with the given ESSID. */ - if ((reply = dbus_message_new_method_return (message))) - { - NMAccessPoint *tmp_ap = NULL; - NMAccessPointList *ap_list; - NMAPListIter *iter; - int best_strength = nm_ap_get_strength (data->ap); + best_strength = nm_ap_get_strength (data->ap); + if (!(ap_list = nm_device_802_11_wireless_ap_list_get (NM_DEVICE_802_11_WIRELESS (data->dev)))) + goto append; - if (!(ap_list = nm_device_802_11_wireless_ap_list_get (NM_DEVICE_802_11_WIRELESS (data->dev)))) - goto append; + if (!(iter = nm_ap_list_iter_new (ap_list))) + goto append; - if (!(iter = nm_ap_list_iter_new (ap_list))) - goto append; + /* Find best strength # among all APs that share this essid */ + while ((tmp_ap = nm_ap_list_iter_next (iter))) { + if (nm_null_safe_strcmp (nm_ap_get_essid (data->ap), nm_ap_get_essid (tmp_ap)) == 0) + if (nm_ap_get_strength (tmp_ap) > best_strength) + best_strength = nm_ap_get_strength (tmp_ap); + } + nm_ap_list_iter_free (iter); - /* Find best strength # among all APs that share this essid */ - while ((tmp_ap = nm_ap_list_iter_next (iter))) - { - if (nm_null_safe_strcmp (nm_ap_get_essid (data->ap), nm_ap_get_essid (tmp_ap)) == 0) - if (nm_ap_get_strength (tmp_ap) > best_strength) - best_strength = nm_ap_get_strength (tmp_ap); - } - nm_ap_list_iter_free (iter); +append: + dbus_message_append_args (reply, DBUS_TYPE_INT32, &best_strength, DBUS_TYPE_INVALID); - append: - dbus_message_append_args (reply, DBUS_TYPE_INT32, &best_strength, DBUS_TYPE_INVALID); + return reply; +} + +static DBusMessage * +nm_dbus_net_get_frequency (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) +{ + NMDbusCBData * data = (NMDbusCBData *) user_data; + DBusMessage * reply = NULL; + double freq; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->ap != NULL, NULL); + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; } - return reply; -} - -static DBusMessage *nm_dbus_net_get_frequency (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) -{ - DBusMessage *reply = NULL; - - g_return_val_if_fail (data && data->data && data->dev && data->ap && connection && message, NULL); - - if ((reply = dbus_message_new_method_return (message))) { - double freq; - freq = nm_ap_get_freq (data->ap); - dbus_message_append_args (reply, DBUS_TYPE_DOUBLE, &freq, DBUS_TYPE_INVALID); - } + freq = nm_ap_get_freq (data->ap); + dbus_message_append_args (reply, DBUS_TYPE_DOUBLE, &freq, DBUS_TYPE_INVALID); return reply; } -static DBusMessage *nm_dbus_net_get_rate (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_net_get_rate (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { - DBusMessage *reply = NULL; + NMDbusCBData * data = (NMDbusCBData *) user_data; + DBusMessage * reply = NULL; + dbus_int32_t rate; - g_return_val_if_fail (data && data->data && data->dev && data->ap && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->ap != NULL, NULL); - if ((reply = dbus_message_new_method_return (message))) { - dbus_int32_t rate; - rate = nm_ap_get_rate (data->ap); - dbus_message_append_args (reply, DBUS_TYPE_INT32, &rate, DBUS_TYPE_INVALID); - } - - return reply; -} - -static DBusMessage *nm_dbus_net_get_encrypted (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) -{ - DBusMessage *reply = NULL; - - g_return_val_if_fail (data && data->data && data->dev && data->ap && connection && message, NULL); - - if ((reply = dbus_message_new_method_return (message))) { - dbus_bool_t is_encrypted; - is_encrypted = nm_ap_get_encrypted (data->ap); - dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &is_encrypted, DBUS_TYPE_INVALID); - } - - return reply; -} - -static DBusMessage *nm_dbus_net_get_mode (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) -{ - DBusMessage *reply = NULL; - - g_return_val_if_fail (data && data->data && data->dev && data->ap && connection && message, NULL); - - if ((reply = dbus_message_new_method_return (message))) - { - dbus_int32_t mode = (dbus_int32_t) nm_ap_get_mode (data->ap); - dbus_message_append_args (reply, DBUS_TYPE_INT32, &mode, DBUS_TYPE_INVALID); + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; } + rate = nm_ap_get_rate (data->ap); + dbus_message_append_args (reply, DBUS_TYPE_INT32, &rate, DBUS_TYPE_INVALID); + return reply; } - -static DBusMessage *nm_dbus_net_get_properties (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_net_get_encrypted (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { - DBusMessage *reply = NULL; + NMDbusCBData * data = (NMDbusCBData *) user_data; + DBusMessage * reply = NULL; + dbus_bool_t is_encrypted; - g_return_val_if_fail (data && data->data && data->dev && data->ap && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->ap != NULL, NULL); - if ((reply = dbus_message_new_method_return (message))) - { - char * op = nm_dbus_get_object_path_for_network (data->dev, data->ap); - const char * essid = nm_ap_get_essid (data->ap); - char hw_addr_buf[20]; - char * hw_addr_buf_ptr = &hw_addr_buf[0]; - dbus_int32_t strength = nm_ap_get_strength (data->ap); - double freq = nm_ap_get_freq (data->ap); - dbus_int32_t rate = nm_ap_get_rate (data->ap); - dbus_int32_t mode = (dbus_int32_t) nm_ap_get_mode (data->ap); - dbus_int32_t capabilities = (dbus_int32_t) nm_ap_get_capabilities (data->ap); - dbus_bool_t broadcast = (dbus_bool_t) nm_ap_get_broadcast (data->ap); - - memset (&hw_addr_buf[0], 0, 20); - if (nm_ap_get_address (data->ap)) - iw_ether_ntop((const struct ether_addr *) (nm_ap_get_address (data->ap)), &hw_addr_buf[0]); - - dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &op, - DBUS_TYPE_STRING, &essid, - DBUS_TYPE_STRING, &hw_addr_buf_ptr, - DBUS_TYPE_INT32, &strength, - DBUS_TYPE_DOUBLE, &freq, - DBUS_TYPE_INT32, &rate, - DBUS_TYPE_INT32, &mode, - DBUS_TYPE_INT32, &capabilities, - DBUS_TYPE_BOOLEAN, &broadcast, - DBUS_TYPE_INVALID); - g_free (op); + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; } + is_encrypted = nm_ap_get_encrypted (data->ap); + dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &is_encrypted, DBUS_TYPE_INVALID); + return reply; } +static DBusMessage * +nm_dbus_net_get_mode (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) +{ + NMDbusCBData * data = (NMDbusCBData *) user_data; + DBusMessage * reply = NULL; + dbus_int32_t mode; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->ap != NULL, NULL); + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; + } + + mode = (dbus_int32_t) nm_ap_get_mode (data->ap); + dbus_message_append_args (reply, DBUS_TYPE_INT32, &mode, DBUS_TYPE_INVALID); + + return reply; +} + + +static DBusMessage * +nm_dbus_net_get_properties (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) +{ + NMDbusCBData * data = (NMDbusCBData *) user_data; + DBusMessage * reply = NULL; + char * op; + const char * essid; + char hw_addr_buf[20]; + char * hw_addr_buf_ptr = &hw_addr_buf[0]; + dbus_int32_t strength; + double freq; + dbus_int32_t rate; + dbus_int32_t mode; + dbus_int32_t capabilities; + dbus_bool_t broadcast; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->ap != NULL, NULL); + g_return_val_if_fail (data->dev != NULL, NULL); + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; + } + + op = nm_dbus_get_object_path_for_network (data->dev, data->ap); + essid = nm_ap_get_essid (data->ap); + strength = nm_ap_get_strength (data->ap); + freq = nm_ap_get_freq (data->ap); + rate = nm_ap_get_rate (data->ap); + mode = (dbus_int32_t) nm_ap_get_mode (data->ap); + capabilities = (dbus_int32_t) nm_ap_get_capabilities (data->ap); + broadcast = (dbus_bool_t) nm_ap_get_broadcast (data->ap); + + memset (&hw_addr_buf[0], 0, 20); + if (nm_ap_get_address (data->ap)) + iw_ether_ntop((const struct ether_addr *) (nm_ap_get_address (data->ap)), &hw_addr_buf[0]); + + dbus_message_append_args (reply, + DBUS_TYPE_OBJECT_PATH, &op, + DBUS_TYPE_STRING, &essid, + DBUS_TYPE_STRING, &hw_addr_buf_ptr, + DBUS_TYPE_INT32, &strength, + DBUS_TYPE_DOUBLE, &freq, + DBUS_TYPE_INT32, &rate, + DBUS_TYPE_INT32, &mode, + DBUS_TYPE_INT32, &capabilities, + DBUS_TYPE_BOOLEAN, &broadcast, + DBUS_TYPE_INVALID); + g_free (op); + + return reply; +} + + +gboolean +nm_dbus_net_methods_dispatch (NMDbusMethodList *list, + DBusConnection *connection, + DBusMessage *message, + gpointer user_data, + DBusMessage **reply) +{ + NMDbusCBData * cb_data = (NMDbusCBData *) user_data; + const char * path; + NMAccessPoint * ap; + gboolean handled = FALSE; + + g_return_val_if_fail (list != NULL, FALSE); + g_return_val_if_fail (connection != NULL, FALSE); + g_return_val_if_fail (message != NULL, FALSE); + g_return_val_if_fail (cb_data != NULL, FALSE); + g_return_val_if_fail (cb_data->dev != NULL, FALSE); + + /* Figure out which network the request is for */ + path = dbus_message_get_path (message); + if ((ap = nm_dbus_get_ap_from_object_path (path, cb_data->dev))) { + cb_data->ap = ap; + handled = nm_dbus_method_list_dispatch (list, + connection, + message, + cb_data, + reply); + } else { + *reply = nm_dbus_create_error_message (message, + NM_DBUS_INTERFACE, + "NetworkNotFound", + "The requested network does not " + "exist for this device."); + handled = TRUE; + } + + return handled; +} /* * nm_dbus_net_methods_setup @@ -276,18 +382,22 @@ static DBusMessage *nm_dbus_net_get_properties (DBusConnection *connection, DBus * org.freedesktop.NetworkManager.Devices..Networks object. * */ -NMDbusMethodList *nm_dbus_net_methods_setup (void) +NMDbusMethodList *nm_dbus_net_methods_setup (NMData *data) { - NMDbusMethodList *list = nm_dbus_method_list_new (nm_dbus_net_validate); + NMDbusMethodList * list; - nm_dbus_method_list_add_method (list, "getProperties", nm_dbus_net_get_properties); - nm_dbus_method_list_add_method (list, "getName", nm_dbus_net_get_name); + g_return_val_if_fail (data != NULL, NULL); + + list = nm_dbus_method_list_new ("", FALSE, data, NULL); + + nm_dbus_method_list_add_method (list, "getProperties", nm_dbus_net_get_properties); + nm_dbus_method_list_add_method (list, "getName", nm_dbus_net_get_name); nm_dbus_method_list_add_method (list, "getAddress", nm_dbus_net_get_address); - nm_dbus_method_list_add_method (list, "getStrength", nm_dbus_net_get_strength); - nm_dbus_method_list_add_method (list, "getFrequency", nm_dbus_net_get_frequency); - nm_dbus_method_list_add_method (list, "getRate", nm_dbus_net_get_rate); - nm_dbus_method_list_add_method (list, "getEncrypted", nm_dbus_net_get_encrypted); - nm_dbus_method_list_add_method (list, "getMode", nm_dbus_net_get_mode); + nm_dbus_method_list_add_method (list, "getStrength", nm_dbus_net_get_strength); + nm_dbus_method_list_add_method (list, "getFrequency", nm_dbus_net_get_frequency); + nm_dbus_method_list_add_method (list, "getRate", nm_dbus_net_get_rate); + nm_dbus_method_list_add_method (list, "getEncrypted", nm_dbus_net_get_encrypted); + nm_dbus_method_list_add_method (list, "getMode", nm_dbus_net_get_mode); return (list); } diff --git a/src/nm-dbus-net.h b/src/nm-dbus-net.h index e40ebc1e6..3e2925a1c 100644 --- a/src/nm-dbus-net.h +++ b/src/nm-dbus-net.h @@ -23,7 +23,15 @@ #define NM_DBUS_NET_H #include "NetworkManagerDbusUtils.h" +#include "NetworkManagerMain.h" -NMDbusMethodList *nm_dbus_net_methods_setup (void); + +NMDbusMethodList *nm_dbus_net_methods_setup (NMData *data); + +gboolean nm_dbus_net_methods_dispatch (NMDbusMethodList *list, + DBusConnection *connection, + DBusMessage *message, + gpointer uesr_data, + DBusMessage **reply); #endif diff --git a/src/nm-dbus-nm.c b/src/nm-dbus-nm.c index 64b33b46a..8c8a78cc5 100644 --- a/src/nm-dbus-nm.c +++ b/src/nm-dbus-nm.c @@ -46,168 +46,201 @@ * devices in the device list. * */ -static DBusMessage *nm_dbus_nm_get_devices (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_nm_get_devices (DBusConnection *connection, + DBusMessage *message, + void * user_data) { - DBusMessage *reply = NULL; - DBusMessageIter iter; - DBusMessageIter iter_array; + NMData * data = (NMData *) user_data; + DBusMessage * reply = NULL; + DBusMessageIter iter; + DBusMessageIter iter_array; g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (data->data != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (message != NULL, NULL); /* Check for no devices */ - if (!data->data->dev_list) - return (nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NoDevices", - "There are no available network devices.")); + if (!data->dev_list) { + return nm_dbus_create_error_message (message, + NM_DBUS_INTERFACE, + "NoDevices", + "There are no available network devices."); + } - if (!(reply = dbus_message_new_method_return (message))) + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); return NULL; + } dbus_message_iter_init_append (reply, &iter); - if (nm_try_acquire_mutex (data->data->dev_list_mutex, __FUNCTION__)) - { + if (nm_try_acquire_mutex (data->dev_list_mutex, __FUNCTION__)) { GSList *elt; - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter_array); - for (elt = data->data->dev_list; elt; elt = g_slist_next (elt)) - { - NMDevice *dev = (NMDevice *)(elt->data); + dbus_message_iter_open_container (&iter, + DBUS_TYPE_ARRAY, + DBUS_TYPE_OBJECT_PATH_AS_STRING, + &iter_array); - if (dev) - { - char *op = nm_dbus_get_object_path_for_device (dev); + for (elt = data->dev_list; elt; elt = g_slist_next (elt)) { + NMDevice * dev = (NMDevice *) elt->data; + char * op = nm_dbus_get_object_path_for_device (dev); - dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_OBJECT_PATH, &op); - g_free (op); - } - } - dbus_message_iter_close_container (&iter, &iter_array); - nm_unlock_mutex (data->data->dev_list_mutex, __FUNCTION__); - } - else - { - dbus_message_unref (reply); - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "Retry", - "NetworkManager could not lock device list, try again."); - } - - return (reply); -} - - -static DBusMessage *nm_dbus_nm_get_dialup (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) -{ - DBusMessage *reply = NULL; - DBusMessageIter iter; - - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (data->data != NULL, NULL); - g_return_val_if_fail (connection != NULL, NULL); - g_return_val_if_fail (message != NULL, NULL); - - /* Check for no dialup devices */ - if (!data->data->dialup_list) - return (nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NoDialup", - "There are no available dialup devices.")); - - reply = dbus_message_new_method_return (message); - if (!reply) - return NULL; - - dbus_message_iter_init_append (reply, &iter); - if (nm_try_acquire_mutex (data->data->dialup_list_mutex, __FUNCTION__)) - { - DBusMessageIter iter_array; - GSList *elt; - - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &iter_array); - - for (elt = data->data->dialup_list; elt; elt = g_slist_next (elt)) - { - NMDialUpConfig *config = (NMDialUpConfig *) elt->data; - dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &config->name); + dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_OBJECT_PATH, &op); + g_free (op); } dbus_message_iter_close_container (&iter, &iter_array); - nm_unlock_mutex (data->data->dialup_list_mutex, __FUNCTION__); - } - else - { + + nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__); + } else { dbus_message_unref (reply); - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "Retry", - "NetworkManager could not lock dialup list, try again."); + reply = nm_dbus_create_error_message (message, + NM_DBUS_INTERFACE, + "Retry", + "NetworkManager could not lock " + " device list, try again."); } return reply; } -static DBusMessage *nm_dbus_nm_activate_dialup (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_nm_get_dialup (DBusConnection *connection, + DBusMessage *message, + void * user_data) { - DBusMessage *reply = NULL; - NMData *nm_data = (NMData *) data->data; - const char *dialup; + NMData * data = (NMData *) user_data; + DBusMessage * reply = NULL; + DBusMessageIter iter; g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (data->data != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (message != NULL, NULL); - reply = dbus_message_new_method_return (message); - if (!reply) + /* Check for no dialup devices */ + if (!data->dialup_list) { + return nm_dbus_create_error_message (message, + NM_DBUS_INTERFACE, + "NoDialup", + "There are no available dialup devices."); + } + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); return NULL; + } + + dbus_message_iter_init_append (reply, &iter); + if (nm_try_acquire_mutex (data->dialup_list_mutex, __FUNCTION__)) { + DBusMessageIter iter_array; + GSList *elt; + + dbus_message_iter_open_container (&iter, + DBUS_TYPE_ARRAY, + DBUS_TYPE_STRING_AS_STRING, + &iter_array); + + for (elt = data->dialup_list; elt; elt = g_slist_next (elt)) { + NMDialUpConfig *config = (NMDialUpConfig *) elt->data; + dbus_message_iter_append_basic (&iter_array, + DBUS_TYPE_STRING, &config->name); + } + + dbus_message_iter_close_container (&iter, &iter_array); + nm_unlock_mutex (data->dialup_list_mutex, __FUNCTION__); + } else { + dbus_message_unref (reply); + reply = nm_dbus_create_error_message (message, + NM_DBUS_INTERFACE, + "Retry", + "NetworkManager could not lock " + " dialup list, try again."); + } + + return reply; +} + + +static DBusMessage * +nm_dbus_nm_activate_dialup (DBusConnection *connection, + DBusMessage *message, + void * user_data) +{ + NMData *data = (NMData *) user_data; + DBusMessage *reply = NULL; + const char *dialup; + + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + return NULL; + } if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &dialup, DBUS_TYPE_INVALID)) { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "InvalidArguments", - "NetworkManager::activateDialup called with invalid arguments."); + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE); goto out; } - nm_lock_mutex (nm_data->dialup_list_mutex, __FUNCTION__); - if (!nm_system_activate_dialup (nm_data->dialup_list, dialup)) - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "ActivationFailed", - "Failed to activate the dialup device."); - else - nm_data->modem_active = TRUE; - nm_unlock_mutex (nm_data->dialup_list_mutex, __FUNCTION__); + nm_lock_mutex (data->dialup_list_mutex, __FUNCTION__); + if (!nm_system_activate_dialup (data->dialup_list, dialup)) { + reply = nm_dbus_create_error_message (message, + NM_DBUS_INTERFACE, + "ActivationFailed", + "Failed to activate the dialup " + "device."); + } else { + data->modem_active = TRUE; + } + nm_unlock_mutex (data->dialup_list_mutex, __FUNCTION__); out: return reply; } -static DBusMessage *nm_dbus_nm_deactivate_dialup (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_nm_deactivate_dialup (DBusConnection *connection, + DBusMessage *message, + void * user_data) { + NMData *data = (NMData *) user_data; DBusMessage *reply = NULL; - NMData *nm_data = (NMData *) data->data; const char *dialup; g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (data->data != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (message != NULL, NULL); - reply = dbus_message_new_method_return (message); - if (!reply) + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); return NULL; + } - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &dialup, DBUS_TYPE_INVALID)) - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "InvalidArguments", - "NetworkManager::deactivateDialup called with invalid arguments."); + if (!dbus_message_get_args (message, + NULL, + DBUS_TYPE_STRING, &dialup, + DBUS_TYPE_INVALID)) { + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE); goto out; } - nm_lock_mutex (nm_data->dialup_list_mutex, __FUNCTION__); - if (!nm_system_deactivate_dialup (nm_data->dialup_list, dialup)) - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeactivationFailed", - "Failed to deactivate the dialup device."); - else - nm_data->modem_active = FALSE; - nm_unlock_mutex (nm_data->dialup_list_mutex, __FUNCTION__); + nm_lock_mutex (data->dialup_list_mutex, __FUNCTION__); + if (!nm_system_deactivate_dialup (data->dialup_list, dialup)) { + reply = nm_dbus_create_error_message (message, + NM_DBUS_INTERFACE, + "DeactivationFailed", + "Failed to deactivate the dialup " + " device."); + } else { + data->modem_active = FALSE; + } + nm_unlock_mutex (data->dialup_list_mutex, __FUNCTION__); out: return reply; @@ -221,10 +254,12 @@ out: * device. * */ -static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_nm_set_active_device (DBusConnection *connection, + DBusMessage *message, + void * user_data) { - const char * INVALID_ARGS_ERROR = "InvalidArguments"; - const char * INVALID_ARGS_MESSAGE = "NetworkManager::setActiveDevice called with invalid arguments."; + NMData * data = (NMData *) user_data; NMDevice * dev = NULL; DBusMessage * reply = NULL; char * dev_path; @@ -234,51 +269,52 @@ static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DB g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (message != NULL, NULL); g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (data->data != NULL, NULL); dbus_message_iter_init (message, &iter); - if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_OBJECT_PATH) - { + if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_OBJECT_PATH) { nm_warning ("%s:%d (%s): Invalid arguments (first arg type was not OBJECT_PATH).", __FILE__, __LINE__, __func__); goto out; } dbus_message_iter_get_basic (&iter, &dev_path); - dev = nm_dbus_get_device_from_escaped_object_path (data->data, dev_path); + dev = nm_dbus_get_device_from_escaped_object_path (data, dev_path); /* Ensure the device exists in our list and is supported */ - if (!dev || !(nm_device_get_capabilities (dev) & NM_DEVICE_CAP_NM_SUPPORTED)) - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound", - "The requested network device does not exist."); - nm_warning ("%s:%d (%s): Invalid device (device not found).", __FILE__, __LINE__, __func__); + if (!dev || !(nm_device_get_capabilities (dev) & NM_DEVICE_CAP_NM_SUPPORTED)) { + reply = nm_dbus_create_error_message (message, + NM_DBUS_INTERFACE, + "DeviceNotFound", + "The requested network device " + "does not exist."); + nm_warning ("%s:%d (%s): Invalid device (device not found).", __FILE__, + __LINE__, __func__); goto out; } - if (nm_device_is_802_11_wireless (dev)) - { + if (nm_device_is_802_11_wireless (dev)) { NMAPSecurity * security = NULL; char * essid = NULL; gboolean fallback = FALSE; - if (!dbus_message_iter_next (&iter) || (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)) - { - nm_warning ("%s:%d (%s): Invalid argument type (essid).", __FILE__, __LINE__, __func__); + if ( !dbus_message_iter_next (&iter) + || (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)) { + nm_warning ("%s:%d (%s): Invalid argument type (essid).", __FILE__, + __LINE__, __func__); goto out; } /* grab ssid and ensure validity */ dbus_message_iter_get_basic (&iter, &essid); - if (!essid || (strlen (essid) <= 0)) - { - nm_warning ("%s:%d (%s): Invalid argument (essid).", __FILE__, __LINE__, __func__); + if (!essid || (strlen (essid) <= 0)) { + nm_warning ("%s:%d (%s): Invalid argument (essid).", + __FILE__, __LINE__, __func__); goto out; } - if (!dbus_message_iter_next (&iter) || (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BOOLEAN)) - { + if ( !dbus_message_iter_next (&iter) + || (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BOOLEAN)) { nm_warning ("Invalid argument type (fallback"); goto out; } @@ -289,13 +325,12 @@ static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DB /* If there's security information, we use that. If not, we * make some up from the scan list. */ - if (dbus_message_iter_next (&iter)) - { - if (!(security = nm_ap_security_new_deserialize (&iter))) - { + if (dbus_message_iter_next (&iter)) { + if (!(security = nm_ap_security_new_deserialize (&iter))) { /* There was security info, but it was invalid */ - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, INVALID_ARGS_ERROR, INVALID_ARGS_MESSAGE); - nm_warning ("%s:%d (%s): Invalid argument (wireless security info).", __FILE__, __LINE__, __func__); + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE); + nm_warning ("%s:%d (%s): Invalid argument (wireless security " + "info).", __FILE__, __LINE__, __func__); goto out; } } @@ -307,22 +342,19 @@ static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DB g_object_unref (G_OBJECT (security)); nm_info ("User Switch: %s / %s", dev_path, essid); - } - else if (nm_device_is_802_3_ethernet (dev)) - { + } else if (nm_device_is_802_3_ethernet (dev)) { nm_info ("User Switch: %s", dev_path); } nm_device_deactivate (dev); - nm_schedule_state_change_signal_broadcast (data->data); - nm_policy_schedule_device_activation (nm_act_request_new (data->data, dev, ap, TRUE)); + nm_schedule_state_change_signal_broadcast (data); + nm_policy_schedule_device_activation (nm_act_request_new (data, dev, ap, TRUE)); out: + if (dev) + g_object_unref (G_OBJECT (dev)); if (!reply) - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, - INVALID_ARGS_ERROR, INVALID_ARGS_MESSAGE); - } + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE); return reply; } @@ -333,10 +365,12 @@ out: * Create a new wireless network and * */ -static DBusMessage *nm_dbus_nm_create_wireless_network (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_nm_create_wireless_network (DBusConnection *connection, + DBusMessage *message, + void * user_data) { - const char * INVALID_ARGS_ERROR = "InvalidArguments"; - const char * INVALID_ARGS_MESSAGE = "NetworkManager::createWirelessNetwork called with invalid arguments."; + NMData * data = (NMData *) user_data; NMDevice * dev = NULL; DBusMessage * reply = NULL; char * dev_path = NULL; @@ -344,50 +378,48 @@ static DBusMessage *nm_dbus_nm_create_wireless_network (DBusConnection *connecti NMAPSecurity * security = NULL; char * essid = NULL; DBusMessageIter iter; + NMActRequest * req; g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (message != NULL, NULL); g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (data->data != NULL, NULL); dbus_message_iter_init (message, &iter); - if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_OBJECT_PATH) - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, INVALID_ARGS_ERROR, INVALID_ARGS_MESSAGE); + if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_OBJECT_PATH) { + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE); goto out; } dbus_message_iter_get_basic (&iter, &dev_path); - dev = nm_dbus_get_device_from_escaped_object_path (data->data, dev_path); + dev = nm_dbus_get_device_from_escaped_object_path (data, dev_path); /* Ensure the device exists in our list and is supported */ - if (!dev || !(nm_device_get_capabilities (dev) & NM_DEVICE_CAP_NM_SUPPORTED)) - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound", - "The requested network device does not exist."); + if (!dev || !(nm_device_get_capabilities (dev) & NM_DEVICE_CAP_NM_SUPPORTED)) { + reply = nm_dbus_create_error_message (message, + NM_DBUS_INTERFACE, + "DeviceNotFound", + "The requested network device " + "does not exist."); goto out; } - if ( !nm_device_is_802_11_wireless (dev) + if ( !nm_device_is_802_11_wireless (dev) || !dbus_message_iter_next (&iter) - || (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)) - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, INVALID_ARGS_ERROR, INVALID_ARGS_MESSAGE); + || (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)) { + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE); goto out; } /* grab ssid and ensure validity */ dbus_message_iter_get_basic (&iter, &essid); - if (!essid || (strlen (essid) <= 0) || !dbus_message_iter_next (&iter)) - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, INVALID_ARGS_ERROR, INVALID_ARGS_MESSAGE); + if (!essid || (strlen (essid) <= 0) || !dbus_message_iter_next (&iter)) { + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE); goto out; } - if (!(security = nm_ap_security_new_deserialize (&iter))) - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, INVALID_ARGS_ERROR, INVALID_ARGS_MESSAGE); + if (!(security = nm_ap_security_new_deserialize (&iter))) { + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE); goto out; } @@ -400,216 +432,282 @@ static DBusMessage *nm_dbus_nm_create_wireless_network (DBusConnection *connecti g_object_unref (G_OBJECT (security)); nm_ap_set_user_created (new_ap, TRUE); - nm_policy_schedule_device_activation (nm_act_request_new (data->data, dev, new_ap, TRUE)); + req = nm_act_request_new (data, dev, new_ap, TRUE); + nm_policy_schedule_device_activation (req); + +out: + if (dev) + g_object_unref (G_OBJECT (dev)); + return reply; +} + + +static DBusMessage * +nm_dbus_nm_create_test_device (DBusConnection *connection, + DBusMessage *message, + void * user_data) +{ + NMData * data = (NMData *) user_data; + NMDeviceType type; + DBusMessage *reply = NULL; + static int test_dev_num = 0; + NMDevice * dev; + char * iface; + char * udi; + char * dev_path; + char * escaped_dev_path; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + + if (!dbus_message_get_args (message, + NULL, + DBUS_TYPE_INT32, &type, + DBUS_TYPE_INVALID)) { + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE); + goto out; + } + + if ( (type != DEVICE_TYPE_802_3_ETHERNET) + && (type == DEVICE_TYPE_802_11_WIRELESS)) { + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE); + goto out; + } + + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + goto out; + } + + iface = g_strdup_printf ("test%d", test_dev_num); + udi = g_strdup_printf ("/test-devices/%s", iface); + + dev = nm_create_device_and_add_to_list (data, udi, iface, TRUE, type); + g_free (iface); + g_free (udi); + + test_dev_num++; + + dev_path = g_strdup_printf ("%s/%s", NM_DBUS_PATH_DEVICES, nm_device_get_iface (dev)); + escaped_dev_path = nm_dbus_escape_object_path (dev_path); + g_free (dev_path); + + dbus_message_append_args (reply, DBUS_TYPE_STRING, &escaped_dev_path, DBUS_TYPE_INVALID); + g_free (escaped_dev_path); out: return reply; } - -static DBusMessage *nm_dbus_nm_create_test_device (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_nm_remove_test_device (DBusConnection *connection, + DBusMessage *message, + void * user_data) { - DBusError err; - NMDeviceType type; + NMData * data = (NMData *) user_data; DBusMessage *reply = NULL; - static int test_dev_num = 0; + char * dev_path; + NMDevice * dev = NULL; - g_return_val_if_fail (data && data->data && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); - dbus_error_init (&err); - if ( dbus_message_get_args (message, &err, DBUS_TYPE_INT32, &type, DBUS_TYPE_INVALID) - && ((type == DEVICE_TYPE_802_3_ETHERNET) || (type == DEVICE_TYPE_802_11_WIRELESS))) - { - char *interface = g_strdup_printf ("test%d", test_dev_num); - char *udi = g_strdup_printf ("/test-devices/%s", interface); - NMDevice *dev = NULL; - - dev = nm_create_device_and_add_to_list (data->data, udi, interface, TRUE, type); - test_dev_num++; - if ((reply = dbus_message_new_method_return (message))) - { - char *dev_path, *escaped_dev_path; - dev_path = g_strdup_printf ("%s/%s", NM_DBUS_PATH_DEVICES, nm_device_get_iface (dev)); - escaped_dev_path = nm_dbus_escape_object_path (dev_path); - dbus_message_append_args (reply, DBUS_TYPE_STRING, &dev_path, DBUS_TYPE_INVALID); - g_free (dev_path); - g_free (escaped_dev_path); - } - g_free (interface); - g_free (udi); + if (!dbus_message_get_args (message, + NULL, + DBUS_TYPE_STRING, &dev_path, + DBUS_TYPE_INVALID)) { + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE); + goto out; } - else - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "BadType", "The test device type was invalid."); - return (reply); + if (!(dev = nm_dbus_get_device_from_escaped_object_path (data, dev_path))) { + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE); + goto out; + } + + if (!nm_device_is_test_device (dev)) { + reply = nm_dbus_create_error_message (message, + NM_DBUS_INTERFACE, + "NotTestDevice", + "Only test devices can be removed" + " via the DBus interface."); + goto out; + } + + nm_remove_device (data, dev); + +out: + if (dev) + g_object_unref (G_OBJECT (dev)); + return reply; } -static DBusMessage *nm_dbus_nm_remove_test_device (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_nm_set_wireless_enabled (DBusConnection *connection, + DBusMessage *message, + void * user_data) { - DBusMessage *reply = NULL; - DBusError err; - char *dev_path; + NMData * data = (NMData *) user_data; + gboolean enabled = FALSE; + DBusMessage * reply = NULL; - g_return_val_if_fail (data && data->data && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); - dbus_error_init (&err); - if (dbus_message_get_args (message, &err, DBUS_TYPE_STRING, &dev_path, DBUS_TYPE_INVALID)) - { - NMDevice *dev; - - if ((dev = nm_dbus_get_device_from_escaped_object_path (data->data, dev_path))) - { - if (nm_device_is_test_device (dev)) - nm_remove_device (data->data, dev); - else - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NotTestDevice", - "Only test devices can be removed via dbus calls."); - } - else - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound", - "The requested network device does not exist."); - } - } - else - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceBad", - "The device ID was bad."); + if (!dbus_message_get_args (message, + NULL, + DBUS_TYPE_BOOLEAN, &enabled, + DBUS_TYPE_INVALID)) { + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE); + goto out; } - if (dbus_error_is_set (&err)) - dbus_error_free (&err); + data->wireless_enabled = enabled; - return (reply); -} + if (!enabled) { + GSList * elt; -static DBusMessage *nm_dbus_nm_set_wireless_enabled (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) -{ - gboolean enabled = FALSE; - DBusError err; - NMData *app_data; + /* Down all wireless devices */ + nm_lock_mutex (data->dev_list_mutex, __FUNCTION__); + for (elt = data->dev_list; elt; elt = g_slist_next (elt)) { + NMDevice * dev = (NMDevice *)(elt->data); - g_return_val_if_fail (data && data->data && connection && message, NULL); - - dbus_error_init (&err); - if (!dbus_message_get_args (message, &err, DBUS_TYPE_BOOLEAN, &enabled, DBUS_TYPE_INVALID)) - return NULL; - - app_data = data->data; - app_data->wireless_enabled = enabled; - - if (!enabled) - { - GSList *elt; - - /* Physically down all wireless devices */ - nm_lock_mutex (app_data->dev_list_mutex, __FUNCTION__); - for (elt = app_data->dev_list; elt; elt = g_slist_next (elt)) - { - NMDevice *dev = (NMDevice *)(elt->data); - if (nm_device_is_802_11_wireless (dev)) - { + if (nm_device_is_802_11_wireless (dev)) { nm_device_deactivate (dev); nm_device_bring_down (dev); } } - nm_unlock_mutex (app_data->dev_list_mutex, __FUNCTION__); + nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__); } - nm_policy_schedule_device_change_check (data->data); + nm_policy_schedule_device_change_check (data); - return NULL; +out: + return reply; } -static DBusMessage *nm_dbus_nm_get_wireless_enabled (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_nm_get_wireless_enabled (DBusConnection *connection, + DBusMessage *message, + void * user_data) { + NMData * data = (NMData *) user_data; DBusMessage *reply = NULL; - g_return_val_if_fail (data && data->data && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); - if ((reply = dbus_message_new_method_return (message))) - dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &data->data->wireless_enabled, DBUS_TYPE_INVALID); + if ((reply = dbus_message_new_method_return (message))) { + dbus_message_append_args (reply, + DBUS_TYPE_BOOLEAN, &data->wireless_enabled, + DBUS_TYPE_INVALID); + } return reply; } -static DBusMessage *nm_dbus_nm_sleep (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_nm_sleep (DBusConnection *connection, + DBusMessage *message, + void * user_data) { - NMData *app_data; + NMData * data = (NMData *) user_data; + GSList * elt; - g_return_val_if_fail (data && data->data && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); - app_data = data->data; - if (app_data->asleep == FALSE) - { - GSList *elt; + if (data->asleep) + return NULL; - nm_info ("Going to sleep."); + nm_info ("Going to sleep."); + data->asleep = TRUE; - app_data->asleep = TRUE; - /* Not using nm_schedule_state_change_signal_broadcast() here - * because we want the signal to go out ASAP. - */ - nm_dbus_signal_state_change (connection, app_data); + /* Not using nm_schedule_state_change_signal_broadcast() here + * because we want the signal to go out ASAP. + */ + nm_dbus_signal_state_change (connection, data); - /* Remove all devices from the device list */ - nm_lock_mutex (app_data->dev_list_mutex, __FUNCTION__); - for (elt = app_data->dev_list; elt; elt = g_slist_next (elt)) - { - NMDevice *dev = (NMDevice *)(elt->data); - nm_device_set_removed (dev, TRUE); - nm_device_deactivate_quickly (dev); - nm_system_device_set_up_down (dev, FALSE); - } - nm_unlock_mutex (app_data->dev_list_mutex, __FUNCTION__); - - nm_lock_mutex (app_data->dialup_list_mutex, __FUNCTION__); - nm_system_deactivate_all_dialup (app_data->dialup_list); - app_data->modem_active = FALSE; - nm_unlock_mutex (app_data->dialup_list_mutex, __FUNCTION__); + /* Just deactivate and down all devices from the device list, + * we'll remove them in 'wake' for speed's sake. + */ + nm_lock_mutex (data->dev_list_mutex, __FUNCTION__); + for (elt = data->dev_list; elt; elt = g_slist_next (elt)) { + NMDevice *dev = (NMDevice *)(elt->data); + nm_device_set_removed (dev, TRUE); + nm_device_deactivate_quickly (dev); + nm_system_device_set_up_down (dev, FALSE); } + nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__); + + nm_lock_mutex (data->dialup_list_mutex, __FUNCTION__); + nm_system_deactivate_all_dialup (data->dialup_list); + data->modem_active = FALSE; + nm_unlock_mutex (data->dialup_list_mutex, __FUNCTION__); return NULL; } -static DBusMessage *nm_dbus_nm_wake (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_nm_wake (DBusConnection *connection, + DBusMessage *message, + void * user_data) { - NMData *app_data; + NMData * data = (NMData *) user_data; - g_return_val_if_fail (data && data->data && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); - app_data = data->data; - if (app_data->asleep == TRUE) - { - nm_info ("Waking up from sleep."); - app_data->asleep = FALSE; + if (!data->asleep) + return NULL; - /* Remove all devices from the device list */ - nm_lock_mutex (app_data->dev_list_mutex, __FUNCTION__); - while (g_slist_length (app_data->dev_list)) - nm_remove_device (app_data, (NMDevice *)(app_data->dev_list->data)); - nm_unlock_mutex (app_data->dev_list_mutex, __FUNCTION__); + nm_info ("Waking up from sleep."); + data->asleep = FALSE; - nm_add_initial_devices (app_data); + /* Remove all devices from the device list */ + nm_lock_mutex (data->dev_list_mutex, __FUNCTION__); + while (g_slist_length (data->dev_list)) + nm_remove_device (data, (NMDevice *)(data->dev_list->data)); + g_slist_free (data->dev_list); + data->dev_list = NULL; + nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__); - nm_schedule_state_change_signal_broadcast (app_data); - nm_policy_schedule_device_change_check (data->data); - } + nm_add_initial_devices (data); + + nm_schedule_state_change_signal_broadcast (data); + nm_policy_schedule_device_change_check (data); return NULL; } -static DBusMessage *nm_dbus_nm_get_state (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_nm_get_state (DBusConnection *connection, + DBusMessage *message, + void * user_data) { + NMData * data = (NMData *) user_data; DBusMessage * reply = NULL; NMState state; - g_return_val_if_fail (data && data->data && connection && message, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); - state = nm_get_app_state_from_data (data->data); - if ((reply = dbus_message_new_method_return (message))) - dbus_message_append_args (reply, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID); + if (!(reply = dbus_message_new_method_return (message))) { + nm_warning ("Not enough memory to create dbus message."); + goto out; + } + state = nm_get_app_state_from_data (data); + dbus_message_append_args (reply, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID); + +out: return reply; } @@ -620,9 +718,13 @@ static DBusMessage *nm_dbus_nm_get_state (DBusConnection *connection, DBusMessag * Register handlers for dbus methods on the org.freedesktop.NetworkManager object. * */ -NMDbusMethodList *nm_dbus_nm_methods_setup (void) +NMDbusMethodList *nm_dbus_nm_methods_setup (NMData *data) { - NMDbusMethodList *list = nm_dbus_method_list_new (NULL); + NMDbusMethodList * list; + + g_return_val_if_fail (data != NULL, NULL); + + list = nm_dbus_method_list_new (NM_DBUS_PATH, FALSE, data, NULL); nm_dbus_method_list_add_method (list, "getDevices", nm_dbus_nm_get_devices); nm_dbus_method_list_add_method (list, "getDialup", nm_dbus_nm_get_dialup); @@ -638,5 +740,5 @@ NMDbusMethodList *nm_dbus_nm_methods_setup (void) nm_dbus_method_list_add_method (list, "createTestDevice", nm_dbus_nm_create_test_device); nm_dbus_method_list_add_method (list, "removeTestDevice", nm_dbus_nm_remove_test_device); - return (list); + return list; } diff --git a/src/nm-dbus-nm.h b/src/nm-dbus-nm.h index 2ad488f37..0e02b6889 100644 --- a/src/nm-dbus-nm.h +++ b/src/nm-dbus-nm.h @@ -22,9 +22,10 @@ #ifndef NM_DBUS_NM_H #define NM_DBUS_NM_H +#include "NetworkManagerMain.h" #include "NetworkManagerDbusUtils.h" -NMDbusMethodList *nm_dbus_nm_methods_setup (void); +NMDbusMethodList *nm_dbus_nm_methods_setup (NMData *data); #endif diff --git a/src/nm-dbus-nmi.c b/src/nm-dbus-nmi.c index 383fe3493..8fe24fdc9 100644 --- a/src/nm-dbus-nmi.c +++ b/src/nm-dbus-nmi.c @@ -27,6 +27,7 @@ #include "NetworkManagerUtils.h" #include "nm-dbus-nmi.h" #include "nm-utils.h" +#include "nm-dbus-manager.h" /* @@ -36,7 +37,9 @@ * the new user key. * */ -static void nm_dbus_get_user_key_for_network_cb (DBusPendingCall *pcall, NMActRequest *req) +static void +nm_dbus_get_user_key_for_network_cb (DBusPendingCall *pcall, + NMActRequest *req) { DBusMessage * reply = NULL; NMData * data; @@ -64,21 +67,23 @@ static void nm_dbus_get_user_key_for_network_cb (DBusPendingCall *pcall, NMActRe if (!(reply = dbus_pending_call_steal_reply (pcall))) goto out; - if (message_is_error (reply)) - { + if (message_is_error (reply)) { DBusError err; dbus_error_init (&err); dbus_set_error_from_message (&err, reply); /* Check for cancelled error */ - if (strcmp (err.name, NMI_DBUS_USER_KEY_CANCELED_ERROR) == 0) - { - nm_info ("Activation (%s) New wireless user key request for network '%s' was canceled.", - nm_device_get_iface (dev), nm_ap_get_essid (ap)); + if (strcmp (err.name, NMI_DBUS_USER_KEY_CANCELED_ERROR) == 0) { + nm_info ("Activation (%s) New wireless user key request for network" + " '%s' was canceled.", + nm_device_get_iface (dev), + nm_ap_get_essid (ap)); + } else { + nm_warning ("dbus returned an error.\n (%s) %s\n", + err.name, + err.message); } - else - nm_warning ("nm_dbus_get_user_key_for_network_cb(): dbus returned an error.\n (%s) %s\n", err.name, err.message); dbus_error_free (&err); @@ -94,11 +99,12 @@ static void nm_dbus_get_user_key_for_network_cb (DBusPendingCall *pcall, NMActRe goto out; } - nm_info ("Activation (%s) New wireless user key for network '%s' received.", nm_device_get_iface (dev), nm_ap_get_essid (ap)); + nm_info ("Activation (%s) New wireless user key for network '%s' received.", + nm_device_get_iface (dev), + nm_ap_get_essid (ap)); dbus_message_iter_init (reply, &iter); - if ((security = nm_ap_security_new_deserialize (&iter))) - { + if ((security = nm_ap_security_new_deserialize (&iter))) { nm_ap_set_security (ap, security); nm_device_activate_schedule_stage1_device_prepare (req); } @@ -118,11 +124,14 @@ out: * Asks the info-daemon for a user-entered WEP key. * */ -void nm_dbus_get_user_key_for_network (DBusConnection *connection, NMActRequest *req, const gboolean new_key) +void +nm_dbus_get_user_key_for_network (NMActRequest *req, + const gboolean new_key) { + NMDBusManager * dbus_mgr = NULL; + DBusConnection *dbus_connection; DBusMessage * message; DBusPendingCall * pcall; - NMData * data; NMDevice * dev; NMAccessPoint * ap; gint32 attempt = 1; @@ -130,11 +139,14 @@ void nm_dbus_get_user_key_for_network (DBusConnection *connection, NMActRequest char * net_path; const char * essid; - g_return_if_fail (connection != NULL); g_return_if_fail (req != NULL); - data = nm_act_request_get_data (req); - g_assert (data); + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get the dbus connection."); + goto out; + } dev = nm_act_request_get_dev (req); g_assert (dev); @@ -143,35 +155,42 @@ void nm_dbus_get_user_key_for_network (DBusConnection *connection, NMActRequest g_assert (ap); essid = nm_ap_get_essid (ap); - nm_info ("Activation (%s) New wireless user key requested for network '%s'.", nm_device_get_iface (dev), essid); + nm_info ("Activation (%s) New wireless user key requested for network '%s'.", + nm_device_get_iface (dev), + essid); - if (!(message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getKeyForNetwork"))) - { - nm_warning ("nm_dbus_get_user_key_for_network(): Couldn't allocate the dbus message"); - return; + message = dbus_message_new_method_call (NMI_DBUS_SERVICE, + NMI_DBUS_PATH, + NMI_DBUS_INTERFACE, + "getKeyForNetwork"); + if (!message) { + nm_warning ("couldn't allocate the dbus message"); + goto out; } dev_path = nm_dbus_get_object_path_for_device (dev); net_path = nm_dbus_get_object_path_for_network (dev, ap); - if (dev_path && strlen (dev_path) && net_path && strlen (net_path)) - { + if (dev_path && strlen (dev_path) && net_path && strlen (net_path)) { dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH, &dev_path, DBUS_TYPE_OBJECT_PATH, &net_path, DBUS_TYPE_STRING, &essid, DBUS_TYPE_INT32, &attempt, DBUS_TYPE_BOOLEAN, &new_key, DBUS_TYPE_INVALID); - if ((pcall = nm_dbus_send_with_callback (connection, message, - (DBusPendingCallNotifyFunction) nm_dbus_get_user_key_for_network_cb, - req, NULL, __func__))) - { + pcall = nm_dbus_send_with_callback (dbus_connection, + message, + (DBusPendingCallNotifyFunction) nm_dbus_get_user_key_for_network_cb, + req, + NULL, + __func__); + if (pcall) { nm_act_request_ref (req); nm_act_request_set_stage (req, NM_ACT_STAGE_NEED_USER_KEY); nm_act_request_set_user_key_pending_call (req, pcall); } - else - nm_warning ("nm_dbus_get_user_key_for_network(): could not send dbus message"); - } else nm_warning ("nm_dbus_get_user_key_for_network(): bad object path data"); + } else { + nm_warning ("bad object path data"); + } g_free (net_path); g_free (dev_path); @@ -181,6 +200,9 @@ void nm_dbus_get_user_key_for_network (DBusConnection *connection, NMActRequest */ dbus_message_unref (message); + +out: + g_object_unref (dbus_mgr); } @@ -190,27 +212,40 @@ void nm_dbus_get_user_key_for_network (DBusConnection *connection, NMActRequest * Sends a user-key cancellation message to NetworkManagerInfo * */ -void nm_dbus_cancel_get_user_key_for_network (DBusConnection *connection, NMActRequest *req) +void +nm_dbus_cancel_get_user_key_for_network (NMActRequest *req) { DBusMessage * message; DBusPendingCall * pcall; + NMDBusManager * dbus_mgr; + DBusConnection * dbus_connection; - g_return_if_fail (connection != NULL); g_return_if_fail (req != NULL); + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get the dbus connection."); + goto out; + } + if ((pcall = nm_act_request_get_user_key_pending_call (req))) dbus_pending_call_cancel (pcall); - if (!(message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "cancelGetKeyForNetwork"))) - { - nm_warning ("nm_dbus_cancel_get_user_key_for_network(): Couldn't allocate the dbus message"); - return; + message = dbus_message_new_method_call (NMI_DBUS_SERVICE, + NMI_DBUS_PATH, + NMI_DBUS_INTERFACE, + "cancelGetKeyForNetwork"); + if (!message) { + nm_warning ("couldn't allocate the dbus message"); + goto out; } - if (!dbus_connection_send (connection, message, NULL)) - nm_warning ("nm_dbus_cancel_get_user_key_for_network(): could not send dbus message"); - + dbus_connection_send (dbus_connection, message, NULL); dbus_message_unref (message); + +out: + g_object_unref (dbus_mgr); } @@ -220,10 +255,13 @@ void nm_dbus_cancel_get_user_key_for_network (DBusConnection *connection, NMActR * Tell NetworkManagerInfo the updated info of the AP * */ -gboolean nm_dbus_update_network_info (DBusConnection *connection, NMAccessPoint *ap, const gboolean automatic) +void +nm_dbus_update_network_info (NMAccessPoint *ap, + const gboolean automatic) { + NMDBusManager * dbus_mgr = NULL; + DBusConnection * dbus_connection; DBusMessage * message; - gboolean success = FALSE; gboolean fallback; const char * essid; gchar * char_bssid; @@ -231,14 +269,23 @@ gboolean nm_dbus_update_network_info (DBusConnection *connection, NMAccessPoint const struct ether_addr *addr; DBusMessageIter iter; - g_return_val_if_fail (connection != NULL, FALSE); - g_return_val_if_fail (ap != NULL, FALSE); + g_return_if_fail (ap != NULL); + + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get the dbus connection."); + goto out; + } essid = nm_ap_get_essid (ap); - if (!(message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "updateNetworkInfo"))) - { - nm_warning ("nm_dbus_update_network_info(): Couldn't allocate the dbus message"); + message = dbus_message_new_method_call (NMI_DBUS_SERVICE, + NMI_DBUS_PATH, + NMI_DBUS_INTERFACE, + "updateNetworkInfo"); + if (!message) { + nm_warning ("couldn't allocate the dbus message"); goto out; } @@ -276,19 +323,13 @@ gboolean nm_dbus_update_network_info (DBusConnection *connection, NMAccessPoint /* Serialize the AP's security info into the message */ security = nm_ap_get_security (ap); g_assert (security); - if (nm_ap_security_serialize (security, &iter) != 0) - goto unref; - - if (dbus_connection_send (connection, message, NULL)) - success = TRUE; - else - nm_warning ("nm_dbus_update_network_info(): failed to send dbus message."); - -unref: + if (nm_ap_security_serialize (security, &iter) == 0) + dbus_connection_send (dbus_connection, message, NULL); dbus_message_unref (message); out: - return success; + g_object_unref (dbus_mgr); + return; } @@ -487,11 +528,15 @@ out: * Async callback from nm_dbus_get_networks * */ -static void nm_dbus_get_networks_cb (DBusPendingCall *pcall, void *user_data) +static void +nm_dbus_get_networks_cb (DBusPendingCall *pcall, + void *user_data) { DBusMessage * reply; DBusMessageIter iter, array_iter; GetNetworksCBData * cb_data = (GetNetworksCBData *)user_data; + NMDBusManager * dbus_mgr = NULL; + DBusConnection *dbus_connection; g_return_if_fail (pcall); g_return_if_fail (cb_data != NULL); @@ -505,8 +550,7 @@ static void nm_dbus_get_networks_cb (DBusPendingCall *pcall, void *user_data) if (!(reply = dbus_pending_call_steal_reply (pcall))) goto out; - if (message_is_error (reply)) - { + if (message_is_error (reply)) { DBusError err; dbus_error_init (&err); @@ -515,18 +559,27 @@ static void nm_dbus_get_networks_cb (DBusPendingCall *pcall, void *user_data) goto out; } + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_warning ("couldn't get dbus connection."); + goto out; + } + dbus_message_iter_init (reply, &iter); dbus_message_iter_recurse (&iter, &array_iter); - while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRING) - { + while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRING) { const char * value; DBusMessage * message; dbus_message_iter_get_basic (&array_iter, &value); /* Get properties on each network */ - if ((message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getNetworkProperties"))) - { + message = dbus_message_new_method_call (NMI_DBUS_SERVICE, + NMI_DBUS_PATH, + NMI_DBUS_INTERFACE, + "getNetworkProperties"); + if (message) { dbus_int32_t type_as_int32 = nm_ap_list_get_type (cb_data->list); GetOneNetworkCBData * net_cb_data = g_slice_new0 (GetOneNetworkCBData); @@ -535,10 +588,16 @@ static void nm_dbus_get_networks_cb (DBusPendingCall *pcall, void *user_data) nm_ap_list_ref (cb_data->list); net_cb_data->list = cb_data->list; - dbus_message_append_args (message, DBUS_TYPE_STRING, &value, DBUS_TYPE_INT32, &type_as_int32, DBUS_TYPE_INVALID); - nm_dbus_send_with_callback (cb_data->data->dbus_connection, message, - (DBusPendingCallNotifyFunction) nm_dbus_get_network_data_cb, net_cb_data, - (DBusFreeFunction) free_get_one_network_cb_data, __func__); + dbus_message_append_args (message, + DBUS_TYPE_STRING, &value, + DBUS_TYPE_INT32, &type_as_int32, + DBUS_TYPE_INVALID); + nm_dbus_send_with_callback (dbus_connection, + message, + (DBusPendingCallNotifyFunction) nm_dbus_get_network_data_cb, + net_cb_data, + (DBusFreeFunction) free_get_one_network_cb_data, + __func__); dbus_message_unref (message); } dbus_message_iter_next(&array_iter); @@ -546,6 +605,8 @@ static void nm_dbus_get_networks_cb (DBusPendingCall *pcall, void *user_data) dbus_message_unref (reply); out: + if (dbus_mgr) + g_object_unref (dbus_mgr); dbus_pending_call_unref (pcall); } @@ -556,29 +617,54 @@ out: * Update all allowed networks from NetworkManagerInfo * */ -void nm_dbus_update_allowed_networks (DBusConnection *connection, NMAccessPointList *list, NMData *data) +void +nm_dbus_update_allowed_networks (NMAccessPointList *list, + NMData *data) { + NMDBusManager * dbus_mgr = NULL; + DBusConnection * dbus_connection; DBusMessage * message; dbus_int32_t type_as_int32 = nm_ap_list_get_type (list); GetNetworksCBData * cb_data; - g_return_if_fail (connection != NULL); g_return_if_fail (list != NULL); g_return_if_fail (data != NULL); - if (!(message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getNetworks"))) - return; - dbus_message_append_args (message, DBUS_TYPE_INT32, &type_as_int32, DBUS_TYPE_INVALID); + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get the dbus connection."); + goto out; + } + + message = dbus_message_new_method_call (NMI_DBUS_SERVICE, + NMI_DBUS_PATH, + NMI_DBUS_INTERFACE, + "getNetworks"); + if (!message) { + nm_warning ("could not allocate the dbus message."); + goto out; + } + + dbus_message_append_args (message, + DBUS_TYPE_INT32, &type_as_int32, + DBUS_TYPE_INVALID); cb_data = g_slice_new0 (GetNetworksCBData); cb_data->data = data; nm_ap_list_ref (list); cb_data->list = list; - nm_dbus_send_with_callback (cb_data->data->dbus_connection, message, - (DBusPendingCallNotifyFunction) nm_dbus_get_networks_cb, cb_data, - (DBusFreeFunction) free_get_networks_cb_data, __func__); + nm_dbus_send_with_callback (dbus_connection, + message, + (DBusPendingCallNotifyFunction) nm_dbus_get_networks_cb, + cb_data, + (DBusFreeFunction) free_get_networks_cb_data, + __func__); dbus_message_unref (message); + +out: + g_object_unref (dbus_mgr); } @@ -588,31 +674,53 @@ void nm_dbus_update_allowed_networks (DBusConnection *connection, NMAccessPointL * Update all networks of a specific type from NetworkManagerInfo * */ -void nm_dbus_update_one_allowed_network (DBusConnection *connection, const char *network, NMData *data) +void +nm_dbus_update_one_allowed_network (const char *network, + NMData *data) { + NMDBusManager * dbus_mgr = NULL; + DBusConnection * dbus_connection; DBusMessage * message; dbus_int32_t type_as_int32 = NETWORK_TYPE_ALLOWED; GetOneNetworkCBData * cb_data = NULL; - g_return_if_fail (connection != NULL); g_return_if_fail (data != NULL); - if (!(message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getNetworkProperties"))) - { - nm_warning ("nm_dbus_update_one_allowed_network(): Couldn't allocate the dbus message"); - return; + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get the dbus connection."); + goto out; + } + + message = dbus_message_new_method_call (NMI_DBUS_SERVICE, + NMI_DBUS_PATH, + NMI_DBUS_INTERFACE, + "getNetworkProperties"); + if (!message) { + nm_warning ("couldn't allocate the dbus message."); + goto out; } - dbus_message_append_args (message, DBUS_TYPE_STRING, &network, DBUS_TYPE_INT32, &type_as_int32, DBUS_TYPE_INVALID); cb_data = g_slice_new0 (GetOneNetworkCBData); cb_data->data = data; cb_data->network = g_strdup (network); cb_data->list = data->allowed_ap_list; - nm_dbus_send_with_callback (cb_data->data->dbus_connection, message, - (DBusPendingCallNotifyFunction) nm_dbus_get_network_data_cb, cb_data, - (DBusFreeFunction) free_get_one_network_cb_data, __func__); + dbus_message_append_args (message, + DBUS_TYPE_STRING, &network, + DBUS_TYPE_INT32, &type_as_int32, + DBUS_TYPE_INVALID); + nm_dbus_send_with_callback (dbus_connection, + message, + (DBusPendingCallNotifyFunction) nm_dbus_get_network_data_cb, + cb_data, + (DBusFreeFunction) free_get_one_network_cb_data, + __func__); dbus_message_unref (message); + +out: + g_object_unref (dbus_mgr); } diff --git a/src/nm-dbus-nmi.h b/src/nm-dbus-nmi.h index 8d2173973..581837130 100644 --- a/src/nm-dbus-nmi.h +++ b/src/nm-dbus-nmi.h @@ -25,17 +25,15 @@ #include "NetworkManager.h" #include "NetworkManagerAP.h" -void nm_dbus_get_user_key_for_network (DBusConnection *connection, NMActRequest *req, const gboolean new_key); +void nm_dbus_get_user_key_for_network (NMActRequest *req, const gboolean new_key); -void nm_dbus_cancel_get_user_key_for_network (DBusConnection *connection, NMActRequest *req); +void nm_dbus_cancel_get_user_key_for_network (NMActRequest *req); -NMAccessPoint *nm_dbus_get_network_object (DBusConnection *connection, NMNetworkType type, const char *network); +void nm_dbus_update_network_info (NMAccessPoint *ap, const gboolean user_requested); -gboolean nm_dbus_update_network_info (DBusConnection *connection, NMAccessPoint *ap, const gboolean user_requested); +void nm_dbus_update_one_allowed_network (const char *network, NMData *data); -void nm_dbus_update_one_allowed_network (DBusConnection *connection, const char *network, NMData *data); - -void nm_dbus_update_allowed_networks (DBusConnection *connection, NMAccessPointList *list, NMData *data); +void nm_dbus_update_allowed_networks (NMAccessPointList *list, NMData *data); #endif /* NM_DBUS_NMI_H */ diff --git a/src/nm-device-802-11-wireless.c b/src/nm-device-802-11-wireless.c index 6ec994511..dd1b8f59e 100644 --- a/src/nm-device-802-11-wireless.c +++ b/src/nm-device-802-11-wireless.c @@ -198,7 +198,7 @@ nm_device_802_11_wireless_update_bssid (NMDevice80211Wireless *self) automatic = !nm_act_request_get_user_requested (req); app_data = nm_device_get_app_data (NM_DEVICE (self)); g_assert (app_data); - nm_dbus_update_network_info (app_data->dbus_connection, ap, automatic); + nm_dbus_update_network_info (ap, automatic); } } @@ -213,9 +213,8 @@ nm_device_802_11_wireless_update_bssid (NMDevice80211Wireless *self) static void nm_device_802_11_wireless_update_signal_strength (NMDevice80211Wireless *self) { - NMData * app_data; - gboolean has_range = FALSE; - NMSock * sk; + gboolean has_range = FALSE; + NMSock * sk; iwrange range; iwstats stats; int percent = -1; @@ -226,14 +225,10 @@ nm_device_802_11_wireless_update_signal_strength (NMDevice80211Wireless *self) if (self->priv->scanning) return; - app_data = nm_device_get_app_data (NM_DEVICE (self)); - g_assert (app_data); - /* If we aren't the active device, we don't really have a signal strength * that would mean anything. */ - if (!nm_device_get_act_request (NM_DEVICE (self))) - { + if (!nm_device_get_act_request (NM_DEVICE (self))) { self->priv->strength = -1; return; } @@ -266,7 +261,7 @@ nm_device_802_11_wireless_update_signal_strength (NMDevice80211Wireless *self) self->priv->invalid_strength_counter = 0; if (percent != self->priv->strength) - nm_dbus_signal_device_strength_change (app_data->dbus_connection, self, percent); + nm_dbus_signal_device_strength_change (self, percent); self->priv->strength = percent; } @@ -1902,7 +1897,7 @@ convert_scan_results (gpointer user_data) { if ((outdated_ap = (NMAccessPoint *)(elt->data))) { - nm_dbus_signal_wireless_network_change (app_data->dbus_connection, self, outdated_ap, NETWORK_STATUS_DISAPPEARED, -1); + nm_dbus_signal_wireless_network_change (self, outdated_ap, NETWORK_STATUS_DISAPPEARED, -1); nm_ap_list_remove_ap (nm_device_802_11_wireless_ap_list_get (self), outdated_ap); } } @@ -2528,7 +2523,6 @@ link_timeout_cb (gpointer user_data) NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (user_data); NMActRequest * req = nm_device_get_act_request (dev); NMAccessPoint * ap = nm_act_request_get_ap (req); - NMData * data = nm_device_get_app_data (dev); gboolean has_key; g_assert (dev); @@ -2544,7 +2538,7 @@ link_timeout_cb (gpointer user_data) nm_info ("Activation (%s/wireless): disconnected during association," " asking for new key.", nm_device_get_iface (dev)); supplicant_remove_timeout(self); - nm_dbus_get_user_key_for_network (data->dbus_connection, req, TRUE); + nm_dbus_get_user_key_for_network (req, TRUE); } else { @@ -2657,7 +2651,6 @@ supplicant_timeout_cb (gpointer user_data) NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (user_data); NMActRequest * req = nm_device_get_act_request (dev); NMAccessPoint * ap = nm_act_request_get_ap (req); - NMData * data = nm_device_get_app_data (dev); gboolean has_key; g_assert (self); @@ -2672,7 +2665,7 @@ supplicant_timeout_cb (gpointer user_data) /* Activation failed, we must have bad encryption key */ nm_info ("Activation (%s/wireless): association took too long (>%us), asking for new key.", nm_device_get_iface (dev), get_supplicant_timeout (self)); - nm_dbus_get_user_key_for_network (data->dbus_connection, req, TRUE); + nm_dbus_get_user_key_for_network (req, TRUE); } else { @@ -3015,7 +3008,6 @@ real_act_stage2_config (NMDevice *dev, NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (dev); NMAccessPoint * ap = nm_act_request_get_ap (req); NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - NMData * data = nm_act_request_get_data (req); const char * iface; gboolean ask_user = FALSE; @@ -3026,7 +3018,7 @@ real_act_stage2_config (NMDevice *dev, /* If we need an encryption key, get one */ if (ap_need_key (self, ap, &ask_user)) { - nm_dbus_get_user_key_for_network (data->dbus_connection, req, ask_user); + nm_dbus_get_user_key_for_network (req, ask_user); return NM_ACT_STAGE_RETURN_POSTPONE; } @@ -3162,7 +3154,7 @@ real_act_stage4_ip_config_timeout (NMDevice *dev, /* Activation failed, we must have bad encryption key */ nm_debug ("Activation (%s/wireless): could not get IP configuration info for '%s', asking for new key.", nm_device_get_iface (dev), nm_ap_get_essid (ap) ? nm_ap_get_essid (ap) : "(none)"); - nm_dbus_get_user_key_for_network (data->dbus_connection, req, TRUE); + nm_dbus_get_user_key_for_network (req, TRUE); ret = NM_ACT_STAGE_RETURN_POSTPONE; } else if (nm_ap_get_mode (ap) == IW_MODE_ADHOC) @@ -3215,7 +3207,7 @@ real_activation_success_handler (NMDevice *dev, if (!nm_ap_get_address (ap) || !nm_ethernet_address_is_valid (nm_ap_get_address (ap))) nm_ap_set_address (ap, &addr); - nm_dbus_update_network_info (app_data->dbus_connection, ap, automatic); + nm_dbus_update_network_info (ap, automatic); } @@ -3271,10 +3263,7 @@ real_activation_cancel_handler (NMDevice *dev, parent_class->activation_cancel_handler (dev, req); if (nm_act_request_get_stage (req) == NM_ACT_STAGE_NEED_USER_KEY) - { - NMData *data = nm_device_get_app_data (dev); - nm_dbus_cancel_get_user_key_for_network (data->dbus_connection, req); - } + nm_dbus_cancel_get_user_key_for_network (req); } @@ -3476,13 +3465,12 @@ add_new_ap_to_device_list (NMDevice80211Wireless *dev, /* If the AP is not broadcasting its ESSID, try to fill it in here from our * allowed list where we cache known MAC->ESSID associations. */ - if (!nm_ap_get_essid (ap)) - { + if (!nm_ap_get_essid (ap)) { NMData * app_data; nm_ap_set_broadcast (ap, FALSE); app_data = nm_device_get_app_data (NM_DEVICE (dev)); - nm_ap_list_copy_one_essid_by_address (app_data, dev, ap, app_data->allowed_ap_list); + nm_ap_list_copy_one_essid_by_address (dev, ap, app_data->allowed_ap_list); } /* Add the AP to the device's AP list */ diff --git a/src/nm-device-private.h b/src/nm-device-private.h index 5ebc0398e..db177a9db 100644 --- a/src/nm-device-private.h +++ b/src/nm-device-private.h @@ -23,6 +23,14 @@ #define NM_DEVICE_PRIVATE_H #include "nm-device.h" +#include "NetworkManagerMain.h" + +typedef struct NMDbusCBData { + NMDevice * dev; + NMAccessPoint * ap; + NMData * data; +} NMDbusCBData; + gboolean nm_device_is_activated (NMDevice *dev); diff --git a/src/nm-marshal.list b/src/nm-marshal.list index a88a93ef8..69de47a51 100644 --- a/src/nm-marshal.list +++ b/src/nm-marshal.list @@ -1,3 +1,4 @@ VOID:OBJECT VOID:OBJECT,POINTER,INT VOID:POINTER +VOID:POINTER,STRING,STRING,STRING diff --git a/src/vpn-manager/nm-dbus-vpn.c b/src/vpn-manager/nm-dbus-vpn.c index 95796ab07..2cb2e5c82 100644 --- a/src/vpn-manager/nm-dbus-vpn.c +++ b/src/vpn-manager/nm-dbus-vpn.c @@ -32,33 +32,48 @@ #include "nm-vpn-service.h" #include "nm-vpn-act-request.h" #include "nm-utils.h" +#include "nm-dbus-manager.h" +static DBusMessage * +new_invalid_vpn_connection_error (DBusMessage *replyto) +{ + return nm_dbus_create_error_message (replyto, NM_DBUS_INTERFACE_VPN, + "InvalidVPNConnection", + "No VPN connection with that name" + " was found."); +} + /* * nm_dbus_vpn_signal_vpn_connection_update * * Notifies the bus that a VPN connection's properties have changed. * */ -void nm_dbus_vpn_signal_vpn_connection_update (DBusConnection *con, NMVPNConnection *vpn, const char *signal) +void +nm_dbus_vpn_signal_vpn_connection_update (DBusConnection *connection, + NMVPNConnection *vpn, + const char *signal) { DBusMessage *message; const char *vpn_name; - g_return_if_fail (con != NULL); + g_return_if_fail (connection != NULL); g_return_if_fail (vpn != NULL); - if (!(message = dbus_message_new_signal (NM_DBUS_PATH_VPN, NM_DBUS_INTERFACE_VPN, signal))) - { - nm_warning ("Not enough memory for new dbus message!"); + message = dbus_message_new_signal (NM_DBUS_PATH_VPN, + NM_DBUS_INTERFACE_VPN, + signal); + if (!message) { + nm_warning ("could not allocate the dbus message."); return; } vpn_name = nm_vpn_connection_get_name (vpn); - dbus_message_append_args (message, DBUS_TYPE_STRING, &vpn_name, DBUS_TYPE_INVALID); - if (!dbus_connection_send (con, message, NULL)) - nm_warning ("Could not raise the %s signal!", signal); - + dbus_message_append_args (message, + DBUS_TYPE_STRING, &vpn_name, + DBUS_TYPE_INVALID); + dbus_connection_send (connection, message, NULL); dbus_message_unref (message); } @@ -67,26 +82,32 @@ void nm_dbus_vpn_signal_vpn_connection_update (DBusConnection *con, NMVPNConnect * * Notifies the bus that a VPN connection's state has changed. */ -void nm_dbus_vpn_signal_vpn_connection_state_change (DBusConnection *con, NMVPNConnection *vpn, NMVPNActStage new_stage) +void +nm_dbus_vpn_signal_vpn_connection_state_change (DBusConnection *connection, + NMVPNConnection *vpn, + NMVPNActStage new_stage) { DBusMessage * message; const char * vpn_name; dbus_uint32_t int_stage = (dbus_uint32_t) new_stage; - g_return_if_fail (con != NULL); + g_return_if_fail (connection != NULL); g_return_if_fail (vpn != NULL); - if (!(message = dbus_message_new_signal (NM_DBUS_PATH_VPN, NM_DBUS_INTERFACE_VPN, "VPNConnectionStateChange"))) - { - nm_warning ("Not enough memory for new dbus message!"); + message = dbus_message_new_signal (NM_DBUS_PATH_VPN, + NM_DBUS_INTERFACE_VPN, + "VPNConnectionStateChange"); + if (!message) { + nm_warning ("could not allocate dbus connection."); return; } vpn_name = nm_vpn_connection_get_name (vpn); - dbus_message_append_args (message, DBUS_TYPE_STRING, &vpn_name, DBUS_TYPE_UINT32, &int_stage, DBUS_TYPE_INVALID); - if (!dbus_connection_send (con, message, NULL)) - nm_warning ("Could not raise the VPNConnectionStateChange signal!"); - + dbus_message_append_args (message, + DBUS_TYPE_STRING, &vpn_name, + DBUS_TYPE_UINT32, &int_stage, + DBUS_TYPE_INVALID); + dbus_connection_send (connection, message, NULL); dbus_message_unref (message); } @@ -97,27 +118,34 @@ void nm_dbus_vpn_signal_vpn_connection_state_change (DBusConnection *con, NMVPNC * Proxy a VPN Failure message from the vpn daemon to the bus. * */ -void nm_dbus_vpn_signal_vpn_failed (DBusConnection *con, const char *signal, NMVPNConnection *vpn, const char *error_msg) +void +nm_dbus_vpn_signal_vpn_failed (DBusConnection *connection, + const char *signal, + NMVPNConnection *vpn, + const char *error_msg) { DBusMessage *message; const char *vpn_name; - g_return_if_fail (con != NULL); + g_return_if_fail (connection != NULL); g_return_if_fail (signal != NULL); g_return_if_fail (vpn != NULL); g_return_if_fail (error_msg != NULL); - if (!(message = dbus_message_new_signal (NM_DBUS_PATH_VPN, NM_DBUS_INTERFACE_VPN, signal))) - { - nm_warning ("Not enough memory for new dbus message!"); + message = dbus_message_new_signal (NM_DBUS_PATH_VPN, + NM_DBUS_INTERFACE_VPN, + signal); + if (!message) { + nm_warning ("could not allocate the dbus message."); return; } vpn_name = nm_vpn_connection_get_name (vpn); - dbus_message_append_args (message, DBUS_TYPE_STRING, &vpn_name, DBUS_TYPE_STRING, &error_msg, DBUS_TYPE_INVALID); - if (!dbus_connection_send (con, message, NULL)) - nm_warning ("Could not raise the %s signal!", signal); - + dbus_message_append_args (message, + DBUS_TYPE_STRING, &vpn_name, + DBUS_TYPE_STRING, &error_msg, + DBUS_TYPE_INVALID); + dbus_connection_send (connection, message, NULL); dbus_message_unref (message); } @@ -128,26 +156,32 @@ void nm_dbus_vpn_signal_vpn_failed (DBusConnection *con, const char *signal, NMV * Pass the VPN's login banner message to the bus if anyone wants to use it. * */ -void nm_dbus_vpn_signal_vpn_login_banner (DBusConnection *con, NMVPNConnection *vpn, const char *banner) +void +nm_dbus_vpn_signal_vpn_login_banner (DBusConnection *connection, + NMVPNConnection *vpn, + const char *banner) { DBusMessage *message; const char *vpn_name; - g_return_if_fail (con != NULL); + g_return_if_fail (connection != NULL); g_return_if_fail (vpn != NULL); g_return_if_fail (banner != NULL); - if (!(message = dbus_message_new_signal (NM_DBUS_PATH_VPN, NM_DBUS_INTERFACE_VPN, NM_DBUS_VPN_SIGNAL_LOGIN_BANNER))) - { - nm_warning ("Not enough memory for new dbus message!"); + message = dbus_message_new_signal (NM_DBUS_PATH_VPN, + NM_DBUS_INTERFACE_VPN, + NM_DBUS_VPN_SIGNAL_LOGIN_BANNER); + if (!message) { + nm_warning ("could not allocate the dbus message."); return; } vpn_name = nm_vpn_connection_get_name (vpn); - dbus_message_append_args (message, DBUS_TYPE_STRING, &vpn_name, DBUS_TYPE_STRING, &banner, DBUS_TYPE_INVALID); - if (!dbus_connection_send (con, message, NULL)) - nm_warning ("Could not raise the VPNLoginBanner signal!"); - + dbus_message_append_args (message, + DBUS_TYPE_STRING, &vpn_name, + DBUS_TYPE_STRING, &banner, + DBUS_TYPE_INVALID); + dbus_connection_send (connection, message, NULL); dbus_message_unref (message); } @@ -160,13 +194,18 @@ void nm_dbus_vpn_signal_vpn_login_banner (DBusConnection *con, NMVPNConnection * * NOTE: caller MUST free returned value using g_strfreev() * */ -static char ** nm_dbus_vpn_get_vpn_data (DBusConnection *connection, NMVPNConnection *vpn, int *num_items) +static char ** +nm_dbus_vpn_get_vpn_data (DBusConnection *connection, + NMVPNConnection *vpn, + int *num_items) { DBusMessage *message; DBusError error; - DBusMessage *reply; + DBusMessage *reply = NULL; char **data_items = NULL; const char *vpn_name; + DBusMessageIter iter, array_iter; + GArray * buffer; g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (vpn != NULL, NULL); @@ -174,62 +213,66 @@ static char ** nm_dbus_vpn_get_vpn_data (DBusConnection *connection, NMVPNConnec *num_items = -1; - if (!(message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getVPNConnectionVPNData"))) - { - nm_warning ("nm_dbus_vpn_get_vpn_data(): Couldn't allocate the dbus message"); - return (NULL); + message = dbus_message_new_method_call (NMI_DBUS_SERVICE, + NMI_DBUS_PATH, + NMI_DBUS_INTERFACE, + "getVPNConnectionVPNData"); + if (!message) { + nm_warning ("couldn't allocate the dbus message."); + return NULL; } vpn_name = nm_vpn_connection_get_name (vpn); - dbus_message_append_args (message, DBUS_TYPE_STRING, &vpn_name, DBUS_TYPE_INVALID); + dbus_message_append_args (message, + DBUS_TYPE_STRING, &vpn_name, + DBUS_TYPE_INVALID); dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error); dbus_message_unref (message); - if (dbus_error_is_set (&error)) - nm_warning ("nm_dbus_vpn_get_vpn_data(): %s raised %s", error.name, error.message); - else if (!reply) - nm_info ("nm_dbus_vpn_get_vpn_data(): reply was NULL."); - else - { - DBusMessageIter iter, array_iter; - GArray *buffer; - - dbus_message_iter_init (reply, &iter); - dbus_message_iter_recurse (&iter, &array_iter); - - buffer = g_array_new (TRUE, TRUE, sizeof (gchar *)); - - if (buffer == NULL) - return NULL; - - while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRING) - { - const char *value; - char *str; - - dbus_message_iter_get_basic (&array_iter, &value); - str = g_strdup (value); - - if (str == NULL) - { - g_array_free (buffer, TRUE); - return NULL; - } - - g_array_append_val (buffer, str); - - dbus_message_iter_next (&array_iter); - } - data_items = (gchar **)(buffer->data); - *num_items = buffer->len; - g_array_free (buffer, FALSE); + if (dbus_error_is_set (&error)) { + nm_warning ("%s raised %s", error.name, error.message); + dbus_error_free (&error); + goto out; } + + if (!reply) { + nm_warning ("did not receive a reply."); + goto out; + } + + dbus_message_iter_init (reply, &iter); + dbus_message_iter_recurse (&iter, &array_iter); + + buffer = g_array_new (TRUE, TRUE, sizeof (gchar *)); + if (buffer == NULL) { + nm_warning ("could not allocate buffer for VPN connection data."); + goto out; + } + + while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRING) { + const char *value; + char *str; + dbus_message_iter_get_basic (&array_iter, &value); + str = g_strdup (value); + if (!str) { + nm_warning ("could not allocate string."); + g_array_free (buffer, TRUE); + goto out; + } + g_array_append_val (buffer, str); + dbus_message_iter_next (&array_iter); + } + data_items = (gchar **)(buffer->data); + *num_items = buffer->len; + g_array_free (buffer, FALSE); + +out: if (reply) dbus_message_unref (reply); - return (data_items); + return data_items; } @@ -241,13 +284,18 @@ static char ** nm_dbus_vpn_get_vpn_data (DBusConnection *connection, NMVPNConnec * NOTE: caller MUST free returned value using g_strfreev() * */ -char ** nm_dbus_vpn_get_routes (DBusConnection *connection, NMVPNConnection *vpn, int *num_items) +char ** +nm_dbus_vpn_get_routes (DBusConnection *connection, + NMVPNConnection *vpn, + int *num_items) { DBusMessage *message; DBusError error; DBusMessage *reply; char **routes = NULL; const char *vpn_name; + DBusMessageIter iter, array_iter; + GArray * buffer; g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (vpn != NULL, NULL); @@ -255,77 +303,81 @@ char ** nm_dbus_vpn_get_routes (DBusConnection *connection, NMVPNConnection *vpn *num_items = -1; - if (!(message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getVPNConnectionRoutes"))) - { - nm_warning ("nm_dbus_vpn_get_routes(): Couldn't allocate the dbus message"); - return (NULL); + message = dbus_message_new_method_call (NMI_DBUS_SERVICE, + NMI_DBUS_PATH, + NMI_DBUS_INTERFACE, + "getVPNConnectionRoutes"); + if (!message) { + nm_warning ("couldn't allocate the dbus message."); + return NULL; } vpn_name = nm_vpn_connection_get_name (vpn); - dbus_message_append_args (message, DBUS_TYPE_STRING, &vpn_name, DBUS_TYPE_INVALID); + dbus_message_append_args (message, + DBUS_TYPE_STRING, &vpn_name, + DBUS_TYPE_INVALID); dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error); dbus_message_unref (message); - if (dbus_error_is_set (&error)) - nm_warning ("nm_dbus_vpn_get_routes(): %s raised %s", error.name, error.message); - else if (!reply) - nm_info ("nm_dbus_vpn_get_routes(): reply was NULL."); - else - { - DBusMessageIter iter, array_iter; - GArray *buffer; - - dbus_message_iter_init (reply, &iter); - dbus_message_iter_recurse (&iter, &array_iter); - - buffer = g_array_new (TRUE, TRUE, sizeof (gchar *)); - - if (buffer == NULL) - return NULL; - - while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRING) - { - const char *value; - char *str; - - dbus_message_iter_get_basic (&array_iter, &value); - str = g_strdup (value); - - if (str == NULL) - { - g_array_free (buffer, TRUE); - return NULL; - } - - g_array_append_val (buffer, str); - - dbus_message_iter_next (&array_iter); - } - routes = (gchar **)(buffer->data); - *num_items = buffer->len; - g_array_free (buffer, FALSE); + if (dbus_error_is_set (&error)) { + nm_warning ("%s raised %s", error.name, error.message); + dbus_error_free (&error); + goto out; } + + if (!reply) { + nm_warning ("did not receive a reply."); + goto out; + } + + dbus_message_iter_init (reply, &iter); + dbus_message_iter_recurse (&iter, &array_iter); + + buffer = g_array_new (TRUE, TRUE, sizeof (gchar *)); + if (!buffer) { + nm_warning ("could not allocate buffer for VPN routes."); + goto out; + } + + while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRING) { + const char *value; + char *str; + dbus_message_iter_get_basic (&array_iter, &value); + str = g_strdup (value); + if (!str) { + nm_warning ("could not allocate string."); + g_array_free (buffer, TRUE); + goto out; + } + g_array_append_val (buffer, str); + dbus_message_iter_next (&array_iter); + } + routes = (gchar **)(buffer->data); + *num_items = buffer->len; + g_array_free (buffer, FALSE); + +out: if (reply) dbus_message_unref (reply); - return (routes); + return routes; } -typedef struct UpdateOneVPNCBData -{ +typedef struct UpdateOneVPNCBData { NMData * data; char * vpn; } UpdateOneVPNCBData; -static void free_update_one_vpn_cb_data (UpdateOneVPNCBData *data) +static void +free_update_one_vpn_cb_data (UpdateOneVPNCBData *data) { if (data) g_free (data->vpn); - g_free (data); + g_slice_free (UpdateOneVPNCBData, data); } /* @@ -334,13 +386,20 @@ static void free_update_one_vpn_cb_data (UpdateOneVPNCBData *data) * Retrieve and add to our VPN Manager one VPN connection from NMI. * */ -static void nm_dbus_vpn_update_one_connection_cb (DBusPendingCall *pcall, void *user_data) +static void +nm_dbus_vpn_update_one_connection_cb (DBusPendingCall *pcall, + void *user_data) { UpdateOneVPNCBData * cb_data = (UpdateOneVPNCBData *) user_data; - DBusMessage * reply; + NMDBusManager * dbus_mgr = NULL; + DBusConnection * dbus_connection; + DBusMessage * reply = NULL; const char * con_name = NULL; const char * service_name = NULL; const char * user_name = NULL; + const char * vpn_service_name; + NMVPNConnection * vpn; + gboolean new = TRUE; g_return_if_fail (pcall != NULL); g_return_if_fail (cb_data != NULL); @@ -352,51 +411,72 @@ static void nm_dbus_vpn_update_one_connection_cb (DBusPendingCall *pcall, void * if (!dbus_pending_call_get_completed (pcall)) goto out; + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_warning ("couldn't get the dbus connection."); + goto out; + } + if (!(reply = dbus_pending_call_steal_reply (pcall))) goto out; - if (dbus_message_is_error (reply, "BadVPNConnectionData")) - { - NMVPNConnection *vpn; - + if (dbus_message_is_error (reply, "BadVPNConnectionData")) { /* Bad VPN, remove it from our VPN connection list */ - if ((vpn = nm_vpn_manager_find_connection_by_name (cb_data->data->vpn_manager, cb_data->vpn))) - { + if ((vpn = nm_vpn_manager_find_connection_by_name (cb_data->data->vpn_manager, + cb_data->vpn))) { nm_vpn_connection_ref (vpn); nm_vpn_manager_remove_connection (cb_data->data->vpn_manager, vpn); - nm_dbus_vpn_signal_vpn_connection_update (cb_data->data->dbus_connection, vpn, "VPNConnectionRemoved"); + nm_dbus_vpn_signal_vpn_connection_update (dbus_connection, + vpn, + "VPNConnectionRemoved"); nm_vpn_connection_unref (vpn); } - goto out; + goto unref_reply; } - if (dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &con_name, DBUS_TYPE_STRING, &service_name, - DBUS_TYPE_STRING, &user_name, DBUS_TYPE_INVALID)) - { - NMVPNConnection * vpn; - gboolean new = TRUE; + if (!dbus_message_get_args (reply, + NULL, + DBUS_TYPE_STRING, &con_name, + DBUS_TYPE_STRING, &service_name, + DBUS_TYPE_STRING, &user_name, + DBUS_TYPE_INVALID)) { + goto unref_reply; + } - if ((vpn = nm_vpn_manager_find_connection_by_name (cb_data->data->vpn_manager, con_name))) - { - const char *vpn_service_name = nm_vpn_connection_get_service_name (vpn); - - /* If all attributes of the existing connection are the same as the one we get from NMI, - * don't do anything. - */ - if (strcmp (vpn_service_name, service_name) || strcmp (nm_vpn_connection_get_user_name (vpn), user_name)) - nm_vpn_manager_remove_connection (cb_data->data->vpn_manager, vpn); - else - new = FALSE; + vpn = nm_vpn_manager_find_connection_by_name (cb_data->data->vpn_manager, + con_name); + if (vpn) { + /* If all attributes of the existing connection are the same as + * the one we get from NMI, don't do anything. + */ + vpn_service_name = nm_vpn_connection_get_service_name (vpn); + if ( (strcmp (vpn_service_name, service_name) != 0) + || (strcmp (nm_vpn_connection_get_user_name (vpn), user_name) != 0)) { + nm_vpn_manager_remove_connection (cb_data->data->vpn_manager, vpn); + } else { + new = FALSE; } - - if (new) - vpn = nm_vpn_manager_add_connection (cb_data->data->vpn_manager, con_name, service_name, user_name); - if (vpn) - nm_dbus_vpn_signal_vpn_connection_update (cb_data->data->dbus_connection, vpn, new ? "VPNConnectionAdded" : "VPNConnectionUpdate"); } + + if (new) { + vpn = nm_vpn_manager_add_connection (cb_data->data->vpn_manager, + con_name, + service_name, + user_name); + } + + if (vpn) { + const char * signal = new ? "VPNConnectionAdded" : "VPNConnectionUpdate"; + nm_dbus_vpn_signal_vpn_connection_update (dbus_connection, vpn, signal); + } + +unref_reply: dbus_message_unref (reply); out: + if (dbus_mgr) + g_object_unref (dbus_mgr); dbus_pending_call_unref (pcall); } @@ -407,13 +487,17 @@ out: * Async callback from nnm_dbus_vpn_connections_update * */ -static void nm_dbus_vpn_connections_update_cb (DBusPendingCall *pcall, void *user_data) +static void +nm_dbus_vpn_connections_update_cb (DBusPendingCall *pcall, + void *user_data) { NMData * data = (NMData *) user_data; DBusMessage * reply; DBusMessageIter iter, array_iter; GSList * remove_list = NULL; GSList * elt; + NMDBusManager * dbus_mgr = NULL; + DBusConnection * dbus_connection; g_return_if_fail (pcall); g_return_if_fail (data != NULL); @@ -423,11 +507,18 @@ static void nm_dbus_vpn_connections_update_cb (DBusPendingCall *pcall, void *use if (!dbus_pending_call_get_completed (pcall)) goto out; + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_warning ("couldn't get the dbus connection."); + goto out; + } + if (!(reply = dbus_pending_call_steal_reply (pcall))) goto out; if (message_is_error (reply)) - goto out; + goto unref_reply; nm_info ("Updating VPN Connections..."); @@ -435,8 +526,7 @@ static void nm_dbus_vpn_connections_update_cb (DBusPendingCall *pcall, void *use dbus_message_iter_init (reply, &iter); dbus_message_iter_recurse (&iter, &array_iter); - while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRING) - { + while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRING) { DBusMessage * message; const char * con_name; NMVPNConnection * vpn; @@ -447,36 +537,46 @@ static void nm_dbus_vpn_connections_update_cb (DBusPendingCall *pcall, void *use if ((vpn = nm_vpn_manager_find_connection_by_name (data->vpn_manager, con_name))) remove_list = g_slist_remove (remove_list, vpn); - if ((message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getVPNConnectionProperties"))) - { - DBusPendingCall * vpn_pcall = NULL; + message = dbus_message_new_method_call (NMI_DBUS_SERVICE, + NMI_DBUS_PATH, + NMI_DBUS_INTERFACE, + "getVPNConnectionProperties"); + if (message) { + DBusPendingCall * vpn_pcall = NULL; - dbus_message_append_args (message, DBUS_TYPE_STRING, &con_name, DBUS_TYPE_INVALID); - dbus_connection_send_with_reply (data->dbus_connection, message, &vpn_pcall, -1); + dbus_message_append_args (message, + DBUS_TYPE_STRING, &con_name, + DBUS_TYPE_INVALID); + dbus_connection_send_with_reply (dbus_connection, message, &vpn_pcall, -1); dbus_message_unref (message); - if (vpn_pcall) - { - UpdateOneVPNCBData * vpn_cb_data = g_malloc0 (sizeof (UpdateOneVPNCBData)); + if (vpn_pcall) { + UpdateOneVPNCBData * vpn_cb_data = g_slice_new0 (UpdateOneVPNCBData); vpn_cb_data->data = data; vpn_cb_data->vpn = g_strdup (con_name); - dbus_pending_call_set_notify (vpn_pcall, nm_dbus_vpn_update_one_connection_cb, vpn_cb_data, (DBusFreeFunction) free_update_one_vpn_cb_data); + dbus_pending_call_set_notify (vpn_pcall, + nm_dbus_vpn_update_one_connection_cb, + vpn_cb_data, + (DBusFreeFunction) free_update_one_vpn_cb_data); } } dbus_message_iter_next (&array_iter); } - dbus_message_unref (reply); /* VPN connections left in the remove list aren't known by NMI, therefore we delete them */ - for (elt = remove_list; elt; elt = g_slist_next (elt)) - { + for (elt = remove_list; elt; elt = g_slist_next (elt)) { nm_vpn_manager_remove_connection (data->vpn_manager, elt->data); nm_vpn_connection_unref (elt->data); } g_slist_free (remove_list); +unref_reply: + dbus_message_unref (reply); + out: + if (dbus_mgr) + g_object_unref (dbus_mgr); dbus_pending_call_unref (pcall); } @@ -487,31 +587,39 @@ out: * Update one VPN connection * */ -void nm_dbus_vpn_update_one_vpn_connection (DBusConnection *connection, const char *vpn, NMData *data) +void +nm_dbus_vpn_update_one_vpn_connection (DBusConnection *connection, + const char *vpn, + NMData *data) { - DBusMessage * message; - DBusPendingCall * pcall = NULL; + DBusMessage * message; + DBusPendingCall * pcall = NULL; g_return_if_fail (connection != NULL); g_return_if_fail (vpn != NULL); g_return_if_fail (data != NULL); - if (!(message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getVPNConnectionProperties"))) - { - nm_warning ("nm_dbus_update_one_vpn_connection(): Couldn't allocate the dbus message"); + message = dbus_message_new_method_call (NMI_DBUS_SERVICE, + NMI_DBUS_PATH, + NMI_DBUS_INTERFACE, + "getVPNConnectionProperties"); + if (!message) { + nm_warning ("Couldn't allocate the dbus message."); return; } dbus_message_append_args (message, DBUS_TYPE_STRING, &vpn, DBUS_TYPE_INVALID); dbus_connection_send_with_reply (connection, message, &pcall, -1); dbus_message_unref (message); - if (pcall) - { - UpdateOneVPNCBData * cb_data = g_malloc0 (sizeof (UpdateOneVPNCBData)); + if (pcall) { + UpdateOneVPNCBData * cb_data = g_slice_new0 (UpdateOneVPNCBData); cb_data->data = data; cb_data->vpn = g_strdup (vpn); - dbus_pending_call_set_notify (pcall, nm_dbus_vpn_update_one_connection_cb, cb_data, (DBusFreeFunction) free_update_one_vpn_cb_data); + dbus_pending_call_set_notify (pcall, + nm_dbus_vpn_update_one_connection_cb, + cb_data, + (DBusFreeFunction) free_update_one_vpn_cb_data); } } @@ -522,29 +630,44 @@ void nm_dbus_vpn_update_one_vpn_connection (DBusConnection *connection, const ch * Update VPN connections from NetworkManagerInfo. * */ -static gboolean nm_dbus_vpn_connections_update_from_nmi (NMData *data) +static gboolean +nm_dbus_vpn_connections_update_from_nmi (NMData *data) { DBusMessage * message; DBusPendingCall * pcall; + NMDBusManager * dbus_mgr; + DBusConnection * dbus_connection; g_return_val_if_fail (data != NULL, FALSE); - g_return_val_if_fail (data->dbus_connection != NULL, FALSE); - g_return_val_if_fail (data->vpn_manager != NULL, FALSE); - if (!(message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getVPNConnections"))) - { - nm_warning ("nm_dbus_vpn_connections_update (): Couldn't allocate the dbus message"); - return FALSE; + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_warning ("couldn't get the dbus connection."); + goto out; } - dbus_connection_send_with_reply (data->dbus_connection, message, &pcall, -1); + message = dbus_message_new_method_call (NMI_DBUS_SERVICE, + NMI_DBUS_PATH, + NMI_DBUS_INTERFACE, + "getVPNConnections"); + if (!message) { + nm_warning ("Couldn't allocate the dbus message."); + goto out; + } + + dbus_connection_send_with_reply (dbus_connection, message, &pcall, -1); dbus_message_unref (message); - if (pcall) - { - dbus_pending_call_set_notify (pcall, nm_dbus_vpn_connections_update_cb, data, NULL); + if (pcall) { + dbus_pending_call_set_notify (pcall, + nm_dbus_vpn_connections_update_cb, + data, + NULL); dbus_pending_call_block (pcall); } +out: + g_object_unref (dbus_mgr); return FALSE; } @@ -577,35 +700,37 @@ void nm_dbus_vpn_schedule_vpn_connections_update (NMData *app_data) * Returns a string array of VPN connection names. * */ -static DBusMessage *nm_dbus_vpn_get_vpn_connections (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_vpn_get_vpn_connections (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { - DBusMessage *reply = NULL; - char **vpn_names = NULL; - int num_names; + NMVPNManager * vpn_mgr = (NMVPNManager *) user_data; + DBusMessage * reply = NULL; + char ** vpn_names = NULL; + int num_names; - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (data->data != NULL, NULL); + g_return_val_if_fail (vpn_mgr != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (message != NULL, NULL); - if (!data->data->vpn_manager) - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_VPN, "NoVPNConnections", "There are no available VPN connections."); - goto out; - } - - vpn_names = nm_vpn_manager_get_connection_names (data->data->vpn_manager); + vpn_names = nm_vpn_manager_get_connection_names (vpn_mgr); num_names = vpn_names ? g_strv_length (vpn_names) : 0; - if (num_names == 0) - { - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_VPN, "NoVPNConnections", "There are no available VPN connections."); + if (num_names == 0) { + reply = nm_dbus_create_error_message (message, + NM_DBUS_INTERFACE_VPN, + "NoVPNConnections", + "There are no available VPN " + "connections."); goto out; } if (!(reply = dbus_message_new_method_return (message))) goto out; - dbus_message_append_args (reply, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &vpn_names, num_names, DBUS_TYPE_INVALID); + dbus_message_append_args (reply, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &vpn_names, num_names, + DBUS_TYPE_INVALID); out: if (vpn_names) @@ -621,54 +746,62 @@ out: * Grab properties of a VPN connection * */ -static DBusMessage *nm_dbus_vpn_get_vpn_connection_properties (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_vpn_get_vpn_connection_properties (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { DBusMessage * reply = NULL; DBusError error; const char * name; - gboolean good = FALSE; - NMVPNManager * manager; + gboolean success = FALSE; + NMVPNManager * vpn_mgr = (NMVPNManager *) user_data; NMVPNConnection * vpn; + const char * user_name; + const char * service_name; + NMVPNService * service; + NMVPNActRequest * req; + dbus_uint32_t stage; - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (data->data != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (vpn_mgr != NULL, NULL); + g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (message != NULL, NULL); - /* Check for no VPN Manager */ - if (!(manager = data->data->vpn_manager)) - return nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_VPN, "NoVPNConnections", "There are no available VPN connections."); - if (!(reply = dbus_message_new_method_return (message))) return NULL; dbus_error_init (&error); - if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) - { - if ((vpn = nm_vpn_manager_find_connection_by_name (manager, name))) - { - const char * user_name; - const char * service_name; - NMVPNService * service; - - user_name = nm_vpn_connection_get_user_name (vpn); - service_name = nm_vpn_connection_get_service_name (vpn); - if ((service = nm_vpn_manager_find_service_by_name (data->data->vpn_manager, service_name))) - { - NMVPNActRequest * req = nm_vpn_manager_get_vpn_act_request (manager); - dbus_uint32_t stage = (dbus_uint32_t) NM_VPN_ACT_STAGE_DISCONNECTED; - - if (req && (nm_vpn_act_request_get_connection (req) == vpn)) - stage = nm_vpn_act_request_get_stage (req); - - dbus_message_append_args (reply, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &user_name, - DBUS_TYPE_STRING, &service_name, DBUS_TYPE_UINT32, &stage, DBUS_TYPE_INVALID); - good = TRUE; - } - } + if (!dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) { + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE_VPN); + goto out; } - if (!good) - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_VPN, "InvalidVPNConnection", "No VPN connection with that name was found."); + if (!(vpn = nm_vpn_manager_find_connection_by_name (vpn_mgr, name))) + goto out; + + user_name = nm_vpn_connection_get_user_name (vpn); + service_name = nm_vpn_connection_get_service_name (vpn); + if (!(service = nm_vpn_manager_find_service_by_name (vpn_mgr, service_name))) + goto out; + + req = nm_vpn_manager_get_vpn_act_request (vpn_mgr); + stage = (dbus_uint32_t) NM_VPN_ACT_STAGE_DISCONNECTED; + if (req && (nm_vpn_act_request_get_connection (req) == vpn)) + stage = nm_vpn_act_request_get_stage (req); + + dbus_message_append_args (reply, DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &user_name, + DBUS_TYPE_STRING, &service_name, + DBUS_TYPE_UINT32, &stage, + DBUS_TYPE_INVALID); + success = TRUE; + +out: + if (!success) + reply = new_invalid_vpn_connection_error (message); return reply; } @@ -680,51 +813,64 @@ static DBusMessage *nm_dbus_vpn_get_vpn_connection_properties (DBusConnection *c * Activate a specific VPN connection. * */ -static DBusMessage *nm_dbus_vpn_activate_connection (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_vpn_activate_connection (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { + NMVPNManager * vpn_mgr = (NMVPNManager *) user_data; + DBusMessage * reply = NULL; DBusError error; const char * name; char ** passwords; int num_passwords; NMVPNConnection * vpn; + int item_count = -1; + char **items; + int routes_count = -1; + char **routes; - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (data->data != NULL, NULL); + g_return_val_if_fail (vpn_mgr != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (message != NULL, NULL); dbus_error_init (&error); - - if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &passwords, &num_passwords, DBUS_TYPE_INVALID)) - { - if ((vpn = nm_vpn_manager_find_connection_by_name (data->data->vpn_manager, name))) - { - int item_count = -1; - char **items; - int routes_count = -1; - char **routes; - routes = nm_dbus_vpn_get_routes (connection, vpn, &routes_count); - if ((items = nm_dbus_vpn_get_vpn_data (connection, vpn, &item_count))) - { - char * joined_string = g_strjoinv (" / ", items); - char * routes_string = g_strjoinv (" / ", routes); - nm_info ("Will activate VPN connection '%s', service '%s', user_name '%s', vpn_data '%s', route '%s'.", - name, nm_vpn_connection_get_service_name (vpn), nm_vpn_connection_get_user_name (vpn), joined_string, routes_string); - nm_vpn_manager_activate_vpn_connection (data->data->vpn_manager, vpn, passwords, num_passwords, items, item_count, - routes, routes_count); - - g_free (joined_string); - g_free (routes_string); - g_strfreev (items); - } - } else { - nm_warning ("nm_dbus_vpn_activate_connection(): cannot find VPN connection '%s'", name); - } - } else { - nm_warning ("nm_dbus_vpn_activate_connection(): syntax error in method arguments"); + if (!dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &passwords, &num_passwords, + DBUS_TYPE_INVALID)) { + reply = nm_dbus_new_invalid_args_error (message, NM_DBUS_INTERFACE_VPN); + goto out; } - return NULL; + if (!(vpn = nm_vpn_manager_find_connection_by_name (vpn_mgr, name))) { + reply = new_invalid_vpn_connection_error (message); + goto out; + } + + routes = nm_dbus_vpn_get_routes (connection, vpn, &routes_count); + if ((items = nm_dbus_vpn_get_vpn_data (connection, vpn, &item_count))) + { + char * joined_string = g_strjoinv (" / ", items); + char * routes_string = g_strjoinv (" / ", routes); + nm_info ("Will activate VPN connection '%s', service '%s', user_name " + "'%s', vpn_data '%s', route '%s'.", + name, + nm_vpn_connection_get_service_name (vpn), + nm_vpn_connection_get_user_name (vpn), + joined_string, + routes_string); + nm_vpn_manager_activate_vpn_connection (vpn_mgr, vpn, passwords, + num_passwords, items, item_count, + routes, routes_count); + + g_free (joined_string); + g_free (routes_string); + g_strfreev (items); + } + +out: + return reply; } @@ -734,25 +880,30 @@ static DBusMessage *nm_dbus_vpn_activate_connection (DBusConnection *connection, * Deactivate the active VPN connection, if any. * */ -static DBusMessage *nm_dbus_vpn_deactivate_connection (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +static DBusMessage * +nm_dbus_vpn_deactivate_connection (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { - NMVPNActRequest *req; - NMVPNConnection *vpn; + NMVPNManager * vpn_mgr = (NMVPNManager *) user_data; + NMVPNActRequest * req; + NMVPNConnection * vpn; - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (data->data != NULL, NULL); + g_return_val_if_fail (vpn_mgr != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (message != NULL, NULL); - if (!(req = nm_vpn_manager_get_vpn_act_request (data->data->vpn_manager))) + if (!(req = nm_vpn_manager_get_vpn_act_request (vpn_mgr))) return NULL; vpn = nm_vpn_act_request_get_connection (req); g_assert (vpn); - nm_info ("Will deactivate the VPN connection '%s', service '%s'.", nm_vpn_connection_get_name (vpn), - nm_vpn_connection_get_service_name (vpn)); - nm_vpn_manager_deactivate_vpn_connection (data->data->vpn_manager, nm_vpn_act_request_get_parent_dev (req)); + nm_info ("Will deactivate the VPN connection '%s', service '%s'.", + nm_vpn_connection_get_name (vpn), + nm_vpn_connection_get_service_name (vpn)); + nm_vpn_manager_deactivate_vpn_connection (vpn_mgr, + nm_vpn_act_request_get_parent_dev (req)); return NULL; } @@ -765,14 +916,20 @@ static DBusMessage *nm_dbus_vpn_deactivate_connection (DBusConnection *connectio * org.freedesktop.NetworkManager.VPNConnections object. * */ -NMDbusMethodList *nm_dbus_vpn_methods_setup (void) +NMDbusMethodList *nm_dbus_vpn_methods_setup (NMVPNManager *mgr) { - NMDbusMethodList *list = nm_dbus_method_list_new (NULL); + NMDbusMethodList * list; - nm_dbus_method_list_add_method (list, "getVPNConnections", nm_dbus_vpn_get_vpn_connections); - nm_dbus_method_list_add_method (list, "getVPNConnectionProperties", nm_dbus_vpn_get_vpn_connection_properties); - nm_dbus_method_list_add_method (list, "activateVPNConnection", nm_dbus_vpn_activate_connection); - nm_dbus_method_list_add_method (list, "deactivateVPNConnection", nm_dbus_vpn_deactivate_connection); + list = nm_dbus_method_list_new (NM_DBUS_PATH_VPN, FALSE, mgr, NULL); + + nm_dbus_method_list_add_method (list, "getVPNConnections", + nm_dbus_vpn_get_vpn_connections); + nm_dbus_method_list_add_method (list, "getVPNConnectionProperties", + nm_dbus_vpn_get_vpn_connection_properties); + nm_dbus_method_list_add_method (list, "activateVPNConnection", + nm_dbus_vpn_activate_connection); + nm_dbus_method_list_add_method (list, "deactivateVPNConnection", + nm_dbus_vpn_deactivate_connection); - return (list); + return list; } diff --git a/src/vpn-manager/nm-dbus-vpn.h b/src/vpn-manager/nm-dbus-vpn.h index 6eab8e615..8e6a85536 100644 --- a/src/vpn-manager/nm-dbus-vpn.h +++ b/src/vpn-manager/nm-dbus-vpn.h @@ -36,6 +36,6 @@ void nm_dbus_vpn_signal_vpn_connection_state_change (DBusConnection *con, NMV char ** nm_dbus_vpn_get_routes (DBusConnection *connection, NMVPNConnection *vpn, int *num_items); -NMDbusMethodList * nm_dbus_vpn_methods_setup (void); +NMDbusMethodList * nm_dbus_vpn_methods_setup (NMVPNManager *mgr); #endif diff --git a/src/vpn-manager/nm-vpn-act-request.c b/src/vpn-manager/nm-vpn-act-request.c index f5da56dad..c0dc2e564 100644 --- a/src/vpn-manager/nm-vpn-act-request.c +++ b/src/vpn-manager/nm-vpn-act-request.c @@ -24,6 +24,8 @@ #include #include "nm-vpn-act-request.h" #include "nm-dbus-vpn.h" +#include "nm-dbus-manager.h" +#include "nm-utils.h" struct NMVPNActRequest @@ -233,10 +235,20 @@ void nm_vpn_act_request_set_stage (NMVPNActRequest *req, NMVPNActStage stage) old_stage = req->stage; if (old_stage != stage) { - DBusConnection *dbus_connection = nm_vpn_service_get_dbus_connection (req->service); + NMDBusManager *dbus_mgr; + DBusConnection *dbus_connection; - req->stage = stage; - nm_dbus_vpn_signal_vpn_connection_state_change (dbus_connection, req->vpn, req->stage); + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (dbus_connection) { + req->stage = stage; + nm_dbus_vpn_signal_vpn_connection_state_change (dbus_connection, + req->vpn, + req->stage); + } else { + nm_warning ("could not get dbus connection."); + } + g_object_unref (dbus_mgr); } } diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index 644285a59..143b10125 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -23,6 +23,8 @@ #include #include "nm-vpn-connection.h" #include "nm-dbus-vpn.h" +#include "nm-dbus-manager.h" +#include "nm-utils.h" #include "NetworkManagerSystem.h" @@ -36,7 +38,6 @@ struct NMVPNConnection char * service_name; NMNamedManager *named_manager; - DBusConnection *dbus_connection; /* Change when connection is activated/deactivated */ NMDevice * parent_dev; @@ -50,8 +51,11 @@ static void nm_vpn_connection_set_ip4_config (NMVPNConnection *con, NMIP4Config static void nm_vpn_connection_set_parent_device(NMVPNConnection *con, NMDevice *parent_dev); -NMVPNConnection *nm_vpn_connection_new (const char *name, const char *user_name, const char *service_name, - NMNamedManager *named_manager, DBusConnection *dbus_connection) +NMVPNConnection * +nm_vpn_connection_new (const char *name, + const char *user_name, + const char *service_name, + NMNamedManager *named_manager) { NMVPNConnection *connection; @@ -59,7 +63,6 @@ NMVPNConnection *nm_vpn_connection_new (const char *name, const char *user_name, g_return_val_if_fail (user_name != NULL, NULL); g_return_val_if_fail (service_name != NULL, NULL); g_return_val_if_fail (named_manager != NULL, NULL); - g_return_val_if_fail (dbus_connection != NULL, NULL); connection = g_malloc0 (sizeof (NMVPNConnection)); connection->refcount = 1; @@ -71,8 +74,6 @@ NMVPNConnection *nm_vpn_connection_new (const char *name, const char *user_name, g_object_ref (named_manager); connection->named_manager = named_manager; - connection->dbus_connection = dbus_connection; - return connection; } @@ -117,28 +118,46 @@ void nm_vpn_connection_activate (NMVPNConnection *connection) } -gboolean nm_vpn_connection_set_config (NMVPNConnection *connection, const char *vpn_iface, NMDevice *dev, NMIP4Config *ip4_config) +gboolean +nm_vpn_connection_set_config (NMVPNConnection *connection, + const char *vpn_iface, + NMDevice *dev, + NMIP4Config *ip4_config) { gboolean success = FALSE; int num_routes = -1; char ** routes; + DBusConnection *dbus_connection; + NMDBusManager * dbus_mgr = NULL; g_return_val_if_fail (connection != NULL, FALSE); g_return_val_if_fail (dev != NULL, FALSE); g_return_val_if_fail (ip4_config != NULL, FALSE); + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_warning ("couldn't get dbus connection."); + goto out; + } + /* IPsec VPNs will not have tunnel device */ if (vpn_iface != NULL && strlen (vpn_iface)) nm_vpn_connection_set_vpn_iface (connection, vpn_iface); nm_vpn_connection_set_parent_device (connection, dev); nm_vpn_connection_set_ip4_config (connection, ip4_config); - routes = nm_dbus_vpn_get_routes (connection->dbus_connection, connection, &num_routes); - nm_system_vpn_device_set_from_ip4_config (connection->named_manager, connection->parent_dev, - connection->vpn_iface, connection->ip4_config, routes, num_routes); + routes = nm_dbus_vpn_get_routes (dbus_connection, connection, &num_routes); + nm_system_vpn_device_set_from_ip4_config (connection->named_manager, + connection->parent_dev, + connection->vpn_iface, + connection->ip4_config, + routes, + num_routes); g_strfreev(routes); success = TRUE; +out: return success; } diff --git a/src/vpn-manager/nm-vpn-connection.h b/src/vpn-manager/nm-vpn-connection.h index a043e4503..3713cb44d 100644 --- a/src/vpn-manager/nm-vpn-connection.h +++ b/src/vpn-manager/nm-vpn-connection.h @@ -27,7 +27,7 @@ typedef struct NMVPNConnection NMVPNConnection; NMVPNConnection * nm_vpn_connection_new (const char *name, const char *user_name, const char *service_name, - NMNamedManager *named_manager, DBusConnection *dbus_connection); + NMNamedManager *named_manager); void nm_vpn_connection_ref (NMVPNConnection *con); void nm_vpn_connection_unref (NMVPNConnection *con); diff --git a/src/vpn-manager/nm-vpn-manager.c b/src/vpn-manager/nm-vpn-manager.c index 2857f292d..361e67c77 100644 --- a/src/vpn-manager/nm-vpn-manager.c +++ b/src/vpn-manager/nm-vpn-manager.c @@ -32,6 +32,7 @@ #include "nm-vpn-service.h" #include "nm-dbus-vpn.h" #include "nm-utils.h" +#include "nm-dbus-manager.h" #define VPN_SERVICE_FILE_PATH SYSCONFDIR"/NetworkManager/VPN" @@ -42,6 +43,7 @@ struct NMVPNManager GSList * connections; NMVPNActRequest * act_req; + NMDbusMethodList * dbus_methods; }; static void load_services (NMVPNManager *manager, GHashTable *table); @@ -55,15 +57,24 @@ static void load_services (NMVPNManager *manager, GHashTable *table); NMVPNManager *nm_vpn_manager_new (NMData *app_data) { NMVPNManager * manager; + NMDBusManager * dbus_mgr; g_return_val_if_fail (app_data != NULL, NULL); - manager = g_malloc0 (sizeof (NMVPNManager)); + manager = g_slice_new0 (NMVPNManager); manager->app_data = app_data; - manager->service_table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) nm_vpn_service_unref); + manager->service_table = g_hash_table_new_full (g_str_hash, + g_str_equal, + NULL, + (GDestroyNotify) nm_vpn_service_unref); load_services (manager, manager->service_table); + manager->dbus_methods = nm_dbus_vpn_methods_setup (manager); + dbus_mgr = nm_dbus_manager_get (NULL); + nm_dbus_manager_register_method_list (dbus_mgr, manager->dbus_methods); + g_object_unref (dbus_mgr); + return manager; } @@ -86,8 +97,10 @@ void nm_vpn_manager_dispose (NMVPNManager *manager) g_hash_table_destroy (manager->service_table); + nm_dbus_method_list_unref (manager->dbus_methods); + memset (manager, 0, sizeof (NMVPNManager)); - g_free (manager); + g_slice_free (NMVPNManager, manager); } @@ -157,10 +170,17 @@ GSList *nm_vpn_manager_vpn_connection_list_copy (NMVPNManager *manager) * Add a new VPN connection if none already exits, otherwise update the existing one. * */ -NMVPNConnection *nm_vpn_manager_add_connection (NMVPNManager *manager, const char *name, const char *service_name, const char *user_name) +NMVPNConnection * +nm_vpn_manager_add_connection (NMVPNManager *manager, + const char *name, + const char *service_name, + const char *user_name) { NMVPNConnection * connection = NULL; NMVPNService * service; + DBusConnection * dbus_connection; + NMDBusManager * dbus_mgr = NULL; + GSList * elt; g_return_val_if_fail (manager != NULL, NULL); g_return_val_if_fail (name != NULL, NULL); @@ -171,28 +191,44 @@ NMVPNConnection *nm_vpn_manager_add_connection (NMVPNManager *manager, const cha if (!(service = nm_vpn_manager_find_service_by_name (manager, service_name))) return NULL; - if ((connection = nm_vpn_connection_new (name, user_name, service_name, manager->app_data->named_manager, - manager->app_data->dbus_connection))) - { - GSList *elt; - - /* Remove the existing connection if found */ - for (elt = manager->connections; elt; elt = g_slist_next (elt)) - { - NMVPNConnection *con = (NMVPNConnection *)(elt->data); - - if (con && nm_vpn_connection_get_name (con) && (strcmp (nm_vpn_connection_get_name (con), name) == 0)) - { - manager->connections = g_slist_remove_link (manager->connections, elt); - nm_vpn_connection_unref (con); - g_slist_free (elt); - } - } - - /* Add in the updated connection */ - manager->connections = g_slist_append (manager->connections, connection); + dbus_mgr = nm_dbus_manager_get (NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); + if (!dbus_connection) { + nm_warning ("couldn't get dbus connection."); + goto out; } + connection = nm_vpn_connection_new (name, + user_name, + service_name, + manager->app_data->named_manager); + if (!connection) { + nm_warning ("couldn't create VPN connecton for '%s (%s).", + name, + service_name); + goto out; + } + + /* Remove the existing connection if found */ + for (elt = manager->connections; elt; elt = g_slist_next (elt)) { + NMVPNConnection *con = (NMVPNConnection *)(elt->data); + + + if (!con || !nm_vpn_connection_get_name (con)) + continue; + if (strcmp (nm_vpn_connection_get_name (con), name) != 0) + continue; + + manager->connections = g_slist_remove_link (manager->connections, elt); + nm_vpn_connection_unref (con); + g_slist_free (elt); + } + + /* Add in the updated connection */ + manager->connections = g_slist_append (manager->connections, connection); + +out: + g_object_unref (dbus_mgr); return connection; } @@ -267,66 +303,6 @@ NMVPNActRequest *nm_vpn_manager_get_vpn_act_request (NMVPNManager *manager) } -static inline gboolean same_service_name (NMVPNService *service, NMVPNConnection *vpn) -{ - g_return_val_if_fail (service != NULL, FALSE); - g_return_val_if_fail (vpn != NULL, FALSE); - - return (!strcmp (nm_vpn_service_get_service_name (service), nm_vpn_connection_get_service_name (vpn))); -} - - -/* - * nm_vpn_manager_process_signal - * - * Possibly process a signal from the bus, if it comes from the currently - * active VPN daemon, if any. Return TRUE if processed, FALSE if not. - * - */ -gboolean nm_vpn_manager_process_signal (NMVPNManager *manager, DBusMessage *message) -{ - const char * service_name; - NMVPNService * service; - gboolean handled = FALSE; - - g_return_val_if_fail (manager != NULL, FALSE); - g_return_val_if_fail (message != NULL, FALSE); - - service_name = dbus_message_get_interface (message); - if ((service = nm_vpn_manager_find_service_by_name (manager, service_name))) - { - nm_vpn_service_process_signal (service, manager->act_req, message); - handled = TRUE; - } - - return handled; -} - - -/* - * nm_vpn_manager_process_name_owner_changed - * - * Respond to "service created"/"service deleted" signals from dbus for our active VPN daemon. - * - */ -gboolean nm_vpn_manager_process_name_owner_changed (NMVPNManager *manager, const char *changed_service_name, const char *old_owner, const char *new_owner) -{ - NMVPNService * service; - gboolean handled = FALSE; - - g_return_val_if_fail (manager != NULL, FALSE); - g_return_val_if_fail (changed_service_name != NULL, FALSE); - - if ((service = nm_vpn_manager_find_service_by_name (manager, changed_service_name))) - { - nm_vpn_service_name_owner_changed (service, manager->act_req, old_owner, new_owner); - handled = TRUE; - } - - return handled; -} - - /* * nm_vpn_manager_activate_vpn_connection * diff --git a/src/vpn-manager/nm-vpn-manager.h b/src/vpn-manager/nm-vpn-manager.h index a46870d57..ed005187d 100644 --- a/src/vpn-manager/nm-vpn-manager.h +++ b/src/vpn-manager/nm-vpn-manager.h @@ -44,9 +44,6 @@ void nm_vpn_manager_deactivate_vpn_connection (NMVPNManager *manager, NMDevic NMVPNConnection * nm_vpn_manager_find_connection_by_name (NMVPNManager *manager, const char *con_name); NMVPNService * nm_vpn_manager_find_service_by_name (NMVPNManager *manager, const char *service_name); -gboolean nm_vpn_manager_process_signal (NMVPNManager *manager, DBusMessage *signal); -gboolean nm_vpn_manager_process_name_owner_changed (NMVPNManager *manager, const char *service, const char *old_owner, const char *new_owner); - void nm_vpn_manager_schedule_vpn_activation_failed(NMVPNManager *manager, NMVPNActRequest *req); void nm_vpn_manager_schedule_vpn_connection_died (NMVPNManager *manager, NMVPNActRequest *req); diff --git a/src/vpn-manager/nm-vpn-service.c b/src/vpn-manager/nm-vpn-service.c index 2f5c2ac26..3c764420c 100644 --- a/src/vpn-manager/nm-vpn-service.c +++ b/src/vpn-manager/nm-vpn-service.c @@ -25,12 +25,16 @@ #include #include #include +#include +#include + #include "NetworkManagerDbus.h" #include "nm-dbus-vpn.h" #include "nm-vpn-service.h" #include "nm-vpn-act-request.h" #include "nm-utils.h" #include "dbus-dict-helpers.h" +#include "nm-dbus-manager.h" /* define this for getting VPN debug messages */ #undef NM_DEBUG_VPN_CONFIG @@ -38,9 +42,12 @@ struct NMVPNService { int refcount; - NMVPNManager * manager; - NMData * app_data; - gboolean watch_active; + NMVPNManager * manager; + NMData * app_data; + GPid pid; + gulong watch_id; + gulong dbus_con_watch_id; + NMDBusManager * dbus_mgr; char * name; char * service; @@ -59,6 +66,21 @@ static void nm_vpn_service_schedule_stage2_daemon_wait (NMVPNService *service, N static void nm_vpn_service_schedule_stage4_ip_config_get_timeout (NMVPNService *service, NMVPNActRequest *req); static void nm_vpn_service_cancel_callback (NMVPNService *service, NMVPNActRequest *req); +static gboolean nm_vpn_service_process_signal (DBusConnection *connection, + DBusMessage *message, + gpointer user_data); + +static void nm_vpn_service_name_owner_changed (NMDBusManager *mgr, + DBusConnection *connection, + const char *name, + const char *old, + const char *new, + gpointer user_data); + +static void nm_vpn_service_dbus_connection_changed (NMDBusManager *mgr, + DBusConnection *connection, + gpointer user_data); + #ifdef NM_DEBUG_VPN_CONFIG static void print_vpn_config (NMIP4Config *config, const char *tundev, @@ -80,6 +102,7 @@ NMVPNService *nm_vpn_service_new (NMVPNManager *manager, NMData *app_data) service->state = NM_VPN_STATE_SHUTDOWN; service->app_data = app_data; service->manager = manager; + service->dbus_mgr = nm_dbus_manager_get (NULL); return service; } @@ -99,9 +122,11 @@ void nm_vpn_service_unref (NMVPNService *service) service->refcount--; if (service->refcount <= 0) { + nm_vpn_service_remove_watch (service); g_free (service->name); g_free (service->service); g_free (service->program); + g_object_unref (service->dbus_mgr); memset (service, 0, sizeof (NMVPNService)); g_free (service); } @@ -143,7 +168,7 @@ void nm_vpn_service_set_service_name (NMVPNService *service, const char *name) service->service = g_strdup (name); /* If the VPN daemon is currently running, tell it to stop */ - if (!dbus_bus_name_has_owner (service->app_data->dbus_connection, service->service, NULL)) + if (nm_dbus_manager_name_has_owner (service->dbus_mgr, service->service)) nm_vpn_service_stop_connection_internal (service); } @@ -182,14 +207,6 @@ static void nm_vpn_service_set_state (NMVPNService *service, const NMVPNState st } -DBusConnection *nm_vpn_service_get_dbus_connection (NMVPNService *service) -{ - g_return_val_if_fail (service != NULL, NULL); - - return service->app_data->dbus_connection; -} - - /* * construct_op_from_service_name * @@ -283,7 +300,7 @@ void nm_vpn_service_start_connection (NMVPNService *service, NMVPNActRequest *re /* Start the daemon if it's not already running */ nm_vpn_act_request_ref (req); - if (!dbus_bus_name_has_owner (service->app_data->dbus_connection, service->service, NULL)) + if (!nm_dbus_manager_name_has_owner (service->dbus_mgr, service->service)) nm_vpn_service_schedule_stage1_daemon_exec (service, req); else nm_vpn_service_schedule_stage2_daemon_wait (service, req); @@ -303,7 +320,7 @@ static gboolean nm_vpn_service_stage1_daemon_exec (gpointer user_data) NMVPNConnection * vpn = NULL; GPtrArray * vpn_argv; GError * error = NULL; - GPid pid; + gboolean launched = FALSE; g_assert (req != NULL); @@ -320,19 +337,32 @@ static gboolean nm_vpn_service_stage1_daemon_exec (gpointer user_data) g_ptr_array_add (vpn_argv, service->program); g_ptr_array_add (vpn_argv, NULL); - if (!g_spawn_async (NULL, (char **) vpn_argv->pdata, NULL, 0, NULL, NULL, &pid, &error)) - { + launched = g_spawn_async (NULL, + (char **) vpn_argv->pdata, + NULL, + 0, + NULL, + NULL, + &service->pid, + &error); + if (!launched) { g_ptr_array_free (vpn_argv, TRUE); - nm_warning ("(VPN Service %s): could not launch the VPN service. error: '%s'.", service->service, error->message); + nm_warning ("(VPN Service %s): could not launch the VPN service. " + "error: '%s'.", + service->service, + error->message); g_error_free (error); nm_vpn_service_act_request_failed (service, req); goto out; } g_ptr_array_free (vpn_argv, TRUE); - nm_info ("VPN Activation (%s) Stage 1 of 4 (Connection Prepare) ran VPN service daemon %s (PID %d)", - nm_vpn_connection_get_name (vpn), service->service, pid); + nm_info ("VPN Activation (%s) Stage 1 of 4 (Connection Prepare) ran VPN " + "service daemon %s (PID %d)", + nm_vpn_connection_get_name (vpn), + service->service, + service->pid); nm_info ("VPN Activation (%s) Stage 1 of 4 (Connection Prepare) complete.", - nm_vpn_connection_get_name (vpn)); + nm_vpn_connection_get_name (vpn)); nm_vpn_service_schedule_stage2_daemon_wait (service, req); @@ -391,8 +421,8 @@ static gboolean nm_vpn_service_stage2_daemon_wait (gpointer user_data) nm_info ("VPN Activation (%s) Stage 2 of 4 (Connection Prepare Wait) " "waiting...", nm_vpn_connection_get_name (vpn)); - service_exists = dbus_bus_name_has_owner (service->app_data->dbus_connection, - service->service, NULL); + service_exists = nm_dbus_manager_name_has_owner (service->dbus_mgr, + service->service); if (service_exists && (service->state == NM_VPN_STATE_STOPPED)) { nm_info ("VPN Activation (%s) Stage 2 of 4 (Connection Prepare Wait) " @@ -525,6 +555,8 @@ static gboolean nm_vpn_service_stage3_connect (gpointer user_data) dbus_uint32_t user_routes_count = 0; DBusMessage * message; DBusPendingCall * pcall = NULL; + DBusConnection * dbus_connection; + gboolean success = FALSE; g_assert (req != NULL); @@ -534,17 +566,28 @@ static gboolean nm_vpn_service_stage3_connect (gpointer user_data) vpn = nm_vpn_act_request_get_connection (req); g_assert (vpn != NULL); + dbus_connection = nm_dbus_manager_get_dbus_connection (service->dbus_mgr); + if (!dbus_connection) { + nm_warning ("VPN Activation (%s) Stage 3 of 4 (Connect) could not get " + "the DBus connection.", + nm_vpn_connection_get_name (vpn)); + goto out; + } + nm_vpn_act_request_set_callback_id (req, 0); /* Send the start vpn request to the daemon */ op = construct_op_from_service_name (service->service); - message = dbus_message_new_method_call (service->service, op, service->service, "startConnection"); + message = dbus_message_new_method_call (service->service, + op, + service->service, + "startConnection"); g_free (op); - if (!message) - { - nm_warning ("(VPN Service %s): couldn't allocate dbus message.", service->service); - nm_vpn_service_act_request_failed (service, req); - return FALSE; + if (!message) { + nm_warning ("VPN Activation (%s) Stage 3 of 4 (Connect): couldn't " + " allocate dbus message.", + service->service); + goto out; } name = nm_vpn_connection_get_name (vpn); @@ -566,17 +609,23 @@ static gboolean nm_vpn_service_stage3_connect (gpointer user_data) DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &user_routes, user_routes_count, DBUS_TYPE_INVALID); - dbus_connection_send_with_reply (service->app_data->dbus_connection, message, &pcall, -1); - if (pcall) - { - dbus_pending_call_set_notify (pcall, nm_vpn_service_stage3_connect_cb, req, NULL); + dbus_connection_send_with_reply (dbus_connection, message, &pcall, -1); + if (pcall) { + dbus_pending_call_set_notify (pcall, + nm_vpn_service_stage3_connect_cb, + req, + NULL); nm_info ("VPN Activation (%s) Stage 3 of 4 (Connect) request sent," - " waiting for reply...", nm_vpn_connection_get_name (vpn)); + " waiting for reply...", + nm_vpn_connection_get_name (vpn)); + success = TRUE; } - else - nm_vpn_service_act_request_failed (service, req); dbus_message_unref (message); +out: + if (!success) + nm_vpn_service_act_request_failed (service, req); + return FALSE; } @@ -711,8 +760,9 @@ get_dbus_string_helper (DBusMessageIter *iter, */ static void nm_vpn_service_stage4_ip4_config_get_old (NMVPNService *service, - NMVPNActRequest *req, - DBusMessage *message) + NMVPNActRequest *req, + DBusConnection *dbus_connection, + DBusMessage *message) { NMVPNConnection * vpn; guint32 num; @@ -722,7 +772,7 @@ nm_vpn_service_stage4_ip4_config_get_old (NMVPNService *service, gboolean success = FALSE; DBusMessageIter iter; DBusMessageIter subiter; - NMIP4Config * config; + NMIP4Config * config = NULL; NMDevice * parent_dev; g_return_if_fail (service != NULL); @@ -741,8 +791,7 @@ nm_vpn_service_stage4_ip4_config_get_old (NMVPNService *service, dbus_message_iter_init (message, &iter); /* First arg: IP4 VPN Gateway address (UINT32) */ - if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32) - { + if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32) { nm_warning ("Error: couldn't get IP4 VPN Gateway Address" " from VPN IP Config message."); goto out; @@ -772,15 +821,13 @@ nm_vpn_service_stage4_ip4_config_get_old (NMVPNService *service, /* Sixth arg: IP4 DNS Server Addresses (ARRAY, UINT32) */ if ( !dbus_message_iter_next (&iter) - || (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)) - { + || (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)) { nm_warning ("Error: couldn't get IP4 DNS Server Addresses" " from VPN IP Config message."); goto out; } dbus_message_iter_recurse (&iter, &subiter); - while (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_UINT32) - { + while (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_UINT32) { dbus_message_iter_get_basic (&subiter, &num); if (num) nm_ip4_config_add_nameserver (config, num); @@ -789,15 +836,13 @@ nm_vpn_service_stage4_ip4_config_get_old (NMVPNService *service, /* Seventh arg: IP4 NBNS Server Addresses (ARRAY, UINT32) */ if ( !dbus_message_iter_next (&iter) - || (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)) - { + || (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)) { nm_warning ("Error: couldn't get IP4 NBNS Server Addresses" " from VPN IP Config message."); goto out; } dbus_message_iter_recurse (&iter, &subiter); - while (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_UINT32) - { + while (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_UINT32) { dbus_message_iter_get_basic (&subiter, &num); /* We don't do anything with these yet */ dbus_message_iter_next (&subiter); @@ -825,21 +870,24 @@ nm_vpn_service_stage4_ip4_config_get_old (NMVPNService *service, if (!(parent_dev = nm_vpn_act_request_get_parent_dev (req))) goto out; - if (nm_vpn_connection_set_config (vpn, tundev, parent_dev, config)) - { + if (nm_vpn_connection_set_config (vpn, tundev, parent_dev, config)) { nm_info ("VPN Activation (%s) Stage 4 of 4 (IP Config Get) complete.", nm_vpn_connection_get_name (vpn)); - if (login_banner && strlen (login_banner)) - nm_dbus_vpn_signal_vpn_login_banner (service->app_data->dbus_connection, vpn, login_banner); + if (login_banner && strlen (login_banner)) { + nm_dbus_vpn_signal_vpn_login_banner (dbus_connection, + vpn, + login_banner); + } success = TRUE; nm_vpn_service_activation_success (service, req); } out: - if (!success) - { + if (!success) { nm_ip4_config_unref (config); - nm_warning ("(VPN Service %s): did not receive valid IP config information.", service->service); + nm_warning ("(VPN Service %s): did not receive valid IP config " + "information.", + service->service); nm_vpn_service_act_request_failed (service, req); } } @@ -876,6 +924,7 @@ nm_vpn_service_stage4_ip4_config_get (NMVPNService *service, NMIP4Config * config = NULL; NMDevice * parent_dev; NMUDictEntry entry = { .type = DBUS_TYPE_STRING }; + DBusConnection *dbus_connection; g_return_if_fail (service != NULL); g_return_if_fail (message != NULL); @@ -887,18 +936,27 @@ nm_vpn_service_stage4_ip4_config_get (NMVPNService *service, nm_info ("VPN Activation (%s) Stage 4 of 4 (IP Config Get) reply received.", nm_vpn_connection_get_name (vpn)); + dbus_connection = nm_dbus_manager_get_dbus_connection (service->dbus_mgr); + if (!dbus_connection) { + nm_info ("VPN Activation (%s) Stage 4 of 4 (IP Config Get) could not " + "get the DBus connection.", + nm_vpn_connection_get_name (vpn)); + goto out; + } + dbus_message_iter_init (message, &iter); /* If first arg is (UINT32) then this is an old type message */ - if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_UINT32) - { + if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_UINT32) { nm_warning ("Warning: VPN plugin is using the old IP4Config message type"); - nm_vpn_service_stage4_ip4_config_get_old (service, req, message); + nm_vpn_service_stage4_ip4_config_get_old (service, + req, + dbus_connection, + message); return; } - if (!nmu_dbus_dict_open_read (&iter, &iter_dict)) - { + if (!nmu_dbus_dict_open_read (&iter, &iter_dict)) { nm_warning ("Warning: couldn't get config dictionary" " from VPN IP Config message."); goto out; @@ -908,17 +966,14 @@ nm_vpn_service_stage4_ip4_config_get (NMVPNService *service, nm_ip4_config_set_secondary (config, TRUE); /* First arg: Dict Type */ - if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) - { + if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) { nm_warning ("Error: couldn't get configuration dict" " from VPN IP Config message."); goto out; } - while (nmu_dbus_dict_has_dict_entry (&iter_dict)) - { - if (!nmu_dbus_dict_get_entry (&iter_dict, &entry)) - { + while (nmu_dbus_dict_has_dict_entry (&iter_dict)) { + if (!nmu_dbus_dict_get_entry (&iter_dict, &entry)) { nm_warning ("Error: couldn't read dict entry" " from VPN IP Config message."); goto out; @@ -964,12 +1019,14 @@ nm_vpn_service_stage4_ip4_config_get (NMVPNService *service, if (!(parent_dev = nm_vpn_act_request_get_parent_dev (req))) goto out; - if (nm_vpn_connection_set_config (vpn, tundev, parent_dev, config)) - { + if (nm_vpn_connection_set_config (vpn, tundev, parent_dev, config)) { nm_info ("VPN Activation (%s) Stage 4 of 4 (IP Config Get) complete.", nm_vpn_connection_get_name (vpn)); - if (login_banner && strlen (login_banner)) - nm_dbus_vpn_signal_vpn_login_banner (service->app_data->dbus_connection, vpn, login_banner); + if (login_banner && strlen (login_banner)) { + nm_dbus_vpn_signal_vpn_login_banner (dbus_connection, + vpn, + login_banner); + } success = TRUE; nm_vpn_service_activation_success (service, req); } @@ -977,33 +1034,54 @@ nm_vpn_service_stage4_ip4_config_get (NMVPNService *service, out: if (tundev) g_free (tundev); if (login_banner) g_free (login_banner); - if (!success) - { - nm_ip4_config_unref (config); - nm_warning ("(VPN Service %s): did not receive valid IP config information.", service->service); + if (!success) { + if (config) + nm_ip4_config_unref (config); + nm_warning ("(VPN Service %s): did not receive valid IP config " + "information.", + service->service); nm_vpn_service_act_request_failed (service, req); } } -static void nm_vpn_service_stop_connection_internal (NMVPNService *service) +static void +nm_vpn_service_stop_connection_internal (NMVPNService *service) { - DBusMessage * message; - char * op; + DBusConnection * dbus_connection; g_return_if_fail (service != NULL); - /* Construct a new method call with the correct service and object path */ - op = construct_op_from_service_name (service->service); - if ((message = dbus_message_new_method_call (service->service, op, service->service, "stopConnection"))) - { - dbus_connection_send (service->app_data->dbus_connection, message, NULL); - dbus_message_unref (message); - } - else - nm_warning ("(VPN Service %s): couldn't allocate dbus message.", service->service); + dbus_connection = nm_dbus_manager_get_dbus_connection (service->dbus_mgr); + if (dbus_connection) { + DBusMessage * message; + char * op; - g_free (op); + /* Construct a new method call with the correct service and object path */ + op = construct_op_from_service_name (service->service); + message = dbus_message_new_method_call (service->service, + op, + service->service, + "stopConnection"); + g_free (op); + if (!message) { + nm_warning ("(VPN Service %s): couldn't allocate dbus message.", + service->service); + } else { + dbus_connection_send (dbus_connection, message, NULL); + dbus_message_unref (message); + } + } else { + /* If we have the PID of the VPN service daemon, send it a TERM */ + if (service->pid) { + kill (service->pid, SIGTERM); + service->pid = 0; + } else { + nm_warning ("(VPN Service %s): stop called, but did not have PID " + "for VPN service daemon.", + service->service); + } + } } @@ -1033,42 +1111,46 @@ void nm_vpn_service_stop_connection (NMVPNService *service, NMVPNActRequest *req } -static void nm_vpn_service_add_watch (NMVPNService *service) +static void +nm_vpn_service_add_watch (NMVPNService *service) { - char * match_string = NULL; - g_return_if_fail (service != NULL); - if (service->watch_active) + if (service->watch_id) return; /* Add a dbus filter for this connection's service name so its signals * get delivered to us. */ - match_string = g_strdup_printf ("type='signal'," - "interface='%s'," - "sender='%s'", service->service, service->service); - dbus_bus_add_match (service->app_data->dbus_connection, match_string, NULL); - g_free (match_string); - service->watch_active = TRUE; + nm_dbus_manager_register_signal_handler (service->dbus_mgr, + service->service, + NULL, + nm_vpn_service_process_signal, + service); + service->watch_id = g_signal_connect (service->dbus_mgr, + "name-owner-changed", + G_CALLBACK (nm_vpn_service_name_owner_changed), + service); + service->dbus_con_watch_id = g_signal_connect (service->dbus_mgr, + "dbus-connection-changed", + G_CALLBACK (nm_vpn_service_dbus_connection_changed), + service); } -static void nm_vpn_service_remove_watch (NMVPNService *service) +static void +nm_vpn_service_remove_watch (NMVPNService *service) { - char * match_string = NULL; - g_return_if_fail (service != NULL); - if (!service->watch_active) + if (!service->watch_id) return; - match_string = g_strdup_printf ("type='signal'," - "interface='%s'," - "sender='%s'", service->service, service->service); - dbus_bus_remove_match (service->app_data->dbus_connection, match_string, NULL); - g_free (match_string); - service->watch_active = FALSE; + nm_dbus_manager_remove_signal_handler (service->dbus_mgr, service->service); + g_signal_handler_disconnect (service->dbus_mgr, service->watch_id); + service->watch_id = 0; + g_signal_handler_disconnect (service->dbus_mgr, service->dbus_con_watch_id); + service->dbus_con_watch_id = 0; } @@ -1080,96 +1162,158 @@ static inline gboolean same_service_name (NMVPNService *service, NMVPNConnection return (!strcmp (nm_vpn_service_get_service_name (service), nm_vpn_connection_get_service_name (vpn))); } - -gboolean nm_vpn_service_name_owner_changed (NMVPNService *service, NMVPNActRequest *req, const char *old, const char *new) +static void +nm_vpn_service_dbus_connection_changed (NMDBusManager *mgr, + DBusConnection *dbus_connection, + gpointer user_data) { + NMVPNService * service = (NMVPNService *) user_data; + + g_return_if_fail (service != NULL); + + if (!dbus_connection) { + NMVPNActRequest * req; + NMVPNConnection * vpn; + gboolean valid_vpn = FALSE; + + /* Kill the VPN service since we can't talk to it anymore anyway */ + nm_vpn_service_set_state (service, NM_VPN_STATE_SHUTDOWN); + nm_vpn_service_remove_watch (service); + + req = nm_vpn_manager_get_vpn_act_request (service->manager); + if (req && (vpn = nm_vpn_act_request_get_connection (req))) + valid_vpn = same_service_name (service, vpn); + + if (valid_vpn) { + nm_vpn_act_request_unref (req); + nm_vpn_manager_schedule_vpn_connection_died (service->manager, req); + } + } +} + +static void +nm_vpn_service_name_owner_changed (NMDBusManager *mgr, + DBusConnection *connection, + const char *name, + const char *old, + const char *new, + gpointer user_data) +{ + NMVPNService * service = (NMVPNService *) user_data; + NMVPNActRequest * req; NMVPNConnection * vpn; gboolean valid_vpn = FALSE; gboolean old_owner_good = (old && strlen (old)); gboolean new_owner_good = (new && strlen (new)); - g_return_val_if_fail (service != NULL, FALSE); + g_return_if_fail (service != NULL); + if (strcmp (name, service->service) != 0) + return; + + req = nm_vpn_manager_get_vpn_act_request (service->manager); if (req && (vpn = nm_vpn_act_request_get_connection (req))) valid_vpn = same_service_name (service, vpn); - if (!old_owner_good && new_owner_good) - { + if (!old_owner_good && new_owner_good) { /* VPN service started. */ nm_vpn_service_add_watch (service); nm_vpn_service_set_state (service, NM_VPN_STATE_INIT); - } - else if (old_owner_good && !new_owner_good) - { + } else if (old_owner_good && !new_owner_good) { /* VPN service went away. */ nm_vpn_service_set_state (service, NM_VPN_STATE_SHUTDOWN); nm_vpn_service_remove_watch (service); - if (valid_vpn) - { + if (valid_vpn) { nm_vpn_act_request_unref (req); nm_vpn_manager_schedule_vpn_connection_died (service->manager, req); } } - - return TRUE; } -gboolean nm_vpn_service_process_signal (NMVPNService *service, NMVPNActRequest *req, DBusMessage *message) +static gboolean +nm_vpn_service_process_signal (DBusConnection *connection, + DBusMessage *message, + gpointer user_data) { + NMVPNService * service = (NMVPNService *) user_data; NMVPNConnection * vpn = NULL; + NMVPNActRequest * req; gboolean valid_vpn = FALSE; - g_return_val_if_fail (service != NULL, FALSE); + g_return_val_if_fail (connection != NULL, FALSE); g_return_val_if_fail (message != NULL, FALSE); + g_return_val_if_fail (service != NULL, FALSE); + req = nm_vpn_manager_get_vpn_act_request (service->manager); if (req && (vpn = nm_vpn_act_request_get_connection (req))) valid_vpn = same_service_name (service, vpn); - if ( dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_LOGIN_FAILED) - || dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_LAUNCH_FAILED) - || dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_CONNECT_FAILED) - || dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD) - || dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_IP_CONFIG_BAD)) + if ( dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_LOGIN_FAILED) + || dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_LAUNCH_FAILED) + || dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_CONNECT_FAILED) + || dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD) + || dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_IP_CONFIG_BAD)) { const char * member = dbus_message_get_member (message); char * error_msg; - if (valid_vpn) - { - if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &error_msg, DBUS_TYPE_INVALID)) + if (valid_vpn) { + if (!dbus_message_get_args (message, + NULL, + DBUS_TYPE_STRING, &error_msg, + DBUS_TYPE_INVALID)) { error_msg = (char *) ""; - nm_warning ("VPN failed for service '%s', signal '%s', with message '%s'.", service->service, member, error_msg); - nm_dbus_vpn_signal_vpn_failed (service->app_data->dbus_connection, member, vpn, error_msg); - /* Don't deal with VPN Connection stopping here, we'll do that when we get the STOPPED or STOPPING signal below */ + } + nm_warning ("VPN failed for service '%s', signal '%s', with " + " message '%s'.", + service->service, + member, + error_msg); + nm_dbus_vpn_signal_vpn_failed (connection, member, vpn, error_msg); + + /* Don't deal with VPN Connection stopping here, we'll do that + * when we get the STOPPED or STOPPING signal below. + */ } - } - else if (dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_STATE_CHANGE)) - { + } else if (dbus_message_is_signal (message, service->service, + NM_DBUS_VPN_SIGNAL_STATE_CHANGE)) { dbus_uint32_t old_state_int; dbus_uint32_t new_state_int; - if (dbus_message_get_args (message, NULL, DBUS_TYPE_UINT32, &old_state_int, DBUS_TYPE_UINT32, &new_state_int, DBUS_TYPE_INVALID)) - { + if (dbus_message_get_args (message, + NULL, + DBUS_TYPE_UINT32, &old_state_int, + DBUS_TYPE_UINT32, &new_state_int, + DBUS_TYPE_INVALID)) { NMVPNState old_state = (NMVPNState) old_state_int; NMVPNState new_state = (NMVPNState) new_state_int; - nm_info ("VPN service '%s' signaled state change %d -> %d.", service->service, old_state, new_state); + nm_info ("VPN service '%s' signaled state change %d -> %d.", + service->service, + old_state, + new_state); nm_vpn_service_set_state (service, new_state); - /* If the VPN daemon state is now stopped and it was starting, clear the active connection */ - if (((new_state == NM_VPN_STATE_STOPPED) || (new_state == NM_VPN_STATE_SHUTDOWN) || (new_state == NM_VPN_STATE_STOPPING)) - && ((old_state == NM_VPN_STATE_STARTED) || (old_state == NM_VPN_STATE_STARTING)) - && valid_vpn) - { + /* If the VPN daemon state is now stopped and it was starting, + * clear the active connection. + */ + if ( ( (new_state == NM_VPN_STATE_STOPPED) + || (new_state == NM_VPN_STATE_SHUTDOWN) + || (new_state == NM_VPN_STATE_STOPPING)) + && ( (old_state == NM_VPN_STATE_STARTED) + || (old_state == NM_VPN_STATE_STARTING)) + && valid_vpn) { nm_vpn_act_request_unref (req); nm_vpn_manager_schedule_vpn_connection_died (service->manager, req); } } - } - else if (valid_vpn && dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_IP4_CONFIG)) + } else if ( valid_vpn + && dbus_message_is_signal (message, service->service, + NM_DBUS_VPN_SIGNAL_IP4_CONFIG)) { nm_vpn_service_stage4_ip4_config_get (service, req, message); + } return TRUE; } diff --git a/src/vpn-manager/nm-vpn-service.h b/src/vpn-manager/nm-vpn-service.h index b1ee92ff6..6e9ad9b09 100644 --- a/src/vpn-manager/nm-vpn-service.h +++ b/src/vpn-manager/nm-vpn-service.h @@ -46,12 +46,7 @@ void nm_vpn_service_set_service_name (NMVPNService *service, const char *name) const char * nm_vpn_service_get_program (NMVPNService *service); void nm_vpn_service_set_program (NMVPNService *service, const char *program); -DBusConnection* nm_vpn_service_get_dbus_connection (NMVPNService *service); - -NMVPNState nm_vpn_service_get_state (NMVPNService *service); - -gboolean nm_vpn_service_name_owner_changed (NMVPNService *service, NMVPNActRequest *req, const char *old, const char *new); -gboolean nm_vpn_service_process_signal (NMVPNService *service, NMVPNActRequest *req, DBusMessage *message); +NMVPNState nm_vpn_service_get_state (NMVPNService *service); void nm_vpn_service_start_connection (NMVPNService *service, NMVPNActRequest *req); void nm_vpn_service_stop_connection (NMVPNService *service, NMVPNActRequest *req);