// SPDX-License-Identifier: LGPL-2.1+ /* * Copyright (C) 2007 - 2008 Novell, Inc. * Copyright (C) 2007 - 2014 Red Hat, Inc. */ #include "nm-default.h" #include "nm-device-wifi.h" #include "nm-glib-aux/nm-dbus-aux.h" #include "nm-setting-connection.h" #include "nm-setting-wireless.h" #include "nm-setting-wireless-security.h" #include "nm-utils.h" #include "nm-access-point.h" #include "nm-object-private.h" #include "nm-core-internal.h" #include "nm-dbus-helpers.h" /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( PROP_PERM_HW_ADDRESS, PROP_MODE, PROP_BITRATE, PROP_ACCESS_POINTS, PROP_ACTIVE_ACCESS_POINT, PROP_WIRELESS_CAPABILITIES, PROP_LAST_SCAN, ); typedef struct { NMLDBusPropertyAO access_points; NMLDBusPropertyO active_access_point; char *perm_hw_address; gint64 last_scan; guint32 mode; guint32 bitrate; guint32 wireless_capabilities; } NMDeviceWifiPrivate; enum { ACCESS_POINT_ADDED, ACCESS_POINT_REMOVED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; struct _NMDeviceWifi { NMDevice parent; NMDeviceWifiPrivate _priv; }; struct _NMDeviceWifiClass { NMDeviceClass parent; }; G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE) #define NM_DEVICE_WIFI_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDeviceWifi, NM_IS_DEVICE_WIFI, NMObject, NMDevice) /*****************************************************************************/ /** * nm_device_wifi_get_hw_address: (skip) * @device: a #NMDeviceWifi * * Gets the actual hardware (MAC) address of the #NMDeviceWifi * * Returns: the actual hardware address. This is the internal string used by the * device, and must not be modified. * * Deprecated: 1.24: Use nm_device_get_hw_address() instead. **/ const char * nm_device_wifi_get_hw_address (NMDeviceWifi *device) { g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL); return nm_device_get_hw_address (NM_DEVICE (device)); } /** * nm_device_wifi_get_permanent_hw_address: * @device: a #NMDeviceWifi * * Gets the permanent hardware (MAC) address of the #NMDeviceWifi * * Returns: the permanent hardware address. This is the internal string used by the * device, and must not be modified. **/ const char * nm_device_wifi_get_permanent_hw_address (NMDeviceWifi *device) { g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL); return _nml_coerce_property_str_not_empty (NM_DEVICE_WIFI_GET_PRIVATE (device)->perm_hw_address); } /** * nm_device_wifi_get_mode: * @device: a #NMDeviceWifi * * Gets the #NMDeviceWifi mode. * * Returns: the mode **/ NM80211Mode nm_device_wifi_get_mode (NMDeviceWifi *device) { g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), 0); return NM_DEVICE_WIFI_GET_PRIVATE (device)->mode; } /** * nm_device_wifi_get_bitrate: * @device: a #NMDeviceWifi * * Gets the bit rate of the #NMDeviceWifi in kbit/s. * * Returns: the bit rate (kbit/s) **/ guint32 nm_device_wifi_get_bitrate (NMDeviceWifi *device) { NMDeviceState state; g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), 0); state = nm_device_get_state (NM_DEVICE (device)); switch (state) { case NM_DEVICE_STATE_IP_CONFIG: case NM_DEVICE_STATE_IP_CHECK: case NM_DEVICE_STATE_SECONDARIES: case NM_DEVICE_STATE_ACTIVATED: case NM_DEVICE_STATE_DEACTIVATING: break; default: return 0; } return NM_DEVICE_WIFI_GET_PRIVATE (device)->bitrate; } /** * nm_device_wifi_get_capabilities: * @device: a #NMDeviceWifi * * Gets the Wi-Fi capabilities of the #NMDeviceWifi. * * Returns: the capabilities **/ NMDeviceWifiCapabilities nm_device_wifi_get_capabilities (NMDeviceWifi *device) { g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), 0); return NM_DEVICE_WIFI_GET_PRIVATE (device)->wireless_capabilities; } /** * nm_device_wifi_get_active_access_point: * @device: a #NMDeviceWifi * * Gets the active #NMAccessPoint. * * Returns: (transfer none): the access point or %NULL if none is active **/ NMAccessPoint * nm_device_wifi_get_active_access_point (NMDeviceWifi *device) { g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL); return nml_dbus_property_o_get_obj (&NM_DEVICE_WIFI_GET_PRIVATE (device)->active_access_point); } /** * nm_device_wifi_get_access_points: * @device: a #NMDeviceWifi * * Gets all the scanned access points of the #NMDeviceWifi. * * Returns: (element-type NMAccessPoint): a #GPtrArray containing all the * scanned #NMAccessPoints. * The returned array is owned by the client and should not be modified. **/ const GPtrArray * nm_device_wifi_get_access_points (NMDeviceWifi *device) { g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL); return nml_dbus_property_ao_get_objs_as_ptrarray (&NM_DEVICE_WIFI_GET_PRIVATE (device)->access_points); } /** * nm_device_wifi_get_access_point_by_path: * @device: a #NMDeviceWifi * @path: the object path of the access point * * Gets a #NMAccessPoint by path. * * Returns: (transfer none): the access point or %NULL if none is found. **/ NMAccessPoint * nm_device_wifi_get_access_point_by_path (NMDeviceWifi *device, const char *path) { const GPtrArray *aps; int i; NMAccessPoint *ap = NULL; g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL); g_return_val_if_fail (path != NULL, NULL); aps = nm_device_wifi_get_access_points (device); if (!aps) return NULL; for (i = 0; i < aps->len; i++) { NMAccessPoint *candidate = g_ptr_array_index (aps, i); if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), path)) { ap = candidate; break; } } return ap; } /** * nm_device_wifi_get_last_scan: * @device: a #NMDeviceWifi * * Returns the timestamp (in CLOCK_BOOTTIME milliseconds) for the last finished * network scan. A value of -1 means the device never scanned for access points. * * Use nm_utils_get_timestamp_msec() to obtain current time value suitable for * comparing to this value. * * Returns: the last scan time in seconds * * Since: 1.12 **/ gint64 nm_device_wifi_get_last_scan (NMDeviceWifi *device) { g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), -1); return NM_DEVICE_WIFI_GET_PRIVATE (device)->last_scan; } /** * nm_device_wifi_request_scan: * @device: a #NMDeviceWifi * @cancellable: a #GCancellable, or %NULL * @error: location for a #GError, or %NULL * * Request NM to scan for access points on @device. Note that the function * returns immediately after requesting the scan, and it may take some time * after that for the scan to complete. * * Returns: %TRUE on success, %FALSE on error, in which case @error will be * set. * * Deprecated: 1.22: Use nm_device_wifi_request_scan_async() or GDBusConnection. **/ gboolean nm_device_wifi_request_scan (NMDeviceWifi *device, GCancellable *cancellable, GError **error) { return nm_device_wifi_request_scan_options (device, NULL, cancellable, error); } /** * nm_device_wifi_request_scan_options: * @device: a #NMDeviceWifi * @options: dictionary with options for RequestScan(), or %NULL * @cancellable: a #GCancellable, or %NULL * @error: location for a #GError, or %NULL * * Request NM to scan for access points on @device. Note that the function * returns immediately after requesting the scan, and it may take some time * after that for the scan to complete. * This is the same as @nm_device_wifi_request_scan except it accepts @options * for the scanning. The argument is the dictionary passed to RequestScan() * D-Bus call. Valid options inside the dictionary are: * 'ssids' => array of SSIDs (saay) * * Returns: %TRUE on success, %FALSE on error, in which case @error will be * set. * * Since: 1.2 * * Deprecated: 1.22: Use nm_device_wifi_request_scan_options_async() or GDBusConnection. **/ gboolean nm_device_wifi_request_scan_options (NMDeviceWifi *device, GVariant *options, GCancellable *cancellable, GError **error) { g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), FALSE); g_return_val_if_fail (!options || g_variant_is_of_type (options, G_VARIANT_TYPE_VARDICT), FALSE); g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE); g_return_val_if_fail (!error || !*error, FALSE); if (!options) options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0); return _nm_client_dbus_call_sync_void (_nm_object_get_client (device), cancellable, _nm_object_get_path (device), NM_DBUS_INTERFACE_DEVICE_WIRELESS, "RequestScan", g_variant_new ("(@a{sv})", options), G_DBUS_CALL_FLAGS_NONE, NM_DBUS_DEFAULT_TIMEOUT_MSEC, TRUE, error); } NM_BACKPORT_SYMBOL (libnm_1_0_6, gboolean, nm_device_wifi_request_scan_options, (NMDeviceWifi *device, GVariant *options, GCancellable *cancellable, GError **error), (device, options, cancellable, error)); /** * nm_device_wifi_request_scan_async: * @device: a #NMDeviceWifi * @cancellable: a #GCancellable, or %NULL * @callback: callback to be called when the scan has been requested * @user_data: caller-specific data passed to @callback * * Request NM to scan for access points on @device. Note that @callback will be * called immediately after requesting the scan, and it may take some time after * that for the scan to complete. **/ void nm_device_wifi_request_scan_async (NMDeviceWifi *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { nm_device_wifi_request_scan_options_async (device, NULL, cancellable, callback, user_data); } /** * nm_device_wifi_request_scan_options_async: * @device: a #NMDeviceWifi * @options: dictionary with options for RequestScan(), or %NULL * @cancellable: a #GCancellable, or %NULL * @callback: callback to be called when the scan has been requested * @user_data: caller-specific data passed to @callback * * Request NM to scan for access points on @device. Note that @callback will be * called immediately after requesting the scan, and it may take some time after * that for the scan to complete. * This is the same as @nm_device_wifi_request_scan_async except it accepts @options * for the scanning. The argument is the dictionary passed to RequestScan() * D-Bus call. Valid options inside the dictionary are: * 'ssids' => array of SSIDs (saay) * * To complete the request call nm_device_wifi_request_scan_finish(). * * Since: 1.2 **/ void nm_device_wifi_request_scan_options_async (NMDeviceWifi *device, GVariant *options, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail (NM_IS_DEVICE_WIFI (device)); g_return_if_fail (!options || g_variant_is_of_type (options, G_VARIANT_TYPE_VARDICT)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); if (!options) options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0); _nm_client_dbus_call (_nm_object_get_client (device), device, nm_device_wifi_request_scan_async, cancellable, callback, user_data, _nm_object_get_path (device), NM_DBUS_INTERFACE_DEVICE_WIRELESS, "RequestScan", g_variant_new ("(@a{sv})", options), G_VARIANT_TYPE ("()"), G_DBUS_CALL_FLAGS_NONE, NM_DBUS_DEFAULT_TIMEOUT_MSEC, nm_dbus_connection_call_finish_void_strip_dbus_error_cb); } NM_BACKPORT_SYMBOL (libnm_1_0_6, void, nm_device_wifi_request_scan_options_async, (NMDeviceWifi *device, GVariant *options, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (device, options, cancellable, callback, user_data)); /** * nm_device_wifi_request_scan_finish: * @device: a #NMDeviceWifi * @result: the result passed to the #GAsyncReadyCallback * @error: location for a #GError, or %NULL * * Gets the result of a call to nm_device_wifi_request_scan_async() and * nm_device_wifi_request_scan_options_async(). * * Returns: %TRUE on success, %FALSE on error, in which case @error will be * set. **/ gboolean nm_device_wifi_request_scan_finish (NMDeviceWifi *device, GAsyncResult *result, GError **error) { g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), FALSE); g_return_val_if_fail (nm_g_task_is_valid (result, device, nm_device_wifi_request_scan_async), FALSE); return g_task_propagate_boolean (G_TASK (result), error); } #define WPA_CAPS (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | \ NM_WIFI_DEVICE_CAP_CIPHER_CCMP | \ NM_WIFI_DEVICE_CAP_WPA | \ NM_WIFI_DEVICE_CAP_RSN) #define RSN_CAPS (NM_WIFI_DEVICE_CAP_CIPHER_CCMP | NM_WIFI_DEVICE_CAP_RSN) static gboolean has_proto (NMSettingWirelessSecurity *s_wsec, const char *proto) { int i; for (i = 0; i < nm_setting_wireless_security_get_num_protos (s_wsec); i++) { if (g_strcmp0 (proto, nm_setting_wireless_security_get_proto (s_wsec, i)) == 0) return TRUE; } return FALSE; } static gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { NMSettingWireless *s_wifi; NMSettingWirelessSecurity *s_wsec; const char *hwaddr, *setting_hwaddr; NMDeviceWifiCapabilities wifi_caps; const char *key_mgmt; if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->connection_compatible (device, connection, error)) return FALSE; if (!nm_connection_is_type (connection, NM_SETTING_WIRELESS_SETTING_NAME)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, _("The connection was not a Wi-Fi connection.")); return FALSE; } /* Check MAC address */ hwaddr = nm_device_wifi_get_permanent_hw_address (NM_DEVICE_WIFI (device)); if (hwaddr) { if (!nm_utils_hwaddr_valid (hwaddr, ETH_ALEN)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, _("Invalid device MAC address.")); return FALSE; } s_wifi = nm_connection_get_setting_wireless (connection); setting_hwaddr = nm_setting_wireless_get_mac_address (s_wifi); if (setting_hwaddr && !nm_utils_hwaddr_matches (setting_hwaddr, -1, hwaddr, -1)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, _("The MACs of the device and the connection didn't match.")); return FALSE; } } /* Check device capabilities; we assume all devices can do WEP at least */ s_wsec = nm_connection_get_setting_wireless_security (connection); if (s_wsec) { /* Connection has security, verify it against the device's capabilities */ key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); if ( !g_strcmp0 (key_mgmt, "wpa-psk") || !g_strcmp0 (key_mgmt, "wpa-eap")) { wifi_caps = nm_device_wifi_get_capabilities (NM_DEVICE_WIFI (device)); /* Is device only WEP capable? */ if (!(wifi_caps & WPA_CAPS)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, _("The device is lacking WPA capabilities required by the connection.")); return FALSE; } /* Make sure WPA2/RSN-only connections don't get chosen for WPA-only cards */ if (has_proto (s_wsec, "rsn") && !has_proto (s_wsec, "wpa") && !(wifi_caps & RSN_CAPS)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, _("The device is lacking WPA2/RSN capabilities required by the connection.")); return FALSE; } } } return TRUE; } static GType get_setting_type (NMDevice *device) { return NM_TYPE_SETTING_WIRELESS; } /*****************************************************************************/ static void _property_ao_notify_changed_access_points_cb (NMLDBusPropertyAO *pr_ao, NMClient *client, NMObject *nmobj, gboolean is_added /* or else removed */) { _nm_client_notify_event_queue_emit_obj_signal (client, G_OBJECT (pr_ao->owner_dbobj->nmobj), nmobj, is_added, 10, is_added ? signals[ACCESS_POINT_ADDED] : signals[ACCESS_POINT_REMOVED]); } /*****************************************************************************/ static void nm_device_wifi_init (NMDeviceWifi *device) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); priv->last_scan = -1; } static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMDeviceWifi *self = NM_DEVICE_WIFI (object); switch (prop_id) { case PROP_PERM_HW_ADDRESS: g_value_set_string (value, nm_device_wifi_get_permanent_hw_address (self)); break; case PROP_MODE: g_value_set_enum (value, nm_device_wifi_get_mode (self)); break; case PROP_BITRATE: g_value_set_uint (value, nm_device_wifi_get_bitrate (self)); break; case PROP_ACTIVE_ACCESS_POINT: g_value_set_object (value, nm_device_wifi_get_active_access_point (self)); break; case PROP_WIRELESS_CAPABILITIES: g_value_set_flags (value, nm_device_wifi_get_capabilities (self)); break; case PROP_ACCESS_POINTS: g_value_take_boxed (value, _nm_utils_copy_object_array (nm_device_wifi_get_access_points (self))); break; case PROP_LAST_SCAN: g_value_set_int64 (value, nm_device_wifi_get_last_scan (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void finalize (GObject *object) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object); g_free (priv->perm_hw_address); G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object); } const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wireless = NML_DBUS_META_IFACE_INIT_PROP ( NM_DBUS_INTERFACE_DEVICE_WIRELESS, nm_device_wifi_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( NML_DBUS_META_PROPERTY_INIT_AO_PROP ("AccessPoints", PROP_ACCESS_POINTS, NMDeviceWifi, _priv.access_points, nm_access_point_get_type, .notify_changed_ao = _property_ao_notify_changed_access_points_cb ), NML_DBUS_META_PROPERTY_INIT_O_PROP ("ActiveAccessPoint", PROP_ACTIVE_ACCESS_POINT, NMDeviceWifi, _priv.active_access_point, nm_access_point_get_type ), NML_DBUS_META_PROPERTY_INIT_U ("Bitrate", PROP_BITRATE, NMDeviceWifi, _priv.bitrate ), NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), NML_DBUS_META_PROPERTY_INIT_X ("LastScan", PROP_LAST_SCAN, NMDeviceWifi, _priv.last_scan ), NML_DBUS_META_PROPERTY_INIT_U ("Mode", PROP_MODE, NMDeviceWifi, _priv.mode ), NML_DBUS_META_PROPERTY_INIT_S ("PermHwAddress", PROP_PERM_HW_ADDRESS, NMDeviceWifi, _priv.perm_hw_address ), NML_DBUS_META_PROPERTY_INIT_U ("WirelessCapabilities", PROP_WIRELESS_CAPABILITIES, NMDeviceWifi, _priv.wireless_capabilities ), ), ); static void nm_device_wifi_class_init (NMDeviceWifiClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->get_property = get_property; object_class->finalize = finalize; _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceWifi); _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_1 (nm_object_class, NMDeviceWifiPrivate, active_access_point); _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1 (nm_object_class, NMDeviceWifiPrivate, access_points); device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; /** * NMDeviceWifi:perm-hw-address: * * The hardware (MAC) address of the device. **/ obj_properties[PROP_PERM_HW_ADDRESS] = g_param_spec_string (NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS, "", "", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); /** * NMDeviceWifi:mode: * * The mode of the device. **/ obj_properties[PROP_MODE] = g_param_spec_enum (NM_DEVICE_WIFI_MODE, "", "", NM_TYPE_802_11_MODE, NM_802_11_MODE_UNKNOWN, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); /** * NMDeviceWifi:bitrate: * * The bit rate of the device in kbit/s. **/ obj_properties[PROP_BITRATE] = g_param_spec_uint (NM_DEVICE_WIFI_BITRATE, "", "", 0, G_MAXUINT32, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); /** * NMDeviceWifi:active-access-point: * * The active #NMAccessPoint of the device. **/ obj_properties[PROP_ACTIVE_ACCESS_POINT] = g_param_spec_object (NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, "", "", NM_TYPE_ACCESS_POINT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); /** * NMDeviceWifi:wireless-capabilities: * * The wireless capabilities of the device. **/ obj_properties[PROP_WIRELESS_CAPABILITIES] = g_param_spec_flags (NM_DEVICE_WIFI_CAPABILITIES, "", "", NM_TYPE_DEVICE_WIFI_CAPABILITIES, NM_WIFI_DEVICE_CAP_NONE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); /** * NMDeviceWifi:access-points: (type GPtrArray(NMAccessPoint)) * * List of all Wi-Fi access points the device can see. **/ obj_properties[PROP_ACCESS_POINTS] = g_param_spec_boxed (NM_DEVICE_WIFI_ACCESS_POINTS, "", "", G_TYPE_PTR_ARRAY, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); /** * NMDeviceWifi:last-scan: * * The timestamp (in CLOCK_BOOTTIME seconds) for the last finished * network scan. A value of -1 means the device never scanned for * access points. * * Since: 1.12 **/ obj_properties[PROP_LAST_SCAN] = g_param_spec_int64 (NM_DEVICE_WIFI_LAST_SCAN, "", "", -1, G_MAXINT64, -1, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_wireless); /** * NMDeviceWifi::access-point-added: * @device: the Wi-Fi device that received the signal * @ap: the new access point * * Notifies that a #NMAccessPoint is added to the Wi-Fi device. **/ signals[ACCESS_POINT_ADDED] = g_signal_new ("access-point-added", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); /** * NMDeviceWifi::access-point-removed: * @device: the Wi-Fi device that received the signal * @ap: the removed access point * * Notifies that a #NMAccessPoint is removed from the Wi-Fi device. **/ signals[ACCESS_POINT_REMOVED] = g_signal_new ("access-point-removed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); }