diff options
Diffstat (limited to 'src/supplicant-manager/nm-supplicant-interface.c')
-rw-r--r-- | src/supplicant-manager/nm-supplicant-interface.c | 1583 |
1 files changed, 679 insertions, 904 deletions
diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index a65a458f5b..93807b9360 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2006 - 2008 Red Hat, Inc. + * Copyright (C) 2006 - 2010 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -34,73 +34,48 @@ #include "nm-glib-compat.h" #define WPAS_DBUS_IFACE_INTERFACE WPAS_DBUS_INTERFACE ".Interface" -#define WPAS_DBUS_IFACE_BSSID WPAS_DBUS_INTERFACE ".BSSID" +#define WPAS_DBUS_IFACE_BSS WPAS_DBUS_INTERFACE ".BSS" #define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network" #define WPAS_ERROR_INVALID_IFACE WPAS_DBUS_INTERFACE ".InvalidInterface" -#define WPAS_ERROR_EXISTS_ERROR WPAS_DBUS_INTERFACE ".ExistsError" - +#define WPAS_ERROR_EXISTS_ERROR WPAS_DBUS_INTERFACE ".InterfaceExists" G_DEFINE_TYPE (NMSupplicantInterface, nm_supplicant_interface, G_TYPE_OBJECT) +static void wpas_iface_properties_changed (DBusGProxy *proxy, + GHashTable *props, + gpointer user_data); + +static void wpas_iface_scan_done (DBusGProxy *proxy, + gboolean success, + gpointer user_data); #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 */ - SCANNED_AP, /* interface saw a new access point from a scan */ - SCAN_REQ_RESULT, /* result of a wireless scan request */ - SCAN_RESULTS, /* scan results returned from supplicant */ - CONNECTION_STATE, /* link state of the device's connection */ + NEW_BSS, /* interface saw a new access point from a scan */ + SCAN_DONE, /* wifi scan is complete */ CONNECTION_ERROR, /* an error occurred during a connection request */ LAST_SIGNAL }; -static guint nm_supplicant_interface_signals[LAST_SIGNAL] = { 0 }; +static guint signals[LAST_SIGNAL] = { 0 }; /* Properties */ enum { PROP_0 = 0, - PROP_SUPPLICANT_MANAGER, - PROP_DEVICE, - PROP_STATE, - PROP_CONNECTION_STATE, PROP_SCANNING, LAST_PROP }; -typedef struct -{ +typedef struct { NMSupplicantManager * smgr; - gulong smgr_state_sig_handler; + gulong smgr_avail_id; NMDBusManager * dbus_mgr; char * dev; gboolean is_wireless; @@ -110,18 +85,19 @@ typedef struct NMCallStore * assoc_pcalls; NMCallStore * other_pcalls; - guint32 con_state; gboolean scanning; + DBusGProxy * wpas_proxy; DBusGProxy * iface_proxy; - DBusGProxy * net_proxy; + DBusGProxy * props_proxy; + char * net_path; + guint32 blobs_left; - guint scan_results_timeout; guint32 last_scan; NMSupplicantConfig * cfg; - gboolean dispose_has_run; + gboolean disposed; } NMSupplicantInterfacePrivate; static gboolean @@ -203,827 +179,485 @@ nm_supplicant_info_destroy (gpointer user_data) } } - -NMSupplicantInterface * -nm_supplicant_interface_new (NMSupplicantManager * smgr, const char *ifname, gboolean is_wireless) -{ - NMSupplicantInterface * iface; - - g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (smgr), NULL); - g_return_val_if_fail (ifname != NULL, NULL); - - iface = g_object_new (NM_TYPE_SUPPLICANT_INTERFACE, - "supplicant-manager", smgr, - "device", ifname, - NULL); - if (iface) { - NM_SUPPLICANT_INTERFACE_GET_PRIVATE (iface)->is_wireless = is_wireless; - nm_supplicant_interface_start (iface); - } - - return iface; -} - static void -nm_supplicant_interface_init (NMSupplicantInterface * self) +emit_error_helper (NMSupplicantInterface *self, + GError *err) { - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - priv->state = NM_SUPPLICANT_INTERFACE_STATE_INIT; - priv->con_state = NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED; - priv->assoc_pcalls = nm_call_store_new (); - priv->other_pcalls = nm_call_store_new (); + const char *name = NULL; - priv->dispose_has_run = FALSE; + if (err->domain == DBUS_GERROR && err->code == DBUS_GERROR_REMOTE_EXCEPTION) + name = dbus_g_error_get_name (err); - priv->dbus_mgr = nm_dbus_manager_get (); + g_signal_emit (self, signals[CONNECTION_ERROR], 0, name, err->message); } - static void -nm_supplicant_interface_set_property (GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec) +bssid_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object); - gulong id; - - switch (prop_id) { - case PROP_SUPPLICANT_MANAGER: - priv->smgr = NM_SUPPLICANT_MANAGER (g_value_get_object (value)); - g_object_ref (G_OBJECT (priv->smgr)); - - id = g_signal_connect (priv->smgr, - "state", - G_CALLBACK (nm_supplicant_interface_smgr_state_changed), - object); - priv->smgr_state_sig_handler = id; - break; - case PROP_DEVICE: - /* Construct-only */ - priv->dev = g_strdup (g_value_get_string (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; + GError *error = NULL; + GHashTable *props = NULL; + + if (dbus_g_proxy_end_call (proxy, call_id, &error, + DBUS_TYPE_G_MAP_OF_VARIANT, &props, + G_TYPE_INVALID)) { + g_signal_emit (info->interface, signals[NEW_BSS], 0, props); + g_hash_table_destroy (props); + } else { + if (!strstr (error->message, "The BSSID requested was invalid")) { + nm_log_warn (LOGD_SUPPLICANT, "Couldn't retrieve BSSID properties: %s.", + error->message); + } + g_error_free (error); } } static void -nm_supplicant_interface_get_property (GObject * object, - guint prop_id, - GValue * value, - GParamSpec * pspec) +request_bss_properties (NMSupplicantInterface *self, + GPtrArray *paths) { - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + int i; - switch (prop_id) { - case PROP_SUPPLICANT_MANAGER: - g_value_set_object (value, G_OBJECT (priv->smgr)); - break; - case PROP_DEVICE: - g_value_set_string (value, priv->dev); - break; - case PROP_STATE: - g_value_set_uint (value, priv->state); - break; - case PROP_CONNECTION_STATE: - g_value_set_uint (value, priv->con_state); - break; - case PROP_SCANNING: - g_value_set_boolean (value, priv->scanning); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + /* Fire off a "properties" call for each returned BSSID */ + for (i = 0; i < paths->len; i++) { + NMSupplicantInfo *info; + DBusGProxy *proxy; + DBusGProxyCall *call; + + proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), + WPAS_DBUS_SERVICE, + g_ptr_array_index (paths, i), + DBUS_INTERFACE_PROPERTIES); + info = nm_supplicant_info_new (self, proxy, priv->other_pcalls); + call = dbus_g_proxy_begin_call (proxy, "GetAll", + bssid_properties_cb, + info, + nm_supplicant_info_destroy, + G_TYPE_STRING, WPAS_DBUS_IFACE_BSS, + G_TYPE_INVALID); + nm_supplicant_info_set_call (info, call); + g_object_unref (proxy); } } static void -try_remove_iface (DBusGConnection *g_connection, - const char *path) +wpas_iface_bss_added (DBusGProxy *proxy, + const char *object_path, + GHashTable *props, + gpointer user_data) { - DBusGProxy *proxy; - - g_return_if_fail (g_connection != NULL); - g_return_if_fail (path != NULL); - - proxy = dbus_g_proxy_new_for_name (g_connection, - WPAS_DBUS_SERVICE, - WPAS_DBUS_PATH, - WPAS_DBUS_INTERFACE); - if (!proxy) - return; - - dbus_g_proxy_call_no_reply (proxy, "removeInterface", - DBUS_TYPE_G_OBJECT_PATH, path, - G_TYPE_INVALID); - g_object_unref (proxy); + g_signal_emit (NM_SUPPLICANT_INTERFACE (user_data), signals[NEW_BSS], 0, props); } -static void -nm_supplicant_interface_dispose (GObject *object) +static int +wpas_state_string_to_enum (const char *str_state) { - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object); - guint32 sm_state; - - if (priv->dispose_has_run) { - G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object); - return; - } - - priv->dispose_has_run = TRUE; - - /* Ask wpa_supplicant to remove this interface */ - sm_state = nm_supplicant_manager_get_state (priv->smgr); - if (sm_state == NM_SUPPLICANT_MANAGER_STATE_IDLE) { - if (priv->object_path) { - try_remove_iface (nm_dbus_manager_get_connection (priv->dbus_mgr), - priv->object_path); - } - } - - if (priv->iface_proxy) - g_object_unref (priv->iface_proxy); - - if (priv->net_proxy) - g_object_unref (priv->net_proxy); - - if (priv->scan_results_timeout) - g_source_remove (priv->scan_results_timeout); - - if (priv->smgr) { - g_signal_handler_disconnect (priv->smgr, - priv->smgr_state_sig_handler); - g_object_unref (priv->smgr); - } - - g_free (priv->dev); - - /* Cancel pending calls before unrefing the dbus manager */ - cancel_all_callbacks (priv->other_pcalls); - nm_call_store_destroy (priv->other_pcalls); - - cancel_all_callbacks (priv->assoc_pcalls); - nm_call_store_destroy (priv->assoc_pcalls); - - if (priv->dbus_mgr) - g_object_unref (priv->dbus_mgr); - - if (priv->cfg) - g_object_unref (priv->cfg); - - g_free (priv->object_path); - - /* Chain up to the parent class */ - G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object); + if (!strcmp (str_state, "disconnected")) + return NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED; + else if (!strcmp (str_state, "inactive")) + return NM_SUPPLICANT_INTERFACE_STATE_INACTIVE; + else if (!strcmp (str_state, "scanning")) + return NM_SUPPLICANT_INTERFACE_STATE_SCANNING; + else if (!strcmp (str_state, "associating")) + return NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING; + else if (!strcmp (str_state, "associated")) + return NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED; + else if (!strcmp (str_state, "4way_handshake")) + return NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE; + else if (!strcmp (str_state, "group_handshake")) + return NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE; + else if (!strcmp (str_state, "completed")) + return NM_SUPPLICANT_INTERFACE_STATE_COMPLETED; + + return -1; } static void -nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) +set_state (NMSupplicantInterface *self, guint32 new_state) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMSupplicantInterfacePrivate)); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + guint32 old_state = priv->state; - object_class->dispose = nm_supplicant_interface_dispose; - object_class->set_property = nm_supplicant_interface_set_property; - object_class->get_property = nm_supplicant_interface_get_property; + g_return_if_fail (new_state < NM_SUPPLICANT_INTERFACE_STATE_LAST); - /* 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_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_DEVICE, - g_param_spec_string ("device", - "Device", - "Device which this interface represents to the supplicant", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_STATE, - 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)); - - g_object_class_install_property (object_class, - PROP_SCANNING, - g_param_spec_boolean ("scanning", - "Scanning", - "Scanning", - FALSE, - G_PARAM_READABLE)); + if (new_state == priv->state) + return; - /* 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); + /* DOWN is a terminal state */ + g_return_if_fail (priv->state != NM_SUPPLICANT_INTERFACE_STATE_DOWN); - 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); + /* Cannot regress to READY, STARTING, or INIT from higher states */ + if (priv->state >= NM_SUPPLICANT_INTERFACE_STATE_READY) + g_return_if_fail (new_state > NM_SUPPLICANT_INTERFACE_STATE_READY); - nm_supplicant_interface_signals[SCANNED_AP] = - g_signal_new ("scanned-ap", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scanned_ap), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - nm_supplicant_interface_signals[SCAN_REQ_RESULT] = - g_signal_new ("scan-req-result", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_req_result), - NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) { + /* Cancel all pending calls when going down */ + cancel_all_callbacks (priv->other_pcalls); + cancel_all_callbacks (priv->assoc_pcalls); - 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, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); + /* Disconnect supplicant manager state listeners since we're done */ + if (priv->smgr_avail_id) { + g_signal_handler_disconnect (priv->smgr, priv->smgr_avail_id); + priv->smgr_avail_id = 0; + } - nm_supplicant_interface_signals[CONNECTION_STATE] = - g_signal_new ("connection-state", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, connection_state), - NULL, NULL, - _nm_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); + if (priv->iface_proxy) { + dbus_g_proxy_disconnect_signal (priv->iface_proxy, + "PropertiesChanged", + G_CALLBACK (wpas_iface_properties_changed), + self); + dbus_g_proxy_disconnect_signal (priv->iface_proxy, + "ScanDone", + G_CALLBACK (wpas_iface_scan_done), + self); + dbus_g_proxy_disconnect_signal (priv->iface_proxy, + "BSSAdded", + G_CALLBACK (wpas_iface_bss_added), + self); + } + } - nm_supplicant_interface_signals[CONNECTION_ERROR] = - g_signal_new ("connection-error", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, connection_error), - NULL, NULL, - _nm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); + priv->state = new_state; + g_signal_emit (self, signals[STATE], 0, priv->state, old_state); } static void -emit_error_helper (NMSupplicantInterface *self, - GError *err) +set_state_from_string (NMSupplicantInterface *self, const char *new_state) { - const char *name = NULL; + int state; - if (err->domain == DBUS_GERROR && err->code == DBUS_GERROR_REMOTE_EXCEPTION) - name = dbus_g_error_get_name (err); - - g_signal_emit (self, - nm_supplicant_interface_signals[CONNECTION_ERROR], - 0, - name, - err->message); + state = wpas_state_string_to_enum (new_state); + g_warn_if_fail (state > 0); + if (state > 0) + set_state (self, (guint32) state); } static void -bssid_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +set_scanning (NMSupplicantInterface *self, gboolean new_scanning) { - NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; - GError *err = NULL; - GHashTable *hash = NULL; + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + GTimeVal cur_time; - if (!dbus_g_proxy_end_call (proxy, call_id, &err, - DBUS_TYPE_G_MAP_OF_VARIANT, &hash, - G_TYPE_INVALID)) { - if (!strstr (err->message, "The BSSID requested was invalid")) { - nm_log_warn (LOGD_SUPPLICANT, "Couldn't retrieve BSSID properties: %s.", - err->message); + if (priv->scanning != new_scanning) { + priv->scanning = new_scanning; + + /* Cache time of last scan completion */ + if (priv->scanning == FALSE) { + g_get_current_time (&cur_time); + priv->last_scan = cur_time.tv_sec; } - g_error_free (err); - } else { - g_signal_emit (info->interface, - nm_supplicant_interface_signals[SCANNED_AP], - 0, - hash); - g_hash_table_destroy (hash); + g_object_notify (G_OBJECT (self), "scanning"); } } -static void -request_bssid_properties (NMSupplicantInterface * self, - const char * op) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - NMSupplicantInfo *info; - DBusGProxy *proxy; - DBusGProxyCall *call; - - proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), - WPAS_DBUS_SERVICE, - op, - WPAS_DBUS_IFACE_BSSID); - info = nm_supplicant_info_new (self, proxy, priv->other_pcalls); - call = dbus_g_proxy_begin_call (proxy, "properties", - bssid_properties_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_INVALID); - nm_supplicant_info_set_call (info, call); - g_object_unref (proxy); -} - -static void -scan_results_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +gboolean +nm_supplicant_interface_get_scanning (NMSupplicantInterface *self) { - GError *err = NULL; - GPtrArray *array = NULL; - - if (!dbus_g_proxy_end_call (proxy, call_id, &err, - DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &array, - G_TYPE_INVALID)) { - nm_log_warn (LOGD_SUPPLICANT, "could not get scan results: %s.", err->message); - g_error_free (err); - } else { - int i; - NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; - - /* Notify listeners of the result of the scan */ - g_signal_emit (info->interface, - nm_supplicant_interface_signals[SCAN_RESULTS], - 0, - array->len); - - /* Fire off a "properties" call for each returned BSSID */ - for (i = 0; i < array->len; i++) { - char *op = g_ptr_array_index (array, i); + NMSupplicantInterfacePrivate *priv; - request_bssid_properties (info->interface, op); - g_free (op); - } + g_return_val_if_fail (self != NULL, FALSE); - g_ptr_array_free (array, TRUE); - } + priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + if (priv->scanning) + return TRUE; + if (priv->state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING) + return TRUE; + return FALSE; } -static gboolean -request_scan_results (gpointer user_data) +static void +wpas_iface_scan_done (DBusGProxy *proxy, + gboolean success, + gpointer user_data) { NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - NMSupplicantInfo *info; - DBusGProxyCall *call; GTimeVal cur_time; - priv->scan_results_timeout = 0; - - g_return_val_if_fail (priv->iface_proxy != NULL, FALSE); - - info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "scanResults", - scan_results_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_INVALID); - nm_supplicant_info_set_call (info, call); - + /* Cache last scan completed time */ g_get_current_time (&cur_time); priv->last_scan = cur_time.tv_sec; - return FALSE; + + g_signal_emit (self, signals[SCAN_DONE], 0, success); } static void -wpas_iface_query_scan_results (DBusGProxy *proxy, gpointer user_data) +wpas_iface_properties_changed (DBusGProxy *proxy, + GHashTable *props, + gpointer user_data) { - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (user_data); - GTimeVal cur_time; + NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + GValue *value; - /* Only query scan results if a query is not queued */ - if (priv->scan_results_timeout) - return; + value = g_hash_table_lookup (props, "Scanning"); + if (value && G_VALUE_HOLDS_BOOLEAN (value)) + set_scanning (self, g_value_get_boolean (value)); - g_get_current_time (&cur_time); - - /* Only fetch scan results every 4s max, but initially do it right away */ - if (priv->last_scan + 4 < cur_time.tv_sec) { - priv->scan_results_timeout = g_idle_add (request_scan_results, - user_data); - } else { - priv->scan_results_timeout = - g_timeout_add_seconds ((4 - (cur_time.tv_sec - priv->last_scan)), - request_scan_results, user_data); - } -} + value = g_hash_table_lookup (props, "State"); + if (value && G_VALUE_HOLDS_STRING (value)) + set_state_from_string (self, g_value_get_string (value)); -static guint32 -wpas_state_string_to_enum (const char * str_state) -{ - guint32 enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED; - - if (!strcmp (str_state, "DISCONNECTED")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED; - else if (!strcmp (str_state, "INACTIVE")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_INACTIVE; - else if (!strcmp (str_state, "SCANNING")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING; - else if (!strcmp (str_state, "ASSOCIATING")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATING; - else if (!strcmp (str_state, "ASSOCIATED")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATED; - else if (!strcmp (str_state, "4WAY_HANDSHAKE")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_4WAY_HANDSHAKE; - else if (!strcmp (str_state, "GROUP_HANDSHAKE")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_GROUP_HANDSHAKE; - else if (!strcmp (str_state, "COMPLETED")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED; - - return enum_state; + value = g_hash_table_lookup (props, "BSSs"); + if (value && G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH)) + request_bss_properties (self, g_value_get_boxed (value)); } static void -wpas_iface_handle_state_change (DBusGProxy *proxy, - const char *str_new_state, - const char *str_old_state, - gpointer user_data) +iface_get_props_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (user_data); - guint32 old_state, enum_new_state; - - enum_new_state = wpas_state_string_to_enum (str_new_state); - old_state = priv->con_state; - priv->con_state = enum_new_state; - if (priv->con_state != old_state) { - g_signal_emit (user_data, - nm_supplicant_interface_signals[CONNECTION_STATE], - 0, - priv->con_state, - old_state); - } -} - - -static void -iface_state_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) -{ - GError *err = NULL; - char *state_str = NULL; - - if (!dbus_g_proxy_end_call (proxy, call_id, &err, - G_TYPE_STRING, &state_str, - G_TYPE_INVALID)) { - nm_log_warn (LOGD_SUPPLICANT, "could not get interface state: %s.", err->message); - g_error_free (err); + NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; + GHashTable *props = NULL; + GError *error = NULL; + + if (dbus_g_proxy_end_call (proxy, call_id, &error, + DBUS_TYPE_G_MAP_OF_VARIANT, &props, + G_TYPE_INVALID)) { + wpas_iface_properties_changed (NULL, props, info->interface); + g_hash_table_destroy (props); } else { - NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - - priv->con_state = wpas_state_string_to_enum (state_str); - g_free (state_str); - nm_supplicant_interface_set_state (info->interface, NM_SUPPLICANT_INTERFACE_STATE_READY); + nm_log_warn (LOGD_SUPPLICANT, "could not get interface properties: %s.", + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); } } static void -wpas_iface_get_state (NMSupplicantInterface *self) +wpas_iface_get_props (NMSupplicantInterface *self) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); NMSupplicantInfo *info; DBusGProxyCall *call; - info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "state", - iface_state_cb, + info = nm_supplicant_info_new (self, priv->props_proxy, priv->other_pcalls); + call = dbus_g_proxy_begin_call (priv->props_proxy, "GetAll", + iface_get_props_cb, info, nm_supplicant_info_destroy, + G_TYPE_STRING, WPAS_DBUS_IFACE_INTERFACE, G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); } static void -iface_scanning_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +interface_add_done (NMSupplicantInterface *self, char *path) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + nm_log_dbg (LOGD_SUPPLICANT, "(%s): interface added to supplicant", priv->dev); + + priv->object_path = path; + + priv->iface_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), + WPAS_DBUS_SERVICE, + path, + WPAS_DBUS_IFACE_INTERFACE); + + dbus_g_object_register_marshaller (g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, + DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (priv->iface_proxy, "PropertiesChanged", + DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->iface_proxy, "PropertiesChanged", + G_CALLBACK (wpas_iface_properties_changed), + self, NULL); + + dbus_g_proxy_add_signal (priv->iface_proxy, "ScanDone", G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->iface_proxy, "ScanDone", + G_CALLBACK (wpas_iface_scan_done), + self, + NULL); + + dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_BOXED, + G_TYPE_NONE, + G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (priv->iface_proxy, "BSSAdded", G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->iface_proxy, "BSSAdded", + G_CALLBACK (wpas_iface_bss_added), + self, + NULL); + + priv->props_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), + WPAS_DBUS_SERVICE, + path, + DBUS_INTERFACE_PROPERTIES); + /* Get initial properties */ + wpas_iface_get_props (self); + + set_state (self, NM_SUPPLICANT_INTERFACE_STATE_READY); +} + +static void +interface_get_cb (DBusGProxy *proxy, + DBusGProxyCall *call_id, + gpointer user_data) { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - gboolean scanning = FALSE; + GError *error = NULL; + char *path = NULL; - if (dbus_g_proxy_end_call (proxy, call_id, NULL, - G_TYPE_BOOLEAN, &scanning, - G_TYPE_INVALID)) { - if (scanning != priv->scanning) { - priv->scanning = scanning; - g_object_notify (G_OBJECT (info->interface), "scanning"); - } + if (dbus_g_proxy_end_call (proxy, call_id, &error, + DBUS_TYPE_G_OBJECT_PATH, &path, + G_TYPE_INVALID)) { + interface_add_done (info->interface, path); + } else { + nm_log_err (LOGD_SUPPLICANT, "(%s): error getting interface: %s", + priv->dev, error->message); + g_clear_error (&error); + set_state (info->interface, NM_SUPPLICANT_INTERFACE_STATE_DOWN); } } static void -wpas_iface_get_scanning (NMSupplicantInterface *self) +interface_get (NMSupplicantInterface *self) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); NMSupplicantInfo *info; DBusGProxyCall *call; - info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "scanning", - iface_scanning_cb, + info = nm_supplicant_info_new (self, priv->wpas_proxy, priv->other_pcalls); + call = dbus_g_proxy_begin_call (priv->wpas_proxy, "GetInterface", + interface_get_cb, info, nm_supplicant_info_destroy, + G_TYPE_STRING, priv->dev, G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); } static void -wpas_iface_handle_scanning (DBusGProxy *proxy, - gboolean scanning, - gpointer user_data) -{ - NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - if (scanning != priv->scanning) { - priv->scanning = scanning; - g_object_notify (G_OBJECT (self), "scanning"); - } -} - -gboolean -nm_supplicant_interface_get_scanning (NMSupplicantInterface *self) -{ - NMSupplicantInterfacePrivate *priv; - - g_return_val_if_fail (self != NULL, FALSE); - - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - if (priv->scanning) - return TRUE; - if (priv->con_state == NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING) - return TRUE; - return FALSE; -} - -static void -nm_supplicant_interface_add_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +interface_add_cb (DBusGProxy *proxy, + DBusGProxyCall *call_id, + gpointer user_data) { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - GError *err = NULL; + GError *error = NULL; char *path = NULL; - if (!dbus_g_proxy_end_call (proxy, call_id, &err, - DBUS_TYPE_G_OBJECT_PATH, &path, - G_TYPE_INVALID)) { - - if (dbus_g_error_has_name (err, WPAS_ERROR_INVALID_IFACE)) { - /* Interface not added, try to add it */ - nm_supplicant_interface_add_to_supplicant (info->interface, FALSE); - } else if (dbus_g_error_has_name (err, WPAS_ERROR_EXISTS_ERROR)) { - /* Interface already added, just try to get the interface */ - nm_supplicant_interface_add_to_supplicant (info->interface, TRUE); + if (dbus_g_proxy_end_call (proxy, call_id, &error, + DBUS_TYPE_G_OBJECT_PATH, &path, + G_TYPE_INVALID)) { + interface_add_done (info->interface, path); + } else { + if (dbus_g_error_has_name (error, WPAS_ERROR_EXISTS_ERROR)) { + /* Interface already added, just get its object path */ + interface_get (info->interface); + } else if ( g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN) + || dbus_g_error_has_name (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND)) { + /* Supplicant wasn't running and could be launched via service + * activation. Wait for it to start by moving back to the INIT + * state. + */ + nm_log_dbg (LOGD_SUPPLICANT, "(%s): failed to activate supplicant: %s", + priv->dev, error->message); + set_state (info->interface, NM_SUPPLICANT_INTERFACE_STATE_INIT); } else { - nm_log_err (LOGD_SUPPLICANT, "(%s): error getting interface: %s", - priv->dev, err->message); + nm_log_err (LOGD_SUPPLICANT, "(%s): error adding interface: %s", + priv->dev, error->message); + set_state (info->interface, NM_SUPPLICANT_INTERFACE_STATE_DOWN); } - - g_error_free (err); - } else { - nm_log_dbg (LOGD_SUPPLICANT, "(%s): interface added to supplicant", priv->dev); - - priv->object_path = path; - - priv->iface_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), - WPAS_DBUS_SERVICE, - path, - WPAS_DBUS_IFACE_INTERFACE); - - dbus_g_proxy_add_signal (priv->iface_proxy, "ScanResultsAvailable", G_TYPE_INVALID); - - dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, - G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_INVALID); - - dbus_g_proxy_add_signal (priv->iface_proxy, "StateChange", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); - - dbus_g_proxy_connect_signal (priv->iface_proxy, "ScanResultsAvailable", - G_CALLBACK (wpas_iface_query_scan_results), - info->interface, - NULL); - - dbus_g_proxy_connect_signal (priv->iface_proxy, "StateChange", - G_CALLBACK (wpas_iface_handle_state_change), - info->interface, - NULL); - - dbus_g_proxy_add_signal (priv->iface_proxy, "Scanning", G_TYPE_BOOLEAN, G_TYPE_INVALID); - - dbus_g_proxy_connect_signal (priv->iface_proxy, "Scanning", - G_CALLBACK (wpas_iface_handle_scanning), - info->interface, - NULL); - - /* Interface added to the supplicant; get its initial state. */ - wpas_iface_get_state (info->interface); - wpas_iface_get_scanning (info->interface); + g_clear_error (&error); } } static void -nm_supplicant_interface_add_to_supplicant (NMSupplicantInterface * self, - gboolean get_only) +interface_add (NMSupplicantInterface *self, gboolean is_wireless) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - NMSupplicantInfo *info; - DBusGProxy *proxy; DBusGProxyCall *call; - - proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), - WPAS_DBUS_SERVICE, - WPAS_DBUS_PATH, - WPAS_DBUS_INTERFACE); - info = nm_supplicant_info_new (self, proxy, priv->other_pcalls); - - if (get_only) { - call = dbus_g_proxy_begin_call (proxy, "getInterface", - nm_supplicant_interface_add_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_STRING, priv->dev, - G_TYPE_INVALID); - } else { - GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal); - GValue *driver; - - driver = g_new0 (GValue, 1); - g_value_init (driver, G_TYPE_STRING); - g_value_set_string (driver, priv->is_wireless ? "wext" : "wired"); - g_hash_table_insert (hash, "driver", driver); - - call = dbus_g_proxy_begin_call (proxy, "addInterface", - nm_supplicant_interface_add_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_STRING, priv->dev, - DBUS_TYPE_G_MAP_OF_VARIANT, hash, - G_TYPE_INVALID); - - g_value_unset (driver); - g_free (driver); - g_hash_table_destroy (hash); - } - - g_object_unref (proxy); - - nm_supplicant_info_set_call (info, call); -} - -static void -nm_supplicant_interface_start (NMSupplicantInterface * self) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - guint32 state; + NMSupplicantInfo *info; + GHashTable *hash; + GValue *driver, *ifname; /* Can only start the interface from INIT state */ g_return_if_fail (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT); nm_log_dbg (LOGD_SUPPLICANT, "(%s): adding interface to supplicant", priv->dev); - state = nm_supplicant_manager_get_state (priv->smgr); - if (state == NM_SUPPLICANT_MANAGER_STATE_IDLE) { - nm_supplicant_interface_set_state (self, NM_SUPPLICANT_INTERFACE_STATE_STARTING); - 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_log_warn (LOGD_SUPPLICANT, "Unknown supplicant manager state!"); -} + /* Move to starting to prevent double-calls of interface_add() */ + set_state (self, NM_SUPPLICANT_INTERFACE_STATE_STARTING); -static void -nm_supplicant_interface_handle_supplicant_manager_idle_state (NMSupplicantInterface * self) -{ - switch (NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->state) { - case NM_SUPPLICANT_INTERFACE_STATE_INIT: - /* Move to STARTING state when supplicant is ready */ - nm_supplicant_interface_start (self); - break; - case NM_SUPPLICANT_INTERFACE_STATE_STARTING: - /* Don't do anything here, though we should never hit this */ - 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_log_warn (LOGD_SUPPLICANT, "Unknown supplicant interface state!"); - break; - } -} + /* Try to add the interface to the supplicant. If the supplicant isn't + * running, this will start it via D-Bus activation and return the response + * when the supplicant has started. + */ + info = nm_supplicant_info_new (self, priv->wpas_proxy, priv->other_pcalls); -static void -nm_supplicant_interface_set_state (NMSupplicantInterface * self, - guint32 new_state) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - guint32 old_state; + hash = g_hash_table_new (g_str_hash, g_str_equal); - g_return_if_fail (new_state < NM_SUPPLICANT_INTERFACE_STATE_LAST); + driver = g_new0 (GValue, 1); + g_value_init (driver, G_TYPE_STRING); + g_value_set_string (driver, is_wireless ? "nl80211,wext" : "wired"); + g_hash_table_insert (hash, "Driver", driver); - if (new_state == priv->state) - return; + ifname = g_new0 (GValue, 1); + g_value_init (ifname, G_TYPE_STRING); + g_value_set_string (ifname, priv->dev); + g_hash_table_insert (hash, "Ifname", ifname); - old_state = priv->state; - if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) { - /* If the interface is transitioning to DOWN and there's are - * in-progress pending calls, cancel them. - */ - cancel_all_callbacks (priv->other_pcalls); - cancel_all_callbacks (priv->assoc_pcalls); - } + call = dbus_g_proxy_begin_call (priv->wpas_proxy, "CreateInterface", + interface_add_cb, + info, + nm_supplicant_info_destroy, + DBUS_TYPE_G_MAP_OF_VARIANT, hash, + G_TYPE_INVALID); - priv->state = new_state; - g_signal_emit (self, - nm_supplicant_interface_signals[STATE], - 0, - priv->state, - old_state); + g_hash_table_destroy (hash); + g_value_unset (driver); + g_free (driver); + g_value_unset (ifname); + g_free (ifname); + + nm_supplicant_info_set_call (info, call); } static void -nm_supplicant_interface_smgr_state_changed (NMSupplicantManager * smgr, - guint32 new_state, - guint32 old_state, - gpointer user_data) +smgr_avail_cb (NMSupplicantManager *smgr, + GParamSpec *pspec, + gpointer user_data) { - NMSupplicantInterface * self = NM_SUPPLICANT_INTERFACE (user_data); + NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (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_log_warn (LOGD_SUPPLICANT, "Unknown supplicant manager state!"); - break; + if (nm_supplicant_manager_available (smgr)) { + /* This can happen if the supplicant couldn't be activated but + * for some reason was started after the activation failure. + */ + if (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT) + interface_add (self, priv->is_wireless); + } else { + /* The supplicant stopped; so we must tear down the interface */ + set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN); } } - static void remove_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { - GError *err = NULL; - guint tmp; + GError *error = NULL; - if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) { + if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) { nm_log_dbg (LOGD_SUPPLICANT, "Couldn't remove network from supplicant interface: %s.", - err->message); - g_error_free (err); + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); } } static void disconnect_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { - GError *err = NULL; - guint tmp; + GError *error = NULL; - if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) { + if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) { nm_log_warn (LOGD_SUPPLICANT, "Couldn't disconnect supplicant interface: %s.", - err->message); - g_error_free (err); + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); } } @@ -1045,32 +679,26 @@ nm_supplicant_interface_disconnect (NMSupplicantInterface * self) if (!priv->iface_proxy) return; - /* Don't try to disconnect if the supplicant interface is already - * disconnected. - */ - if (priv->con_state == NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED - || priv->con_state == NM_SUPPLICANT_INTERFACE_CON_STATE_INACTIVE) { - if (priv->net_proxy) { - g_object_unref (priv->net_proxy); - priv->net_proxy = NULL; - } - + /* Don't try to disconnect if the supplicant interface is already disconnected */ + if ( priv->state == NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED + || priv->state == NM_SUPPLICANT_INTERFACE_STATE_INACTIVE) { + g_free (priv->net_path); + priv->net_path = NULL; return; } /* Remove any network that was added by NetworkManager */ - if (priv->net_proxy) { - dbus_g_proxy_begin_call (priv->iface_proxy, "removeNetwork", + if (priv->net_path) { + dbus_g_proxy_begin_call (priv->iface_proxy, "RemoveNetwork", remove_network_cb, NULL, NULL, - DBUS_TYPE_G_OBJECT_PATH, dbus_g_proxy_get_path (priv->net_proxy), + DBUS_TYPE_G_OBJECT_PATH, priv->net_path, G_TYPE_INVALID); - - g_object_unref (priv->net_proxy); - priv->net_proxy = NULL; + g_free (priv->net_path); + priv->net_path = NULL; } - dbus_g_proxy_begin_call (priv->iface_proxy, "disconnect", + dbus_g_proxy_begin_call (priv->iface_proxy, "Disconnect", disconnect_cb, NULL, NULL, G_TYPE_INVALID); @@ -1081,9 +709,8 @@ select_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_dat { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; GError *err = NULL; - guint tmp; - if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) { + if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_INVALID)) { nm_log_warn (LOGD_SUPPLICANT, "Couldn't select network config: %s.", err->message); emit_error_helper (info->interface, err); g_error_free (err); @@ -1091,163 +718,86 @@ select_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_dat } static void -set_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) -{ - NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - GError *err = NULL; - guint tmp; - - if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) { - nm_log_warn (LOGD_SUPPLICANT, "Couldn't set network config: %s.", err->message); - emit_error_helper (info->interface, err); - g_error_free (err); - } else { - DBusGProxyCall *call; - - info = nm_supplicant_info_new (info->interface, priv->iface_proxy, priv->assoc_pcalls); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "selectNetwork", - select_network_cb, - info, - nm_supplicant_info_destroy, - DBUS_TYPE_G_OBJECT_PATH, dbus_g_proxy_get_path (proxy), - G_TYPE_INVALID); - nm_supplicant_info_set_call (info, call); - } -} - -static void -call_set_network (NMSupplicantInfo *info) +call_select_network (NMSupplicantInterface *self) { - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - GHashTable *config_hash; + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); DBusGProxyCall *call; + NMSupplicantInfo *info; - config_hash = nm_supplicant_config_get_hash (priv->cfg); - call = dbus_g_proxy_begin_call (priv->net_proxy, "set", - set_network_cb, + /* We only select the network after all blobs (if any) have been set */ + if (priv->blobs_left > 0) + return; + + info = nm_supplicant_info_new (self, priv->iface_proxy, priv->assoc_pcalls); + call = dbus_g_proxy_begin_call (priv->iface_proxy, "SelectNetwork", + select_network_cb, info, nm_supplicant_info_destroy, - DBUS_TYPE_G_MAP_OF_VARIANT, config_hash, + DBUS_TYPE_G_OBJECT_PATH, priv->net_path, G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); - g_hash_table_destroy (config_hash); } static void -set_blobs_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +add_blob_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); GError *err = NULL; guint tmp; + priv->blobs_left--; + if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) { nm_log_warn (LOGD_SUPPLICANT, "Couldn't set network certificates: %s.", err->message); emit_error_helper (info->interface, err); g_error_free (err); - } else { - info = nm_supplicant_info_new (info->interface, priv->iface_proxy, priv->assoc_pcalls); - call_set_network (info); - } -} - -static GValue * -byte_array_to_gvalue (const GByteArray *array) -{ - GValue *val; - - val = g_slice_new0 (GValue); - g_value_init (val, DBUS_TYPE_G_UCHAR_ARRAY); - g_value_set_boxed (val, array); - - return val; -} - -static void -blob_free (GValue *val) -{ - g_value_unset (val); - g_slice_free (GValue, val); -} - -static void -convert_blob (const char *key, const GByteArray *value, GHashTable *hash) -{ - GValue *val; - - val = byte_array_to_gvalue (value); - g_hash_table_insert (hash, g_strdup (key), val); -} - -static void -call_set_blobs (NMSupplicantInfo *info, GHashTable *orig_blobs) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - DBusGProxyCall *call; - GHashTable *blobs; - - blobs = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) blob_free); - if (!blobs) { - const char *msg = "Not enough memory to create blob table."; - - nm_log_warn (LOGD_SUPPLICANT, "%s", msg); - g_signal_emit (info->interface, - nm_supplicant_interface_signals[CONNECTION_ERROR], - 0, "SendBlobError", msg); - return; - } - - g_hash_table_foreach (orig_blobs, (GHFunc) convert_blob, blobs); - - call = dbus_g_proxy_begin_call (priv->iface_proxy, "setBlobs", - set_blobs_cb, - info, - nm_supplicant_info_destroy, - DBUS_TYPE_G_MAP_OF_VARIANT, blobs, - G_TYPE_INVALID); - nm_supplicant_info_set_call (info, call); - g_hash_table_destroy (blobs); + } else + call_select_network (info->interface); } static void add_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); GError *err = NULL; - char *path = NULL; + GHashTable *blobs; + GHashTableIter iter; + gpointer name, data; + DBusGProxyCall *call; + NMSupplicantInfo *blob_info; + + g_free (priv->net_path); + priv->net_path = NULL; if (!dbus_g_proxy_end_call (proxy, call_id, &err, - DBUS_TYPE_G_OBJECT_PATH, &path, + DBUS_TYPE_G_OBJECT_PATH, &priv->net_path, G_TYPE_INVALID)) { nm_log_warn (LOGD_SUPPLICANT, "Couldn't add a network to the supplicant interface: %s.", err->message); emit_error_helper (info->interface, err); g_error_free (err); - } else { - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - GHashTable *blobs; - - priv->net_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), - WPAS_DBUS_SERVICE, - path, - WPAS_DBUS_IFACE_NETWORK); - g_free (path); - - info = nm_supplicant_info_new (info->interface, - priv->net_proxy, - priv->assoc_pcalls); - /* Send any blobs first; if there aren't any jump to sending the - * config settings. - */ - blobs = nm_supplicant_config_get_blobs (priv->cfg); - if (g_hash_table_size (blobs) > 0) - call_set_blobs (info, blobs); - else - call_set_network (info); + return; + } + + /* Send blobs first; otherwise jump to sending the config settings */ + blobs = nm_supplicant_config_get_blobs (priv->cfg); + priv->blobs_left = g_hash_table_size (blobs); + g_hash_table_iter_init (&iter, blobs); + while (g_hash_table_iter_next (&iter, &name, &data)) { + blob_info = nm_supplicant_info_new (info->interface, priv->iface_proxy, priv->assoc_pcalls); + call = dbus_g_proxy_begin_call (priv->iface_proxy, "AddBlob", + add_blob_cb, + blob_info, + nm_supplicant_info_destroy, + DBUS_TYPE_STRING, name, + DBUS_TYPE_G_UCHAR_ARRAY, blobs, + G_TYPE_INVALID); + nm_supplicant_info_set_call (blob_info, call); } + + call_select_network (info->interface); } static void @@ -1256,10 +806,10 @@ set_ap_scan_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); GError *err = NULL; - guint32 tmp; DBusGProxyCall *call; + GHashTable *config_hash; - if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) { + if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_INVALID)) { nm_log_warn (LOGD_SUPPLICANT, "Couldn't send AP scan mode to the supplicant interface: %s.", err->message); emit_error_helper (info->interface, err); @@ -1270,12 +820,15 @@ set_ap_scan_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) nm_log_info (LOGD_SUPPLICANT, "Config: set interface ap_scan to %d", nm_supplicant_config_get_ap_scan (priv->cfg)); - info = nm_supplicant_info_new (info->interface, proxy, info->store); - call = dbus_g_proxy_begin_call (proxy, "addNetwork", + info = nm_supplicant_info_new (info->interface, priv->iface_proxy, info->store); + config_hash = nm_supplicant_config_get_hash (priv->cfg); + call = dbus_g_proxy_begin_call (priv->iface_proxy, "AddNetwork", add_network_cb, info, nm_supplicant_info_destroy, + DBUS_TYPE_G_MAP_OF_VARIANT, config_hash, G_TYPE_INVALID); + g_hash_table_destroy (config_hash); nm_supplicant_info_set_call (info, call); } @@ -1286,7 +839,7 @@ nm_supplicant_interface_set_config (NMSupplicantInterface * self, NMSupplicantInterfacePrivate *priv; NMSupplicantInfo *info; DBusGProxyCall *call; - guint32 ap_scan; + GValue value = { 0, }; g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE); @@ -1303,46 +856,54 @@ nm_supplicant_interface_set_config (NMSupplicantInterface * self, g_object_ref (priv->cfg); - info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); - ap_scan = nm_supplicant_config_get_ap_scan (priv->cfg); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "setAPScan", + g_value_init (&value, G_TYPE_UINT); + g_value_set_uint (&value, nm_supplicant_config_get_ap_scan (priv->cfg)); + + info = nm_supplicant_info_new (self, priv->props_proxy, priv->other_pcalls); + call = dbus_g_proxy_begin_call (priv->props_proxy, "Set", set_ap_scan_cb, info, nm_supplicant_info_destroy, - G_TYPE_UINT, ap_scan, + G_TYPE_STRING, WPAS_DBUS_IFACE_INTERFACE, + G_TYPE_STRING, "ApScan", + G_TYPE_VALUE, &value, G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); + g_value_unset (&value); return call != NULL; } -const char * -nm_supplicant_interface_get_device (NMSupplicantInterface * self) -{ - g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NULL); - - return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev; -} - static void scan_request_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; GError *err = NULL; - guint32 success = 0; - if (!dbus_g_proxy_end_call (proxy, call_id, &err, - G_TYPE_UINT, &success, - G_TYPE_INVALID)) { + if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_INVALID)) { nm_log_warn (LOGD_SUPPLICANT, "Could not get scan request result: %s", err->message); - g_error_free (err); } + g_signal_emit (info->interface, signals[SCAN_DONE], 0, err ? FALSE : TRUE); + g_clear_error (&err); +} + +static void +destroy_gvalue (gpointer data) +{ + GValue *value = (GValue *) data; - /* Notify listeners of the result of the scan */ - g_signal_emit (info->interface, - nm_supplicant_interface_signals[SCAN_REQ_RESULT], - 0, - success ? TRUE : FALSE); + g_value_unset (value); + g_slice_free (GValue, value); +} + +static GValue * +string_to_gvalue (const char *str) +{ + GValue *val = g_slice_new0 (GValue); + + g_value_init (val, G_TYPE_STRING); + g_value_set_string (val, str); + return val; } gboolean @@ -1351,17 +912,24 @@ nm_supplicant_interface_request_scan (NMSupplicantInterface * self) NMSupplicantInterfacePrivate *priv; NMSupplicantInfo *info; DBusGProxyCall *call; + GHashTable *hash; g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE); priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + /* Scan parameters */ + hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, destroy_gvalue); + g_hash_table_insert (hash, "Type", string_to_gvalue ("active")); + info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "scan", + call = dbus_g_proxy_begin_call (priv->iface_proxy, "Scan", scan_request_cb, info, nm_supplicant_info_destroy, + DBUS_TYPE_G_MAP_OF_VARIANT, hash, G_TYPE_INVALID); + g_hash_table_destroy (hash); nm_supplicant_info_set_call (info, call); return call != NULL; @@ -1375,14 +943,6 @@ nm_supplicant_interface_get_state (NMSupplicantInterface * self) return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->state; } -guint32 -nm_supplicant_interface_get_connection_state (NMSupplicantInterface * self) -{ - g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED); - - return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->con_state; -} - const char * nm_supplicant_interface_state_to_string (guint32 state) { @@ -1393,6 +953,22 @@ nm_supplicant_interface_state_to_string (guint32 state) return "starting"; case NM_SUPPLICANT_INTERFACE_STATE_READY: return "ready"; + case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED: + return "disconnected"; + case NM_SUPPLICANT_INTERFACE_STATE_INACTIVE: + return "inactive"; + case NM_SUPPLICANT_INTERFACE_STATE_SCANNING: + return "scanning"; + case NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING: + return "associating"; + case NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED: + return "associated"; + case NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE: + return "4-way handshake"; + case NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE: + return "group handshake"; + case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED: + return "completed"; case NM_SUPPLICANT_INTERFACE_STATE_DOWN: return "down"; default: @@ -1402,28 +978,227 @@ nm_supplicant_interface_state_to_string (guint32 state) } const char * -nm_supplicant_interface_connection_state_to_string (guint32 state) +nm_supplicant_interface_get_device (NMSupplicantInterface * self) { - switch (state) { - case NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED: - return "disconnected"; - case NM_SUPPLICANT_INTERFACE_CON_STATE_INACTIVE: - return "inactive"; - case NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING: - return "scanning"; - case NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATING: - return "associating"; - case NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATED: - return "associated"; - case NM_SUPPLICANT_INTERFACE_CON_STATE_4WAY_HANDSHAKE: - return "4-way handshake"; - case NM_SUPPLICANT_INTERFACE_CON_STATE_GROUP_HANDSHAKE: - return "group handshake"; - case NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED: - return "completed"; + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NULL); + + return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev; +} + +const char * +nm_supplicant_interface_get_object_path (NMSupplicantInterface *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NULL); + + return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->object_path; +} + +const char * +nm_supplicant_interface_get_ifname (NMSupplicantInterface *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE); + + return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev; +} + +/*******************************************************************/ + +NMSupplicantInterface * +nm_supplicant_interface_new (NMSupplicantManager *smgr, + const char *ifname, + gboolean is_wireless, + gboolean start_now) +{ + NMSupplicantInterface *self; + NMSupplicantInterfacePrivate *priv; + guint id; + + g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (smgr), NULL); + g_return_val_if_fail (ifname != NULL, NULL); + + self = g_object_new (NM_TYPE_SUPPLICANT_INTERFACE, NULL); + if (self) { + priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + priv->smgr = g_object_ref (smgr); + id = g_signal_connect (priv->smgr, + "notify::" NM_SUPPLICANT_MANAGER_AVAILABLE, + G_CALLBACK (smgr_avail_cb), + self); + priv->smgr_avail_id = id; + + priv->dev = g_strdup (ifname); + priv->is_wireless = is_wireless; + + if (start_now) + interface_add (self, priv->is_wireless); + } + + return self; +} + +static void +nm_supplicant_interface_init (NMSupplicantInterface * self) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + DBusGConnection *bus; + + priv->state = NM_SUPPLICANT_INTERFACE_STATE_INIT; + priv->assoc_pcalls = nm_call_store_new (); + priv->other_pcalls = nm_call_store_new (); + priv->dbus_mgr = nm_dbus_manager_get (); + + bus = nm_dbus_manager_get_connection (priv->dbus_mgr); + priv->wpas_proxy = dbus_g_proxy_new_for_name (bus, + WPAS_DBUS_SERVICE, + WPAS_DBUS_PATH, + WPAS_DBUS_INTERFACE); +} + +static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } - return "unknown"; +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_SCANNING: + g_value_set_boolean (value, NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object)->scanning); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object); + + if (priv->disposed) { + G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object); + return; + } + priv->disposed = TRUE; + + /* Cancel pending calls before unrefing the dbus manager */ + cancel_all_callbacks (priv->other_pcalls); + nm_call_store_destroy (priv->other_pcalls); + + cancel_all_callbacks (priv->assoc_pcalls); + nm_call_store_destroy (priv->assoc_pcalls); + + if (priv->props_proxy) + g_object_unref (priv->props_proxy); + + if (priv->iface_proxy) + g_object_unref (priv->iface_proxy); + + g_free (priv->net_path); + + if (priv->wpas_proxy) + g_object_unref (priv->wpas_proxy); + + if (priv->smgr) { + if (priv->smgr_avail_id) + g_signal_handler_disconnect (priv->smgr, priv->smgr_avail_id); + g_object_unref (priv->smgr); + } + + g_free (priv->dev); + + if (priv->dbus_mgr) + g_object_unref (priv->dbus_mgr); + + if (priv->cfg) + g_object_unref (priv->cfg); + + g_free (priv->object_path); + + /* Chain up to the parent class */ + G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object); +} + +static void +nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMSupplicantInterfacePrivate)); + + object_class->dispose = dispose; + object_class->set_property = set_property; + object_class->get_property = get_property; + + /* Properties */ + g_object_class_install_property (object_class, PROP_SCANNING, + g_param_spec_boolean ("scanning", + "Scanning", + "Scanning", + FALSE, + G_PARAM_READABLE)); + + /* Signals */ + signals[STATE] = + g_signal_new (NM_SUPPLICANT_INTERFACE_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); + + signals[REMOVED] = + g_signal_new (NM_SUPPLICANT_INTERFACE_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); + + signals[NEW_BSS] = + g_signal_new (NM_SUPPLICANT_INTERFACE_NEW_BSS, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, new_bss), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + + signals[SCAN_DONE] = + g_signal_new (NM_SUPPLICANT_INTERFACE_SCAN_DONE, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_done), + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + + signals[CONNECTION_ERROR] = + g_signal_new (NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, connection_error), + NULL, NULL, + _nm_marshal_VOID__STRING_STRING, + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); } |