From 4bc25ba3bf733d9be2e6f0787f798eb2e692f023 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 25 Nov 2006 15:41:04 +0000 Subject: [PATCH] 2006-11-25 Dan Williams * src/supplicant-manager/nm-supplicant-types.h - new file; move all supplicant manager object typedefs here for #include sanity * src/supplicant-manager/nm-supplicant-interface.c src/supplicant-manager/nm-supplicant-interface.h - new file; an object that interfaces an NMDevice object to the supplicant and handles signals from the supplicant. This object does all necessary DBus communication with wpa_supplicant. * src/supplicant-manager/nm-supplicant-manager.c src/supplicant-manager/nm-supplicant-manager.h - Actually do something. Track the state of the wpa_supplicant service and deal with its comings & goings. Handle life events of supplicant interfaces too. - Move NMSupplicantManager typedef to nm-supplicant-types.h * src/supplicant-manager/nm-supplicant-connection.h - Move NMSupplicantConnection typedef to nm-supplicant-types.h * src/supplicant-manager/Makefile.am - Add new files to build, and add libnm-util to includes * src/nm-marshal.list - New marshaler type: VOID:UINT,UINT * src/nm-device-802-3-ethernet.c - (real_init): grab a supplicant interface - (nm_device_802_3_ethernet_dispose): release the supplicant interface - (supplicant_iface_state_cb): new function, stub for handling supplicant interface state changes * src/nm-device-802-11-wireless.c - (real_init): grab a supplicant interface - (nm_device_802_11_wireless_dispose): release the supplicant interface - (supplicant_iface_state_cb): new function, stub for handling supplicant interface state changes * src/NetworkManager.c - (main): create and keep the supplicant manager around for the lifetime of NetworkManager * src/Makefile.am - Link to the supplicant manager sub-library and use the supplicant manager includes git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2125 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- ChangeLog | 48 ++ src/Makefile.am | 2 + src/NetworkManager.c | 13 + src/nm-device-802-11-wireless.c | 53 +- src/nm-device-802-3-ethernet.c | 47 ++ src/nm-marshal.list | 1 + src/supplicant-manager/Makefile.am | 8 +- .../nm-supplicant-connection.h | 2 +- .../nm-supplicant-interface.c | 722 ++++++++++++++++++ .../nm-supplicant-interface.h | 98 +++ .../nm-supplicant-manager.c | 253 +++++- .../nm-supplicant-manager.h | 38 +- src/supplicant-manager/nm-supplicant-types.h | 29 + 13 files changed, 1296 insertions(+), 18 deletions(-) create mode 100644 src/supplicant-manager/nm-supplicant-interface.c create mode 100644 src/supplicant-manager/nm-supplicant-interface.h create mode 100644 src/supplicant-manager/nm-supplicant-types.h diff --git a/ChangeLog b/ChangeLog index ba2fd8a941..fbd387d62a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,51 @@ +2006-11-25 Dan Williams + + * src/supplicant-manager/nm-supplicant-types.h + - new file; move all supplicant manager object typedefs here for + #include sanity + + * src/supplicant-manager/nm-supplicant-interface.c + src/supplicant-manager/nm-supplicant-interface.h + - new file; an object that interfaces an NMDevice object to the + supplicant and handles signals from the supplicant. This object + does all necessary DBus communication with wpa_supplicant. + + * src/supplicant-manager/nm-supplicant-manager.c + src/supplicant-manager/nm-supplicant-manager.h + - Actually do something. Track the state of the wpa_supplicant service + and deal with its comings & goings. Handle life events of + supplicant interfaces too. + - Move NMSupplicantManager typedef to nm-supplicant-types.h + + * src/supplicant-manager/nm-supplicant-connection.h + - Move NMSupplicantConnection typedef to nm-supplicant-types.h + + * src/supplicant-manager/Makefile.am + - Add new files to build, and add libnm-util to includes + + * src/nm-marshal.list + - New marshaler type: VOID:UINT,UINT + + * src/nm-device-802-3-ethernet.c + - (real_init): grab a supplicant interface + - (nm_device_802_3_ethernet_dispose): release the supplicant interface + - (supplicant_iface_state_cb): new function, stub for handling + supplicant interface state changes + + * src/nm-device-802-11-wireless.c + - (real_init): grab a supplicant interface + - (nm_device_802_11_wireless_dispose): release the supplicant interface + - (supplicant_iface_state_cb): new function, stub for handling + supplicant interface state changes + + * src/NetworkManager.c + - (main): create and keep the supplicant manager around for the lifetime + of NetworkManager + + * src/Makefile.am + - Link to the supplicant manager sub-library and use the supplicant + manager includes + 2006-11-25 Dan Williams Rework DBus manager signal handling to be more flexible. Previously, diff --git a/src/Makefile.am b/src/Makefile.am index 5f59a01ae7..7b7b2e5c35 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,6 +5,7 @@ INCLUDES = -I${top_srcdir} \ -I${top_srcdir}/src/named-manager \ -I${top_srcdir}/src/vpn-manager \ -I${top_srcdir}/src/dhcp-manager \ + -I${top_srcdir}/src/supplicant-manager \ -I${top_srcdir}/utils \ -I${top_srcdir}/libnm-util @@ -123,6 +124,7 @@ NetworkManager_LDADD = \ ./named-manager/libnamed-manager.la \ ./vpn-manager/libvpn-manager.la \ ./dhcp-manager/libdhcp-manager.la \ + ./supplicant-manager/libsupplicant-manager.la \ ./backends/libnmbackend.la \ $(top_builddir)/libnm-util/libnm-util.la diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 656b9a55aa..1676bb1268 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -55,6 +55,7 @@ #include "nm-dbus-nm.h" #include "nm-dbus-manager.h" #include "nm-dbus-device.h" +#include "nm-supplicant-manager.h" #include "nm-dbus-net.h" #include "nm-netlink-monitor.h" #include "nm-dhcp-manager.h" @@ -743,6 +744,7 @@ main (int argc, char *argv[]) char * user_pidfile = NULL; NMDBusManager * dbus_mgr; DBusConnection *dbus_connection; + NMSupplicantManager * sup_mgr = NULL; int exit_status = EXIT_FAILURE; guint32 id; @@ -846,6 +848,13 @@ 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); + /* Initialize the supplicant manager */ + sup_mgr = nm_supplicant_manager_get (); + if (!sup_mgr) { + nm_error ("Failed to initialize the supplicant manager."); + goto done; + } + nm_data->vpn_manager = nm_vpn_manager_new (nm_data); if (!nm_data->vpn_manager) { nm_warning ("Failed to start the VPN manager."); @@ -907,6 +916,10 @@ done: nm_dbus_manager_remove_signal_handler (dbus_mgr, nm_data->nmi_sig_handler_id); nm_data_free (nm_data); + + if (sup_mgr) + g_object_unref (sup_mgr); + /* nm_data_free needs the dbus connection, so must kill the * dbus manager after that. */ diff --git a/src/nm-device-802-11-wireless.c b/src/nm-device-802-11-wireless.c index 0f720740cd..3bf6ae0fd3 100644 --- a/src/nm-device-802-11-wireless.c +++ b/src/nm-device-802-11-wireless.c @@ -41,6 +41,8 @@ #include "NetworkManagerPolicy.h" #include "nm-activation-request.h" #include "nm-dbus-nmi.h" +#include "nm-supplicant-manager.h" +#include "nm-supplicant-interface.h" #include "wpa_ctrl.h" #include "cipher.h" @@ -84,6 +86,8 @@ struct _NMDevice80211WirelessPrivate struct _Supplicant supplicant; + NMSupplicantInterface * sup_iface; + guint32 failed_link_count; GSource * link_timeout; gulong wireless_event_id; @@ -139,6 +143,11 @@ static void nm_device_802_11_wireless_event (NmNetlinkMonitor *monitor, int data_len, NMDevice80211Wireless *self); +static void supplicant_iface_state_cb (NMSupplicantInterface * iface, + guint32 new_state, + guint32 old_state, + NMDevice80211Wireless *self); + /* * nm_device_802_11_wireless_update_bssid @@ -390,6 +399,7 @@ real_init (NMDevice *dev) guint32 caps; NMSock * sk; NmNetlinkMonitor * monitor; + NMSupplicantManager * sup_mgr; self->priv->is_initialized = TRUE; self->priv->scanning = FALSE; @@ -448,6 +458,20 @@ real_init (NMDevice *dev) self->priv->wireless_event_id = g_signal_connect (G_OBJECT (monitor), "wireless-event", G_CALLBACK (nm_device_802_11_wireless_event), self); + + sup_mgr = nm_supplicant_manager_get (); + self->priv->sup_iface = nm_supplicant_manager_get_iface (sup_mgr, + NM_DEVICE (self)); + if (self->priv->sup_iface == NULL) { + nm_warning ("Couldn't initialize supplicant interface for %s.", + nm_device_get_iface (NM_DEVICE (self))); + } else { + g_signal_connect (G_OBJECT (self->priv->sup_iface), + "state", + G_CALLBACK (supplicant_iface_state_cb), + self); + } + g_object_unref (sup_mgr); } @@ -2385,6 +2409,28 @@ ap_is_auth_required (NMAccessPoint *ap, gboolean *has_key) } +/**************************************************************************** + * WPA Supplicant control stuff + * + */ +static void +supplicant_iface_state_cb (NMSupplicantInterface * iface, + guint32 new_state, + guint32 old_state, + NMDevice80211Wireless *self) +{ + g_return_if_fail (self != NULL); + + nm_info ("(%s) supplicant interface is now in state %d (from %d).", + nm_device_get_iface (NM_DEVICE (self)), + new_state, + old_state); +} + + + + + /****************************************************************************/ /* WPA Supplicant control stuff * @@ -3323,7 +3369,8 @@ nm_device_802_11_wireless_dispose (GObject *object) /* Only do this part of the cleanup if the object is initialized */ if (self->priv->is_initialized) { - NMData * data = nm_device_get_app_data (NM_DEVICE (self)); + NMData * data = nm_device_get_app_data (NM_DEVICE (self)); + NMSupplicantManager * sup_mgr; self->priv->is_initialized = FALSE; @@ -3337,6 +3384,10 @@ nm_device_802_11_wireless_dispose (GObject *object) g_signal_handler_disconnect (G_OBJECT (data->netlink_monitor), self->priv->wireless_event_id); + + sup_mgr = nm_supplicant_manager_get (); + nm_supplicant_manager_release_iface (sup_mgr, self->priv->sup_iface); + g_object_unref (sup_mgr); } /* Chain up to the parent class */ diff --git a/src/nm-device-802-3-ethernet.c b/src/nm-device-802-3-ethernet.c index 99861a97f1..2fce4c800a 100644 --- a/src/nm-device-802-3-ethernet.c +++ b/src/nm-device-802-3-ethernet.c @@ -33,6 +33,7 @@ #include "nm-activation-request.h" #include "NetworkManagerUtils.h" #include "NetworkManagerPolicy.h" +#include "nm-supplicant-manager.h" #include "nm-utils.h" #include "kernel-types.h" @@ -46,6 +47,8 @@ struct _NMDevice8023EthernetPrivate char * carrier_file_path; gulong link_connected_id; gulong link_disconnected_id; + + NMSupplicantInterface * sup_iface; }; static gboolean supports_mii_carrier_detect (NMDevice8023Ethernet *dev); @@ -58,6 +61,11 @@ static void nm_device_802_3_ethernet_link_deactivated (NmNetlinkMonitor *monitor GObject *obj, NMDevice8023Ethernet *self); +static void supplicant_iface_state_cb (NMSupplicantInterface * iface, + guint32 new_state, + guint32 old_state, + NMDevice80211Wireless *self); + static void nm_device_802_3_ethernet_init (NMDevice8023Ethernet * self) @@ -74,6 +82,7 @@ real_init (NMDevice *dev) NMDevice8023Ethernet * self = NM_DEVICE_802_3_ETHERNET (dev); NMData * app_data; NmNetlinkMonitor * monitor; + NMSupplicantManager * sup_mgr; app_data = nm_device_get_app_data (NM_DEVICE (self)); monitor = app_data->netlink_monitor; @@ -85,6 +94,20 @@ real_init (NMDevice *dev) self->priv->link_disconnected_id = g_signal_connect (G_OBJECT (monitor), "interface-disconnected", G_CALLBACK (nm_device_802_3_ethernet_link_deactivated), self); + + sup_mgr = nm_supplicant_manager_get (); + self->priv->sup_iface = nm_supplicant_manager_get_iface (sup_mgr, + NM_DEVICE (self)); + if (self->priv->sup_iface == NULL) { + nm_warning ("Couldn't initialize supplicant interface for %s.", + nm_device_get_iface (NM_DEVICE (self))); + } else { + g_signal_connect (G_OBJECT (self->priv->sup_iface), + "state", + G_CALLBACK (supplicant_iface_state_cb), + self); + } + g_object_unref (sup_mgr); } static gboolean @@ -300,6 +323,7 @@ nm_device_802_3_ethernet_dispose (GObject *object) NMDevice8023EthernetClass * klass = NM_DEVICE_802_3_ETHERNET_GET_CLASS (object); NMDeviceClass * parent_class; NMData * data = nm_device_get_app_data (NM_DEVICE (self)); + NMSupplicantManager * sup_mgr; if (self->priv->dispose_has_run) /* If dispose did already run, return. */ @@ -314,6 +338,10 @@ nm_device_802_3_ethernet_dispose (GObject *object) * the most simple solution is to unref all members on which you own a * reference. */ + sup_mgr = nm_supplicant_manager_get (); + nm_supplicant_manager_release_iface (sup_mgr, self->priv->sup_iface); + self->priv->sup_iface = NULL; + g_object_unref (sup_mgr); g_signal_handler_disconnect (G_OBJECT (data->netlink_monitor), self->priv->link_connected_id); @@ -384,6 +412,25 @@ nm_device_802_3_ethernet_get_type (void) } +/**************************************************************************** + * WPA Supplicant control stuff + * + */ +static void +supplicant_iface_state_cb (NMSupplicantInterface * iface, + guint32 new_state, + guint32 old_state, + NMDevice80211Wireless *self) +{ + g_return_if_fail (self != NULL); + + nm_info ("(%s) supplicant interface is now in state %d (from %d).", + nm_device_get_iface (NM_DEVICE (self)), + new_state, + old_state); +} + + /**************************************/ /* Ethtool capability detection */ /**************************************/ diff --git a/src/nm-marshal.list b/src/nm-marshal.list index 69de47a519..42b2f86a2d 100644 --- a/src/nm-marshal.list +++ b/src/nm-marshal.list @@ -2,3 +2,4 @@ VOID:OBJECT VOID:OBJECT,POINTER,INT VOID:POINTER VOID:POINTER,STRING,STRING,STRING +VOID:UINT,UINT diff --git a/src/supplicant-manager/Makefile.am b/src/supplicant-manager/Makefile.am index d080a80245..2265530e77 100644 --- a/src/supplicant-manager/Makefile.am +++ b/src/supplicant-manager/Makefile.am @@ -1,12 +1,18 @@ -INCLUDES = -I${top_srcdir}/utils -I${top_srcdir}/src -I${top_srcdir}/include +INCLUDES = -I${top_srcdir}/utils \ + -I${top_srcdir}/src \ + -I${top_srcdir}/include \ + -I${top_srcdir}/libnm-util noinst_LTLIBRARIES = libsupplicant-manager.la libsupplicant_manager_la_SOURCES = \ + nm-supplicant-types.h \ nm-supplicant-manager.h \ nm-supplicant-manager.c \ nm-supplicant-connection.h \ nm-supplicant-connection.c \ + nm-supplicant-interface.c \ + nm-supplicant-interface.h \ nm-supplicant-settings-verify.h \ nm-supplicant-settings-verify.c diff --git a/src/supplicant-manager/nm-supplicant-connection.h b/src/supplicant-manager/nm-supplicant-connection.h index e291f803fd..5ed5b41668 100644 --- a/src/supplicant-manager/nm-supplicant-connection.h +++ b/src/supplicant-manager/nm-supplicant-connection.h @@ -23,6 +23,7 @@ #define NM_SUPPLICANT_CONNECTION_H #include +#include "nm-supplicant-types.h" #include "nm-device.h" G_BEGIN_DECLS @@ -34,7 +35,6 @@ G_BEGIN_DECLS #define NM_IS_SUPPLICANT_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SUPPLICANT_CONNECTION)) #define NM_SUPPLICANT_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SUPPLICANT_CONNECTION, NMSupplicantConnectionClass)) -typedef struct _NMSupplicantConnection NMSupplicantConnection; typedef struct _NMSupplicantConnectionClass NMSupplicantConnectionClass; typedef struct _NMSupplicantConnectionPrivate NMSupplicantConnectionPrivate; diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c new file mode 100644 index 0000000000..ec2a8764c4 --- /dev/null +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -0,0 +1,722 @@ +/* NetworkManager -- Network link manager + * + * 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. + * + * (C) Copyright 2006 Red Hat, Inc. + */ + +#include +#include + +#include "nm-supplicant-interface.h" +#include "nm-supplicant-manager.h" +#include "nm-device.h" +#include "nm-device-802-3-ethernet.h" +#include "nm-utils.h" +#include "nm-marshal.h" +#include "nm-dbus-manager.h" +#include "dbus-dict-helpers.h" + +#define WPAS_DBUS_IFACE_INTERFACE WPAS_DBUS_INTERFACE ".Interface" + + +#define NM_SUPPLICANT_INTERFACE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + NM_TYPE_SUPPLICANT_INTERFACE, \ + NMSupplicantInterfacePrivate)) + +static void nm_supplicant_interface_set_property (GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec); + +static void nm_supplicant_interface_get_property (GObject * object, + guint prop_id, + GValue * value, + GParamSpec * pspec); + +static void nm_supplicant_interface_start (NMSupplicantInterface * self); + +static void nm_supplicant_interface_add_to_supplicant (NMSupplicantInterface * self, + gboolean get_only); + +static void nm_supplicant_interface_smgr_state_changed (NMSupplicantManager * smgr, + guint32 new_state, + guint32 old_state, + gpointer user_data); + +static void nm_supplicant_interface_set_state (NMSupplicantInterface * self, + guint32 new_state); + + +/* Signals */ +enum { + STATE, /* change in the interface's state */ + REMOVED, /* interface was removed by the supplicant */ + SCAN_RESULTS, /* interface has new scan results */ + LAST_SIGNAL +}; +static guint nm_supplicant_interface_signals[LAST_SIGNAL] = { 0 }; + + +/* Properties */ +enum { + PROP_0 = 0, + PROP_SUPPLICANT_MANAGER, + PROP_DEVICE, + PROP_STATE, + LAST_PROP +}; + + +struct _NMSupplicantInterfacePrivate +{ + NMSupplicantManager * smgr; + NMDBusManager * dbus_mgr; + NMDevice * dev; + + guint32 state; + DBusPendingCall * pcall; + + char * wpas_iface_op; + char * wpas_net_op; + guint32 wpas_sig_handler_id; + + NMSupplicantConnection * con; + + gboolean dispose_has_run; +}; + + +NMSupplicantInterface * +nm_supplicant_interface_new (NMSupplicantManager * smgr, NMDevice * dev) +{ + NMSupplicantInterface * iface; + + g_return_val_if_fail (smgr != NULL, NULL); + g_return_val_if_fail (dev != NULL, NULL); + + iface = g_object_new (NM_TYPE_SUPPLICANT_INTERFACE, + "supplicant-manager", smgr, + "device", dev, + NULL); + if (iface) { + nm_supplicant_interface_start (iface); + } + + return iface; +} + +static void +nm_supplicant_interface_init (NMSupplicantInterface * self) +{ + self->priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + self->priv->state = NM_SUPPLICANT_INTERFACE_STATE_INIT; + self->priv->smgr = NULL; + self->priv->dev = NULL; + self->priv->wpas_iface_op = NULL; + self->priv->pcall = NULL; + self->priv->dispose_has_run = FALSE; + + self->priv->dbus_mgr = nm_dbus_manager_get (NULL); +} + + +static void +nm_supplicant_interface_set_property (GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec) +{ + NMSupplicantInterface * self = NM_SUPPLICANT_INTERFACE (object); + + switch (prop_id) { + case PROP_SUPPLICANT_MANAGER: + self->priv->smgr = NM_SUPPLICANT_MANAGER (g_value_get_object (value)); + g_object_ref (G_OBJECT (self->priv->smgr)); + + g_signal_connect (G_OBJECT (self->priv->smgr), + "state", + G_CALLBACK (nm_supplicant_interface_smgr_state_changed), + self); + break; + case PROP_DEVICE: + self->priv->dev = NM_DEVICE (g_value_get_object (value)); + g_object_ref (G_OBJECT (self->priv->dev)); + break; + case PROP_STATE: + /* warn on setting read-only property */ + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_supplicant_interface_get_property (GObject * object, + guint prop_id, + GValue * value, + GParamSpec * pspec) +{ + NMSupplicantInterface * self = NM_SUPPLICANT_INTERFACE (object); + + switch (prop_id) { + case PROP_SUPPLICANT_MANAGER: + g_value_set_object (value, G_OBJECT (self->priv->smgr)); + break; + case PROP_DEVICE: + g_value_set_object (value, G_OBJECT (self->priv->dev)); + break; + case PROP_STATE: + g_value_set_uint (value, self->priv->state); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_supplicant_interface_dispose (GObject *object) +{ + NMSupplicantInterface * self = NM_SUPPLICANT_INTERFACE (object); + NMSupplicantInterfaceClass * klass; + GObjectClass * parent_class; + + if (self->priv->dispose_has_run) { + /* If dispose did already run, return. */ + return; + } + + /* Make sure dispose does not run twice. */ + self->priv->dispose_has_run = TRUE; + + /* + * In dispose, you are supposed to free all types referenced from this + * object which might themselves hold a reference to self. Generally, + * the most simple solution is to unref all members on which you own a + * reference. + */ + if (self->priv->smgr) { + g_object_unref (self->priv->smgr); + self->priv->smgr = NULL; + } + + if (self->priv->dev) { + g_object_unref (self->priv->dev); + self->priv->dev = NULL; + } + + if (self->priv->dbus_mgr) { + nm_dbus_manager_remove_signal_handler (self->priv->dbus_mgr, + self->priv->wpas_sig_handler_id); + + g_object_unref (self->priv->dbus_mgr); + self->priv->dbus_mgr = NULL; + } + + if (self->priv->con) { + g_object_unref (self->priv->con); + self->priv->con = NULL; + } + + /* Chain up to the parent class */ + klass = NM_SUPPLICANT_INTERFACE_CLASS (g_type_class_peek (NM_TYPE_SUPPLICANT_INTERFACE)); + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); + parent_class->dispose (object); +} + +static void +nm_supplicant_interface_finalize (GObject *object) +{ + NMSupplicantInterface * self = NM_SUPPLICANT_INTERFACE (object); + NMSupplicantInterfaceClass * klass; + GObjectClass * parent_class; + + if (self->priv->wpas_iface_op) + g_free (self->priv->wpas_iface_op); + + if (self->priv->wpas_net_op) + g_free (self->priv->wpas_net_op); + + if (self->priv->pcall) { + dbus_pending_call_cancel (self->priv->pcall); + self->priv->pcall = NULL; + } + + /* Chain up to the parent class */ + klass = NM_SUPPLICANT_INTERFACE_CLASS (g_type_class_peek (NM_TYPE_SUPPLICANT_INTERFACE)); + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); + parent_class->finalize (object); +} + + +static void +nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = nm_supplicant_interface_dispose; + object_class->finalize = nm_supplicant_interface_finalize; + object_class->set_property = nm_supplicant_interface_set_property; + object_class->get_property = nm_supplicant_interface_get_property; + + g_type_class_add_private (object_class, sizeof (NMSupplicantInterfacePrivate)); + + /* Properties */ + g_object_class_install_property (object_class, + PROP_SUPPLICANT_MANAGER, + g_param_spec_object ("supplicant-manager", + "Supplicant Manager", + "Supplicant manager to which this interface belongs", + NM_TYPE_SUPPLICANT_MANAGER, + G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, + PROP_DEVICE, + g_param_spec_object ("device", + "Device", + "Device which this interface represents to the supplicant", + NM_TYPE_DEVICE, + G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, + PROP_DEVICE, + g_param_spec_uint ("state", + "State", + "State of the supplicant interface; INIT, READY, or DOWN", + NM_SUPPLICANT_INTERFACE_STATE_INIT, + NM_SUPPLICANT_INTERFACE_STATE_LAST - 1, + NM_SUPPLICANT_INTERFACE_STATE_INIT, + G_PARAM_READABLE)); + + /* Signals */ + nm_supplicant_interface_signals[STATE] = + g_signal_new ("state", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, state), + NULL, NULL, + nm_marshal_VOID__UINT_UINT, + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); + klass->state = NULL; + + nm_supplicant_interface_signals[REMOVED] = + g_signal_new ("removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, removed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + klass->removed = NULL; + + nm_supplicant_interface_signals[SCAN_RESULTS] = + g_signal_new ("scan-results", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_results), + NULL, NULL, + nm_marshal_VOID__UINT_UINT, + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); + klass->scan_results = NULL; +} + +GType +nm_supplicant_interface_get_type (void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (NMSupplicantInterfaceClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) nm_supplicant_interface_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (NMSupplicantInterface), + 0, /* n_preallocs */ + (GInstanceInitFunc) nm_supplicant_interface_init, + NULL /* value_table */ + }; + + type = g_type_register_static (G_TYPE_OBJECT, + "NMSupplicantInterface", + &info, 0); + } + return type; +} + + +static void +set_wpas_iface_op_from_message (NMSupplicantInterface * self, + DBusMessage * message) +{ + DBusError error; + char * path = NULL; + + dbus_error_init (&error); + + /* Interface was found; cache its object path */ + if (!dbus_message_get_args (message, + &error, + DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_INVALID)) { + nm_warning ("Error getting interface path from supplicant: %s - %s", + error.name, + error.message); + } else { + if (self->priv->wpas_iface_op) + g_free (self->priv->wpas_iface_op); + self->priv->wpas_iface_op = g_strdup (path); + } + + if (dbus_error_is_set (&error)) + dbus_error_free (&error); +} + + +static gboolean +wpas_iface_signal_handler (DBusConnection * connection, + DBusMessage * message, + gpointer user_data) +{ + NMSupplicantInterface * self = (NMSupplicantInterface *) user_data; + const char * op = dbus_message_get_path (message); + gboolean handled = FALSE; + + g_return_val_if_fail (self != NULL, FALSE); + + if (!op || !self->priv->wpas_iface_op) + return FALSE; + + /* Only handle signals for our interface */ + if (strcmp (op, self->priv->wpas_iface_op) != 0) + return FALSE; + + if (dbus_message_is_signal (message, WPAS_DBUS_IFACE_INTERFACE, "ScanResultsAvailable")) { + handled = TRUE; + } + + return handled; +} + + +#define WPAS_ERROR_INVALID_IFACE \ + WPAS_DBUS_INTERFACE ".InvalidInterface" +#define WPAS_ERROR_EXISTS_ERROR \ + WPAS_DBUS_INTERFACE ".ExistsError" + +static void +nm_supplicant_interface_add_cb (DBusPendingCall *pcall, + NMSupplicantInterface * self) +{ + DBusError error; + DBusMessage * reply = NULL; + gboolean clear_pcall = TRUE; + + g_return_if_fail (pcall != NULL); + g_return_if_fail (self != NULL); + + dbus_error_init (&error); + + nm_dbus_send_with_callback_replied (pcall, __func__); + + if (!dbus_pending_call_get_completed (pcall)) + goto out; + + if (!(reply = dbus_pending_call_steal_reply (pcall))) + goto out; + + if (dbus_message_is_error (reply, WPAS_ERROR_INVALID_IFACE)) { + /* Interface not added, try to add it */ + nm_supplicant_interface_add_to_supplicant (self, FALSE); + clear_pcall = FALSE; + } else if (dbus_message_is_error (reply, WPAS_ERROR_EXISTS_ERROR)) { + /* Interface already added, just try to get the interface */ + nm_supplicant_interface_add_to_supplicant (self, TRUE); + clear_pcall = FALSE; + } else if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) { + if (!dbus_set_error_from_message (&error, reply)) + goto out; + + nm_warning ("Unexpected supplicant error getting interface: %s - %s", + error.name, + error.message); + } else { + guint32 id; + + /* Success; cache the object path */ + set_wpas_iface_op_from_message (self, reply); + + /* Attach to the scan results signal */ + id = nm_dbus_manager_register_signal_handler (self->priv->dbus_mgr, + WPAS_DBUS_IFACE_INTERFACE, + WPAS_DBUS_SERVICE, + wpas_iface_signal_handler, + self); + self->priv->wpas_sig_handler_id = id; + + /* Interface added to the supplicant; transition to the READY state. */ + nm_supplicant_interface_set_state (self, NM_SUPPLICANT_INTERFACE_STATE_READY); + } + +out: + if (reply) + dbus_message_unref (reply); + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + dbus_pending_call_unref (pcall); + if (self->priv->pcall && clear_pcall) + self->priv->pcall = NULL; +} + + +static void +nm_supplicant_interface_add_to_supplicant (NMSupplicantInterface * self, + gboolean get_only) +{ + DBusConnection * dbus_connection; + DBusMessage * message = NULL; + DBusMessageIter iter; + const char * dev_iface; + + g_return_if_fail (self != NULL); + + dbus_connection = nm_dbus_manager_get_dbus_connection (self->priv->dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get the dbus connection."); + goto out; + } + + /* Request the interface object from the supplicant */ + message = dbus_message_new_method_call (WPAS_DBUS_SERVICE, + WPAS_DBUS_PATH, + WPAS_DBUS_INTERFACE, + get_only ? "getInterface" : "addInterface"); + if (!message) { + nm_warning ("Not enough memory to allocate dbus message."); + goto out; + } + + dbus_message_iter_init_append (message, &iter); + dev_iface = nm_device_get_iface (self->priv->dev); + if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &dev_iface)) { + nm_warning ("Couldn't add device interface to message."); + goto out; + } + + /* Add the supplicant driver name if we're adding */ + if (!get_only) { + DBusMessageIter iter_dict; + char * driver = "wext"; + + if (!nmu_dbus_dict_open_write (&iter, &iter_dict)) { + nm_warning ("dict open write failed!"); + goto out; + } + + if (nm_device_is_802_3_ethernet (self->priv->dev)) + driver = "wired"; + if (!nmu_dbus_dict_append_string (&iter_dict, "driver", driver)) { + nm_warning ("couldn't append driver to dict"); + goto out; + } + + if (!nmu_dbus_dict_close_write (&iter, &iter_dict)) { + nm_warning ("dict close write failed!"); + goto out; + } + } + + self->priv->pcall = nm_dbus_send_with_callback (dbus_connection, + message, + (DBusPendingCallNotifyFunction) nm_supplicant_interface_add_cb, + self, + NULL, + __func__); + +out: + if (message) + dbus_message_unref (message); +} + +static void +nm_supplicant_interface_start (NMSupplicantInterface * self) +{ + guint32 state; + + g_return_if_fail (self != NULL); + + /* Can only start the interface from INIT state */ + g_return_if_fail (self->priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT); + + /* Just return if the interface is already starting the transition + * to READY. + */ + if (self->priv->pcall) + return; + + state = nm_supplicant_manager_get_state (self->priv->smgr); + if (state == NM_SUPPLICANT_MANAGER_STATE_IDLE) { + nm_supplicant_interface_add_to_supplicant (self, FALSE); + } else if (state == NM_SUPPLICANT_MANAGER_STATE_DOWN) { + /* Don't do anything; wait for signal from supplicant manager + * that its state has changed. + */ + } else { + nm_warning ("Unknown supplicant manager state!"); + } +} + +static void +nm_supplicant_interface_handle_supplicant_manager_idle_state (NMSupplicantInterface * self) +{ + g_return_if_fail (self != NULL); + + switch (self->priv->state) { + case NM_SUPPLICANT_INTERFACE_STATE_INIT: + /* Start the move to READY state when supplicant is ready */ + nm_supplicant_interface_start (self); + break; + case NM_SUPPLICANT_INTERFACE_STATE_READY: + /* Don't do anything here, though we should never hit this */ + break; + case NM_SUPPLICANT_INTERFACE_STATE_DOWN: + /* Don't do anything here; interface can't get out of DOWN state */ + break; + default: + nm_warning ("Unknown supplicant interface state!"); + break; + } +} + + +static void +nm_supplicant_interface_set_state (NMSupplicantInterface * self, + guint32 new_state) +{ + guint32 old_state; + + g_return_if_fail (self != NULL); + g_return_if_fail (new_state < NM_SUPPLICANT_INTERFACE_STATE_LAST); + + if (new_state == self->priv->state) + return; + + old_state = self->priv->state; + if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN && self->priv->pcall) { + /* If the interface is transitioning to DOWN and there's an + * in-progress pending call, cancel it. + */ + dbus_pending_call_cancel (self->priv->pcall); + self->priv->pcall = NULL; + } + + self->priv->state = new_state; + g_signal_emit (G_OBJECT (self), + nm_supplicant_interface_signals[STATE], + 0, + self->priv->state, + old_state); +} + +static void +nm_supplicant_interface_smgr_state_changed (NMSupplicantManager * smgr, + guint32 new_state, + guint32 old_state, + gpointer user_data) +{ + NMSupplicantInterface * self = NM_SUPPLICANT_INTERFACE (user_data); + + switch (new_state) { + case NM_SUPPLICANT_MANAGER_STATE_DOWN: + /* The supplicant went away, likely the connection to it is also + * gone. Therefore, this interface must move to the DOWN state + * and be disposed of. + */ + nm_supplicant_interface_set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN); + break; + case NM_SUPPLICANT_MANAGER_STATE_IDLE: + /* Handle the supplicant now being available. */ + nm_supplicant_interface_handle_supplicant_manager_idle_state (self); + break; + default: + nm_warning ("Unknown supplicant manager state!"); + break; + } +} + +#if 0 +static void +add_connection_to_iface (NMSupplicantInterface *self) +{ + DBusConnection * dbus_connection; + DBusMessage * message = NULL; + + g_return_if_fail (self != NULL); + + dbus_connection = nm_dbus_manager_get_dbus_connection (self->priv->dbus_mgr); + if (!dbus_connection) { + nm_warning ("could not get the dbus connection."); + goto out; + } + + message = dbus_message_new_method_call (WPAS_DBUS_SERVICE, + WPAS_DBUS_IFACE_INTERFACE, + self->priv->wpas_iface_op, + "addNetwork"); + if (!message) { + nm_warning ("Couldn't create dbus message."); + goto out; + } + +#if 0 + self->priv->pcall = nm_dbus_send_with_callback (dbus_connection, + message, + (DBusPendingCallNotifyFunction) nm_supplicant_interface_add_connection_cb, + self, + NULL, + __func__); +#endif + +out: + ; +} +#endif + +void +nm_supplicant_interface_set_connection (NMSupplicantInterface * self, + NMSupplicantConnection * con) +{ + g_return_if_fail (self != NULL); + + if (self->priv->con) + g_object_unref (self->priv->con); + self->priv->con = con; + if (self->priv->con) + g_object_ref (self->priv->con); +} + +NMDevice * +nm_supplicant_interface_get_device (NMSupplicantInterface * self) +{ + g_return_val_if_fail (self != NULL, NULL); + + return self->priv->dev; +} diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h new file mode 100644 index 0000000000..8025adf838 --- /dev/null +++ b/src/supplicant-manager/nm-supplicant-interface.h @@ -0,0 +1,98 @@ +/* NetworkManager -- Network link manager + * + * 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. + * + * (C) Copyright 2006 Red Hat, Inc. + */ + +#ifndef NM_SUPPLICANT_INTERFACE_H +#define NM_SUPPLICANT_INTERFACE_H + +#include +#include "nm-supplicant-types.h" +#include "nm-device.h" + +G_BEGIN_DECLS + +/* + * Supplicant interface states + * The states are linear, ie INIT -> READY -> DOWN and state may only be + * changed in one direction. If an interface reaches the DOWN state, it + * cannot be re-initialized; it must be torn down and a new one created. + * + * INIT: interface has been created, but cannot be used yet; it is waiting + * for pending requests of the supplicant to complete. + * READY: interface is ready for use + * DOWN: interface has been removed or has otherwise been made invalid; it + * must be torn down. + * + * Note: LAST is an invalid state and only used for boundary checking. + */ +enum { + NM_SUPPLICANT_INTERFACE_STATE_INIT = 0, + NM_SUPPLICANT_INTERFACE_STATE_READY, + NM_SUPPLICANT_INTERFACE_STATE_DOWN, + NM_SUPPLICANT_INTERFACE_STATE_LAST +}; + + +#define NM_TYPE_SUPPLICANT_INTERFACE (nm_supplicant_interface_get_type ()) +#define NM_SUPPLICANT_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterface)) +#define NM_SUPPLICANT_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterfaceClass)) +#define NM_IS_SUPPLICANT_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SUPPLICANT_INTERFACE)) +#define NM_IS_SUPPLICANT_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SUPPLICANT_INTERFACE)) +#define NM_SUPPLICANT_INTERFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterfaceClass)) + +typedef struct _NMSupplicantInterfaceClass NMSupplicantInterfaceClass; +typedef struct _NMSupplicantInterfacePrivate NMSupplicantInterfacePrivate; + +struct _NMSupplicantInterface +{ + GObject parent; + + /*< private >*/ + NMSupplicantInterfacePrivate *priv; +}; + +struct _NMSupplicantInterfaceClass +{ + GObjectClass parent; + + /* class members */ + void (* state) (NMSupplicantInterface * iface, + guint32 new_state, + guint32 old_state); + + void (* removed) (NMSupplicantInterface * iface); + + void (* scan_results) (NMSupplicantInterface * iface); +}; + + +GType nm_supplicant_interface_get_type (void); + +NMSupplicantInterface * nm_supplicant_interface_new (NMSupplicantManager * smgr, + NMDevice * dev); + +void nm_supplicant_interface_set_connection (NMSupplicantInterface * iface, + NMSupplicantConnection * con); + +NMDevice * nm_supplicant_interface_get_device (NMSupplicantInterface * iface); + +G_END_DECLS + +#endif /* NM_SUPPLICANT_INTERFACE_H */ diff --git a/src/supplicant-manager/nm-supplicant-manager.c b/src/supplicant-manager/nm-supplicant-manager.c index 48d5f5d460..3d810038ea 100644 --- a/src/supplicant-manager/nm-supplicant-manager.c +++ b/src/supplicant-manager/nm-supplicant-manager.c @@ -19,48 +19,149 @@ * */ +#include #include #include + #include "nm-supplicant-manager.h" +#include "nm-supplicant-interface.h" +#include "nm-dbus-manager.h" +#include "nm-marshal.h" + #define NM_SUPPLICANT_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ NM_TYPE_SUPPLICANT_MANAGER, \ NMSupplicantManagerPrivate)) +static void nm_supplicant_manager_name_owner_changed (NMDBusManager *dbus_mgr, + DBusConnection *connection, + const char *name, + const char *old, + const char *new, + gpointer user_data); + +static void nm_supplicant_manager_set_state (NMSupplicantManager * self, + guint32 new_state); + +static void nm_supplicant_manager_startup (NMSupplicantManager * self); + + +/* Signals */ +enum { + STATE, /* change in the manager's state */ + LAST_SIGNAL +}; +static guint nm_supplicant_manager_signals[LAST_SIGNAL] = { 0 }; + + struct _NMSupplicantManagerPrivate { - gboolean running; - gboolean dispose_has_run; + NMDBusManager * dbus_mgr; + guint32 state; + GSList * ifaces; + gboolean dispose_has_run; }; NMSupplicantManager * -nm_supplicant_manager_new (void) +nm_supplicant_manager_get (void) { - NMSupplicantManager * mgr; + static NMSupplicantManager * singleton = NULL; + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; - mgr = g_object_new (NM_TYPE_SUPPLICANT_MANAGER, NULL); - return mgr; + g_static_mutex_lock (&mutex); + if (!singleton) { + singleton = NM_SUPPLICANT_MANAGER (g_object_new (NM_TYPE_SUPPLICANT_MANAGER, NULL)); + } else { + g_object_ref (singleton); + } + g_static_mutex_unlock (&mutex); + + g_assert (singleton); + return singleton; } + static void nm_supplicant_manager_init (NMSupplicantManager * self) { self->priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); - self->priv->running = FALSE; + self->priv->dispose_has_run = FALSE; + self->priv->state = NM_SUPPLICANT_MANAGER_STATE_DOWN; + self->priv->dbus_mgr = nm_dbus_manager_get (NULL); + + nm_supplicant_manager_startup (self); + + g_signal_connect (G_OBJECT (self->priv->dbus_mgr), + "name-owner-changed", + G_CALLBACK (nm_supplicant_manager_name_owner_changed), + self); +} + +static void +nm_supplicant_manager_dispose (GObject *object) +{ + NMSupplicantManager * self = NM_SUPPLICANT_MANAGER (object); + NMSupplicantManagerClass * klass; + GObjectClass * parent_class; + + if (self->priv->dispose_has_run) { + /* If dispose did already run, return. */ + return; + } + + /* Make sure dispose does not run twice. */ + self->priv->dispose_has_run = TRUE; + + /* + * In dispose, you are supposed to free all types referenced from this + * object which might themselves hold a reference to self. Generally, + * the most simple solution is to unref all members on which you own a + * reference. + */ + if (self->priv->dbus_mgr) { + g_object_unref (G_OBJECT (self->priv->dbus_mgr)); + self->priv->dbus_mgr = NULL; + } + + /* Chain up to the parent class */ + klass = NM_SUPPLICANT_MANAGER_CLASS (g_type_class_peek (NM_TYPE_SUPPLICANT_MANAGER)); + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); + parent_class->dispose (object); +} + +static void +nm_supplicant_manager_finalize (GObject *object) +{ + NMSupplicantManagerClass * klass; + GObjectClass * parent_class; + + /* Chain up to the parent class */ + klass = NM_SUPPLICANT_MANAGER_CLASS (g_type_class_peek (NM_TYPE_SUPPLICANT_MANAGER)); + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); + parent_class->finalize (object); } static void nm_supplicant_manager_class_init (NMSupplicantManagerClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + GObjectClass * object_class = G_OBJECT_CLASS (klass); -/* object_class->dispose = nm_supplicant_manager_dispose; object_class->finalize = nm_supplicant_manager_finalize; -*/ g_type_class_add_private (object_class, sizeof (NMSupplicantManagerPrivate)); + + /* Signals */ + nm_supplicant_manager_signals[STATE] = + g_signal_new ("state", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantManagerClass, state), + NULL, NULL, + nm_marshal_VOID__UINT_UINT, + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); + klass->state = NULL; } GType @@ -87,3 +188,135 @@ nm_supplicant_manager_get_type (void) } return type; } + +static void +nm_supplicant_manager_name_owner_changed (NMDBusManager *dbus_mgr, + DBusConnection *connection, + const char *name, + const char *old, + const char *new, + gpointer user_data) +{ + NMSupplicantManager * self = (NMSupplicantManager *) user_data; + gboolean old_owner_good = (old && strlen (old)); + gboolean new_owner_good = (new && strlen (new)); + + g_return_if_fail (connection != NULL); + + /* Can't handle the signal if its not from the supplicant service */ + if (strcmp (WPAS_DBUS_SERVICE, name) != 0) + return; + + if (!old_owner_good && new_owner_good) { + nm_supplicant_manager_startup (self); + } else if (old_owner_good && !new_owner_good) { + nm_supplicant_manager_set_state (self, NM_SUPPLICANT_MANAGER_STATE_DOWN); + } +} + + +guint32 +nm_supplicant_manager_get_state (NMSupplicantManager * self) +{ + g_return_val_if_fail (self != NULL, FALSE); + + return self->priv->state; +} + +static void +nm_supplicant_manager_set_state (NMSupplicantManager * self, guint32 new_state) +{ + guint32 old_state; + + g_return_if_fail (self != NULL); + g_return_if_fail (new_state < NM_SUPPLICANT_MANAGER_STATE_LAST); + + if (new_state == self->priv->state) + return; + + old_state = self->priv->state; + self->priv->state = new_state; + g_signal_emit (G_OBJECT (self), + nm_supplicant_manager_signals[STATE], + 0, + self->priv->state, + old_state); +} + +static void +nm_supplicant_manager_startup (NMSupplicantManager * self) +{ + gboolean running; + + /* FIXME: convert to pending call */ + running = nm_dbus_manager_name_has_owner (self->priv->dbus_mgr, + WPAS_DBUS_SERVICE); + if (running) { + nm_supplicant_manager_set_state (self, NM_SUPPLICANT_MANAGER_STATE_IDLE); + } +} + +NMSupplicantInterface * +nm_supplicant_manager_get_iface (NMSupplicantManager * self, + NMDevice * dev) +{ + NMSupplicantInterface * iface = NULL; + GSList * elt; + const char * ifname; + + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (dev != NULL, NULL); + + /* Ensure we don't already have this interface */ + ifname = nm_device_get_iface (dev); + for (elt = self->priv->ifaces; elt; elt = g_slist_next (elt)) { + NMSupplicantInterface * if_tmp = (NMSupplicantInterface *) elt->data; + NMDevice * if_dev = nm_supplicant_interface_get_device (if_tmp); + + if (!strcmp (nm_device_get_iface (if_dev), ifname)) { + iface = if_tmp; + break; + } + } + + if (!iface) { + iface = nm_supplicant_interface_new (self, dev); + if (iface) + self->priv->ifaces = g_slist_append (self->priv->ifaces, iface); + } + + /* Object should have 2 references by now; one from the object's creation + * which is for the caller of this function, and one for the supplicant + * manager (because it's kept in the ifaces list) which is grabbed below. + */ + g_object_ref (iface); + + return iface; +} + +void +nm_supplicant_manager_release_iface (NMSupplicantManager * self, + NMSupplicantInterface * iface) +{ + GSList * elt; + + g_return_if_fail (self != NULL); + g_return_if_fail (iface != NULL); + + for (elt = self->priv->ifaces; elt; elt = g_slist_next (elt)) { + NMSupplicantInterface * if_tmp = (NMSupplicantInterface *) elt->data; + + if (if_tmp == iface) { + /* Remove the iface from the supplicant manager's list and + * dereference to match additional reference in get_iface. + */ + self->priv->ifaces = g_slist_remove_link (self->priv->ifaces, elt); + g_slist_free_1 (elt); + g_object_unref (iface); + break; + } + } + + /* One further dereference to match g_object_new() initial refcount of 1 */ + g_object_unref (iface); +} diff --git a/src/supplicant-manager/nm-supplicant-manager.h b/src/supplicant-manager/nm-supplicant-manager.h index ccebdba757..d3f88d3400 100644 --- a/src/supplicant-manager/nm-supplicant-manager.h +++ b/src/supplicant-manager/nm-supplicant-manager.h @@ -23,9 +23,33 @@ #define NM_SUPPLICANT_MANAGER_H #include +#include "nm-supplicant-types.h" +#include "nm-device.h" + +#define WPAS_DBUS_SERVICE "fi.epitest.hostap.WPASupplicant" +#define WPAS_DBUS_PATH "/fi/epitest/hostap/WPASupplicant" +#define WPAS_DBUS_INTERFACE "fi.epitest.hostap.WPASupplicant" + G_BEGIN_DECLS +/* + * Supplicant manager states + * Either state may transition to the other state at any time. + * + * DOWN: supplicant manager has been created, but cannot be used; the supplicant + * is either not running or has not yet been fully initialized. + * IDLE: supplicant manager is ready for use + * + * Note: LAST is an invalid state and only used for boundary checking. + */ +enum { + NM_SUPPLICANT_MANAGER_STATE_DOWN = 0, + NM_SUPPLICANT_MANAGER_STATE_IDLE, + NM_SUPPLICANT_MANAGER_STATE_LAST +}; + + #define NM_TYPE_SUPPLICANT_MANAGER (nm_supplicant_manager_get_type ()) #define NM_SUPPLICANT_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SUPPLICANT_MANAGER, NMSupplicantManager)) #define NM_SUPPLICANT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SUPPLICANT_MANAGER, NMSupplicantManagerClass)) @@ -33,7 +57,6 @@ G_BEGIN_DECLS #define NM_IS_SUPPLICANT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SUPPLICANT_MANAGER)) #define NM_SUPPLICANT_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SUPPLICANT_MANAGER, NMSupplicantManagerClass)) -typedef struct _NMSupplicantManager NMSupplicantManager; typedef struct _NMSupplicantManagerClass NMSupplicantManagerClass; typedef struct _NMSupplicantManagerPrivate NMSupplicantManagerPrivate; @@ -45,19 +68,24 @@ struct _NMSupplicantManager NMSupplicantManagerPrivate *priv; }; -struct NMAccessPoint; -struct wpa_ctrl; - struct _NMSupplicantManagerClass { GObjectClass parent; /* class members */ + void (* state) (NMSupplicantManager * mgr, guint32 new_state, guint32 old_state); }; GType nm_supplicant_manager_get_type (void); -NMSupplicantManager * nm_supplicant_manager_new (void); +NMSupplicantManager * nm_supplicant_manager_get (void); +guint32 nm_supplicant_manager_get_state (NMSupplicantManager * mgr); + +NMSupplicantInterface * nm_supplicant_manager_get_iface (NMSupplicantManager * mgr, + NMDevice * dev); + +void nm_supplicant_manager_release_iface (NMSupplicantManager * mgr, + NMSupplicantInterface * iface); #endif /* NM_SUPPLICANT_MANAGER_H */ diff --git a/src/supplicant-manager/nm-supplicant-types.h b/src/supplicant-manager/nm-supplicant-types.h new file mode 100644 index 0000000000..8057d8e95f --- /dev/null +++ b/src/supplicant-manager/nm-supplicant-types.h @@ -0,0 +1,29 @@ +/* NetworkManager -- Network link manager + * + * 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. + * + * (C) Copyright 2006 Red Hat, Inc. + */ + +#ifndef NM_SUPPLICANT_TYPES_H +#define NM_SUPPLICANT_TYPES_H + +typedef struct _NMSupplicantManager NMSupplicantManager; +typedef struct _NMSupplicantInterface NMSupplicantInterface; +typedef struct _NMSupplicantConnection NMSupplicantConnection; + +#endif /* NM_SUPPLICANT_TYPES_H */