diff --git a/src/Makefile.am b/src/Makefile.am index 811470adf..7e7487593 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -42,6 +42,8 @@ NetworkManager_SOURCES = \ nm-dbus-net.h \ nm-dbus-nmi.c \ nm-dbus-nmi.h \ + nm-hal-manager.c \ + nm-hal-manager.h \ nm-ip4-config.c \ nm-ip4-config.h \ NetworkManager.c \ @@ -54,6 +56,8 @@ NetworkManager_SOURCES = \ NetworkManagerSystem.h \ nm-logging.c \ nm-logging.h \ + nm-manager.c \ + nm-manager.h \ nm-netlink-monitor.c \ nm-netlink-monitor.h \ nm-activation-request.c \ diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 73fd6de27..354e3d2d7 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -41,6 +40,8 @@ #include "NetworkManager.h" #include "nm-utils.h" #include "NetworkManagerUtils.h" +#include "nm-manager.h" +#include "nm-hal-manager.h" #include "nm-device.h" #include "nm-device-802-3-ethernet.h" #include "nm-device-802-11-wireless.h" @@ -64,329 +65,14 @@ #define NM_DEFAULT_PID_FILE LOCALSTATEDIR"/run/NetworkManager.pid" -#define NO_HAL_MSG "Could not initialize connection to the HAL daemon." - /* * Globals */ static NMData *nm_data = NULL; +static NMManager *manager = 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 - * - */ -static char *nm_get_device_interface_from_hal (LibHalContext *ctx, const char *udi) -{ - char *iface = NULL; - - if (libhal_device_property_exists (ctx, udi, "net.interface", NULL)) - { - /* Only use Ethernet and Wireless devices at the moment */ - if (libhal_device_property_exists (ctx, udi, "info.category", NULL)) - { - char *category = libhal_device_get_property_string (ctx, udi, "info.category", NULL); - if (category && (!strcmp (category, "net.80203") || !strcmp (category, "net.80211"))) - { - char *temp = libhal_device_get_property_string (ctx, udi, "net.interface", NULL); - iface = g_strdup (temp); - libhal_free_string (temp); - } - libhal_free_string (category); - } - } - - return (iface); -} - - -/* - * nm_device_test_wireless_extensions - * - * Test whether a given device is a wireless one or not. - * - */ -static NMDeviceType -discover_device_type (LibHalContext *ctx, const char *udi) -{ - char * category = NULL; - - if (libhal_device_property_exists (ctx, udi, "info.category", NULL)) - category = libhal_device_get_property_string(ctx, udi, "info.category", NULL); - if (category && (!strcmp (category, "net.80211"))) - return DEVICE_TYPE_802_11_WIRELESS; - else if (category && (!strcmp (category, "net.80203"))) - return DEVICE_TYPE_802_3_ETHERNET; - return DEVICE_TYPE_UNKNOWN; -} - -/* - * nm_get_device_driver_name - * - * Get the device's driver name from HAL. - * - */ -static char * -nm_get_device_driver_name (LibHalContext *ctx, const char *udi) -{ - char * driver_name = NULL; - char * physdev_udi = NULL; - - g_return_val_if_fail (ctx != NULL, NULL); - g_return_val_if_fail (udi != NULL, NULL); - - physdev_udi = libhal_device_get_property_string (ctx, udi, "net.physical_device", NULL); - if (physdev_udi && libhal_device_property_exists (ctx, physdev_udi, "info.linux.driver", NULL)) - { - char *drv = libhal_device_get_property_string (ctx, physdev_udi, "info.linux.driver", NULL); - driver_name = g_strdup (drv); - g_free (drv); - } - g_free (physdev_udi); - - return driver_name; -} - - -static NMDevice * -create_nm_device (LibHalContext *ctx, - const char *iface, - const char *udi) -{ - NMDevice *dev; - char *driver; - NMDeviceType type; - - type = discover_device_type (ctx, udi); - driver = nm_get_device_driver_name (ctx, udi); - - switch (type) { - case DEVICE_TYPE_802_11_WIRELESS: - dev = (NMDevice *) nm_device_802_11_wireless_new (iface, udi, driver, FALSE, nm_data); - break; - case DEVICE_TYPE_802_3_ETHERNET: - dev = (NMDevice *) nm_device_802_3_ethernet_new (iface, udi, driver, FALSE, nm_data); - break; - - default: - g_assert_not_reached (); - } - - g_free (driver); - - return dev; -} - - -/* - * nm_create_device_and_add_to_list - * - * Create a new network device and add it to our device list. - * - * Returns: newly allocated device on success - * NULL on failure - */ -NMDevice * nm_create_device_and_add_to_list (NMData *data, const char *udi, const char *iface, - gboolean test_device, NMDeviceType test_device_type) -{ - NMDevice *dev = NULL; - - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (udi != NULL, NULL); - g_return_val_if_fail (iface != NULL, NULL); - g_return_val_if_fail (strlen (iface) > 0, NULL); - - /* If we are called to create a test devices, but test devices weren't enabled - * on the command-line, don't create the device. - */ - if (!data->enable_test_devices && test_device) - { - nm_warning ("attempted to create a test device, " - "but test devices were not enabled " - "on the command line."); - return (NULL); - } - - /* Make sure the device is not already in the device list */ - if ((dev = nm_get_device_by_iface (data, iface))) - return (NULL); - - if ((dev = create_nm_device (data->hal_ctx, iface, udi))) { - nm_info ("Now managing %s device '%s'.", - NM_IS_DEVICE_802_11_WIRELESS (dev) ? "wireless (802.11)" : "wired Ethernet (802.3)", - nm_device_get_iface (dev)); - - data->dev_list = g_slist_append (data->dev_list, dev); - nm_device_deactivate (dev); - - nm_policy_schedule_device_change_check (data); - nm_dbus_schedule_device_status_change_signal (data, dev, NULL, DEVICE_ADDED); - } - - return dev; -} - - -/* - * nm_remove_device - * - * Removes a particular device from the device list. - */ -void nm_remove_device (NMData *data, NMDevice *dev) -{ - g_return_if_fail (data != NULL); - g_return_if_fail (dev != NULL); - - nm_device_set_removed (dev, TRUE); - nm_device_stop (dev); - nm_dbus_schedule_device_status_change_signal (data, dev, NULL, DEVICE_REMOVED); - - g_object_unref (G_OBJECT (dev)); - - /* Remove the device entry from the device list and free its data */ - data->dev_list = g_slist_remove (data->dev_list, dev); -} - - -/* - * nm_get_active_device - * - * Return the currently active device. - * - */ -NMDevice *nm_get_active_device (NMData *data) -{ - GSList * elt; - - g_return_val_if_fail (data != NULL, NULL); - - for (elt = data->dev_list; elt; elt = g_slist_next (elt)) { - NMDevice * dev = NM_DEVICE (elt->data); - - g_assert (dev); - if (nm_device_get_act_request (dev)) - return dev; - } - - return NULL; -} - - -/* - * nm_hal_device_added - * - */ -static void nm_hal_device_added (LibHalContext *ctx, const char *udi) -{ - NMData *data = (NMData *)libhal_ctx_get_user_data (ctx); - char *iface = NULL; - - g_return_if_fail (data != NULL); - - nm_debug ("New device added (hal udi is '%s').", udi ); - - /* Sometimes the device's properties (like net.interface) are not set up yet, - * so this call will fail, and it will actually be added when hal sets the device's - * capabilities a bit later on. - */ - if ((iface = nm_get_device_interface_from_hal (data->hal_ctx, udi))) - { - nm_create_device_and_add_to_list (data, udi, iface, FALSE, DEVICE_TYPE_UNKNOWN); - g_free (iface); - } -} - - -/* - * nm_hal_device_removed - * - */ -static void nm_hal_device_removed (LibHalContext *ctx, const char *udi) -{ - NMData * data; - NMDevice * dev; - - data = (NMData *) libhal_ctx_get_user_data (ctx); - g_return_if_fail (data != NULL); - - nm_debug ("Device removed (hal udi is '%s').", udi ); - - if ((dev = nm_get_device_by_udi (data, udi))) { - nm_remove_device (data, dev); - nm_policy_schedule_device_change_check (data); - } -} - - -/* - * nm_hal_device_new_capability - * - */ -static void nm_hal_device_new_capability (LibHalContext *ctx, const char *udi, const char *capability) -{ - NMData *data = (NMData *)libhal_ctx_get_user_data (ctx); - - g_return_if_fail (data != NULL); - - /*nm_debug ("nm_hal_device_new_capability() called with udi = %s, capability = %s", udi, capability );*/ - - if (capability && ((strcmp (capability, "net.80203") == 0) || (strcmp (capability, "net.80211") == 0))) - { - char *iface; - - if ((iface = nm_get_device_interface_from_hal (data->hal_ctx, udi))) - { - nm_create_device_and_add_to_list (data, udi, iface, FALSE, DEVICE_TYPE_UNKNOWN); - g_free (iface); - } - } -} - - -/* - * nm_add_initial_devices - * - * Add all devices that hal knows about right now (ie not hotplug devices) - * - */ -void nm_add_initial_devices (NMData *data) -{ - char ** net_devices; - int num_net_devices; - int i; - DBusError error; - - g_return_if_fail (data != NULL); - - dbus_error_init (&error); - /* Grab a list of network devices */ - net_devices = libhal_find_device_by_capability (data->hal_ctx, "net", &num_net_devices, &error); - if (dbus_error_is_set (&error)) - { - nm_warning ("could not find existing networking devices: %s", error.message); - dbus_error_free (&error); - } - - if (net_devices) - { - for (i = 0; i < num_net_devices; i++) - { - char *iface; - - if ((iface = nm_get_device_interface_from_hal (data->hal_ctx, net_devices[i]))) - { - nm_create_device_and_add_to_list (data, net_devices[i], iface, FALSE, DEVICE_TYPE_UNKNOWN); - g_free (iface); - } - } - } - - libhal_free_string_array (net_devices); -} - /* * nm_state_change_signal_broadcast @@ -394,17 +80,18 @@ 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; + NMState state; + NMDBusManager *dbus_mgr; + DBusConnection *dbus_connection; - g_return_val_if_fail (data != NULL, FALSE); + state = nm_manager_get_state (manager); dbus_mgr = nm_dbus_manager_get (); dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); if (dbus_connection) - nm_dbus_signal_state_change (dbus_connection, data); + nm_dbus_signal_state_change (dbus_connection, state); g_object_unref (dbus_mgr); + return FALSE; } @@ -415,16 +102,10 @@ static gboolean nm_state_change_signal_broadcast (gpointer user_data) */ void nm_schedule_state_change_signal_broadcast (NMData *data) { - guint id = 0; - GSource * source; - - g_return_if_fail (data != NULL); - - id = g_idle_add (nm_state_change_signal_broadcast, data); - source = g_main_context_find_source_by_id (NULL, id); - if (source) { - g_source_set_priority (source, G_PRIORITY_HIGH); - } + g_idle_add_full (G_PRIORITY_HIGH, + nm_state_change_signal_broadcast, + NULL, + NULL); } @@ -466,88 +147,6 @@ 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); - 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 * @@ -601,16 +200,6 @@ static NMData *nm_data_new (gboolean enable_test_devices) } -static void device_stop_and_free (NMDevice *dev, gpointer user_data) -{ - g_return_if_fail (dev != NULL); - - nm_device_set_removed (dev, TRUE); - nm_device_deactivate (dev); - g_object_unref (G_OBJECT (dev)); -} - - /* * nm_data_free * @@ -627,10 +216,6 @@ static void nm_data_free (NMData *data) if ((req = nm_vpn_manager_get_vpn_act_request (data->vpn_manager))) nm_vpn_manager_deactivate_vpn_connection (data->vpn_manager, nm_vpn_act_request_get_parent_dev (req)); - /* Stop and destroy all devices */ - g_slist_foreach (data->dev_list, (GFunc) device_stop_and_free, NULL); - g_slist_free (data->dev_list); - if (data->netlink_monitor) { g_object_unref (G_OBJECT (data->netlink_monitor)); data->netlink_monitor = NULL; @@ -648,8 +233,6 @@ static void nm_data_free (NMData *data) g_main_loop_unref (data->main_loop); g_io_channel_unref(data->sigterm_iochannel); - nm_hal_deinit (data); - g_slice_free (NMData, data); } @@ -679,19 +262,7 @@ nm_name_owner_changed_handler (NMDBusManager *mgr, gboolean old_owner_good = (old && (strlen (old) > 0)); gboolean new_owner_good = (new && (strlen (new) > 0)); - /* Only care about signals from HAL */ - if (strcmp (name, "org.freedesktop.Hal") == 0) { - if (!old_owner_good && new_owner_good) { - /* HAL just appeared */ - if (!nm_hal_init (data, connection)) { - nm_error (NO_HAL_MSG); - exit (EXIT_FAILURE); - } - } else if (old_owner_good && !new_owner_good) { - /* HAL went away. Bad HAL. */ - nm_hal_deinit (data); - } - } else if (strcmp (name, NMI_DBUS_SERVICE) == 0) { + if (strcmp (name, NMI_DBUS_SERVICE) == 0) { if (!old_owner_good && new_owner_good) { /* NMI appeared, update stuff */ nm_policy_schedule_allowed_ap_list_update (data); @@ -702,28 +273,6 @@ nm_name_owner_changed_handler (NMDBusManager *mgr, } } -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) { @@ -774,6 +323,8 @@ main (int argc, char *argv[]) gboolean show_usage = FALSE; char * pidfile = NULL; char * user_pidfile = NULL; + NMPolicy *policy; + NMHalManager *hal_manager = NULL; NMDBusManager * dbus_mgr; DBusConnection *dbus_connection; NMSupplicantManager * sup_mgr = NULL; @@ -864,8 +415,6 @@ main (int argc, char *argv[]) } 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); id = nm_dbus_manager_register_signal_handler (dbus_mgr, NMI_DBUS_INTERFACE, NULL, @@ -880,6 +429,9 @@ main (int argc, char *argv[]) nm_dbus_manager_register_method_list (dbus_mgr, nm_data->device_methods); nm_data->net_methods = nm_dbus_net_methods_setup (nm_data); + manager = nm_manager_new (); + policy = nm_policy_new (manager); + /* Initialize the supplicant manager */ sup_mgr = nm_supplicant_manager_get (); if (!sup_mgr) { @@ -887,7 +439,7 @@ main (int argc, char *argv[]) goto done; } - nm_data->vpn_manager = nm_vpn_manager_new (nm_data); + nm_data->vpn_manager = nm_vpn_manager_new (manager, nm_data); if (!nm_data->vpn_manager) { nm_warning ("Failed to start the VPN manager."); goto done; @@ -905,13 +457,9 @@ main (int argc, char *argv[]) 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; - } - } + hal_manager = nm_hal_manager_new (manager, nm_data); + if (!hal_manager) + goto done; /* If NMI is running, grab allowed wireless network lists from it ASAP */ if (nm_dbus_manager_name_has_owner (dbus_mgr, NMI_DBUS_SERVICE)) { @@ -941,6 +489,12 @@ done: nm_dbus_manager_remove_signal_handler (dbus_mgr, nm_data->nmi_sig_handler_id); + nm_hal_manager_destroy (hal_manager); + nm_policy_destroy (policy); + + if (manager) + g_object_unref (manager); + nm_data_free (nm_data); if (sup_mgr) diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index a3d76ab1b..56df35c76 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -304,45 +304,17 @@ void nm_dbus_schedule_device_status_change_signal (NMData *data, NMDevice *dev, } -/* - * nm_get_app_state_from_data - * - * Return the state of the network connection - * - */ -NMState nm_get_app_state_from_data (NMData *data) -{ - NMDevice * act_dev = NULL; - - g_return_val_if_fail (data != NULL, NM_STATE_DISCONNECTED); - - if (data->asleep == TRUE) - return NM_STATE_ASLEEP; - - act_dev = nm_get_active_device (data); - if (!act_dev && !data->modem_active) - return NM_STATE_DISCONNECTED; - - if (nm_device_is_activating (act_dev)) - return NM_STATE_CONNECTING; - else - return NM_STATE_CONNECTED; -} - - /* * nm_dbus_signal_state_change * * Signal a change in state * */ -void nm_dbus_signal_state_change (DBusConnection *connection, NMData *data) +void nm_dbus_signal_state_change (DBusConnection *connection, NMState state) { DBusMessage * message; - NMState state; - + g_return_if_fail (connection != NULL); - g_return_if_fail (data != NULL); if (!(message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, NM_DBUS_SIGNAL_STATE_CHANGE))) { @@ -350,7 +322,6 @@ void nm_dbus_signal_state_change (DBusConnection *connection, NMData *data) return; } - state = nm_get_app_state_from_data (data); dbus_message_append_args (message, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID); if (!dbus_connection_send (connection, message, NULL)) nm_warning ("nm_dbus_signal_state_change(): Could not raise the signal!"); diff --git a/src/NetworkManagerDbus.h b/src/NetworkManagerDbus.h index 9a73956cc..5e3057599 100644 --- a/src/NetworkManagerDbus.h +++ b/src/NetworkManagerDbus.h @@ -59,15 +59,13 @@ char * nm_dbus_get_object_path_for_network (NMDevice *dev, NMAccessPoint *ap); void nm_dbus_schedule_device_status_change_signal (NMData *data, NMDevice *dev, NMAccessPoint *ap, DeviceStatus status); -void nm_dbus_signal_state_change (DBusConnection *connection, NMData *data); +void nm_dbus_signal_state_change (DBusConnection *connection, NMState state); 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); -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); diff --git a/src/NetworkManagerMain.h b/src/NetworkManagerMain.h index 8ba8f88bb..f8c89ebbe 100644 --- a/src/NetworkManagerMain.h +++ b/src/NetworkManagerMain.h @@ -25,7 +25,6 @@ #include #include #include -#include #include "NetworkManager.h" #include "NetworkManagerAP.h" #include "nm-netlink-monitor.h" @@ -34,18 +33,6 @@ #include "NetworkManagerDbusUtils.h" -typedef enum NMIntState -{ - NM_INT_STATE_UNKNOWN = 0, - NM_INT_STATE_ASLEEP, - NM_INT_STATE_CONFIGURE_AP, - NM_INT_STATE_CONFIGURE_DEV, - NM_INT_STATE_CONFIGURE_IP, - NM_INT_STATE_CONNECTED, - NM_INT_STATE_DISCONNECTED -} NMIntState; - - typedef struct NMActRequest NMActRequest; typedef struct NMVPNActRequest NMVPNActRequest; typedef struct NMVPNManager NMVPNManager; @@ -55,8 +42,6 @@ typedef struct NMData GIOChannel * sigterm_iochannel; int sigterm_pipe[2]; - LibHalContext * hal_ctx; - NmNetlinkMonitor * netlink_monitor; NMNamedManager * named_manager; @@ -85,15 +70,6 @@ typedef struct NMData } NMData; -NMDevice * nm_get_active_device (NMData *data); - -NMDevice * nm_create_device_and_add_to_list (NMData *data, const char *udi, const char *iface, - gboolean test_device, NMDeviceType test_device_type); - -void nm_add_initial_devices (NMData *data); - -void nm_remove_device (NMData *data, NMDevice *dev); - void nm_schedule_state_change_signal_broadcast (NMData *data); int nm_get_sigterm_pipe (void); diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index 5f8ac40b8..617c301c2 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -40,6 +40,20 @@ #include "nm-device-802-3-ethernet.h" #include "nm-dbus-manager.h" +struct NMPolicy { + NMManager *manager; + guint device_state_changed_idle_id; +}; + +/* NMPolicy is supposed to be one of the highest classes of the + NM class hierarchy and the only public API it needs is: + NMPolicy *nm_policy_new (NMManager *manager); + void nm_policy_destroy (NMPolicy *policy); + + Until this hasn't fixed, keep the global policy around. +*/ +static NMPolicy *global_policy; + /* * nm_policy_activation_finish @@ -286,15 +300,16 @@ nm_policy_device_change_check (gpointer user_data) { NMData * data = (NMData *) user_data; NMAccessPoint * ap = NULL; - NMDevice * new_dev = NULL; - NMDevice * old_dev = NULL; + NMDevice * new_dev; + NMDevice * old_dev; gboolean do_switch = FALSE; g_return_val_if_fail (data != NULL, FALSE); data->dev_change_check_idle_id = 0; - old_dev = nm_get_active_device (data); + g_assert (global_policy != NULL); + old_dev = nm_manager_get_active_device (global_policy->manager); if (old_dev) { guint32 caps = nm_device_get_capabilities (old_dev); @@ -455,16 +470,13 @@ static gboolean nm_policy_device_activation (gpointer user_data) { NMActRequest * req = (NMActRequest *) user_data; - NMData * data; - NMDevice * new_dev = NULL; - NMDevice * old_dev = NULL; + NMDevice * new_dev; + NMDevice * old_dev; g_return_val_if_fail (req != NULL, FALSE); - data = nm_act_request_get_data (req); - g_assert (data); - - if ((old_dev = nm_get_active_device (data))) + g_assert (global_policy != NULL); + if ((old_dev = nm_manager_get_active_device (global_policy->manager))) nm_device_deactivate (old_dev); new_dev = nm_act_request_get_dev (req); @@ -634,3 +646,136 @@ nm_policy_schedule_device_ap_lists_update_from_allowed (NMData *app_data) g_source_set_priority (source, G_PRIORITY_HIGH_IDLE); } } + +/*****************************************************************************/ + +static void +device_change_check_done (gpointer user_data) +{ + NMPolicy *policy = (NMPolicy *) user_data; + policy->device_state_changed_idle_id = 0; +} + +static void +schedule_change_check (NMPolicy *policy) +{ + if (policy->device_state_changed_idle_id > 0) + return; + + /* FIXME: Uncomment this when nm_policy_schedule_device_change_check and + all it's callers have been removed. */ +#if 0 + policy->device_state_changed_idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, + nm_policy_device_change_check, + policy, + device_change_check_done); +#endif +} + +static void +device_state_changed (NMDevice *device, NMDeviceState state, gpointer user_data) +{ + NMPolicy *policy = (NMPolicy *) user_data; + + if (state == NM_DEVICE_STATE_FAILED || state == NM_DEVICE_STATE_CANCELLED) + schedule_change_check (policy); +} + +static void +device_carrier_changed (NMDevice *device, gboolean carrier_on, gpointer user_data) +{ + NMPolicy *policy = (NMPolicy *) user_data; + + schedule_change_check (policy); +} + +static void +device_added (NMManager *manager, NMDevice *device, gpointer user_data) +{ + NMPolicy *policy = (NMPolicy *) user_data; + + g_signal_connect (device, "state-changed", + G_CALLBACK (device_state_changed), + policy); + + g_signal_connect (device, "carrier-changed", + G_CALLBACK (device_carrier_changed), + policy); + + /* FIXME: */ + { + NMData *nm_data = nm_device_get_app_data (device); + nm_data->dev_list = g_slist_append (nm_data->dev_list, device); + } + + /* FIXME: Uncomment once the patch to add these signals to wireless devices is committed */ +#if 0 + if (NM_IS_DEVICE_802_11_WIRELESS (device)) { + g_signal_connect (device, "network-added", + G_CALLBACK (wireless_networks_changed), + policy); + g_signal_connect (device, "network-removed", + G_CALLBACK (wireless_networks_changed), + policy); + } +#endif + + schedule_change_check (policy); +} + +static void +device_removed (NMManager *manager, NMDevice *device, gpointer user_data) +{ + NMPolicy *policy = (NMPolicy *) user_data; + + /* FIXME: */ + { + NMData *nm_data = nm_device_get_app_data (device); + nm_data->dev_list = g_slist_remove (nm_data->dev_list, device); + } + + schedule_change_check (policy); +} + +static void +state_changed (NMManager *manager, NMState state, gpointer user_data) +{ + /* FIXME: Do cool stuff here */ +} + +NMPolicy * +nm_policy_new (NMManager *manager) +{ + NMPolicy *policy; + + g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); + + g_assert (global_policy == NULL); + + policy = g_slice_new (NMPolicy); + policy->manager = g_object_ref (manager); + + g_signal_connect (manager, "device-added", + G_CALLBACK (device_added), policy); + + g_signal_connect (manager, "device-removed", + G_CALLBACK (device_removed), policy); + + g_signal_connect (manager, "state-change", + G_CALLBACK (state_changed), policy); + + global_policy = policy; + + return policy; +} + +void +nm_policy_destroy (NMPolicy *policy) +{ + if (policy) { + g_object_unref (policy->manager); + g_slice_free (NMPolicy, policy); + } + + global_policy = NULL; +} diff --git a/src/NetworkManagerPolicy.h b/src/NetworkManagerPolicy.h index eb11228ac..62de7d2c9 100644 --- a/src/NetworkManagerPolicy.h +++ b/src/NetworkManagerPolicy.h @@ -23,10 +23,17 @@ #define NETWORK_MANAGER_POLICY_H #include "NetworkManager.h" +#include "nm-manager.h" #include "nm-device.h" #include "NetworkManagerDbus.h" #include "nm-activation-request.h" +typedef struct NMPolicy NMPolicy; + +NMPolicy *nm_policy_new (NMManager *manager); +void nm_policy_destroy (NMPolicy *policy); + + void nm_policy_schedule_device_change_check (NMData *data); void nm_policy_schedule_device_activation (NMActRequest *req); diff --git a/src/nm-dbus-nm.c b/src/nm-dbus-nm.c index d75c6c4b6..cbc35e580 100644 --- a/src/nm-dbus-nm.c +++ b/src/nm-dbus-nm.c @@ -419,7 +419,7 @@ out: return reply; } - +#if 0 static DBusMessage * nm_dbus_nm_create_test_device (DBusConnection *connection, DBusMessage *message, @@ -521,6 +521,7 @@ out: g_object_unref (G_OBJECT (dev)); return reply; } +#endif static DBusMessage * nm_dbus_nm_set_wireless_enabled (DBusConnection *connection, @@ -606,7 +607,7 @@ nm_dbus_nm_sleep (DBusConnection *connection, /* 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); + nm_dbus_signal_state_change (connection, NM_STATE_ASLEEP); /* Just deactivate and down all devices from the device list, * we'll remove them in 'wake' for speed's sake. @@ -642,12 +643,15 @@ nm_dbus_nm_wake (DBusConnection *connection, data->asleep = FALSE; /* Remove all devices from the device list */ + /* FIXME: Well, not really. This whole file will be gone soon. */ +#if 0 while (g_slist_length (data->dev_list)) nm_remove_device (data, NM_DEVICE (data->dev_list->data)); g_slist_free (data->dev_list); data->dev_list = NULL; nm_add_initial_devices (data); +#endif nm_schedule_state_change_signal_broadcast (data); nm_policy_schedule_device_change_check (data); @@ -655,6 +659,8 @@ nm_dbus_nm_wake (DBusConnection *connection, return NULL; } + + static DBusMessage * nm_dbus_nm_get_state (DBusConnection *connection, DBusMessage *message, @@ -673,7 +679,8 @@ nm_dbus_nm_get_state (DBusConnection *connection, goto out; } - state = nm_get_app_state_from_data (data); + /* FIXME: This function is deprecated and doesn't work anymore */ + state = NM_STATE_UNKNOWN; dbus_message_append_args (reply, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID); out: @@ -706,8 +713,10 @@ NMDbusMethodList *nm_dbus_nm_methods_setup (NMData *data) nm_dbus_method_list_add_method (list, "sleep", nm_dbus_nm_sleep); nm_dbus_method_list_add_method (list, "wake", nm_dbus_nm_wake); nm_dbus_method_list_add_method (list, "state", nm_dbus_nm_get_state); +#if 0 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); +#endif return list; } diff --git a/src/nm-device-802-11-wireless.h b/src/nm-device-802-11-wireless.h index 7d5dcaf81..6bf98a7a4 100644 --- a/src/nm-device-802-11-wireless.h +++ b/src/nm-device-802-11-wireless.h @@ -42,6 +42,14 @@ G_BEGIN_DECLS #define NM_IS_DEVICE_802_11_WIRELESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_802_11_WIRELESS)) #define NM_DEVICE_802_11_WIRELESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_802_11_WIRELESS, NMDevice80211WirelessClass)) +typedef enum NMWirelessScanInterval +{ + NM_WIRELESS_SCAN_INTERVAL_INIT = 0, + NM_WIRELESS_SCAN_INTERVAL_ACTIVE, + NM_WIRELESS_SCAN_INTERVAL_INACTIVE +} NMWirelessScanInterval; + + #ifndef NM_DEVICE_802_11_WIRELESS_DEFINED #define NM_DEVICE_802_11_WIRELESS_DEFINED typedef struct _NMDevice80211Wireless NMDevice80211Wireless; diff --git a/src/nm-device-802-3-ethernet.c b/src/nm-device-802-3-ethernet.c index d8ffa4ddd..6a5e962ad 100644 --- a/src/nm-device-802-3-ethernet.c +++ b/src/nm-device-802-3-ethernet.c @@ -284,24 +284,11 @@ real_get_generic_capabilities (NMDevice *dev) { NMDevice8023Ethernet * self = NM_DEVICE_802_3_ETHERNET (dev); guint32 caps = NM_DEVICE_CAP_NONE; - const char * udi = NULL; - char * usb_test = NULL; - NMData * app_data; /* cipsec devices are also explicitly unsupported at this time */ if (strstr (nm_device_get_iface (dev), "cipsec")) return NM_DEVICE_CAP_NONE; - /* Ignore Ethernet-over-USB devices too for the moment (Red Hat #135722) */ - app_data = nm_device_get_app_data (dev); - udi = nm_device_get_udi (dev); - if ( libhal_device_property_exists (app_data->hal_ctx, udi, "usb.interface.class", NULL) - && (usb_test = libhal_device_get_property_string (app_data->hal_ctx, udi, "usb.interface.class", NULL))) - { - libhal_free_string (usb_test); - return NM_DEVICE_CAP_NONE; - } - if (supports_ethtool_carrier_detect (self) || supports_mii_carrier_detect (self)) caps |= NM_DEVICE_CAP_CARRIER_DETECT; diff --git a/src/nm-device-interface.c b/src/nm-device-interface.c index 45513ffb2..ed5a4a3ca 100644 --- a/src/nm-device-interface.c +++ b/src/nm-device-interface.c @@ -83,7 +83,7 @@ nm_device_interface_init (gpointer g_iface) G_PARAM_READABLE)); /* Signals */ - g_signal_new ("state_changed", + g_signal_new ("state-changed", iface_type, G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMDeviceInterface, state_changed), @@ -92,7 +92,7 @@ nm_device_interface_init (gpointer g_iface) G_TYPE_NONE, 1, G_TYPE_UINT); - g_signal_new ("carrier_changed", + g_signal_new ("carrier-changed", iface_type, G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMDeviceInterface, carrier_changed), diff --git a/src/nm-device-interface.h b/src/nm-device-interface.h index 13083466b..4bd9d6d23 100644 --- a/src/nm-device-interface.h +++ b/src/nm-device-interface.h @@ -6,7 +6,7 @@ #include "NetworkManager.h" #define NM_TYPE_DEVICE_INTERFACE (nm_device_interface_get_type ()) -#define NM_DEVICE_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_INTERFACE, NmDeviceInterface)) +#define NM_DEVICE_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_INTERFACE, NMDeviceInterface)) #define NM_IS_DEVICE_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_INTERFACE)) #define NM_DEVICE_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_DEVICE_INTERFACE, NMDeviceInterface)) diff --git a/src/nm-device.c b/src/nm-device.c index c1211fe37..d6a75f648 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -419,55 +419,15 @@ void nm_device_set_active_link (NMDevice *self, const gboolean link_active) { - NMData * app_data; - NMActRequest * req; + NMDevicePrivate *priv; - g_return_if_fail (self != NULL); - g_return_if_fail (self->priv->app_data != NULL); + g_return_if_fail (NM_IS_DEVICE (self)); - app_data = self->priv->app_data; - req = nm_device_get_act_request (self); - - if (self->priv->link_active == link_active) - return; - - self->priv->link_active = link_active; - - /* Deactivate a currently active device */ - if (!link_active && req) { - nm_policy_schedule_device_change_check (app_data); - } else if (link_active && !req) { - NMDevice * act_dev = nm_get_active_device (app_data); - NMActRequest * act_dev_req = act_dev ? nm_device_get_act_request (act_dev) : NULL; - - /* Should we switch to this device now that it has a link? - * - * Only auto-switch for wired devices, AND... - * - * only switch to fully-supported devices, since ones that don't have carrier detection - * capability usually report the carrier as "always on" even if its not really on. User - * must manually choose semi-supported devices. - * - */ - if (NM_IS_DEVICE_802_3_ETHERNET (self) && (nm_device_get_capabilities (self) & NM_DEVICE_CAP_CARRIER_DETECT)) - { - gboolean do_switch = act_dev ? FALSE : TRUE; /* If no currently active device, switch to this one */ - NMActRequest * act_req; - - /* If active device is wireless, switch to this one */ - if (act_dev && NM_IS_DEVICE_802_11_WIRELESS (act_dev) && act_dev_req && !nm_act_request_get_user_requested (act_dev_req)) - do_switch = TRUE; - - if (do_switch && (act_req = nm_act_request_new (app_data, self, NULL, TRUE))) - { - nm_info ("Will activate wired connection '%s' because it now has a link.", nm_device_get_iface (self)); - nm_policy_schedule_device_change_check (app_data); - } - } + priv = NM_DEVICE_GET_PRIVATE (self); + if (priv->link_active != link_active) { + priv->link_active = link_active; + g_signal_emit_by_name (self, "carrier-changed", link_active); } - - g_signal_emit_by_name (self, "carrier_changed", link_active); - nm_dbus_schedule_device_status_change_signal (app_data, self, NULL, link_active ? DEVICE_CARRIER_ON : DEVICE_CARRIER_OFF); } @@ -1862,7 +1822,7 @@ nm_device_state_changed (NMDevice *device, NMDeviceState state) break; } - g_signal_emit_by_name (device, "state_changed", state); + g_signal_emit_by_name (device, "state-changed", state); } diff --git a/src/nm-device.h b/src/nm-device.h index 7d0b7068f..ce88b6dbe 100644 --- a/src/nm-device.h +++ b/src/nm-device.h @@ -42,13 +42,6 @@ # define nm_ioctl_info(fmt, args...) do { } while(0) #endif -typedef enum NMWirelessScanInterval -{ - NM_WIRELESS_SCAN_INTERVAL_INIT = 0, - NM_WIRELESS_SCAN_INTERVAL_ACTIVE, - NM_WIRELESS_SCAN_INTERVAL_INACTIVE -} NMWirelessScanInterval; - typedef enum NMActStageReturn { NM_ACT_STAGE_RETURN_FAILURE = 0, diff --git a/src/nm-hal-manager.c b/src/nm-hal-manager.c new file mode 100644 index 000000000..0a9e50ad9 --- /dev/null +++ b/src/nm-hal-manager.c @@ -0,0 +1,396 @@ +#include +#include +#include +#include "nm-hal-manager.h" +#include "nm-dbus-manager.h" +#include "nm-utils.h" +#include "nm-device-802-11-wireless.h" +#include "nm-device-802-3-ethernet.h" + +struct _NMHalManager { + LibHalContext *hal_ctx; + NMDBusManager *dbus_mgr; + NMManager *nm_manager; + NMData *nm_data; + + gboolean nm_sleeping; +}; + +static char * +get_device_interface_from_hal (LibHalContext *ctx, const char *udi) +{ + char *iface = NULL; + + if (libhal_device_property_exists (ctx, udi, "net.interface", NULL)) { + /* Only use Ethernet and Wireless devices at the moment */ + if (libhal_device_property_exists (ctx, udi, "info.category", NULL)) { + char *category = libhal_device_get_property_string (ctx, udi, "info.category", NULL); + if (category && (!strcmp (category, "net.80203") || !strcmp (category, "net.80211"))) { + char *temp = libhal_device_get_property_string (ctx, udi, "net.interface", NULL); + iface = g_strdup (temp); + libhal_free_string (temp); + } + libhal_free_string (category); + } + } + + return iface; +} + +static NMDeviceType +discover_device_type (LibHalContext *ctx, const char *udi) +{ + char *category = NULL; + + if (libhal_device_property_exists (ctx, udi, "info.category", NULL)) + category = libhal_device_get_property_string (ctx, udi, "info.category", NULL); + if (category && (!strcmp (category, "net.80211"))) + return DEVICE_TYPE_802_11_WIRELESS; + else if (category && (!strcmp (category, "net.80203"))) + return DEVICE_TYPE_802_3_ETHERNET; + + return DEVICE_TYPE_UNKNOWN; +} + +/* + * nm_get_device_driver_name + * + * Get the device's driver name from HAL. + * + */ +static char * +nm_get_device_driver_name (LibHalContext *ctx, const char *udi) +{ + char *physdev_udi; + char *driver_name = NULL; + + physdev_udi = libhal_device_get_property_string (ctx, udi, "net.physical_device", NULL); + if (physdev_udi && libhal_device_property_exists (ctx, physdev_udi, "info.linux.driver", NULL)) { + char *drv = libhal_device_get_property_string (ctx, physdev_udi, "info.linux.driver", NULL); + driver_name = g_strdup (drv); + g_free (drv); + } + libhal_free_string (physdev_udi); + + return driver_name; +} + +static NMDevice * +create_nm_device (LibHalContext *ctx, + NMData *nm_data, + const char *iface, + const char *udi) +{ + NMDevice *dev; + char *driver; + NMDeviceType type; + + type = discover_device_type (ctx, udi); + driver = nm_get_device_driver_name (ctx, udi); + + switch (type) { + case DEVICE_TYPE_802_11_WIRELESS: + dev = (NMDevice *) nm_device_802_11_wireless_new (iface, udi, driver, FALSE, nm_data); + break; + case DEVICE_TYPE_802_3_ETHERNET: + dev = (NMDevice *) nm_device_802_3_ethernet_new (iface, udi, driver, FALSE, nm_data); + break; + + default: + g_assert_not_reached (); + } + + g_free (driver); + + return dev; +} + +static NMDevice * +create_device_and_add_to_list (NMHalManager *manager, const char *udi, const char *iface, + gboolean test_device, NMDeviceType test_device_type) +{ + NMDevice *dev = NULL; + char *usb_test = NULL; + + /* Make sure the device is not already in the device list */ + if ((dev = nm_manager_get_device_by_iface (manager->nm_manager, iface))) + return NULL; + + /* Ignore Ethernet-over-USB devices too for the moment (Red Hat #135722) */ + if (libhal_device_property_exists (manager->hal_ctx, udi, "usb.interface.class", NULL) + && (usb_test = libhal_device_get_property_string (manager->hal_ctx, udi, "usb.interface.class", NULL))) { + + libhal_free_string (usb_test); + return NULL; + } + + if ((dev = create_nm_device (manager->hal_ctx, manager->nm_data, iface, udi))) { + nm_info ("Now managing %s device '%s'.", + NM_IS_DEVICE_802_11_WIRELESS (dev) ? "wireless (802.11)" : "wired Ethernet (802.3)", + nm_device_get_iface (dev)); + + nm_manager_add_device (manager->nm_manager, dev); + } + + return dev; +} + +static void +device_added (LibHalContext *ctx, const char *udi) +{ + NMHalManager *manager = (NMHalManager *) libhal_ctx_get_user_data (ctx); + char *iface; + + nm_debug ("New device added (hal udi is '%s').", udi ); + + /* Sometimes the device's properties (like net.interface) are not set up yet, + * so this call will fail, and it will actually be added when hal sets the device's + * capabilities a bit later on. + */ + if ((iface = get_device_interface_from_hal (manager->hal_ctx, udi))) { + create_device_and_add_to_list (manager, udi, iface, FALSE, DEVICE_TYPE_UNKNOWN); + g_free (iface); + } +} + +static void +device_removed (LibHalContext *ctx, const char *udi) +{ + NMHalManager *manager = (NMHalManager *) libhal_ctx_get_user_data (ctx); + NMDevice *dev; + + nm_debug ("Device removed (hal udi is '%s').", udi ); + + if ((dev = nm_manager_get_device_by_udi (manager->nm_manager, udi))) + nm_manager_remove_device (manager->nm_manager, dev); +} + +static void +device_new_capability (LibHalContext *ctx, const char *udi, const char *capability) +{ + NMHalManager *manager = (NMHalManager *) libhal_ctx_get_user_data (ctx); + + /*nm_debug ("nm_hal_device_new_capability() called with udi = %s, capability = %s", udi, capability );*/ + + if (capability && ((strcmp (capability, "net.80203") == 0) || (strcmp (capability, "net.80211") == 0))) { + char *iface; + + if ((iface = get_device_interface_from_hal (manager->hal_ctx, udi))) { + create_device_and_add_to_list (manager, udi, iface, FALSE, DEVICE_TYPE_UNKNOWN); + g_free (iface); + } + } +} + +static void +add_initial_devices (NMHalManager *manager) +{ + char **net_devices; + int num_net_devices; + int i; + DBusError error; + + dbus_error_init (&error); + /* Grab a list of network devices */ + net_devices = libhal_find_device_by_capability (manager->hal_ctx, "net", &num_net_devices, &error); + if (dbus_error_is_set (&error)) { + nm_warning ("could not find existing networking devices: %s", error.message); + dbus_error_free (&error); + } + + if (net_devices) { + for (i = 0; i < num_net_devices; i++) { + char *iface; + + if ((iface = get_device_interface_from_hal (manager->hal_ctx, net_devices[i]))) { + create_device_and_add_to_list (manager, net_devices[i], iface, FALSE, DEVICE_TYPE_UNKNOWN); + g_free (iface); + } + } + } + + libhal_free_string_array (net_devices); +} + +static gboolean +hal_init (NMHalManager *manager) +{ + DBusError error; + DBusGConnection *connection; + gboolean success = FALSE; + + manager->hal_ctx = libhal_ctx_new (); + if (!manager->hal_ctx) { + nm_warning ("Could not get connection to the HAL service."); + return FALSE; + } + + connection = nm_dbus_manager_get_connection (manager->dbus_mgr); + libhal_ctx_set_dbus_connection (manager->hal_ctx, + dbus_g_connection_get_connection (connection)); + + dbus_error_init (&error); + if (!libhal_ctx_init (manager->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 (manager->hal_ctx, manager); + libhal_ctx_set_device_added (manager->hal_ctx, device_added); + libhal_ctx_set_device_removed (manager->hal_ctx, device_removed); + libhal_ctx_set_device_new_capability (manager->hal_ctx, device_new_capability); + + libhal_device_property_watch_all (manager->hal_ctx, &error); + if (dbus_error_is_set (&error)) { + nm_error ("libhal_device_property_watch_all(): %s", error.message); + libhal_ctx_shutdown (manager->hal_ctx, NULL); + goto out; + } + + /* Add any devices we know about */ + add_initial_devices (manager); + success = TRUE; + +out: + if (!success) { + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + if (manager->hal_ctx) { + libhal_ctx_free (manager->hal_ctx); + manager->hal_ctx = NULL; + } + } + + return success; +} + +static void +hal_deinit (NMHalManager *manager) +{ + DBusError error; + + if (!manager->hal_ctx) + return; + + dbus_error_init (&error); + libhal_ctx_shutdown (manager->hal_ctx, &error); + if (dbus_error_is_set (&error)) { + nm_warning ("libhal shutdown failed - %s", error.message); + dbus_error_free (&error); + } + + libhal_ctx_free (manager->hal_ctx); + manager->hal_ctx = NULL; +} + +static void +name_owner_changed (NMDBusManager *dbus_mgr, + DBusGConnection *connection, + const char *name, + const char *old, + const char *new, + gpointer user_data) +{ + NMHalManager *manager = (NMHalManager *) user_data; + gboolean old_owner_good = (old && (strlen (old) > 0)); + gboolean new_owner_good = (new && (strlen (new) > 0)); + + /* Only care about signals from HAL */ + if (strcmp (name, "org.freedesktop.Hal")) + return; + + if (!old_owner_good && new_owner_good) { + /* HAL just appeared */ + if (!hal_init (manager)) + exit (EXIT_FAILURE); + } else if (old_owner_good && !new_owner_good) { + /* HAL went away. Bad HAL. */ + hal_deinit (manager); + } +} + +static void +connection_changed (NMDBusManager *dbus_mgr, + DBusGConnection *connection, + gpointer user_data) +{ + NMHalManager *manager = (NMHalManager *) user_data; + char *owner; + + if (!connection) { + hal_deinit (manager); + return; + } + + if ((owner = nm_dbus_manager_get_name_owner (dbus_mgr, "org.freedesktop.Hal"))) { + if (!hal_init (manager)) + exit (EXIT_FAILURE); + g_free (owner); + } +} + +static void +nm_manager_state_changed (NMManager *nm_manager, NMState state, gpointer user_data) +{ + NMHalManager *manager = (NMHalManager *) user_data; + + if (state == NM_STATE_ASLEEP) { + /* Save the sleep state */ + manager->nm_sleeping = TRUE; + } else if (manager->nm_sleeping) { + /* If the previous state was sleep, the next one means we just woke up */ + manager->nm_sleeping = FALSE; + add_initial_devices (manager); + } +} + +NMHalManager * +nm_hal_manager_new (NMManager *nm_manager, NMData *nm_data) +{ + NMHalManager *manager; + NMDBusManager *dbus_mgr; + + g_return_val_if_fail (NM_IS_MANAGER (nm_manager), NULL); + + dbus_mgr = nm_dbus_manager_get (); + if (!nm_dbus_manager_name_has_owner (dbus_mgr, "org.freedesktop.Hal")) { + nm_warning ("Could not initialize connection to the HAL daemon."); + return NULL; + } + + manager = g_slice_new0 (NMHalManager); + manager->nm_manager = g_object_ref (nm_manager); + manager->dbus_mgr = dbus_mgr; + manager->nm_data = nm_data; + + g_signal_connect (manager->dbus_mgr, + "name-owner-changed", + G_CALLBACK (name_owner_changed), + manager); + g_signal_connect (manager->dbus_mgr, + "dbus-connection-changed", + G_CALLBACK (connection_changed), + manager); + + g_signal_connect (nm_manager, + "state-change", + G_CALLBACK (nm_manager_state_changed), + manager); + + hal_init (manager); + add_initial_devices (manager); + + return manager; +} + +void +nm_hal_manager_destroy (NMHalManager *manager) +{ + if (manager) { + hal_deinit (manager); + g_object_unref (manager->nm_manager); + g_slice_free (NMHalManager, manager); + } +} diff --git a/src/nm-hal-manager.h b/src/nm-hal-manager.h new file mode 100644 index 000000000..06008ed03 --- /dev/null +++ b/src/nm-hal-manager.h @@ -0,0 +1,12 @@ +#ifndef NM_HAL_MANAGER_H +#define NM_HAL_MANAGER_H + +#include "nm-manager.h" +#include "NetworkManagerMain.h" + +typedef struct _NMHalManager NMHalManager; + +NMHalManager *nm_hal_manager_new (NMManager *nm_manager, NMData *nm_data); +void nm_hal_manager_destroy (NMHalManager *manager); + +#endif /* NM_HAL_MANAGER_H */ diff --git a/src/nm-manager.c b/src/nm-manager.c new file mode 100644 index 000000000..c8ee6e71c --- /dev/null +++ b/src/nm-manager.c @@ -0,0 +1,417 @@ +#include + +#include "nm-manager.h" +#include "nm-utils.h" +#include "nm-dbus-manager.h" +#include "nm-device-802-11-wireless.h" +#include "NetworkManagerSystem.h" +// #include "NetworkManagerDbus.h" + +static void manager_state_changed (NMManager *manager); +static void manager_set_wireless_enabled (NMManager *manager, gboolean enabled); + +typedef struct { + GSList *devices; + gboolean wireless_enabled; + gboolean sleeping; +} NMManagerPrivate; + +#define NM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MANAGER, NMManagerPrivate)) + +G_DEFINE_TYPE (NMManager, nm_manager, G_TYPE_OBJECT) + +enum { + DEVICE_ADDED, + DEVICE_REMOVED, + STATE_CHANGE, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +enum { + PROP_0, + PROP_STATE, + PROP_WIRELESS_ENABLED, + + LAST_PROP +}; + +static void +nm_manager_init (NMManager *msg) +{ +} + +static void +device_stop_and_free (gpointer data, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (data); + + nm_device_set_removed (device, TRUE); + nm_device_deactivate (device); + g_object_unref (device); +} + +static void +finalize (GObject *object) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object); + + g_slist_foreach (priv->devices, + device_stop_and_free, + NULL); + g_slist_free (priv->devices); + + G_OBJECT_CLASS (nm_manager_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_WIRELESS_ENABLED: + manager_set_wireless_enabled (NM_MANAGER (object), g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_STATE: + g_value_set_uint (value, nm_manager_get_state (NM_MANAGER (object))); + break; + case PROP_WIRELESS_ENABLED: + g_value_set_boolean (value, priv->wireless_enabled); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_manager_class_init (NMManagerClass *manager_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (manager_class); + + g_type_class_add_private (manager_class, sizeof (NMManagerPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + /* properties */ + g_object_class_install_property + (object_class, PROP_STATE, + g_param_spec_uint (NM_MANAGER_STATE, + "State", + "Current state", + 0, 5, 0, /* FIXME */ + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_WIRELESS_ENABLED, + g_param_spec_boolean (NM_MANAGER_WIRELESS_ENABLED, + "WirelessEnabled", + "Is wireless enabled", + TRUE, + G_PARAM_READWRITE)); + + /* signals */ + signals[DEVICE_ADDED] = + g_signal_new ("device-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMManagerClass, device_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + signals[DEVICE_REMOVED] = + g_signal_new ("device-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMManagerClass, device_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + signals[STATE_CHANGE] = + g_signal_new ("state-change", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMManagerClass, state_change), + NULL, NULL, + g_cclosure_marshal_VOID__UCHAR, + G_TYPE_NONE, 1, + G_TYPE_UCHAR); +} + +NMManager * +nm_manager_new (void) +{ + GObject *object; + DBusGConnection *connection; + + object = g_object_new (NM_TYPE_MANAGER, NULL); + + connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); + dbus_g_connection_register_g_object (connection, + NM_DBUS_PATH, + object); + + return (NMManager *) object; +} + +static void +manager_state_changed (NMManager *manager) +{ + g_signal_emit (manager, signals[STATE_CHANGE], 0, nm_manager_get_state (manager)); +} + +static void +manager_set_wireless_enabled (NMManager *manager, gboolean enabled) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + GSList *iter; + + if (priv->wireless_enabled == enabled) + return; + + priv->wireless_enabled = enabled; + + /* Tear down all wireless devices */ + for (iter = priv->devices; iter; iter = iter->next) { + if (NM_IS_DEVICE_802_11_WIRELESS (iter->data)) { + NMDevice *dev = NM_DEVICE (iter->data); + + if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) { + nm_device_deactivate (dev); + nm_device_bring_down (dev); + } + } + } +} + +static void +manager_device_added (NMManager *manager, NMDevice *device) +{ + g_signal_emit (manager, signals[DEVICE_ADDED], 0, device); +} + +static void +manager_device_state_changed (NMDevice *device, NMDeviceState state, gpointer user_data) +{ + NMManager *manager = NM_MANAGER (user_data); + + /* Only these state changes can modify the manager state */ + if (state == NM_DEVICE_STATE_ACTIVATED || state == NM_DEVICE_STATE_FAILED || + state == NM_DEVICE_STATE_CANCELLED || state == NM_DEVICE_STATE_DISCONNECTED) + + manager_state_changed (manager); +} + +void +nm_manager_add_device (NMManager *manager, NMDevice *device) +{ + NMManagerPrivate *priv; + + g_return_if_fail (NM_IS_MANAGER (manager)); + g_return_if_fail (NM_IS_DEVICE (device)); + + priv = NM_MANAGER_GET_PRIVATE (manager); + + priv->devices = g_slist_append (priv->devices, g_object_ref (device)); + + g_signal_connect (device, "state-changed", + G_CALLBACK (manager_device_state_changed), + manager); + nm_device_deactivate (device); + + manager_device_added (manager, device); +} + +static void +manager_device_removed (NMManager *manager, NMDevice *device) +{ + g_signal_emit (manager, signals[DEVICE_REMOVED], 0, device); +} + +void +nm_manager_remove_device (NMManager *manager, NMDevice *device) +{ + NMManagerPrivate *priv; + GSList *iter; + + g_return_if_fail (NM_IS_MANAGER (manager)); + g_return_if_fail (NM_IS_DEVICE (device)); + + priv = NM_MANAGER_GET_PRIVATE (manager); + + for (iter = priv->devices; iter; iter = iter->next) { + if (iter->data == device) { + priv->devices = g_slist_delete_link (priv->devices, iter); + + g_signal_handlers_disconnect_by_func (device, manager_device_state_changed, manager); + + nm_device_set_removed (device, TRUE); + nm_device_stop (device); + + manager_device_removed (manager, device); + g_object_unref (device); + break; + } + } +} + +GSList * +nm_manager_get_devices (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); + + return NM_MANAGER_GET_PRIVATE (manager)->devices; +} + +NMDevice * +nm_manager_get_device_by_iface (NMManager *manager, const char *iface) +{ + GSList *iter; + + g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); + + for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) { + NMDevice *device = NM_DEVICE (iter->data); + + if (!strcmp (nm_device_get_iface (device), iface)) + return device; + } + + return NULL; +} + +NMDevice * +nm_manager_get_device_by_udi (NMManager *manager, const char *udi) +{ + GSList *iter; + + g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); + + for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) { + NMDevice *device = NM_DEVICE (iter->data); + + if (!strcmp (nm_device_get_udi (device), udi)) + return device; + } + + return NULL; +} + +NMState +nm_manager_get_state (NMManager *manager) +{ + NMManagerPrivate *priv; + GSList *iter; + NMState state = NM_STATE_DISCONNECTED; + + g_return_val_if_fail (NM_IS_MANAGER (manager), NM_STATE_UNKNOWN); + + priv = NM_MANAGER_GET_PRIVATE (manager); + + if (priv->sleeping) + return NM_STATE_ASLEEP; + + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *dev = NM_DEVICE (iter->data); + + if (nm_device_has_active_link (dev)) + return NM_STATE_CONNECTED; + + if (nm_device_is_activating (dev)) + state = NM_STATE_CONNECTING; + } + + return state; +} + +gboolean +nm_manager_wireless_enabled (NMManager *manager) +{ + gboolean enabled; + + g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); + + g_object_get (manager, NM_MANAGER_WIRELESS_ENABLED, &enabled, NULL); + + return enabled; +} + +void +nm_manager_sleep (NMManager *manager, gboolean sleep) +{ + NMManagerPrivate *priv; + + g_return_if_fail (NM_IS_MANAGER (manager)); + + priv = NM_MANAGER_GET_PRIVATE (manager); + + if (priv->sleeping == sleep) + return; + + priv->sleeping = sleep; + + if (sleep) { + GSList *iter; + + nm_info ("Going to sleep."); + + /* Just deactivate and down all devices from the device list, + * we'll remove them in 'wake' for speed's sake. + */ + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *dev = NM_DEVICE (iter->data); + + nm_device_set_removed (dev, TRUE); + nm_device_deactivate_quickly (dev); + nm_system_device_set_up_down (dev, FALSE); + } + } else { + nm_info ("Waking up from sleep."); + + while (g_slist_length (priv->devices)) + nm_manager_remove_device (manager, NM_DEVICE (priv->devices->data)); + + priv->devices = NULL; + } + + manager_state_changed (manager); +} + +NMDevice * +nm_manager_get_active_device (NMManager *manager) +{ + GSList *iter; + + g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); + + for (iter = nm_manager_get_devices (manager); iter; iter = iter->next) { + NMDevice *dev = NM_DEVICE (iter->data); + + if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) + return dev; + } + + return NULL; +} diff --git a/src/nm-manager.h b/src/nm-manager.h new file mode 100644 index 000000000..040ffb796 --- /dev/null +++ b/src/nm-manager.h @@ -0,0 +1,48 @@ +#ifndef NM_MANAGER_H +#define NM_MANAGER_H 1 + +#include +#include +#include +#include "nm-device.h" + +#define NM_TYPE_MANAGER (nm_manager_get_type ()) +#define NM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MANAGER, NMManager)) +#define NM_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MANAGER, NMManagerClass)) +#define NM_IS_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MANAGER)) +#define NM_IS_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_MANAGER)) +#define NM_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MANAGER, NMManagerClass)) + +#define NM_MANAGER_STATE "state" +#define NM_MANAGER_WIRELESS_ENABLED "wireless-enabled" + +typedef struct { + GObject parent; +} NMManager; + +typedef struct { + GObjectClass parent; + + /* Signals */ + void (*device_added) (NMManager *manager, NMDevice *device); + void (*device_removed) (NMManager *manager, NMDevice *device); + void (*state_change) (NMManager *manager, guint state); + +} NMManagerClass; + +GType nm_manager_get_type (void); + +NMManager *nm_manager_new (void); + +void nm_manager_add_device (NMManager *manager, NMDevice *device); +void nm_manager_remove_device (NMManager *manager, NMDevice *device); +GSList *nm_manager_get_devices (NMManager *manager); +NMDevice *nm_manager_get_device_by_iface (NMManager *manager, const char *iface); +NMDevice *nm_manager_get_device_by_udi (NMManager *manager, const char *udi); +NMState nm_manager_get_state (NMManager *manager); +gboolean nm_manager_wireless_enabled (NMManager *manager); +void nm_manager_sleep (NMManager *manager, gboolean sleep); + +NMDevice *nm_manager_get_active_device (NMManager *manager); + +#endif /* NM_MANAGER_H */ diff --git a/src/vpn-manager/nm-vpn-manager.c b/src/vpn-manager/nm-vpn-manager.c index 0ef582df6..3aaad79dd 100644 --- a/src/vpn-manager/nm-vpn-manager.c +++ b/src/vpn-manager/nm-vpn-manager.c @@ -38,6 +38,7 @@ struct NMVPNManager { + NMManager * nm_manager; NMData * app_data; GHashTable * service_table; GSList * connections; @@ -54,14 +55,16 @@ static void load_services (NMVPNManager *manager, GHashTable *table); * Create a new VPN manager instance. * */ -NMVPNManager *nm_vpn_manager_new (NMData *app_data) +NMVPNManager *nm_vpn_manager_new (NMManager *nm_manager, NMData *app_data) { NMVPNManager * manager; NMDBusManager * dbus_mgr; + g_return_val_if_fail (NM_IS_MANAGER (nm_manager), NULL); g_return_val_if_fail (app_data != NULL, NULL); manager = g_slice_new0 (NMVPNManager); + manager->nm_manager = g_object_ref (nm_manager); manager->app_data = app_data; manager->service_table = g_hash_table_new_full (g_str_hash, @@ -98,6 +101,7 @@ void nm_vpn_manager_dispose (NMVPNManager *manager) g_hash_table_destroy (manager->service_table); nm_dbus_method_list_unref (manager->dbus_methods); + g_object_unref (manager->nm_manager); memset (manager, 0, sizeof (NMVPNManager)); g_slice_free (NMVPNManager, manager); @@ -330,7 +334,7 @@ void nm_vpn_manager_activate_vpn_connection (NMVPNManager *manager, NMVPNConnect if (!(service = nm_vpn_manager_find_service_by_name (manager, service_name))) return; - if (!(parent_dev = nm_get_active_device (manager->app_data))) + if (!(parent_dev = nm_manager_get_active_device (manager->nm_manager))) { nm_warning ("nm_vpn_manager_activate_vpn_connection(): no currently active network device, won't activate VPN."); return; diff --git a/src/vpn-manager/nm-vpn-manager.h b/src/vpn-manager/nm-vpn-manager.h index ed005187d..ad79d9428 100644 --- a/src/vpn-manager/nm-vpn-manager.h +++ b/src/vpn-manager/nm-vpn-manager.h @@ -21,12 +21,13 @@ #define NM_VPN_MANAGER_H #include +#include "nm-manager.h" #include "NetworkManagerMain.h" #include "nm-vpn-connection.h" #include "nm-vpn-service.h" -NMVPNManager * nm_vpn_manager_new (NMData *app_data); +NMVPNManager * nm_vpn_manager_new (NMManager *nm_manager, NMData *app_data); NMVPNConnection * nm_vpn_manager_add_connection (NMVPNManager *manager, const char *name, const char *service_name, const char *user_name); void nm_vpn_manager_remove_connection (NMVPNManager *manager, NMVPNConnection *vpn); char ** nm_vpn_manager_get_connection_names (NMVPNManager *manager);