diff options
| author | Michael Biebl <biebl@debian.org> | 2020-04-11 21:28:04 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2020-04-11 21:28:04 +0200 |
| commit | 1e5977b62f896e844b548c3007ace9e1dfa7f9ed (patch) | |
| tree | 7a7416ed410e72b6200f3d860fd315ec11cc106b /libnm | |
| parent | b012fa6e1d808e0736c009799c62d835cbfcc1dd (diff) | |
New upstream version 1.23.90 upstream/1.23.90
Diffstat (limited to 'libnm')
69 files changed, 2930 insertions, 1944 deletions
diff --git a/libnm/NetworkManager.h b/libnm/NetworkManager.h index 6a0f1178..41f93542 100644 --- a/libnm/NetworkManager.h +++ b/libnm/NetworkManager.h @@ -88,6 +88,7 @@ #include "nm-setting-user.h" #include "nm-setting-vlan.h" #include "nm-setting-vpn.h" +#include "nm-setting-vrf.h" #include "nm-setting-vxlan.h" #include "nm-setting-wimax.h" #include "nm-setting-wired.h" diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 326383c8..b5ce8c34 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1662,3 +1662,36 @@ libnm_1_22_8 { global: nm_setting_ip6_config_get_ra_timeout; } libnm_1_22_2; + +libnm_1_24_0 { +global: + nm_client_dbus_call; + nm_client_dbus_call_finish; + nm_client_dbus_set_property; + nm_client_dbus_set_property_finish; + nm_client_get_instance_flags; + nm_client_get_object_by_path; + nm_client_get_permissions_state; + nm_client_instance_flags_get_type; + nm_device_vrf_get_table; + nm_device_vrf_get_type; + nm_object_get_client; + nm_secret_agent_old_destroy; + nm_secret_agent_old_enable; + nm_secret_agent_old_get_context_busy_watcher; + nm_secret_agent_old_get_dbus_connection; + nm_secret_agent_old_get_dbus_name_owner; + nm_secret_agent_old_get_main_context; + nm_setting_802_1x_get_domain_match; + nm_setting_802_1x_get_phase2_domain_match; + nm_setting_bond_get_option_normalized; + nm_setting_bridge_get_group_address; + nm_setting_bridge_get_multicast_querier; + nm_setting_bridge_get_multicast_query_use_ifaddr; + nm_setting_bridge_get_multicast_router; + nm_setting_bridge_get_vlan_protocol; + nm_setting_bridge_get_vlan_stats_enabled; + nm_setting_vrf_get_table; + nm_setting_vrf_get_type; + nm_setting_vrf_new; +} libnm_1_22_8; diff --git a/libnm/meson.build b/libnm/meson.build index 51ca46d2..98d39f8e 100644 --- a/libnm/meson.build +++ b/libnm/meson.build @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1+ + libnm_inc = include_directories('.') libnm_nm_default_dep = declare_dependency( @@ -39,6 +41,7 @@ libnm_headers = files( 'nm-device-team.h', 'nm-device-tun.h', 'nm-device-vlan.h', + 'nm-device-vrf.h', 'nm-device-vxlan.h', 'nm-device-wifi-p2p.h', 'nm-device-wifi.h', @@ -104,6 +107,7 @@ libnm_sources = files( 'nm-device-team.c', 'nm-device-tun.c', 'nm-device-vlan.c', + 'nm-device-vrf.c', 'nm-device-vxlan.c', 'nm-device-wifi-p2p.c', 'nm-device-wifi.c', @@ -278,3 +282,22 @@ endif if enable_tests subdir('tests') endif + +libnm_libnm_aux = static_library( + 'nm-libnm-aux', + sources: nm_libnm_aux_source, + c_args: [ + '-DG_LOG_DOMAIN="@0@"'.format('libnmc'), + '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_CLIENT', + ], + dependencies: [ + libnm_core_nm_default_dep, + libnm_libnm_core_intern_dep, + libnm_dep, + ], +) + +libnm_libnm_aux_dep = declare_dependency( + include_directories: [shared_inc], + link_with: [libnm_libnm_aux], +) diff --git a/libnm/nm-access-point.c b/libnm/nm-access-point.c index 77ba6527..6b49f458 100644 --- a/libnm/nm-access-point.c +++ b/libnm/nm-access-point.c @@ -573,7 +573,7 @@ nm_access_point_class_init (NMAccessPointClass *ap_class) * * Alias for #NMAccessPoint:bssid. * - * Deprecated: 1.0: use #NMAccessPoint:bssid. + * Deprecated: 1.0: Use #NMAccessPoint:bssid. **/ obj_properties[PROP_HW_ADDRESS] = g_param_spec_string (NM_ACCESS_POINT_HW_ADDRESS, "", "", diff --git a/libnm/nm-client.c b/libnm/nm-client.c index 0c4daab2..68a1836d 100644 --- a/libnm/nm-client.c +++ b/libnm/nm-client.c @@ -60,7 +60,7 @@ /*****************************************************************************/ -static NM_CACHED_QUARK_FCN ("nm-client-context-busy-watcher", nm_client_context_busy_watcher_quark) +NM_CACHED_QUARK_FCN ("nm-context-busy-watcher", nm_context_busy_watcher_quark) static void _context_busy_watcher_attach_integration_source_cb (gpointer data, @@ -69,10 +69,21 @@ _context_busy_watcher_attach_integration_source_cb (gpointer data, nm_g_source_destroy_and_unref (data); } -static void -_context_busy_watcher_attach_integration_source (GObject *context_busy_watcher, - GSource *source_take) +void +nm_context_busy_watcher_integrate_source (GMainContext *outer_context, + GMainContext *inner_context, + GObject *context_busy_watcher) { + GSource *source; + + nm_assert (outer_context); + nm_assert (inner_context); + nm_assert (outer_context != inner_context); + nm_assert (G_IS_OBJECT (context_busy_watcher)); + + source = nm_utils_g_main_context_create_integrate_source (inner_context); + g_source_attach (source, outer_context); + /* The problem is... * * NMClient is associated with a GMainContext, just like its underlying GDBusConnection @@ -114,7 +125,7 @@ _context_busy_watcher_attach_integration_source (GObject *context_busy_watcher, g_object_weak_ref (context_busy_watcher, _context_busy_watcher_attach_integration_source_cb, - source_take); + source); } /*****************************************************************************/ @@ -175,26 +186,11 @@ typedef struct { /*****************************************************************************/ -typedef struct { - GCancellable *cancellable; - GSource *cancel_on_idle_source; - gulong cancelled_id; - union { - struct { - GTask *task; - } async; - struct { - GMainLoop *main_loop; - GError **error_location; - } sync; - } data; - bool is_sync:1; -} InitData; - NM_GOBJECT_PROPERTIES_DEFINE (NMClient, PROP_DBUS_CONNECTION, PROP_DBUS_NAME_OWNER, PROP_VERSION, + PROP_INSTANCE_FLAGS, PROP_STATE, PROP_STARTUP, PROP_NM_RUNNING, @@ -223,6 +219,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMClient, PROP_DNS_CONFIGURATION, PROP_CHECKPOINTS, PROP_CAPABILITIES, + PROP_PERMISSIONS_STATE, ); enum { @@ -261,7 +258,7 @@ typedef struct { GMainContext *dbus_context; GObject *context_busy_watcher; GDBusConnection *dbus_connection; - InitData *init_data; + NMLInitData *init_data; GHashTable *dbus_objects; CList obj_changed_lst_head; GCancellable *name_owner_get_cancellable; @@ -279,7 +276,7 @@ typedef struct { NMLDBusObject *dbobj_settings; NMLDBusObject *dbobj_dns_manager; - GHashTable *permissions; + guint8 *permissions; GCancellable *permissions_cancellable; char *name_owner; @@ -291,6 +288,12 @@ typedef struct { guint dbsid_nm_vpn_connection_state_changed; guint dbsid_nm_check_permissions; + NMClientInstanceFlags instance_flags:3; + + NMTernary permissions_state:3; + + bool instance_flags_constructed:1; + bool udev_inited:1; bool notify_event_lst_changed:1; bool check_dbobj_visible_all:1; @@ -379,7 +382,8 @@ static NMRefString *_dbus_path_dns_manager = NULL; /*****************************************************************************/ -NM_UTILS_LOOKUP_STR_DEFINE_STATIC (nml_dbus_obj_state_to_string, NMLDBusObjState, +static +NM_UTILS_LOOKUP_STR_DEFINE (nml_dbus_obj_state_to_string, NMLDBusObjState, NM_UTILS_LOOKUP_DEFAULT_WARN ("???"), NM_UTILS_LOOKUP_ITEM (NML_DBUS_OBJ_STATE_UNLINKED, "unlinked"), NM_UTILS_LOOKUP_ITEM (NML_DBUS_OBJ_STATE_WATCHED_ONLY, "watched-only"), @@ -401,15 +405,15 @@ NM_CACHED_QUARK_FCN ("nm-client-error-quark", nm_client_error_quark) /*****************************************************************************/ -static InitData * -_init_data_new_sync (GCancellable *cancellable, - GMainLoop *main_loop, - GError **error_location) +NMLInitData * +nml_init_data_new_sync (GCancellable *cancellable, + GMainLoop *main_loop, + GError **error_location) { - InitData *init_data; + NMLInitData *init_data; - init_data = g_slice_new (InitData); - *init_data = (InitData) { + init_data = g_slice_new (NMLInitData); + *init_data = (NMLInitData) { .cancellable = nm_g_object_ref (cancellable), .is_sync = TRUE, .data.sync = { @@ -420,14 +424,14 @@ _init_data_new_sync (GCancellable *cancellable, return init_data; } -static InitData * -_init_data_new_async (GCancellable *cancellable, - GTask *task_take) +NMLInitData * +nml_init_data_new_async (GCancellable *cancellable, + GTask *task_take) { - InitData *init_data; + NMLInitData *init_data; - init_data = g_slice_new (InitData); - *init_data = (InitData) { + init_data = g_slice_new (NMLInitData); + *init_data = (NMLInitData) { .cancellable = nm_g_object_ref (cancellable), .is_sync = FALSE, .data.async = { @@ -437,6 +441,30 @@ _init_data_new_async (GCancellable *cancellable, return init_data; } +void +nml_init_data_return (NMLInitData *init_data, + GError *error_take) +{ + nm_assert (init_data); + + nm_clear_pointer (&init_data->cancel_on_idle_source, nm_g_source_destroy_and_unref); + nm_clear_g_signal_handler (init_data->cancellable, &init_data->cancelled_id); + + if (init_data->is_sync) { + if (error_take) + g_propagate_error (init_data->data.sync.error_location, error_take); + g_main_loop_quit (init_data->data.sync.main_loop); + } else { + if (error_take) + g_task_return_error (init_data->data.async.task, error_take); + else + g_task_return_boolean (init_data->data.async.task, TRUE); + g_object_unref (init_data->data.async.task); + } + nm_g_object_unref (init_data->cancellable); + nm_g_slice_free (init_data); +} + /*****************************************************************************/ GError * @@ -1000,7 +1028,7 @@ nm_client_get_context_busy_watcher (NMClient *self) g_return_val_if_fail (NM_IS_CLIENT (self), NULL); w = NM_CLIENT_GET_PRIVATE (self)->context_busy_watcher; - return g_object_get_qdata (w, nm_client_context_busy_watcher_quark ()) + return g_object_get_qdata (w, nm_context_busy_watcher_quark ()) ?: w; } @@ -3115,7 +3143,7 @@ _dbus_get_managed_objects_cb (GObject *source, nm_assert ((!!ret) != (!!error)); if ( !ret - && nm_utils_error_is_cancelled (error, FALSE)) + && nm_utils_error_is_cancelled (error)) return; priv = NM_CLIENT_GET_PRIVATE (self); @@ -3166,7 +3194,7 @@ _nm_client_get_settings_call_cb (GObject *source, GAsyncResult *result, gpointer ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); if ( !ret - && nm_utils_error_is_cancelled (error, FALSE)) + && nm_utils_error_is_cancelled (error)) return; remote_connection = user_data; @@ -3356,27 +3384,35 @@ _dbus_nm_vpn_connection_state_changed_cb (GDBusConnection *connection, static void _emit_permissions_changed (NMClient *self, - GHashTable *permissions, - gboolean force_unknown) + const guint8 *old_permissions, + const guint8 *permissions) { - GHashTableIter iter; - gpointer key; - gpointer value; + int i; - if (!permissions) - return; if (self->obj_base.is_disposing) return; - g_hash_table_iter_init (&iter, permissions); - while (g_hash_table_iter_next (&iter, &key, &value)) { + if (old_permissions == permissions) + return; + + for (i = 0; i < (int) G_N_ELEMENTS (nm_auth_permission_sorted); i++) { + NMClientPermission perm = nm_auth_permission_sorted[i]; + NMClientPermissionResult perm_result = NM_CLIENT_PERMISSION_RESULT_UNKNOWN; + NMClientPermissionResult perm_result_old = NM_CLIENT_PERMISSION_RESULT_UNKNOWN; + + if (permissions) + perm_result = permissions[perm - 1]; + if (old_permissions) + perm_result_old = old_permissions[perm - 1]; + + if (perm_result == perm_result_old) + continue; + g_signal_emit (self, signals[PERMISSION_CHANGED], 0, - GPOINTER_TO_UINT (key), - force_unknown - ? (guint) NM_CLIENT_PERMISSION_NONE - : GPOINTER_TO_UINT (value)); + (guint) perm, + (guint) perm_result); } } @@ -3389,14 +3425,15 @@ _dbus_check_permissions_start_cb (GObject *source, GAsyncResult *result, gpointe NMClientPrivate *priv; gs_unref_variant GVariant *ret = NULL; nm_auto_free_variant_iter GVariantIter *v_permissions = NULL; - gs_unref_hashtable GHashTable *old_permissions = NULL; + gs_free guint8 *old_permissions = NULL; gs_free_error GError *error = NULL; const char *pkey; const char *pvalue; + int i; ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); if ( !ret - && nm_utils_error_is_cancelled (error, FALSE)) + && nm_utils_error_is_cancelled (error)) return; self = user_data; @@ -3404,63 +3441,73 @@ _dbus_check_permissions_start_cb (GObject *source, GAsyncResult *result, gpointe g_clear_object (&priv->permissions_cancellable); + old_permissions = g_steal_pointer (&priv->permissions); + if (!ret) { + /* when the call completes, we always pretend success. Even a failure means + * that we fetched the permissions, however they are all unknown. */ NML_NMCLIENT_LOG_T (self, "GetPermissions call failed: %s", error->message); - return; + goto out; } NML_NMCLIENT_LOG_T (self, "GetPermissions call finished with success"); - /* get list of old permissions for change notification */ - old_permissions = g_steal_pointer (&priv->permissions); - priv->permissions = g_hash_table_new (nm_direct_hash, NULL); - g_variant_get (ret, "(a{ss})", &v_permissions); while (g_variant_iter_next (v_permissions, "{&s&s}", &pkey, &pvalue)) { NMClientPermission perm; NMClientPermissionResult perm_result; - perm = nm_permission_to_client (pkey); + perm = nm_auth_permission_from_string (pkey); if (perm == NM_CLIENT_PERMISSION_NONE) continue; - perm_result = nm_permission_result_to_client (pvalue); + perm_result = nm_client_permission_result_from_string (pvalue); - g_hash_table_insert (priv->permissions, - GUINT_TO_POINTER (perm), - GUINT_TO_POINTER (perm_result)); - if (old_permissions) { - g_hash_table_remove (old_permissions, - GUINT_TO_POINTER (perm)); + if (!priv->permissions) { + if (perm_result == NM_CLIENT_PERMISSION_RESULT_UNKNOWN) + continue; + priv->permissions = g_new (guint8, G_N_ELEMENTS (nm_auth_permission_sorted)); + for (i = 0; i < (int) G_N_ELEMENTS (nm_auth_permission_sorted); i++) + priv->permissions[i] = NM_CLIENT_PERMISSION_RESULT_UNKNOWN; } + priv->permissions[perm - 1] = perm_result; } +out: + priv->permissions_state = NM_TERNARY_TRUE; + dbus_context = nm_g_main_context_push_thread_default_if_necessary (priv->main_context); - _emit_permissions_changed (self, priv->permissions, FALSE); - _emit_permissions_changed (self, old_permissions, TRUE); + _emit_permissions_changed (self, old_permissions, priv->permissions); + _notify (self, PROP_PERMISSIONS_STATE); } static void _dbus_check_permissions_start (NMClient *self) { NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + gboolean fetch; + + fetch = !NM_FLAGS_HAS ((NMClientInstanceFlags) priv->instance_flags, + NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS); nm_clear_g_cancellable (&priv->permissions_cancellable); - priv->permissions_cancellable = g_cancellable_new (); - NML_NMCLIENT_LOG_T (self, "GetPermissions() call started..."); + if (fetch) { + NML_NMCLIENT_LOG_T (self, "GetPermissions() call started..."); - _nm_client_dbus_call_simple (self, - priv->permissions_cancellable, - NM_DBUS_PATH, - NM_DBUS_INTERFACE, - "GetPermissions", - g_variant_new ("()"), - G_VARIANT_TYPE ("(a{ss})"), - G_DBUS_CALL_FLAGS_NONE, - NM_DBUS_DEFAULT_TIMEOUT_MSEC, - _dbus_check_permissions_start_cb, - self); + priv->permissions_cancellable = g_cancellable_new (); + _nm_client_dbus_call_simple (self, + priv->permissions_cancellable, + NM_DBUS_PATH, + NM_DBUS_INTERFACE, + "GetPermissions", + g_variant_new ("()"), + G_VARIANT_TYPE ("(a{ss})"), + G_DBUS_CALL_FLAGS_NONE, + NM_DBUS_DEFAULT_TIMEOUT_MSEC, + _dbus_check_permissions_start_cb, + self); + } } static void @@ -3473,6 +3520,7 @@ _dbus_nm_check_permissions_cb (GDBusConnection *connection, gpointer user_data) { NMClient *self = user_data; + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("()"))) { NML_NMCLIENT_LOG_E (self, "ignore CheckPermissions signal with unexpected signature %s", @@ -3481,6 +3529,10 @@ _dbus_nm_check_permissions_cb (GDBusConnection *connection, } _dbus_check_permissions_start (self); + + if (priv->permissions_state == NM_TERNARY_TRUE) + priv->permissions_state = NM_TERNARY_FALSE; + _notify (self, PROP_PERMISSIONS_STATE); } /*****************************************************************************/ @@ -3794,6 +3846,22 @@ _request_wait_finish (NMClient *client, /*****************************************************************************/ /** + * nm_client_get_instance_flags: + * @self: the #NMClient instance. + * + * Returns: the #NMClientInstanceFlags flags. + * + * Since: 1.24 + */ +NMClientInstanceFlags +nm_client_get_instance_flags (NMClient *self) +{ + g_return_val_if_fail (NM_IS_CLIENT (self), NM_CLIENT_INSTANCE_FLAGS_NONE); + + return NM_CLIENT_GET_PRIVATE (self)->instance_flags; +} + +/** * nm_client_get_dbus_connection: * @client: a #NMClient * @@ -3908,6 +3976,26 @@ nm_client_get_nm_running (NMClient *client) } /** + * nm_client_get_object_by_path: + * @client: the #NMClient instance + * @dbus_path: the D-Bus path of the object to look up + * + * Returns: (transfer none): the #NMObject instance that is + * cached under @dbus_path, or %NULL if no such object exists. + * + * Since: 1.24 + */ +NMObject * +nm_client_get_object_by_path (NMClient *client, + const char *dbus_path) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + g_return_val_if_fail (dbus_path, NULL); + + return _dbobjs_get_nmobj_unpack_visible (client, dbus_path, G_TYPE_NONE); +} + +/** * nm_client_get_metered: * @client: a #NMClient * @@ -3951,15 +4039,14 @@ nm_client_networking_get_enabled (NMClient *client) * * Returns: %TRUE on success, %FALSE otherwise * - * Deprecated: 1.22, use nm_client_networking_set_enabled_async() or GDBusConnection + * Deprecated: 1.22: Use the async command nm_client_dbus_call() on %NM_DBUS_PATH, + * %NM_DBUS_INTERFACE to call "Enable" with "(b)" arguments and no return value. **/ gboolean nm_client_networking_set_enabled (NMClient *client, gboolean enable, GError **error) { g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); - /* FIXME(libnm-async-api): add nm_client_networking_set_enabled_async(). */ - return _nm_client_dbus_call_sync_void (client, NULL, NM_DBUS_PATH, @@ -3995,15 +4082,14 @@ nm_client_wireless_get_enabled (NMClient *client) * * Enables or disables wireless devices. * - * Deprecated: 1.22, use nm_client_wireless_set_enabled_async() or GDBusConnection + * Deprecated: 1.22: Use the async command nm_client_dbus_set_property() on %NM_DBUS_PATH, + * %NM_DBUS_INTERFACE to set "WirelessEnabled" property to a "(b)" value. */ void nm_client_wireless_set_enabled (NMClient *client, gboolean enabled) { g_return_if_fail (NM_IS_CLIENT (client)); - /* FIXME(libnm-async-api): add nm_client_wireless_set_enabled_async(). */ - _nm_client_set_property_sync_legacy (client, NM_DBUS_PATH, NM_DBUS_INTERFACE, @@ -4050,14 +4136,15 @@ nm_client_wwan_get_enabled (NMClient *client) * @enabled: %TRUE to enable WWAN * * Enables or disables WWAN devices. + * + * Deprecated: 1.22: Use the async command nm_client_dbus_set_property() on %NM_DBUS_PATH, + * %NM_DBUS_INTERFACE to set "WwanEnabled" property to a "(b)" value. **/ void nm_client_wwan_set_enabled (NMClient *client, gboolean enabled) { g_return_if_fail (NM_IS_CLIENT (client)); - /* FIXME(libnm-async-api): add nm_client_wwan_set_enabled_async(). */ - _nm_client_set_property_sync_legacy (client, NM_DBUS_PATH, NM_DBUS_INTERFACE, @@ -4090,7 +4177,7 @@ nm_client_wwan_hardware_get_enabled (NMClient *client) * * Returns: %TRUE if WiMAX is enabled * - * Deprecated: 1.22 This function always returns FALSE because WiMax is no longer supported + * Deprecated: 1.22: This function always returns FALSE because WiMax is no longer supported. **/ gboolean nm_client_wimax_get_enabled (NMClient *client) @@ -4107,7 +4194,7 @@ nm_client_wimax_get_enabled (NMClient *client) * * Enables or disables WiMAX devices. * - * Deprecated: 1.22 This function does nothing because WiMax is no longer supported + * Deprecated: 1.22: This function does nothing because WiMax is no longer supported. **/ void nm_client_wimax_set_enabled (NMClient *client, gboolean enabled) @@ -4123,7 +4210,7 @@ nm_client_wimax_set_enabled (NMClient *client, gboolean enabled) * * Returns: %TRUE if the WiMAX hardware is enabled * - * Deprecated: 1.22 This function always returns FALSE because WiMax is no longer supported + * Deprecated: 1.22: This function always returns FALSE because WiMax is no longer supported. **/ gboolean nm_client_wimax_hardware_get_enabled (NMClient *client) @@ -4181,14 +4268,15 @@ nm_client_connectivity_check_get_enabled (NMClient *client) * have any effect. * * Since: 1.10 + * + * Deprecated: 1.22: Use the async command nm_client_dbus_set_property() on %NM_DBUS_PATH, + * %NM_DBUS_INTERFACE to set "ConnectivityCheckEnabled" property to a "(b)" value. */ void nm_client_connectivity_check_set_enabled (NMClient *client, gboolean enabled) { g_return_if_fail (NM_IS_CLIENT (client)); - /* FIXME(libnm-async-api): add nm_client_wireless_set_enabled_async(). */ - _nm_client_set_property_sync_legacy (client, NM_DBUS_PATH, NM_DBUS_INTERFACE, @@ -4228,7 +4316,9 @@ nm_client_connectivity_check_get_uri (NMClient *client) * * Returns: %TRUE on success, %FALSE otherwise * - * Deprecated: 1.22, use nm_client_get_logging_async() or GDBusConnection + * Deprecated: 1.22: Use the async command nm_client_dbus_call() on %NM_DBUS_PATH, + * %NM_DBUS_INTERFACE to call "GetLogging" with no arguments to get "(ss)" for level + * and domains. **/ gboolean nm_client_get_logging (NMClient *client, @@ -4243,8 +4333,6 @@ nm_client_get_logging (NMClient *client, g_return_val_if_fail (domains == NULL || *domains == NULL, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - /* FIXME(libnm-async-api): add nm_client_get_logging_async(). */ - ret = _nm_client_dbus_call_sync (client, NULL, NM_DBUS_PATH, @@ -4278,7 +4366,8 @@ nm_client_get_logging (NMClient *client, * * Returns: %TRUE on success, %FALSE otherwise * - * Deprecated: 1.22, use nm_client_set_logging_async() or GDBusConnection + * Deprecated: 1.22: Use the async command nm_client_dbus_call() on %NM_DBUS_PATH, + * %NM_DBUS_INTERFACE to call "SetLogging" with "(ss)" arguments for level and domains. **/ gboolean nm_client_set_logging (NMClient *client, const char *level, const char *domains, GError **error) @@ -4286,8 +4375,6 @@ nm_client_set_logging (NMClient *client, const char *level, const char *domains, g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - /* FIXME(libnm-async-api): add nm_client_set_logging_async(). */ - return _nm_client_dbus_call_sync_void (client, NULL, NM_DBUS_PATH, @@ -4316,18 +4403,39 @@ NMClientPermissionResult nm_client_get_permission_result (NMClient *client, NMClientPermission permission) { NMClientPrivate *priv; - gpointer result; + NMClientPermissionResult result = NM_CLIENT_PERMISSION_RESULT_UNKNOWN; g_return_val_if_fail (NM_IS_CLIENT (client), NM_CLIENT_PERMISSION_RESULT_UNKNOWN); - priv = NM_CLIENT_GET_PRIVATE (client); - if ( !priv->permissions - || !g_hash_table_lookup_extended (priv->permissions, - GUINT_TO_POINTER (permission), - NULL, - &result)) - return NM_CLIENT_PERMISSION_RESULT_UNKNOWN; - return GPOINTER_TO_UINT (result); + if ( permission > NM_CLIENT_PERMISSION_NONE + && permission <= NM_CLIENT_PERMISSION_LAST) { + priv = NM_CLIENT_GET_PRIVATE (client); + if (priv->permissions) + result = priv->permissions[permission - 1]; + } + + return result; +} + +/** + * nm_client_get_permissions_state: + * @self: the #NMClient instance + * + * Returns: the state of the cached permissions. %NM_TERNARY_DEFAULT + * means that no permissions result was yet received. All permissions + * are unknown. %NM_TERNARY_TRUE means that the permissions got received + * and are cached. %%NM_TERNARY_FALSE means that permissions are cached, + * but they are invalided as as "CheckPermissions" signal was received + * in the meantime. + * + * Since: 1.24 + */ +NMTernary +nm_client_get_permissions_state (NMClient *self) +{ + g_return_val_if_fail (NM_IS_CLIENT (self), NM_TERNARY_DEFAULT); + + return NM_CLIENT_GET_PRIVATE (self)->permissions_state; } /** @@ -4364,7 +4472,7 @@ nm_client_get_connectivity (NMClient *client) * * Returns: the (new) current connectivity state * - * Deprecated: 1.22, use nm_client_check_connectivity_async() or GDBusConnection + * Deprecated: 1.22: Use nm_client_check_connectivity_async() or GDBusConnection. */ NMConnectivityState nm_client_check_connectivity (NMClient *client, @@ -4493,7 +4601,7 @@ nm_client_check_connectivity_finish (NMClient *client, * * Returns: %TRUE if the request was successful, %FALSE if it failed * - * Deprecated: 1.22, use nm_client_save_hostname_async() or GDBusConnection + * Deprecated: 1.22: Use nm_client_save_hostname_async() or GDBusConnection. **/ gboolean nm_client_save_hostname (NMClient *client, @@ -4757,7 +4865,7 @@ activate_connection_cb (GObject *object, ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), result, &error); if (!ret) { - if (!nm_utils_error_is_cancelled (error, FALSE)) + if (!nm_utils_error_is_cancelled (error)) g_dbus_error_strip_remote_error (error); g_task_return_error (task, error); return; @@ -4895,7 +5003,7 @@ _add_and_activate_connection_done (GObject *object, ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), result, &error); if (!ret) { - if (!nm_utils_error_is_cancelled (error, FALSE)) + if (!nm_utils_error_is_cancelled (error)) g_dbus_error_strip_remote_error (error); g_task_return_error (task, error); return; @@ -5203,7 +5311,7 @@ nm_client_add_and_activate_connection2_finish (NMClient *client, * * Returns: success or failure * - * Deprecated: 1.22, use nm_client_deactivate_connection_async() or GDBusConnection + * Deprecated: 1.22: Use nm_client_deactivate_connection_async() or GDBusConnection. **/ gboolean nm_client_deactivate_connection (NMClient *client, @@ -5418,7 +5526,7 @@ _add_connection_cb (GObject *source, ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); if (!ret) { - if (!nm_utils_error_is_cancelled (error, FALSE)) + if (!nm_utils_error_is_cancelled (error)) g_dbus_error_strip_remote_error (error); g_task_return_error (task, error); return; @@ -5708,7 +5816,7 @@ nm_client_add_connection2_finish (NMClient *client, * set. Note that even in the success case, you might have individual @failures. * With 1.22, the return value is consistent with nm_client_load_connections_finish(). * - * Deprecated: 1.22, use nm_client_load_connections_async() or GDBusConnection + * Deprecated: 1.22: Use nm_client_load_connections_async() or GDBusConnection. **/ gboolean nm_client_load_connections (NMClient *client, @@ -5839,7 +5947,7 @@ nm_client_load_connections_finish (NMClient *client, * * Return value: %TRUE on success, %FALSE on failure * - * Deprecated: 1.22, use nm_client_reload_connections_async() or GDBusConnection + * Deprecated: 1.22: Use nm_client_reload_connections_async() or GDBusConnection. **/ gboolean nm_client_reload_connections (NMClient *client, @@ -6080,7 +6188,7 @@ _notify_update_prop_dns_manager_configuration (NMClient *self, * The array is terminated by a numeric zero sentinel * at position @length. * - * Since: 1.24, 1.22.2 + * Since: 1.24 */ const guint32 * nm_client_get_capabilities (NMClient *client, @@ -6160,7 +6268,7 @@ checkpoint_create_cb (GObject *object, ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), result, &error); if (!ret) { - if (!nm_utils_error_is_cancelled (error, FALSE)) + if (!nm_utils_error_is_cancelled (error)) g_dbus_error_strip_remote_error (error); g_task_return_error (task, error); return; @@ -6540,6 +6648,174 @@ nm_client_reload_finish (NMClient *client, /*****************************************************************************/ +/** + * nm_client_dbus_call: + * @client: the #NMClient + * @object_path: path of remote object + * @interface_name: D-Bus interface to invoke method on + * @method_name: the name of the method to invoke + * @parameters: (nullable): a #GVariant tuple with parameters for the method + * or %NULL if not passing parameters + * @reply_type: (nullable): the expected type of the reply (which will be a + * tuple), or %NULL + * @timeout_msec: the timeout in milliseconds, -1 to use the default + * timeout or %G_MAXINT for no timeout + * @cancellable: (nullable): a #GCancellable or %NULL + * @callback: (nullable): a #GAsyncReadyCallback to call when the request + * is satisfied or %NULL if you don't care about the result of the + * method invocation + * @user_data: the data to pass to @callback + * + * Call g_dbus_connection_call() on the current name owner with the specified + * arguments. Most importantly, this invokes g_dbus_connection_call() with the + * client's #GMainContext, so that the response is always in order with other + * events D-Bus events. Of course, the call uses #GTask and will invoke the + * callback on the current g_main_context_get_thread_default(). + * + * This API is merely a convenient wrapper for g_dbus_connection_call(). You can + * also use g_dbus_connection_call() directly, with the same effect. + * + * Since: 1.24 + **/ +void +nm_client_dbus_call (NMClient *client, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + const GVariantType *reply_type, + int timeout_msec, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_return_if_fail (NM_IS_CLIENT (client)); + + _nm_client_dbus_call (client, + client, + nm_client_dbus_call, + cancellable, + callback, + user_data, + object_path, + interface_name, + method_name, + parameters, + reply_type, + G_DBUS_CALL_FLAGS_NONE, + timeout_msec == -1 + ? NM_DBUS_DEFAULT_TIMEOUT_MSEC + : timeout_msec, + nm_dbus_connection_call_finish_variant_cb); +} + +/** + * nm_client_dbus_call_finish: + * @client: the #NMClient instance + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_client_dbus_call(). + * + * Returns: (transfer full): the result #GVariant or %NULL on error. + * + * Since: 1.24 + **/ +GVariant * +nm_client_dbus_call_finish (NMClient *client, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + g_return_val_if_fail (nm_g_task_is_valid (result, client, nm_client_dbus_call), FALSE); + + return g_task_propagate_pointer (G_TASK (result), error); +} + +/*****************************************************************************/ + +/** + * nm_client_dbus_set_property: + * @client: the #NMClient + * @object_path: path of remote object + * @interface_name: D-Bus interface to invoke method on + * @property_name: the name of the property to set + * @value: a #GVariant tuple with the value to set + * @timeout_msec: the timeout in milliseconds, -1 to use the default + * timeout or %G_MAXINT for no timeout + * @cancellable: (nullable): a #GCancellable or %NULL + * @callback: (nullable): a #GAsyncReadyCallback to call when the request + * is satisfied or %NULL if you don't care about the result of the + * method invocation + * @user_data: the data to pass to @callback + * + * Like nm_client_dbus_call() but calls "Set" on the standard "org.freedesktop.DBus.Properties" + * D-Bus interface. + * + * Since: 1.24 + **/ +void +nm_client_dbus_set_property (NMClient *client, + const char *object_path, + const char *interface_name, + const char *property_name, + GVariant *value, + int timeout_msec, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_return_if_fail (NM_IS_CLIENT (client)); + g_return_if_fail (interface_name); + g_return_if_fail (property_name); + g_return_if_fail (value); + + _nm_client_dbus_call (client, + client, + nm_client_dbus_set_property, + cancellable, + callback, + user_data, + object_path, + DBUS_INTERFACE_PROPERTIES, + "Set", + g_variant_new ("(ssv)", + interface_name, + property_name, + value), + G_VARIANT_TYPE ("()"), + G_DBUS_CALL_FLAGS_NONE, + timeout_msec == -1 + ? NM_DBUS_DEFAULT_TIMEOUT_MSEC + : timeout_msec, + nm_dbus_connection_call_finish_void_cb); +} + +/** + * nm_client_dbus_set_property_finish: + * @client: the #NMClient instance + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_client_dbus_set_property(). + * + * Returns: %TRUE on success or %FALSE on failure. + * + * Since: 1.24 + **/ +gboolean +nm_client_dbus_set_property_finish (NMClient *client, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + g_return_val_if_fail (nm_g_task_is_valid (result, client, nm_client_dbus_set_property), FALSE); + + return g_task_propagate_boolean (G_TASK (result), error); +} + +/*****************************************************************************/ + static void _init_fetch_all (NMClient *self) { @@ -6554,13 +6830,13 @@ _init_fetch_all (NMClient *self) priv->get_managed_objects_cancellable = g_cancellable_new (); - priv->dbsid_nm_object_manager = nm_dbus_connection_signal_subscribe_object_manager_plain (priv->dbus_connection, - priv->name_owner, - "/org/freedesktop", - NULL, - _dbus_managed_objects_changed_cb, - self, - NULL); + priv->dbsid_nm_object_manager = nm_dbus_connection_signal_subscribe_object_manager (priv->dbus_connection, + priv->name_owner, + "/org/freedesktop", + NULL, + _dbus_managed_objects_changed_cb, + self, + NULL); priv->dbsid_dbus_properties_properties_changed = nm_dbus_connection_signal_subscribe_properties_changed (priv->dbus_connection, priv->name_owner, @@ -6637,6 +6913,7 @@ _init_release_all (NMClient *self) CList **dbus_objects_lst_heads; NMLDBusObject *dbobj; int i; + gboolean permissions_state_changed = FALSE; NML_NMCLIENT_LOG_D (self, "release all"); @@ -6656,12 +6933,20 @@ _init_release_all (NMClient *self) nm_clear_g_dbus_connection_signal (priv->dbus_connection, &priv->dbsid_nm_check_permissions); + if (priv->permissions_state != NM_TERNARY_DEFAULT) { + priv->permissions_state = NM_TERNARY_DEFAULT; + permissions_state_changed = TRUE; + } + if (priv->permissions) { - gs_unref_hashtable GHashTable *old_permissions = g_steal_pointer (&priv->permissions); + gs_free guint8 *old_permissions = g_steal_pointer (&priv->permissions); - _emit_permissions_changed (self, old_permissions, TRUE); + _emit_permissions_changed (self, old_permissions, NULL); } + if (permissions_state_changed) + _notify (self, PROP_PERMISSIONS_STATE); + nm_assert (c_list_is_empty (&priv->obj_changed_lst_head)); dbus_objects_lst_heads = ((CList *[]) { @@ -6726,7 +7011,7 @@ name_owner_changed (NMClient *self, old_context_busy_watcher = g_steal_pointer (&priv->context_busy_watcher); priv->context_busy_watcher = g_object_ref (g_object_get_qdata (old_context_busy_watcher, - nm_client_context_busy_watcher_quark ())); + nm_context_busy_watcher_quark ())); g_main_context_ref (priv->main_context); g_main_context_unref (priv->dbus_context); @@ -6825,7 +7110,7 @@ name_owner_get_cb (GObject *source, ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); if ( !ret - && nm_utils_error_is_cancelled (error, FALSE)) + && nm_utils_error_is_cancelled (error)) return; priv = NM_CLIENT_GET_PRIVATE (self); @@ -6862,35 +7147,80 @@ name_owner_get_call (NMClient *self) /*****************************************************************************/ +static inline gboolean +_nml_cleanup_context_busy_watcher_on_idle_cb (gpointer user_data) +{ + nm_auto_unref_gmaincontext GMainContext *context = NULL; + gs_unref_object GObject *context_busy_watcher = NULL; + + nm_utils_user_data_unpack (user_data, &context, &context_busy_watcher); + + nm_assert (context); + nm_assert (G_IS_OBJECT (context_busy_watcher)); + return G_SOURCE_REMOVE; +} + +void +nml_cleanup_context_busy_watcher_on_idle (GObject *context_busy_watcher_take, + GMainContext *context) +{ + gs_unref_object GObject *context_busy_watcher = g_steal_pointer (&context_busy_watcher_take); + GSource *cleanup_source; + + nm_assert (G_IS_OBJECT (context_busy_watcher)); + nm_assert (context); + + /* Technically, we cancelled all pending actions (and these actions + * (GTask) keep the context_busy_watcher object alive). Also, we passed + * no destroy notify to g_dbus_connection_signal_subscribe(). + * That means, there should be no other unaccounted GSource'es left. + * + * However, we really need to be sure that the context_busy_watcher's + * lifetime matches the time that the context is busy. That is especially + * important with synchronous initialization, where the context-busy-watcher + * keeps the inner GMainContext integrated in the caller's. + * We must not g_source_destroy() that integration too early. + * + * So to be really sure all this is given, always schedule one last + * cleanup idle action with low priority. This should be the last + * thing related to this instance that keeps the context busy. + * + * Note that we could also *not* take a reference on @context + * and unref @context_busy_watcher via the GDestroyNotify. That would + * allow for the context to be wrapped up early, and when the last user + * gives up the reference to the context, the destroy notify could complete + * without even invoke the idle handler. However, that destroy notify may + * not be called in the right thread. So, we want to be sure that we unref + * the context-busy-watcher in the right context. Hence, we always take an + * additional reference and always cleanup in the idle handler. This means: + * the user *MUST* always keep iterating the context after NMClient got destroyed. + * But that is not a severe limitation, because the user anyway must be prepared + * to do that. That is because in many cases it is necessary anyway (and the user + * wouldn't know a priory when not). This way, it is just always necessary. */ + + cleanup_source = nm_g_idle_source_new (G_PRIORITY_LOW + 10, + _nml_cleanup_context_busy_watcher_on_idle_cb, + nm_utils_user_data_pack (g_main_context_ref (context), + g_steal_pointer (&context_busy_watcher)), + NULL); + g_source_attach (cleanup_source, context); + g_source_unref (cleanup_source); +} + +/*****************************************************************************/ + static void _init_start_complete (NMClient *self, GError *error_take) { NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); - InitData *init_data; - - init_data = g_steal_pointer (&priv->init_data); NML_NMCLIENT_LOG_D (self, "%s init complete with %s%s%s", - init_data->is_sync ? "sync" : "async", + priv->init_data->is_sync ? "sync" : "async", NM_PRINT_FMT_QUOTED (error_take, "error: ", error_take->message, "", "success")); - nm_clear_pointer (&init_data->cancel_on_idle_source, nm_g_source_destroy_and_unref); - nm_clear_g_signal_handler (init_data->cancellable, &init_data->cancelled_id); - - if (init_data->is_sync) { - if (error_take) - g_propagate_error (init_data->data.sync.error_location, error_take); - g_main_loop_quit (init_data->data.sync.main_loop); - } else { - if (error_take) - g_task_return_error (init_data->data.async.task, error_take); - else - g_task_return_boolean (init_data->data.async.task, TRUE); - g_object_unref (init_data->data.async.task); - } - nm_g_object_unref (init_data->cancellable); - nm_g_slice_free (init_data); + nml_init_data_return (g_steal_pointer (&priv->init_data), + error_take); } static void @@ -7033,6 +7363,9 @@ get_property (GObject *object, guint prop_id, NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object); switch (prop_id) { + case PROP_INSTANCE_FLAGS: + g_value_set_uint (value, priv->instance_flags); + break; case PROP_DBUS_CONNECTION: g_value_set_object (value, priv->dbus_connection); break; @@ -7121,6 +7454,9 @@ get_property (GObject *object, guint prop_id, g_value_take_boxed (value, out); } break; + case PROP_PERMISSIONS_STATE: + g_value_set_enum (value, priv->permissions_state); + break; /* Settings properties. */ case PROP_CONNECTIONS: @@ -7159,8 +7495,38 @@ set_property (GObject *object, guint prop_id, NMClient *self = NM_CLIENT (object); NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); gboolean b; + guint v_uint; switch (prop_id) { + + case PROP_INSTANCE_FLAGS: + /* construct */ + + v_uint = g_value_get_uint (value); + g_return_if_fail (!NM_FLAGS_ANY (v_uint, ~((guint) NM_CLIENT_INSTANCE_FLAGS_ALL))); + v_uint &= ((guint) NM_CLIENT_INSTANCE_FLAGS_ALL); + + if (!priv->instance_flags_constructed) { + priv->instance_flags_constructed = TRUE; + priv->instance_flags = v_uint; + nm_assert ((guint) priv->instance_flags == v_uint); + } else { + NMClientInstanceFlags flags = v_uint; + + /* After object construction, we only allow to toggle certain flags and + * ignore all other flags. */ + + if ((priv->instance_flags ^ flags) & NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS) { + if (NM_FLAGS_HAS (flags, NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS)) + priv->instance_flags |= NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS; + else + priv->instance_flags &= ~NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS; + if (priv->dbsid_nm_check_permissions != 0) + _dbus_check_permissions_start (self); + } + } + break; + case PROP_DBUS_CONNECTION: /* construct-only */ priv->dbus_connection = g_value_dup_object (value); @@ -7253,12 +7619,12 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) * to resync and drop the inner context. That means, requests made against the inner * context have a different lifetime. Hence, we create a separate tracking * object. This "wraps" the outer context-busy-watcher and references it, so - * that the work together. Grep for nm_client_context_busy_watcher_quark() to + * that the work together. Grep for nm_context_busy_watcher_quark() to * see how this works. */ parent_context_busy_watcher = g_steal_pointer (&priv->context_busy_watcher); priv->context_busy_watcher = g_object_new (G_TYPE_OBJECT, NULL); g_object_set_qdata_full (priv->context_busy_watcher, - nm_client_context_busy_watcher_quark (), + nm_context_busy_watcher_quark (), parent_context_busy_watcher, g_object_unref); @@ -7266,7 +7632,7 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) main_loop = g_main_loop_new (dbus_context, FALSE); - priv->init_data = _init_data_new_sync (cancellable, main_loop, &local_error); + priv->init_data = nml_init_data_new_sync (cancellable, main_loop, &local_error); _init_start (self); @@ -7277,12 +7643,9 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) g_main_context_pop_thread_default (dbus_context); if (priv->main_context != priv->dbus_context) { - GSource *source; - - source = nm_utils_g_main_context_create_integrate_source (priv->dbus_context); - g_source_attach (source, priv->main_context); - _context_busy_watcher_attach_integration_source (priv->context_busy_watcher, - g_steal_pointer (&source)); + nm_context_busy_watcher_integrate_source (priv->main_context, + priv->dbus_context, + priv->context_busy_watcher); } g_main_context_unref (dbus_context); @@ -7322,7 +7685,7 @@ init_async (GAsyncInitable *initable, task = nm_g_task_new (self, cancellable, init_async, callback, user_data); g_task_set_priority (task, io_priority); - priv->init_data = _init_data_new_async (cancellable, g_steal_pointer (&task)); + priv->init_data = nml_init_data_new_async (cancellable, g_steal_pointer (&task)); _init_start (self); } @@ -7343,6 +7706,8 @@ nm_client_init (NMClient *self) { NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self); + priv->permissions_state = NM_TERNARY_DEFAULT; + priv->context_busy_watcher = g_object_new (G_TYPE_OBJECT, NULL); c_list_init (&self->obj_base.queue_notify_lst); @@ -7441,18 +7806,6 @@ constructed (GObject *object) NML_NMCLIENT_LOG_D (self, "new NMClient instance"); } -static inline gboolean -_dispose_cleanup_context_busy_watcher_cb (gpointer user_data) -{ - nm_auto_unref_gmaincontext GMainContext *context = NULL; - gs_unref_object GObject *context_busy_watcher = NULL; - - nm_utils_user_data_unpack (user_data, &context, &context_busy_watcher); - - nm_assert (G_IS_OBJECT (context_busy_watcher)); - return G_SOURCE_REMOVE; -} - static void dispose (GObject *object) { @@ -7503,48 +7856,14 @@ dispose (GObject *object) if ( priv->context_busy_watcher && priv->dbus_context) { - GSource *cleanup_source; - - /* Technically, we cancelled all pending actions (and these actions - * (GTask) keep the context_busy_watcher object alive). Also, we passed - * no destroy notify to g_dbus_connection_signal_subscribe(). - * That means, there should be no other unaccounted GSource'es left. - * - * However, we really need to be sure that the context_busy_watcher's - * lifetime matches the time that the context is busy. That is especially - * important with synchronous initialization, where the context-busy-watcher - * keeps the inner GMainContext integrated in the caller's. - * We must not g_source_destroy() that integration too early. - * - * So to be really sure all this is given, always schedule one last - * cleanup idle action with low priority. This should be the last - * thing related to this instance that keeps the context busy. - * - * Note that we could also *not* take a reference on priv->dbus_context - * and unref priv->context_busy_watcher via the GDestroyNotify. That would - * allow for the context to be wrapped up early, and when the last user - * gives up the reference to the context, the destroy notify could complete - * without even invoke the idle handler. However, that destroy notify may - * not be called in the right thread. So, we want to be sure that we unref - * the context-busy-watcher in the right context. Hence, we always take an - * additional reference and always cleanup in the idle handler. This means: - * the user *MUST* always keep iterating the context after NMClient got destroyed. - * But that is not a severe limitation, because the user anyway must be prepared - * to do that. That is because in many cases it is necessary anyway (and the user - * wouldn't know a priory when not). This way, it is just always necessary. */ - cleanup_source = nm_g_idle_source_new (G_PRIORITY_LOW + 10, - _dispose_cleanup_context_busy_watcher_cb, - nm_utils_user_data_pack (g_main_context_ref (priv->dbus_context), - g_steal_pointer (&priv->context_busy_watcher)), - NULL); - g_source_attach (cleanup_source, priv->dbus_context); - g_source_unref (cleanup_source); + nml_cleanup_context_busy_watcher_on_idle (g_steal_pointer (&priv->context_busy_watcher), + priv->dbus_context); } nm_clear_pointer (&priv->dbus_context, g_main_context_unref); nm_clear_pointer (&priv->main_context, g_main_context_unref); - nm_clear_pointer (&priv->permissions, g_hash_table_unref); + nm_clear_g_free (&priv->permissions); g_clear_object (&priv->dbus_connection); @@ -7554,6 +7873,8 @@ dispose (GObject *object) priv->nm.capabilities_len = 0; nm_clear_g_free (&priv->nm.capabilities_arr); + + NML_NMCLIENT_LOG_D (self, "disposed"); } const NMLDBusMetaIface _nml_dbus_meta_iface_nm_agentmanager = NML_DBUS_META_IFACE_INIT ( @@ -7649,6 +7970,30 @@ nm_client_class_init (NMClientClass *client_class) G_PARAM_STATIC_STRINGS); /** + * NMClient:instance-flags: + * + * #NMClientInstanceFlags for the instance. These affect behavior of #NMClient. + * This is a construct property and you may only set most flags only during + * construction. + * + * The flag %NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS can be toggled any time, + * even after constructing the instance. Note that you may want to watch NMClient:permissions-state + * property to know whether permissions are ready. Note that permissions are only fetched + * when NMClient has a D-Bus name owner. + * + * Since: 1.24 + */ + obj_properties[PROP_INSTANCE_FLAGS] = + g_param_spec_uint (NM_CLIENT_INSTANCE_FLAGS, "", "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS); + + /** * NMClient:dbus-name-owner: * * The name owner of the NetworkManager D-Bus service. @@ -8014,7 +8359,7 @@ nm_client_class_init (NMClientClass *client_class) * there are no capabitilies. The numeric value correspond * to %NMCapability enum. * - * Since: 1.24, 1.22.2 + * Since: 1.24 */ obj_properties[PROP_CAPABILITIES] = g_param_spec_boxed (NM_CLIENT_CAPABILITIES, "", "", @@ -8022,6 +8367,32 @@ nm_client_class_init (NMClientClass *client_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + /** + * NMClient:permissions-state: + * + * The state of the cached permissions. The value %NM_TERNARY_DEFAULT + * means that no permissions are yet received (or not yet requested). + * %NM_TERNARY_TRUE means that permissions are received, cached and up + * to date. %NM_TERNARY_FALSE means that permissions were received and are + * cached, but in the meantime a "CheckPermissions" signal was received + * that invalidated the cached permissions. + * Note that NMClient will always emit a notify::permissions-state signal + * when a "CheckPermissions" signal got received or after new permissions + * got received (that is regardless whether the value of the permission state + * actually changed). With this you can watch the permissions-state property + * to know whether the permissions are ready. Note that while NMClient has + * no D-Bus name owner, no permissions are fetched (and this property won't + * change). + * + * Since: 1.24 + */ + obj_properties[PROP_PERMISSIONS_STATE] = + g_param_spec_enum (NM_CLIENT_PERMISSIONS_STATE, "", "", + NM_TYPE_TERNARY, + NM_TERNARY_DEFAULT, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm, &_nml_dbus_meta_iface_nm_settings, &_nml_dbus_meta_iface_nm_dnsmanager); diff --git a/libnm/nm-client.h b/libnm/nm-client.h index 8af956b4..627b228f 100644 --- a/libnm/nm-client.h +++ b/libnm/nm-client.h @@ -15,6 +15,23 @@ G_BEGIN_DECLS +/** + * NMClientInstanceFlags: + * @NM_CLIENT_INSTANCE_FLAGS_NONE: special value to indicate no flags. + * @NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS: by default, NMClient + * will fetch the permissions via "GetPermissions" and refetch them when + * "CheckPermissions" signal gets received. By setting this flag, this behavior + * can be disabled. You can toggle this flag to enable and disable automatic + * fetching of the permissions. Watch also nm_client_get_permissions_state() + * to know whether the permissions are up to date. + * + * Since: 1.24 + */ +typedef enum { /*< flags >*/ + NM_CLIENT_INSTANCE_FLAGS_NONE = 0, + NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS = 1, +} NMClientInstanceFlags; + #define NM_TYPE_CLIENT (nm_client_get_type ()) #define NM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CLIENT, NMClient)) #define NM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CLIENT, NMClientClass)) @@ -28,6 +45,7 @@ G_BEGIN_DECLS #define NM_CLIENT_NM_RUNNING "nm-running" #define NM_CLIENT_DBUS_CONNECTION "dbus-connection" #define NM_CLIENT_DBUS_NAME_OWNER "dbus-name-owner" +#define NM_CLIENT_INSTANCE_FLAGS "instance-flags" _NM_DEPRECATED_SYNC_WRITABLE_PROPERTY #define NM_CLIENT_NETWORKING_ENABLED "networking-enabled" @@ -64,6 +82,7 @@ _NM_DEPRECATED_SYNC_WRITABLE_PROPERTY #define NM_CLIENT_DNS_CONFIGURATION "dns-configuration" #define NM_CLIENT_CHECKPOINTS "checkpoints" #define NM_CLIENT_CAPABILITIES "capabilities" +#define NM_CLIENT_PERMISSIONS_STATE "permissions-state" #define NM_CLIENT_DEVICE_ADDED "device-added" #define NM_CLIENT_DEVICE_REMOVED "device-removed" @@ -76,87 +95,6 @@ _NM_DEPRECATED_SYNC_WRITABLE_PROPERTY #define NM_CLIENT_ACTIVE_CONNECTION_REMOVED "active-connection-removed" /** - * NMClientPermission: - * @NM_CLIENT_PERMISSION_NONE: unknown or no permission - * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK: controls whether networking - * can be globally enabled or disabled - * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI: controls whether Wi-Fi can be - * globally enabled or disabled - * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN: controls whether WWAN (3G) can be - * globally enabled or disabled - * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX: controls whether WiMAX can be - * globally enabled or disabled - * @NM_CLIENT_PERMISSION_SLEEP_WAKE: controls whether the client can ask - * NetworkManager to sleep and wake - * @NM_CLIENT_PERMISSION_NETWORK_CONTROL: controls whether networking connections - * can be started, stopped, and changed - * @NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED: controls whether a password - * protected Wi-Fi hotspot can be created - * @NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN: controls whether an open Wi-Fi hotspot - * can be created - * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM: controls whether connections - * that are available to all users can be modified - * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN: controls whether connections - * owned by the current user can be modified - * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME: controls whether the - * persistent hostname can be changed - * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS: modify persistent global - * DNS configuration - * @NM_CLIENT_PERMISSION_RELOAD: controls access to Reload. - * @NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK: permission to create checkpoints. - * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS: controls whether device - * statistics can be globally enabled or disabled - * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK: controls whether - * connectivity check can be enabled or disabled - * @NM_CLIENT_PERMISSION_WIFI_SCAN: controls whether wifi scans can be performed - * @NM_CLIENT_PERMISSION_LAST: a reserved boundary value - * - * #NMClientPermission values indicate various permissions that NetworkManager - * clients can obtain to perform certain tasks on behalf of the current user. - **/ -typedef enum { - NM_CLIENT_PERMISSION_NONE = 0, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK = 1, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI = 2, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN = 3, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX = 4, - NM_CLIENT_PERMISSION_SLEEP_WAKE = 5, - NM_CLIENT_PERMISSION_NETWORK_CONTROL = 6, - NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED = 7, - NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN = 8, - NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM = 9, - NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN = 10, - NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME = 11, - NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS = 12, - NM_CLIENT_PERMISSION_RELOAD = 13, - NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK = 14, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS = 15, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK = 16, - NM_CLIENT_PERMISSION_WIFI_SCAN = 17, - - NM_CLIENT_PERMISSION_LAST = 17, -} NMClientPermission; - -/** - * NMClientPermissionResult: - * @NM_CLIENT_PERMISSION_RESULT_UNKNOWN: unknown or no authorization - * @NM_CLIENT_PERMISSION_RESULT_YES: the permission is available - * @NM_CLIENT_PERMISSION_RESULT_AUTH: authorization is necessary before the - * permission is available - * @NM_CLIENT_PERMISSION_RESULT_NO: permission to perform the operation is - * denied by system policy - * - * #NMClientPermissionResult values indicate what authorizations and permissions - * the user requires to obtain a given #NMClientPermission - **/ -typedef enum { - NM_CLIENT_PERMISSION_RESULT_UNKNOWN = 0, - NM_CLIENT_PERMISSION_RESULT_YES, - NM_CLIENT_PERMISSION_RESULT_AUTH, - NM_CLIENT_PERMISSION_RESULT_NO -} NMClientPermissionResult; - -/** * NMClientError: * @NM_CLIENT_ERROR_FAILED: unknown or unclassified error * @NM_CLIENT_ERROR_MANAGER_NOT_RUNNING: an operation that requires NetworkManager @@ -215,6 +153,10 @@ void nm_client_new_async (GCancellable *cancellable, NMClient *nm_client_new_finish (GAsyncResult *result, GError **error); + +NM_AVAILABLE_IN_1_24 +NMClientInstanceFlags nm_client_get_instance_flags (NMClient *self); + NM_AVAILABLE_IN_1_22 GDBusConnection *nm_client_get_dbus_connection (NMClient *client); @@ -232,12 +174,15 @@ NMState nm_client_get_state (NMClient *client); gboolean nm_client_get_startup (NMClient *client); gboolean nm_client_get_nm_running (NMClient *client); +NMObject *nm_client_get_object_by_path (NMClient *client, + const char *dbus_path); + NM_AVAILABLE_IN_1_22 NMMetered nm_client_get_metered (NMClient *client); gboolean nm_client_networking_get_enabled (NMClient *client); -NM_AVAILABLE_IN_1_22_2 +NM_AVAILABLE_IN_1_24 const guint32 *nm_client_get_capabilities (NMClient *client, gsize *length); @@ -299,6 +244,9 @@ gboolean nm_client_set_logging (NMClient *client, NMClientPermissionResult nm_client_get_permission_result (NMClient *client, NMClientPermission permission); +NM_AVAILABLE_IN_1_24 +NMTernary nm_client_get_permissions_state (NMClient *self); + NMConnectivityState nm_client_get_connectivity (NMClient *client); _NM_DEPRECATED_SYNC_METHOD @@ -530,6 +478,41 @@ gboolean nm_client_reload_finish (NMClient *client, GAsyncResult *result, GError **error); +/*****************************************************************************/ + +NM_AVAILABLE_IN_1_24 +void nm_client_dbus_call (NMClient *client, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + const GVariantType *reply_type, + int timeout_msec, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +NM_AVAILABLE_IN_1_24 +GVariant *nm_client_dbus_call_finish (NMClient *client, + GAsyncResult *result, + GError **error); + +NM_AVAILABLE_IN_1_24 +void nm_client_dbus_set_property (NMClient *client, + const char *object_path, + const char *interface_name, + const char *property_name, + GVariant *value, + int timeout_msec, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +NM_AVAILABLE_IN_1_24 +gboolean nm_client_dbus_set_property_finish (NMClient *client, + GAsyncResult *result, + GError **error); + G_END_DECLS #endif /* __NM_CLIENT_H__ */ diff --git a/libnm/nm-device-6lowpan.c b/libnm/nm-device-6lowpan.c index 5899df30..0b428c2d 100644 --- a/libnm/nm-device-6lowpan.c +++ b/libnm/nm-device-6lowpan.c @@ -13,12 +13,10 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( PROP_PARENT, - PROP_HW_ADDRESS, ); typedef struct { NMLDBusPropertyO parent; - char *hw_address; } NMDevice6LowpanPrivate; struct _NMDevice6Lowpan { @@ -62,19 +60,15 @@ nm_device_6lowpan_get_parent (NMDevice6Lowpan *device) * device, and must not be modified. * * Since: 1.14 + * + * Deprecated: 1.24: Use nm_device_get_hw_address() instead. **/ const char * nm_device_6lowpan_get_hw_address (NMDevice6Lowpan *device) { g_return_val_if_fail (NM_IS_DEVICE_6LOWPAN (device), NULL); - return NM_DEVICE_6LOWPAN_GET_PRIVATE (device)->hw_address; -} - -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_6lowpan_get_hw_address (NM_DEVICE_6LOWPAN (device)); + return nm_device_get_hw_address (NM_DEVICE (device)); } /*****************************************************************************/ @@ -85,16 +79,6 @@ nm_device_6lowpan_init (NMDevice6Lowpan *device) } static void -dispose (GObject *object) -{ - NMDevice6LowpanPrivate *priv = NM_DEVICE_6LOWPAN_GET_PRIVATE (object); - - G_OBJECT_CLASS (nm_device_6lowpan_parent_class)->dispose (object); - - nm_clear_g_free (&priv->hw_address); -} - -static void get_property (GObject *object, guint prop_id, GValue *value, @@ -106,9 +90,6 @@ get_property (GObject *object, case PROP_PARENT: g_value_set_object (value, nm_device_6lowpan_get_parent (device)); break; - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_6lowpan_get_hw_address (device)); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -120,8 +101,8 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_lowpan = NML_DBUS_META_IFA nm_device_6lowpan_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( - NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDevice6Lowpan, _priv.hw_address ), - NML_DBUS_META_PROPERTY_INIT_O_PROP ("Parent", PROP_PARENT, NMDevice6Lowpan, _priv.parent, nm_device_get_type ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Parent", PROP_PARENT, NMDevice6Lowpan, _priv.parent, nm_device_get_type ), ), ); @@ -130,17 +111,13 @@ nm_device_6lowpan_class_init (NMDevice6LowpanClass *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->dispose = dispose; _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDevice6Lowpan); _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_1 (nm_object_class, NMDevice6LowpanPrivate, parent); - device_class->get_hw_address = get_hw_address; - /** * NMDevice6Lowpan:parent: * @@ -154,18 +131,5 @@ nm_device_6lowpan_class_init (NMDevice6LowpanClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - /** - * NMDevice6Lowpan:hw-address: - * - * The hardware (MAC) address of the device. - * - * Since: 1.14 - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_6LOWPAN_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_lowpan); } diff --git a/libnm/nm-device-6lowpan.h b/libnm/nm-device-6lowpan.h index eba4886e..6f400c8d 100644 --- a/libnm/nm-device-6lowpan.h +++ b/libnm/nm-device-6lowpan.h @@ -34,8 +34,11 @@ GType nm_device_6lowpan_get_type (void); NM_AVAILABLE_IN_1_14 NMDevice * nm_device_6lowpan_get_parent (NMDevice6Lowpan *device); + NM_AVAILABLE_IN_1_14 +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char * nm_device_6lowpan_get_hw_address (NMDevice6Lowpan *device); + G_END_DECLS #endif /* __NM_DEVICE_6LOWPAN_H__ */ diff --git a/libnm/nm-device-bond.c b/libnm/nm-device-bond.c index 66c1bf83..cb236af9 100644 --- a/libnm/nm-device-bond.c +++ b/libnm/nm-device-bond.c @@ -16,7 +16,6 @@ /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_HW_ADDRESS, PROP_CARRIER, PROP_SLAVES, ); @@ -50,13 +49,15 @@ G_DEFINE_TYPE (NMDeviceBond, nm_device_bond, NM_TYPE_DEVICE) * * Returns: the 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_bond_get_hw_address (NMDeviceBond *device) { g_return_val_if_fail (NM_IS_DEVICE_BOND (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_BOND_GET_PRIVATE (device)->hw_address); + return nm_device_get_hw_address (NM_DEVICE (device)); } /** @@ -116,12 +117,6 @@ get_setting_type (NMDevice *device) return NM_TYPE_SETTING_BOND; } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_bond_get_hw_address (NM_DEVICE_BOND (device)); -} - /*****************************************************************************/ static void @@ -148,9 +143,6 @@ get_property (GObject *object, NMDeviceBond *device = NM_DEVICE_BOND (object); switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_bond_get_hw_address (device)); - break; case PROP_CARRIER: g_value_set_boolean (value, nm_device_bond_get_carrier (device)); break; @@ -168,9 +160,9 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_bond = NML_DBUS_META_IFACE nm_device_bond_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( - NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceBond, _priv.carrier ), - NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceBond, _priv.hw_address ), - NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Slaves", PROP_SLAVES, NMDeviceBond, _priv.slaves, nm_device_get_type ), + NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceBond, _priv.carrier ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Slaves", PROP_SLAVES, NMDeviceBond, _priv.slaves, nm_device_get_type ), ), ); @@ -190,18 +182,6 @@ nm_device_bond_class_init (NMDeviceBondClass *klass) device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; - device_class->get_hw_address = get_hw_address; - - /** - * NMDeviceBond:hw-address: - * - * The hardware (MAC) address of the device. - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_BOND_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); /** * NMDeviceBond:carrier: diff --git a/libnm/nm-device-bond.h b/libnm/nm-device-bond.h index a65f88f9..2ffe974e 100644 --- a/libnm/nm-device-bond.h +++ b/libnm/nm-device-bond.h @@ -32,7 +32,9 @@ typedef struct _NMDeviceBondClass NMDeviceBondClass; GType nm_device_bond_get_type (void); +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char *nm_device_bond_get_hw_address (NMDeviceBond *device); + gboolean nm_device_bond_get_carrier (NMDeviceBond *device); const GPtrArray *nm_device_bond_get_slaves (NMDeviceBond *device); diff --git a/libnm/nm-device-bridge.c b/libnm/nm-device-bridge.c index f50054d4..977db146 100644 --- a/libnm/nm-device-bridge.c +++ b/libnm/nm-device-bridge.c @@ -16,14 +16,12 @@ /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_HW_ADDRESS, PROP_CARRIER, PROP_SLAVES, ); typedef struct { NMLDBusPropertyAO slaves; - char *hw_address; bool carrier; } NMDeviceBridgePrivate; @@ -50,13 +48,15 @@ G_DEFINE_TYPE (NMDeviceBridge, nm_device_bridge, NM_TYPE_DEVICE) * * Returns: the 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_bridge_get_hw_address (NMDeviceBridge *device) { g_return_val_if_fail (NM_IS_DEVICE_BRIDGE (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_BRIDGE_GET_PRIVATE (device)->hw_address); + return nm_device_get_hw_address (NM_DEVICE (device)); } /** @@ -121,12 +121,6 @@ get_setting_type (NMDevice *device) return NM_TYPE_SETTING_BRIDGE; } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_bridge_get_hw_address (NM_DEVICE_BRIDGE (device)); -} - /*****************************************************************************/ static void @@ -135,16 +129,6 @@ nm_device_bridge_init (NMDeviceBridge *device) } static void -finalize (GObject *object) -{ - NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (object); - - g_free (priv->hw_address); - - G_OBJECT_CLASS (nm_device_bridge_parent_class)->finalize (object); -} - -static void get_property (GObject *object, guint prop_id, GValue *value, @@ -153,9 +137,6 @@ get_property (GObject *object, NMDeviceBridge *device = NM_DEVICE_BRIDGE (object); switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_bridge_get_hw_address (device)); - break; case PROP_CARRIER: g_value_set_boolean (value, nm_device_bridge_get_carrier (device)); break; @@ -173,9 +154,9 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_bridge = NML_DBUS_META_IFA nm_device_bridge_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( - NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceBridge, _priv.carrier ), - NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceBridge, _priv.hw_address ), - NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Slaves", PROP_SLAVES, NMDeviceBridge, _priv.slaves, nm_device_get_type ), + NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceBridge, _priv.carrier ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Slaves", PROP_SLAVES, NMDeviceBridge, _priv.slaves, nm_device_get_type ), ), ); @@ -186,7 +167,6 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass) NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - object_class->finalize = finalize; object_class->get_property = get_property; _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceBridge); @@ -195,18 +175,6 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass) device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; - device_class->get_hw_address = get_hw_address; - - /** - * NMDeviceBridge:hw-address: - * - * The hardware (MAC) address of the device. - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_BRIDGE_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); /** * NMDeviceBridge:carrier: diff --git a/libnm/nm-device-bridge.h b/libnm/nm-device-bridge.h index 339f44dd..c1d1e183 100644 --- a/libnm/nm-device-bridge.h +++ b/libnm/nm-device-bridge.h @@ -32,7 +32,9 @@ typedef struct _NMDeviceBridgeClass NMDeviceBridgeClass; GType nm_device_bridge_get_type (void); +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char *nm_device_bridge_get_hw_address (NMDeviceBridge *device); + gboolean nm_device_bridge_get_carrier (NMDeviceBridge *device); const GPtrArray *nm_device_bridge_get_slaves (NMDeviceBridge *device); diff --git a/libnm/nm-device-bt.c b/libnm/nm-device-bt.c index 150b5d84..8df95265 100644 --- a/libnm/nm-device-bt.c +++ b/libnm/nm-device-bt.c @@ -17,13 +17,11 @@ /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_HW_ADDRESS, PROP_NAME, PROP_BT_CAPABILITIES, ); typedef struct { - char *hw_address; char *name; guint32 bt_capabilities; } NMDeviceBtPrivate; @@ -51,13 +49,15 @@ G_DEFINE_TYPE (NMDeviceBt, nm_device_bt, NM_TYPE_DEVICE) * * Returns: the 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_bt_get_hw_address (NMDeviceBt *device) { g_return_val_if_fail (NM_IS_DEVICE_BT (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_BT_GET_PRIVATE (device)->hw_address); + return nm_device_get_hw_address (NM_DEVICE (device)); } /** @@ -138,7 +138,7 @@ connection_compatible (NMDevice *device, NMConnection *connection, GError **erro } /* Check BT address */ - hw_addr = nm_device_bt_get_hw_address (NM_DEVICE_BT (device)); + hw_addr = nm_device_get_hw_address (device); if (hw_addr) { if (!nm_utils_hwaddr_valid (hw_addr, ETH_ALEN)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, @@ -170,12 +170,6 @@ get_setting_type (NMDevice *device) return NM_TYPE_SETTING_BLUETOOTH; } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_bt_get_hw_address (NM_DEVICE_BT (device)); -} - /*****************************************************************************/ static void @@ -188,7 +182,6 @@ finalize (GObject *object) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); - g_free (priv->hw_address); g_free (priv->name); G_OBJECT_CLASS (nm_device_bt_parent_class)->finalize (object); @@ -203,9 +196,6 @@ get_property (GObject *object, NMDeviceBt *device = NM_DEVICE_BT (object); switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_bt_get_hw_address (device)); - break; case PROP_NAME: g_value_set_string (value, nm_device_bt_get_name (device)); break; @@ -223,9 +213,9 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_bluetooth = NML_DBUS_META_ nm_device_bt_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( - NML_DBUS_META_PROPERTY_INIT_U ("BtCapabilities", PROP_BT_CAPABILITIES, NMDeviceBt, _priv.bt_capabilities ), - NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceBt, _priv.hw_address ), - NML_DBUS_META_PROPERTY_INIT_S ("Name", PROP_NAME, NMDeviceBt, _priv.name ), + NML_DBUS_META_PROPERTY_INIT_U ("BtCapabilities", PROP_BT_CAPABILITIES, NMDeviceBt, _priv.bt_capabilities ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), + NML_DBUS_META_PROPERTY_INIT_S ("Name", PROP_NAME, NMDeviceBt, _priv.name ), ), ); @@ -240,18 +230,6 @@ nm_device_bt_class_init (NMDeviceBtClass *bt_class) device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; - device_class->get_hw_address = get_hw_address; - - /** - * NMDeviceBt:hw-address: - * - * The hardware (MAC) address of the device. - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_BT_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); /** * NMDeviceBt:name: diff --git a/libnm/nm-device-bt.h b/libnm/nm-device-bt.h index 2633c2dc..4e38f104 100644 --- a/libnm/nm-device-bt.h +++ b/libnm/nm-device-bt.h @@ -33,6 +33,7 @@ typedef struct _NMDeviceBtClass NMDeviceBtClass; GType nm_device_bt_get_type (void); +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char *nm_device_bt_get_hw_address (NMDeviceBt *device); const char *nm_device_bt_get_name (NMDeviceBt *device); diff --git a/libnm/nm-device-dummy.c b/libnm/nm-device-dummy.c index 4916cc7d..3bf8e09f 100644 --- a/libnm/nm-device-dummy.c +++ b/libnm/nm-device-dummy.c @@ -13,17 +13,8 @@ /*****************************************************************************/ -NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_HW_ADDRESS, -); - -typedef struct { - char *hw_address; -} NMDeviceDummyPrivate; - struct _NMDeviceDummy { NMDevice parent; - NMDeviceDummyPrivate _priv; }; struct _NMDeviceDummyClass { @@ -46,13 +37,15 @@ G_DEFINE_TYPE (NMDeviceDummy, nm_device_dummy, NM_TYPE_DEVICE) * device, and must not be modified. * * Since: 1.10 + * + * Deprecated: 1.24: Use nm_device_get_hw_address() instead. **/ const char * nm_device_dummy_get_hw_address (NMDeviceDummy *device) { g_return_val_if_fail (NM_IS_DEVICE_DUMMY (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_DUMMY_GET_PRIVATE (device)->hw_address); + return nm_device_get_hw_address (NM_DEVICE (device)); } static gboolean @@ -85,12 +78,6 @@ get_setting_type (NMDevice *device) return NM_TYPE_SETTING_DUMMY; } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_dummy_get_hw_address (NM_DEVICE_DUMMY (device)); -} - /*****************************************************************************/ static void @@ -98,68 +85,20 @@ nm_device_dummy_init (NMDeviceDummy *device) { } -static void -finalize (GObject *object) -{ - NMDeviceDummyPrivate *priv = NM_DEVICE_DUMMY_GET_PRIVATE (object); - - g_free (priv->hw_address); - - G_OBJECT_CLASS (nm_device_dummy_parent_class)->finalize (object); -} - -static void -get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - NMDeviceDummy *device = NM_DEVICE_DUMMY (object); - - switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_dummy_get_hw_address (device)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_dummy = NML_DBUS_META_IFACE_INIT_PROP ( +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_dummy = NML_DBUS_META_IFACE_INIT ( NM_DBUS_INTERFACE_DEVICE_DUMMY, nm_device_dummy_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( - NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceDummy, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), ), ); static void nm_device_dummy_class_init (NMDeviceDummyClass *dummy_class) { - GObjectClass *object_class = G_OBJECT_CLASS (dummy_class); NMDeviceClass *device_class = NM_DEVICE_CLASS (dummy_class); - object_class->get_property = get_property; - object_class->finalize = finalize; - device_class->connection_compatible = connection_compatible; - device_class->get_hw_address = get_hw_address; device_class->get_setting_type = get_setting_type; - - /** - * NMDeviceDummy:hw-address: - * - * The active hardware (MAC) address of the device. - * - * Since: 1.10 - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_DUMMY_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_dummy); } diff --git a/libnm/nm-device-dummy.h b/libnm/nm-device-dummy.h index 4b33490c..0878936e 100644 --- a/libnm/nm-device-dummy.h +++ b/libnm/nm-device-dummy.h @@ -29,7 +29,9 @@ G_BEGIN_DECLS typedef struct _NMDeviceDummyClass NMDeviceDummyClass; GType nm_device_dummy_get_type (void); + NM_AVAILABLE_IN_1_10 +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char *nm_device_dummy_get_hw_address (NMDeviceDummy *device); G_END_DECLS diff --git a/libnm/nm-device-ethernet.c b/libnm/nm-device-ethernet.c index 7cd5b89f..944f7b81 100644 --- a/libnm/nm-device-ethernet.c +++ b/libnm/nm-device-ethernet.c @@ -17,7 +17,6 @@ /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_HW_ADDRESS, PROP_PERM_HW_ADDRESS, PROP_SPEED, PROP_CARRIER, @@ -26,7 +25,6 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( typedef struct { char **s390_subchannels; - char *hw_address; char *perm_hw_address; guint32 speed; bool carrier; @@ -55,13 +53,15 @@ G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE) * * Returns: the active 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_ethernet_get_hw_address (NMDeviceEthernet *device) { g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_ETHERNET_GET_PRIVATE (device)->hw_address); + return nm_device_get_hw_address (NM_DEVICE (device)); } /** @@ -210,7 +210,7 @@ connection_compatible (NMDevice *device, NMConnection *connection, GError **erro /* Virtual devices will have empty permanent addr but they should not be excluded * from the MAC address check specified in the connection */ if (*perm_addr == 0) - perm_addr = nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (device)); + perm_addr = nm_device_get_hw_address (NM_DEVICE (device)); if (!nm_utils_hwaddr_valid (perm_addr, ETH_ALEN)) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, @@ -251,12 +251,6 @@ get_setting_type (NMDevice *device) return NM_TYPE_SETTING_WIRED; } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (device)); -} - /*****************************************************************************/ static void @@ -269,7 +263,6 @@ finalize (GObject *object) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object); - g_free (priv->hw_address); g_free (priv->perm_hw_address); g_strfreev (priv->s390_subchannels); @@ -286,9 +279,6 @@ get_property (GObject *object, NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_ethernet_get_hw_address (device)); - break; case PROP_PERM_HW_ADDRESS: g_value_set_string (value, nm_device_ethernet_get_permanent_hw_address (device)); break; @@ -312,6 +302,9 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_veth = NML_DBUS_META_IFACE NM_DBUS_INTERFACE_DEVICE_VETH, NULL, NML_DBUS_META_INTERFACE_PRIO_NONE, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_TODO ("Peer", "o"), + ), ); const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wired = NML_DBUS_META_IFACE_INIT_PROP ( @@ -319,11 +312,11 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wired = NML_DBUS_META_IFAC nm_device_ethernet_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( - NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceEthernet, _priv.carrier ), - NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceEthernet, _priv.hw_address ), - NML_DBUS_META_PROPERTY_INIT_S ("PermHwAddress", PROP_PERM_HW_ADDRESS, NMDeviceEthernet, _priv.perm_hw_address ), - NML_DBUS_META_PROPERTY_INIT_AS ("S390Subchannels", PROP_S390_SUBCHANNELS, NMDeviceEthernet, _priv.s390_subchannels ), - NML_DBUS_META_PROPERTY_INIT_U ("Speed", PROP_SPEED, NMDeviceEthernet, _priv.speed ), + NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceEthernet, _priv.carrier ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), + NML_DBUS_META_PROPERTY_INIT_S ("PermHwAddress", PROP_PERM_HW_ADDRESS, NMDeviceEthernet, _priv.perm_hw_address ), + NML_DBUS_META_PROPERTY_INIT_AS ("S390Subchannels", PROP_S390_SUBCHANNELS, NMDeviceEthernet, _priv.s390_subchannels ), + NML_DBUS_META_PROPERTY_INIT_U ("Speed", PROP_SPEED, NMDeviceEthernet, _priv.speed ), ), ); @@ -338,18 +331,6 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *eth_class) device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; - device_class->get_hw_address = get_hw_address; - - /** - * NMDeviceEthernet:hw-address: - * - * The active hardware (MAC) address of the device. - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_ETHERNET_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); /** * NMDeviceEthernet:perm-hw-address: diff --git a/libnm/nm-device-ethernet.h b/libnm/nm-device-ethernet.h index 28b95dc2..1a430cb6 100644 --- a/libnm/nm-device-ethernet.h +++ b/libnm/nm-device-ethernet.h @@ -35,7 +35,9 @@ typedef struct _NMDeviceEthernetClass NMDeviceEthernetClass; GType nm_device_ethernet_get_type (void); +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char * nm_device_ethernet_get_hw_address (NMDeviceEthernet *device); + const char * nm_device_ethernet_get_permanent_hw_address (NMDeviceEthernet *device); guint32 nm_device_ethernet_get_speed (NMDeviceEthernet *device); gboolean nm_device_ethernet_get_carrier (NMDeviceEthernet *device); diff --git a/libnm/nm-device-generic.c b/libnm/nm-device-generic.c index b1c78475..3751cb51 100644 --- a/libnm/nm-device-generic.c +++ b/libnm/nm-device-generic.c @@ -14,12 +14,10 @@ /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_HW_ADDRESS, PROP_TYPE_DESCRIPTION, ); typedef struct { - char *hw_address; char *type_description; } NMDeviceGenericPrivate; @@ -46,13 +44,15 @@ G_DEFINE_TYPE (NMDeviceGeneric, nm_device_generic, NM_TYPE_DEVICE) * * Returns: the 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_generic_get_hw_address (NMDeviceGeneric *device) { g_return_val_if_fail (NM_IS_DEVICE_GENERIC (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_GENERIC_GET_PRIVATE (device)->hw_address); + return nm_device_get_hw_address (NM_DEVICE (device)); } /*****************************************************************************/ @@ -65,12 +65,6 @@ get_type_description (NMDevice *device) return _nml_coerce_property_str_not_empty (priv->type_description); } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_generic_get_hw_address (NM_DEVICE_GENERIC (device)); -} - static gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { @@ -113,7 +107,6 @@ finalize (GObject *object) { NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (object); - g_free (priv->hw_address); g_free (priv->type_description); G_OBJECT_CLASS (nm_device_generic_parent_class)->finalize (object); @@ -126,12 +119,8 @@ get_property (GObject *object, GParamSpec *pspec) { NMDeviceGeneric *self = NM_DEVICE_GENERIC (object); - NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (self); switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, priv->hw_address); - break; case PROP_TYPE_DESCRIPTION: g_value_set_string (value, get_type_description ((NMDevice *) self)); break; @@ -146,8 +135,8 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_generic = NML_DBUS_META_IF nm_device_generic_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( - NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceGeneric, _priv.hw_address ), - NML_DBUS_META_PROPERTY_INIT_S ("TypeDescription", PROP_TYPE_DESCRIPTION, NMDeviceGeneric, _priv.type_description ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), + NML_DBUS_META_PROPERTY_INIT_S ("TypeDescription", PROP_TYPE_DESCRIPTION, NMDeviceGeneric, _priv.type_description ), ), ); @@ -161,20 +150,9 @@ nm_device_generic_class_init (NMDeviceGenericClass *klass) object_class->finalize = finalize; device_class->get_type_description = get_type_description; - device_class->get_hw_address = get_hw_address; device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; - /** - * NMDeviceGeneric:hw-address: - * - * The hardware address of the device. - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_GENERIC_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); /** * NMDeviceGeneric:type-description: diff --git a/libnm/nm-device-generic.h b/libnm/nm-device-generic.h index aa52023a..c62afcd7 100644 --- a/libnm/nm-device-generic.h +++ b/libnm/nm-device-generic.h @@ -31,6 +31,7 @@ typedef struct _NMDeviceGenericClass NMDeviceGenericClass; GType nm_device_generic_get_type (void); +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char *nm_device_generic_get_hw_address (NMDeviceGeneric *device); G_END_DECLS diff --git a/libnm/nm-device-infiniband.c b/libnm/nm-device-infiniband.c index c3e57c95..ad47c2ed 100644 --- a/libnm/nm-device-infiniband.c +++ b/libnm/nm-device-infiniband.c @@ -15,12 +15,10 @@ /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_HW_ADDRESS, PROP_CARRIER, ); typedef struct { - char *hw_address; bool carrier; } NMDeviceInfinibandPrivate; @@ -47,13 +45,15 @@ G_DEFINE_TYPE (NMDeviceInfiniband, nm_device_infiniband, NM_TYPE_DEVICE) * * Returns: the 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_infiniband_get_hw_address (NMDeviceInfiniband *device) { g_return_val_if_fail (NM_IS_DEVICE_INFINIBAND (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_INFINIBAND_GET_PRIVATE (device)->hw_address); + return nm_device_get_hw_address (NM_DEVICE (device)); } /** @@ -87,7 +87,7 @@ connection_compatible (NMDevice *device, NMConnection *connection, GError **erro return FALSE; } - hwaddr = nm_device_infiniband_get_hw_address (NM_DEVICE_INFINIBAND (device)); + hwaddr = nm_device_get_hw_address (NM_DEVICE (device)); if (hwaddr) { if (!nm_utils_hwaddr_valid (hwaddr, INFINIBAND_ALEN)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, @@ -113,12 +113,6 @@ get_setting_type (NMDevice *device) return NM_TYPE_SETTING_INFINIBAND; } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_infiniband_get_hw_address (NM_DEVICE_INFINIBAND (device)); -} - /*****************************************************************************/ static void @@ -127,16 +121,6 @@ nm_device_infiniband_init (NMDeviceInfiniband *device) } static void -finalize (GObject *object) -{ - NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (object); - - g_free (priv->hw_address); - - G_OBJECT_CLASS (nm_device_infiniband_parent_class)->finalize (object); -} - -static void get_property (GObject *object, guint prop_id, GValue *value, @@ -145,9 +129,6 @@ get_property (GObject *object, NMDeviceInfiniband *device = NM_DEVICE_INFINIBAND (object); switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_infiniband_get_hw_address (device)); - break; case PROP_CARRIER: g_value_set_boolean (value, nm_device_infiniband_get_carrier (device)); break; @@ -162,8 +143,8 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_infiniband = NML_DBUS_META nm_device_infiniband_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( - NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceInfiniband, _priv.carrier ), - NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceInfiniband, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceInfiniband, _priv.carrier ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), ), ); @@ -174,22 +155,9 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *ib_class) NMDeviceClass *device_class = NM_DEVICE_CLASS (ib_class); object_class->get_property = get_property; - object_class->finalize = finalize; device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; - device_class->get_hw_address = get_hw_address; - - /** - * NMDeviceInfiniband:hw-address: - * - * The hardware (MAC) address of the device. - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_INFINIBAND_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); /** * NMDeviceInfiniband:carrier: diff --git a/libnm/nm-device-infiniband.h b/libnm/nm-device-infiniband.h index 06a2c257..c6b62377 100644 --- a/libnm/nm-device-infiniband.h +++ b/libnm/nm-device-infiniband.h @@ -31,7 +31,9 @@ typedef struct _NMDeviceInfinibandClass NMDeviceInfinibandClass; GType nm_device_infiniband_get_type (void); +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char * nm_device_infiniband_get_hw_address (NMDeviceInfiniband *device); + gboolean nm_device_infiniband_get_carrier (NMDeviceInfiniband *device); G_END_DECLS diff --git a/libnm/nm-device-macsec.c b/libnm/nm-device-macsec.c index 194261f0..d8352f9c 100644 --- a/libnm/nm-device-macsec.c +++ b/libnm/nm-device-macsec.c @@ -15,7 +15,6 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( PROP_PARENT, - PROP_HW_ADDRESS, PROP_SCI, PROP_CIPHER_SUITE, PROP_ICV_LENGTH, @@ -32,7 +31,6 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( typedef struct { NMLDBusPropertyO parent; - char *hw_address; char *validation; guint64 sci; guint64 cipher_suite; @@ -88,13 +86,15 @@ nm_device_macsec_get_parent (NMDeviceMacsec *device) * device, and must not be modified. * * Since: 1.6 + * + * Deprecated: 1.24: Use nm_device_get_hw_address() instead. **/ const char * nm_device_macsec_get_hw_address (NMDeviceMacsec *device) { g_return_val_if_fail (NM_IS_DEVICE_MACSEC (device), NULL); - return NM_DEVICE_MACSEC_GET_PRIVATE (device)->hw_address; + return nm_device_get_hw_address (NM_DEVICE (device)); } /** @@ -318,12 +318,6 @@ nm_device_macsec_get_replay_protect (NMDeviceMacsec *device) return NM_DEVICE_MACSEC_GET_PRIVATE (device)->replay_protect; } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_macsec_get_hw_address (NM_DEVICE_MACSEC (device)); -} - /***********************************************************/ static void @@ -337,7 +331,6 @@ finalize (GObject *object) NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (object); g_free (priv->validation); - g_free (priv->hw_address); G_OBJECT_CLASS (nm_device_macsec_parent_class)->finalize (object); } @@ -354,9 +347,6 @@ get_property (GObject *object, case PROP_PARENT: g_value_set_object (value, nm_device_macsec_get_parent (device)); break; - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_macsec_get_hw_address (device)); - break; case PROP_SCI: g_value_set_uint64 (value, nm_device_macsec_get_sci (device)); break; @@ -425,7 +415,6 @@ nm_device_macsec_class_init (NMDeviceMacsecClass *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; @@ -434,8 +423,6 @@ nm_device_macsec_class_init (NMDeviceMacsecClass *klass) _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_1 (nm_object_class, NMDeviceMacsecPrivate, parent); - device_class->get_hw_address = get_hw_address; - /** * NMDeviceMacsec:parent: * @@ -450,19 +437,6 @@ nm_device_macsec_class_init (NMDeviceMacsecClass *klass) G_PARAM_STATIC_STRINGS); /** - * NMDeviceMacsec:hw-address: - * - * The hardware (MAC) address of the device. - * - * Since: 1.6 - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_MACSEC_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - /** * NMDeviceMacsec:sci: * * The Secure Channel Identifier in use. diff --git a/libnm/nm-device-macsec.h b/libnm/nm-device-macsec.h index acf6269b..3f9a40d4 100644 --- a/libnm/nm-device-macsec.h +++ b/libnm/nm-device-macsec.h @@ -46,8 +46,11 @@ GType nm_device_macsec_get_type (void); NM_AVAILABLE_IN_1_6 NMDevice * nm_device_macsec_get_parent (NMDeviceMacsec *device); + NM_AVAILABLE_IN_1_6 +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char * nm_device_macsec_get_hw_address (NMDeviceMacsec *device); + NM_AVAILABLE_IN_1_6 guint64 nm_device_macsec_get_sci (NMDeviceMacsec *device); NM_AVAILABLE_IN_1_6 diff --git a/libnm/nm-device-macvlan.c b/libnm/nm-device-macvlan.c index e703cb5c..83dc0e25 100644 --- a/libnm/nm-device-macvlan.c +++ b/libnm/nm-device-macvlan.c @@ -20,7 +20,6 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( PROP_MODE, PROP_NO_PROMISC, PROP_TAP, - PROP_HW_ADDRESS, ); typedef struct { @@ -128,13 +127,15 @@ nm_device_macvlan_get_tap (NMDeviceMacvlan *device) * Since: 1.2 * * This property is not implemented yet, and the function always return NULL. + * + * Deprecated: 1.24: Use nm_device_get_hw_address() instead. **/ const char * nm_device_macvlan_get_hw_address (NMDeviceMacvlan *device) { g_return_val_if_fail (NM_IS_DEVICE_MACVLAN (device), NULL); - return NULL; + return nm_device_get_hw_address (NM_DEVICE (device)); } static gboolean @@ -161,12 +162,6 @@ connection_compatible (NMDevice *device, NMConnection *connection, GError **erro return TRUE; } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_macvlan_get_hw_address (NM_DEVICE_MACVLAN (device)); -} - static GType get_setting_type (NMDevice *device) { @@ -211,9 +206,6 @@ get_property (GObject *object, case PROP_TAP: g_value_set_boolean (value, nm_device_macvlan_get_tap (device)); break; - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_macvlan_get_hw_address (device)); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -248,7 +240,6 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; - device_class->get_hw_address = get_hw_address; /** * NMDeviceMacvlan:parent: @@ -302,20 +293,5 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - /** - * NMDeviceMacvlan:hw-address: - * - * The hardware (MAC) address of the device. - * - * Since: 1.2 - * - * This property is not implemented yet, and the function always return NULL. - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_MACVLAN_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_macvlan); } diff --git a/libnm/nm-device-macvlan.h b/libnm/nm-device-macvlan.h index c991f8bd..4467cc3f 100644 --- a/libnm/nm-device-macvlan.h +++ b/libnm/nm-device-macvlan.h @@ -43,7 +43,9 @@ NM_AVAILABLE_IN_1_2 gboolean nm_device_macvlan_get_no_promisc (NMDeviceMacvlan *device); NM_AVAILABLE_IN_1_2 gboolean nm_device_macvlan_get_tap (NMDeviceMacvlan *device); + NM_AVAILABLE_IN_1_2 +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char * nm_device_macvlan_get_hw_address (NMDeviceMacvlan *device); G_END_DECLS diff --git a/libnm/nm-device-olpc-mesh.c b/libnm/nm-device-olpc-mesh.c index 1ad320bf..d6fa03f1 100644 --- a/libnm/nm-device-olpc-mesh.c +++ b/libnm/nm-device-olpc-mesh.c @@ -15,14 +15,12 @@ /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_HW_ADDRESS, PROP_COMPANION, PROP_ACTIVE_CHANNEL, ); typedef struct { NMLDBusPropertyO companion; - char *hw_address; guint32 active_channel; } NMDeviceOlpcMeshPrivate; @@ -49,13 +47,15 @@ G_DEFINE_TYPE (NMDeviceOlpcMesh, nm_device_olpc_mesh, NM_TYPE_DEVICE) * * Returns: the 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_olpc_mesh_get_hw_address (NMDeviceOlpcMesh *device) { g_return_val_if_fail (NM_IS_DEVICE_OLPC_MESH (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->hw_address); + return nm_device_get_hw_address (NM_DEVICE (device)); } /** @@ -90,12 +90,6 @@ nm_device_olpc_mesh_get_active_channel (NMDeviceOlpcMesh *device) return NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->active_channel; } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_olpc_mesh_get_hw_address (NM_DEVICE_OLPC_MESH (device)); -} - static gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { @@ -125,16 +119,6 @@ nm_device_olpc_mesh_init (NMDeviceOlpcMesh *device) } static void -finalize (GObject *object) -{ - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object); - - g_free (priv->hw_address); - - G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->finalize (object); -} - -static void get_property (GObject *object, guint prop_id, GValue *value, @@ -143,9 +127,6 @@ get_property (GObject *object, NMDeviceOlpcMesh *device = NM_DEVICE_OLPC_MESH (object); switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_olpc_mesh_get_hw_address (device)); - break; case PROP_COMPANION: g_value_set_object (value, nm_device_olpc_mesh_get_companion (device)); break; @@ -163,9 +144,9 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_olpcmesh = NML_DBUS_META_I nm_device_olpc_mesh_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( - NML_DBUS_META_PROPERTY_INIT_U ("ActiveChannel", PROP_ACTIVE_CHANNEL, NMDeviceOlpcMesh, _priv.active_channel ), - NML_DBUS_META_PROPERTY_INIT_O_PROP ("Companion", PROP_COMPANION, NMDeviceOlpcMesh, _priv.companion, nm_device_wifi_get_type ), - NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceOlpcMesh, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_U ("ActiveChannel", PROP_ACTIVE_CHANNEL, NMDeviceOlpcMesh, _priv.active_channel ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Companion", PROP_COMPANION, NMDeviceOlpcMesh, _priv.companion, nm_device_wifi_get_type ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), ), ); @@ -177,7 +158,6 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *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, NMDeviceOlpcMesh); @@ -185,18 +165,6 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass) device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; - device_class->get_hw_address = get_hw_address; - - /** - * NMDeviceOlpcMesh:hw-address: - * - * The hardware (MAC) address of the device. - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_OLPC_MESH_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); /** * NMDeviceOlpcMesh:companion: diff --git a/libnm/nm-device-olpc-mesh.h b/libnm/nm-device-olpc-mesh.h index 2794e6ee..d3157a32 100644 --- a/libnm/nm-device-olpc-mesh.h +++ b/libnm/nm-device-olpc-mesh.h @@ -32,7 +32,9 @@ typedef struct _NMDeviceOlpcMeshClass NMDeviceOlpcMeshClass; GType nm_device_olpc_mesh_get_type (void); +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char *nm_device_olpc_mesh_get_hw_address (NMDeviceOlpcMesh *device); + NMDeviceWifi *nm_device_olpc_mesh_get_companion (NMDeviceOlpcMesh *device); guint32 nm_device_olpc_mesh_get_active_channel (NMDeviceOlpcMesh *device); diff --git a/libnm/nm-device-team.c b/libnm/nm-device-team.c index a1c04c18..5e97a7df 100644 --- a/libnm/nm-device-team.c +++ b/libnm/nm-device-team.c @@ -16,7 +16,6 @@ /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_HW_ADDRESS, PROP_CARRIER, PROP_SLAVES, PROP_CONFIG, @@ -24,7 +23,6 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( typedef struct { NMLDBusPropertyAO slaves; - char *hw_address; char *config; bool carrier; } NMDeviceTeamPrivate; @@ -52,13 +50,15 @@ G_DEFINE_TYPE (NMDeviceTeam, nm_device_team, NM_TYPE_DEVICE) * * Returns: the 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_team_get_hw_address (NMDeviceTeam *device) { g_return_val_if_fail (NM_IS_DEVICE_TEAM (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_TEAM_GET_PRIVATE (device)->hw_address); + return nm_device_get_hw_address (NM_DEVICE (device)); } /** @@ -114,12 +114,6 @@ nm_device_team_get_config (NMDeviceTeam *device) return _nml_coerce_property_str_not_empty (NM_DEVICE_TEAM_GET_PRIVATE (device)->config); } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_team_get_hw_address (NM_DEVICE_TEAM (device)); -} - static gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { @@ -155,7 +149,6 @@ finalize (GObject *object) { NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (object); - g_free (priv->hw_address); g_free (priv->config); G_OBJECT_CLASS (nm_device_team_parent_class)->finalize (object); @@ -170,9 +163,6 @@ get_property (GObject *object, NMDeviceTeam *device = NM_DEVICE_TEAM (object); switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_team_get_hw_address (device)); - break; case PROP_CARRIER: g_value_set_boolean (value, nm_device_team_get_carrier (device)); break; @@ -193,10 +183,10 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_team = NML_DBUS_META_IFACE nm_device_team_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( - NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceTeam, _priv.carrier ), - NML_DBUS_META_PROPERTY_INIT_S ("Config", PROP_CONFIG, NMDeviceTeam, _priv.config ), - NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceTeam, _priv.hw_address ), - NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Slaves", PROP_SLAVES, NMDeviceTeam, _priv.slaves, nm_device_get_type ), + NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceTeam, _priv.carrier ), + NML_DBUS_META_PROPERTY_INIT_S ("Config", PROP_CONFIG, NMDeviceTeam, _priv.config ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Slaves", PROP_SLAVES, NMDeviceTeam, _priv.slaves, nm_device_get_type ), ), ); @@ -216,18 +206,6 @@ nm_device_team_class_init (NMDeviceTeamClass *klass) device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; - device_class->get_hw_address = get_hw_address; - - /** - * NMDeviceTeam:hw-address: - * - * The hardware (MAC) address of the device. - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_TEAM_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); /** * NMDeviceTeam:carrier: diff --git a/libnm/nm-device-team.h b/libnm/nm-device-team.h index 8bc0d2cd..ad4ea947 100644 --- a/libnm/nm-device-team.h +++ b/libnm/nm-device-team.h @@ -33,7 +33,9 @@ typedef struct _NMDeviceTeamClass NMDeviceTeamClass; GType nm_device_team_get_type (void); +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char *nm_device_team_get_hw_address (NMDeviceTeam *device); + gboolean nm_device_team_get_carrier (NMDeviceTeam *device); const GPtrArray *nm_device_team_get_slaves (NMDeviceTeam *device); NM_AVAILABLE_IN_1_4 diff --git a/libnm/nm-device-tun.c b/libnm/nm-device-tun.c index cc84774b..26e4a318 100644 --- a/libnm/nm-device-tun.c +++ b/libnm/nm-device-tun.c @@ -17,7 +17,6 @@ /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_HW_ADDRESS, PROP_MODE, PROP_OWNER, PROP_GROUP, @@ -27,7 +26,6 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - char *hw_address; char *mode; gint64 owner; gint64 group; @@ -61,13 +59,15 @@ G_DEFINE_TYPE (NMDeviceTun, nm_device_tun, NM_TYPE_DEVICE) * device, and must not be modified. * * Since: 1.2 + * + * Deprecated: 1.24: Use nm_device_get_hw_address() instead. **/ const char * nm_device_tun_get_hw_address (NMDeviceTun *device) { g_return_val_if_fail (NM_IS_DEVICE_TUN (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_TUN_GET_PRIVATE (device)->hw_address); + return nm_device_get_hw_address (NM_DEVICE (device)); } /** @@ -221,12 +221,6 @@ get_setting_type (NMDevice *device) return NM_TYPE_SETTING_TUN; } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_tun_get_hw_address (NM_DEVICE_TUN (device)); -} - /*****************************************************************************/ static void @@ -240,7 +234,6 @@ finalize (GObject *object) NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (object); g_free (priv->mode); - g_free (priv->hw_address); G_OBJECT_CLASS (nm_device_tun_parent_class)->finalize (object); } @@ -254,9 +247,6 @@ get_property (GObject *object, NMDeviceTun *device = NM_DEVICE_TUN (object); switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_tun_get_hw_address (device)); - break; case PROP_MODE: g_value_set_string (value, nm_device_tun_get_mode (device)); break; @@ -287,13 +277,13 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_tun = NML_DBUS_META_IFACE_ nm_device_tun_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( - NML_DBUS_META_PROPERTY_INIT_X ("Group", PROP_GROUP, NMDeviceTun, _priv.group ), - NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceTun, _priv.hw_address ), - NML_DBUS_META_PROPERTY_INIT_S ("Mode", PROP_MODE, NMDeviceTun, _priv.mode ), - NML_DBUS_META_PROPERTY_INIT_B ("MultiQueue", PROP_MULTI_QUEUE, NMDeviceTun, _priv.multi_queue ), - NML_DBUS_META_PROPERTY_INIT_B ("NoPi", PROP_NO_PI, NMDeviceTun, _priv.no_pi ), - NML_DBUS_META_PROPERTY_INIT_X ("Owner", PROP_OWNER, NMDeviceTun, _priv.owner ), - NML_DBUS_META_PROPERTY_INIT_B ("VnetHdr", PROP_VNET_HDR, NMDeviceTun, _priv.vnet_hdr ), + NML_DBUS_META_PROPERTY_INIT_X ("Group", PROP_GROUP, NMDeviceTun, _priv.group ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), + NML_DBUS_META_PROPERTY_INIT_S ("Mode", PROP_MODE, NMDeviceTun, _priv.mode ), + NML_DBUS_META_PROPERTY_INIT_B ("MultiQueue", PROP_MULTI_QUEUE, NMDeviceTun, _priv.multi_queue ), + NML_DBUS_META_PROPERTY_INIT_B ("NoPi", PROP_NO_PI, NMDeviceTun, _priv.no_pi ), + NML_DBUS_META_PROPERTY_INIT_X ("Owner", PROP_OWNER, NMDeviceTun, _priv.owner ), + NML_DBUS_META_PROPERTY_INIT_B ("VnetHdr", PROP_VNET_HDR, NMDeviceTun, _priv.vnet_hdr ), ), ); @@ -308,20 +298,6 @@ nm_device_tun_class_init (NMDeviceTunClass *gre_class) device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; - device_class->get_hw_address = get_hw_address; - - /** - * NMDeviceTun:hw-address: - * - * The hardware (MAC) address of the device. - * - * Since: 1.2 - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_TUN_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); /** * NMDeviceTun:mode: diff --git a/libnm/nm-device-tun.h b/libnm/nm-device-tun.h index bcb2cbb3..8d95342e 100644 --- a/libnm/nm-device-tun.h +++ b/libnm/nm-device-tun.h @@ -38,7 +38,9 @@ NM_AVAILABLE_IN_1_2 GType nm_device_tun_get_type (void); NM_AVAILABLE_IN_1_2 +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char * nm_device_tun_get_hw_address (NMDeviceTun *device); + NM_AVAILABLE_IN_1_2 const char * nm_device_tun_get_mode (NMDeviceTun *device); NM_AVAILABLE_IN_1_2 diff --git a/libnm/nm-device-vlan.c b/libnm/nm-device-vlan.c index ee57d0f4..fdc21936 100644 --- a/libnm/nm-device-vlan.c +++ b/libnm/nm-device-vlan.c @@ -16,7 +16,6 @@ /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_HW_ADDRESS, PROP_CARRIER, PROP_PARENT, PROP_VLAN_ID, @@ -24,7 +23,6 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( typedef struct { NMLDBusPropertyO parent; - char *hw_address; guint32 vlan_id; bool carrier; } NMDeviceVlanPrivate; @@ -52,13 +50,15 @@ G_DEFINE_TYPE (NMDeviceVlan, nm_device_vlan, NM_TYPE_DEVICE) * * Returns: the 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_vlan_get_hw_address (NMDeviceVlan *device) { g_return_val_if_fail (NM_IS_DEVICE_VLAN (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_VLAN_GET_PRIVATE (device)->hw_address); + return nm_device_get_hw_address (NM_DEVICE (device)); } /** @@ -108,10 +108,10 @@ nm_device_vlan_get_vlan_id (NMDeviceVlan *device) static gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { - NMDeviceVlanPrivate *priv; NMSettingVlan *s_vlan; NMSettingWired *s_wired; const char *setting_hwaddr; + const char *hw_address; if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->connection_compatible (device, connection, error)) return FALSE; @@ -135,10 +135,11 @@ connection_compatible (NMDevice *device, NMConnection *connection, GError **erro else setting_hwaddr = NULL; if (setting_hwaddr) { - priv = NM_DEVICE_VLAN_GET_PRIVATE (device); - if ( !priv->hw_address + hw_address = nm_device_get_hw_address (NM_DEVICE (device)); + + if ( !hw_address || !nm_utils_hwaddr_matches (setting_hwaddr, -1, - priv->hw_address, -1)) { + hw_address, -1)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, _("The hardware address of the device and the connection didn't match.")); } @@ -153,12 +154,6 @@ get_setting_type (NMDevice *device) return NM_TYPE_SETTING_VLAN; } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_vlan_get_hw_address (NM_DEVICE_VLAN (device)); -} - /*****************************************************************************/ static void @@ -167,16 +162,6 @@ nm_device_vlan_init (NMDeviceVlan *device) } static void -finalize (GObject *object) -{ - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object); - - g_free (priv->hw_address); - - G_OBJECT_CLASS (nm_device_vlan_parent_class)->finalize (object); -} - -static void get_property (GObject *object, guint prop_id, GValue *value, @@ -185,9 +170,6 @@ get_property (GObject *object, NMDeviceVlan *device = NM_DEVICE_VLAN (object); switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_vlan_get_hw_address (device)); - break; case PROP_CARRIER: g_value_set_boolean (value, nm_device_vlan_get_carrier (device)); break; @@ -208,10 +190,10 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_vlan = NML_DBUS_META_IFACE nm_device_vlan_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( - NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceVlan, _priv.carrier ), - NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceVlan, _priv.hw_address ), - NML_DBUS_META_PROPERTY_INIT_O_PROP ("Parent", PROP_PARENT, NMDeviceVlan, _priv.parent, nm_device_get_type ), - NML_DBUS_META_PROPERTY_INIT_U ("VlanId", PROP_VLAN_ID, NMDeviceVlan, _priv.vlan_id ), + NML_DBUS_META_PROPERTY_INIT_B ("Carrier", PROP_CARRIER, NMDeviceVlan, _priv.carrier ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Parent", PROP_PARENT, NMDeviceVlan, _priv.parent, nm_device_get_type ), + NML_DBUS_META_PROPERTY_INIT_U ("VlanId", PROP_VLAN_ID, NMDeviceVlan, _priv.vlan_id ), ), ); @@ -223,7 +205,6 @@ nm_device_vlan_class_init (NMDeviceVlanClass *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, NMDeviceVlan); @@ -231,18 +212,6 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass) device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; - device_class->get_hw_address = get_hw_address; - - /** - * NMDeviceVlan:hw-address: - * - * The hardware (MAC) address of the device. - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_VLAN_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); /** * NMDeviceVlan:carrier: diff --git a/libnm/nm-device-vlan.h b/libnm/nm-device-vlan.h index 7a412cb0..104a1e82 100644 --- a/libnm/nm-device-vlan.h +++ b/libnm/nm-device-vlan.h @@ -33,7 +33,9 @@ typedef struct _NMDeviceVlanClass NMDeviceVlanClass; GType nm_device_vlan_get_type (void); +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char * nm_device_vlan_get_hw_address (NMDeviceVlan *device); + gboolean nm_device_vlan_get_carrier (NMDeviceVlan *device); NMDevice * nm_device_vlan_get_parent (NMDeviceVlan *device); guint nm_device_vlan_get_vlan_id (NMDeviceVlan *device); diff --git a/libnm/nm-device-vrf.c b/libnm/nm-device-vrf.c new file mode 100644 index 00000000..2036e16f --- /dev/null +++ b/libnm/nm-device-vrf.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: LGPL-2.1+ + +#include "nm-default.h" + +#include "nm-device-vrf.h" + +#include "nm-setting-connection.h" +#include "nm-setting-vrf.h" +#include "nm-utils.h" +#include "nm-object-private.h" + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE ( + PROP_TABLE, +); + +typedef struct { + guint32 table; +} NMDeviceVrfPrivate; + +struct _NMDeviceVrf { + NMDevice parent; + NMDeviceVrfPrivate _priv; +}; + +struct _NMDeviceVrfClass { + NMDeviceClass parent; +}; + +G_DEFINE_TYPE (NMDeviceVrf, nm_device_vrf, NM_TYPE_DEVICE) + +#define NM_DEVICE_VRF_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDeviceVrf, NM_IS_DEVICE_VRF, NMObject, NMDevice) + +/*****************************************************************************/ + +/** + * nm_device_vrf_get_table: + * @device: a #NMDeviceVrf + * + * Returns: the device's VRF routing table. + * + * Since: 1.24 + **/ +guint32 +nm_device_vrf_get_table (NMDeviceVrf *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VRF (device), 0); + + return NM_DEVICE_VRF_GET_PRIVATE (device)->table; +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + NMSettingVrf *s_vrf; + + if (!NM_DEVICE_CLASS (nm_device_vrf_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_VRF_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not a VRF connection.")); + return FALSE; + } + + s_vrf = (NMSettingVrf *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VRF); + if (nm_setting_vrf_get_table (s_vrf) != nm_device_vrf_get_table (NM_DEVICE_VRF (device))) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The VRF table of the device and the connection didn't match.")); + return FALSE; + } + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_VRF; +} + +/*****************************************************************************/ + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceVrf *device = NM_DEVICE_VRF (object); + + switch (prop_id) { + case PROP_TABLE: + g_value_set_uint (value, nm_device_vrf_get_table (device)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_vrf_init (NMDeviceVrf *device) +{ +} + +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_vrf = NML_DBUS_META_IFACE_INIT_PROP ( + NM_DBUS_INTERFACE_DEVICE_VRF, + nm_device_vrf_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, + NML_DBUS_META_IFACE_DBUS_PROPERTIES ( + NML_DBUS_META_PROPERTY_INIT_U ("Table", PROP_TABLE, NMDeviceVrf, _priv.table), + ), +); + +static void +nm_device_vrf_class_init (NMDeviceVrfClass *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; + + _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT (nm_object_class, NMDeviceVrf); + + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + + /** + * NMDeviceVrf:table: + * + * The device's VRF table. + * + * Since: 1.24 + **/ + obj_properties[PROP_TABLE] = + g_param_spec_uint (NM_DEVICE_VRF_TABLE, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_vrf); +} diff --git a/libnm/nm-device-vrf.h b/libnm/nm-device-vrf.h new file mode 100644 index 00000000..bf7499ca --- /dev/null +++ b/libnm/nm-device-vrf.h @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: LGPL-2.1+ + +#ifndef __NM_DEVICE_VRF_H__ +#define __NM_DEVICE_VRF_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_VRF (nm_device_vrf_get_type ()) +#define NM_DEVICE_VRF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_VRF, NMDeviceVrf)) +#define NM_DEVICE_VRF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_VRF, NMDeviceVrfClass)) +#define NM_IS_DEVICE_VRF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_VRF)) +#define NM_IS_DEVICE_VRF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_VRF)) +#define NM_DEVICE_VRF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_VRF, NMDeviceVrfClass)) + +#define NM_DEVICE_VRF_TABLE "table" + +/** + * NMDeviceVrf: + */ +typedef struct _NMDeviceVrfClass NMDeviceVrfClass; + +NM_AVAILABLE_IN_1_24 +GType nm_device_vrf_get_type (void); +NM_AVAILABLE_IN_1_24 +guint32 nm_device_vrf_get_table (NMDeviceVrf *device); + +G_END_DECLS + +#endif /* __NM_DEVICE_VRF_H__ */ diff --git a/libnm/nm-device-vxlan.c b/libnm/nm-device-vxlan.c index 4397977c..c048a980 100644 --- a/libnm/nm-device-vxlan.c +++ b/libnm/nm-device-vxlan.c @@ -15,7 +15,6 @@ /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_HW_ADDRESS, PROP_CARRIER, PROP_PARENT, PROP_ID, @@ -37,7 +36,6 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( typedef struct { NMLDBusPropertyO parent; - char *hw_address; char *group; char *local; guint32 id; @@ -80,13 +78,15 @@ G_DEFINE_TYPE (NMDeviceVxlan, nm_device_vxlan, NM_TYPE_DEVICE) * device, and must not be modified. * * Since: 1.2 + * + * Deprecated: 1.24: Use nm_device_get_hw_address() instead. **/ const char * nm_device_vxlan_get_hw_address (NMDeviceVxlan *device) { g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_VXLAN_GET_PRIVATE (device)->hw_address); + return nm_device_get_hw_address (NM_DEVICE (device)); } /** @@ -398,12 +398,6 @@ get_setting_type (NMDevice *device) return NM_TYPE_SETTING_VXLAN; } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_vxlan_get_hw_address (NM_DEVICE_VXLAN (device)); -} - /*****************************************************************************/ static void @@ -416,7 +410,6 @@ finalize (GObject *object) { NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (object); - g_free (priv->hw_address); g_free (priv->group); g_free (priv->local); @@ -432,9 +425,6 @@ get_property (GObject *object, NMDeviceVxlan *device = NM_DEVICE_VXLAN (object); switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_vxlan_get_hw_address (device)); - break; case PROP_CARRIER: g_value_set_boolean (value, nm_device_vxlan_get_carrier (device)); break; @@ -497,23 +487,23 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_vxlan = NML_DBUS_META_IFAC nm_device_vxlan_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( - NML_DBUS_META_PROPERTY_INIT_U ("Ageing", PROP_AGEING, NMDeviceVxlan, _priv.ageing ), - NML_DBUS_META_PROPERTY_INIT_Q ("DstPort", PROP_DST_PORT, NMDeviceVxlan, _priv.dst_port ), - NML_DBUS_META_PROPERTY_INIT_S ("Group", PROP_GROUP, NMDeviceVxlan, _priv.group ), - NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceVxlan, _priv.hw_address ), - NML_DBUS_META_PROPERTY_INIT_U ("Id", PROP_ID, NMDeviceVxlan, _priv.id ), - NML_DBUS_META_PROPERTY_INIT_B ("L2miss", PROP_L2MISS, NMDeviceVxlan, _priv.l2miss ), - NML_DBUS_META_PROPERTY_INIT_B ("L3miss", PROP_L3MISS, NMDeviceVxlan, _priv.l3miss ), - NML_DBUS_META_PROPERTY_INIT_B ("Learning", PROP_LEARNING, NMDeviceVxlan, _priv.learning ), - NML_DBUS_META_PROPERTY_INIT_U ("Limit", PROP_LIMIT, NMDeviceVxlan, _priv.limit ), - NML_DBUS_META_PROPERTY_INIT_S ("Local", PROP_LOCAL, NMDeviceVxlan, _priv.local ), - NML_DBUS_META_PROPERTY_INIT_O_PROP ("Parent", PROP_PARENT, NMDeviceVxlan, _priv.parent, nm_device_get_type ), - NML_DBUS_META_PROPERTY_INIT_B ("Proxy", PROP_PROXY, NMDeviceVxlan, _priv.proxy ), - NML_DBUS_META_PROPERTY_INIT_B ("Rsc", PROP_RSC, NMDeviceVxlan, _priv.rsc ), - NML_DBUS_META_PROPERTY_INIT_Q ("SrcPortMax", PROP_SRC_PORT_MAX, NMDeviceVxlan, _priv.src_port_max ), - NML_DBUS_META_PROPERTY_INIT_Q ("SrcPortMin", PROP_SRC_PORT_MIN, NMDeviceVxlan, _priv.src_port_min ), - NML_DBUS_META_PROPERTY_INIT_Y ("Tos", PROP_TOS, NMDeviceVxlan, _priv.tos ), - NML_DBUS_META_PROPERTY_INIT_Y ("Ttl", PROP_TTL, NMDeviceVxlan, _priv.ttl ), + NML_DBUS_META_PROPERTY_INIT_U ("Ageing", PROP_AGEING, NMDeviceVxlan, _priv.ageing ), + NML_DBUS_META_PROPERTY_INIT_Q ("DstPort", PROP_DST_PORT, NMDeviceVxlan, _priv.dst_port ), + NML_DBUS_META_PROPERTY_INIT_S ("Group", PROP_GROUP, NMDeviceVxlan, _priv.group ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), + NML_DBUS_META_PROPERTY_INIT_U ("Id", PROP_ID, NMDeviceVxlan, _priv.id ), + NML_DBUS_META_PROPERTY_INIT_B ("L2miss", PROP_L2MISS, NMDeviceVxlan, _priv.l2miss ), + NML_DBUS_META_PROPERTY_INIT_B ("L3miss", PROP_L3MISS, NMDeviceVxlan, _priv.l3miss ), + NML_DBUS_META_PROPERTY_INIT_B ("Learning", PROP_LEARNING, NMDeviceVxlan, _priv.learning ), + NML_DBUS_META_PROPERTY_INIT_U ("Limit", PROP_LIMIT, NMDeviceVxlan, _priv.limit ), + NML_DBUS_META_PROPERTY_INIT_S ("Local", PROP_LOCAL, NMDeviceVxlan, _priv.local ), + NML_DBUS_META_PROPERTY_INIT_O_PROP ("Parent", PROP_PARENT, NMDeviceVxlan, _priv.parent, nm_device_get_type ), + NML_DBUS_META_PROPERTY_INIT_B ("Proxy", PROP_PROXY, NMDeviceVxlan, _priv.proxy ), + NML_DBUS_META_PROPERTY_INIT_B ("Rsc", PROP_RSC, NMDeviceVxlan, _priv.rsc ), + NML_DBUS_META_PROPERTY_INIT_Q ("SrcPortMax", PROP_SRC_PORT_MAX, NMDeviceVxlan, _priv.src_port_max ), + NML_DBUS_META_PROPERTY_INIT_Q ("SrcPortMin", PROP_SRC_PORT_MIN, NMDeviceVxlan, _priv.src_port_min ), + NML_DBUS_META_PROPERTY_INIT_Y ("Tos", PROP_TOS, NMDeviceVxlan, _priv.tos ), + NML_DBUS_META_PROPERTY_INIT_Y ("Ttl", PROP_TTL, NMDeviceVxlan, _priv.ttl ), ), ); @@ -533,20 +523,6 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; - device_class->get_hw_address = get_hw_address; - - /** - * NMDeviceVxlan:hw-address: - * - * The hardware (MAC) address of the device. - * - * Since: 1.2 - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_VXLAN_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); /** * NMDeviceVxlan:carrier: diff --git a/libnm/nm-device-vxlan.h b/libnm/nm-device-vxlan.h index fef2365f..b285bf02 100644 --- a/libnm/nm-device-vxlan.h +++ b/libnm/nm-device-vxlan.h @@ -47,8 +47,11 @@ typedef struct _NMDeviceVxlanClass NMDeviceVxlanClass; NM_AVAILABLE_IN_1_2 GType nm_device_vxlan_get_type (void); + NM_AVAILABLE_IN_1_2 +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char * nm_device_vxlan_get_hw_address (NMDeviceVxlan *device); + NM_AVAILABLE_IN_1_2 gboolean nm_device_vxlan_get_carrier (NMDeviceVxlan *device); NM_AVAILABLE_IN_1_2 diff --git a/libnm/nm-device-wifi-p2p.c b/libnm/nm-device-wifi-p2p.c index aa5089c7..972983d1 100644 --- a/libnm/nm-device-wifi-p2p.c +++ b/libnm/nm-device-wifi-p2p.c @@ -19,7 +19,6 @@ /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_HW_ADDRESS, PROP_PEERS, ); @@ -34,7 +33,6 @@ static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { NMLDBusPropertyAO peers; - char *hw_address; } NMDeviceWifiP2PPrivate; struct _NMDeviceWifiP2P { @@ -62,13 +60,15 @@ G_DEFINE_TYPE (NMDeviceWifiP2P, nm_device_wifi_p2p, NM_TYPE_DEVICE) * device, and must not be modified. * * Since: 1.16 + * + * Deprecated: 1.24: Use nm_device_get_hw_address() instead. **/ const char * nm_device_wifi_p2p_get_hw_address (NMDeviceWifiP2P *device) { g_return_val_if_fail (NM_IS_DEVICE_WIFI_P2P (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_WIFI_P2P_GET_PRIVATE (device)->hw_address); + return nm_device_get_hw_address (NM_DEVICE (device)); } /** @@ -279,12 +279,6 @@ get_setting_type (NMDevice *device) } static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_wifi_p2p_get_hw_address (NM_DEVICE_WIFI_P2P (device)); -} - -static const char * get_type_description (NMDevice *device) { return "wifi-p2p"; @@ -319,9 +313,6 @@ get_property (GObject *object, NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P (object); switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_wifi_p2p_get_hw_address (self)); - break; case PROP_PEERS: g_value_take_boxed (value, _nm_utils_copy_object_array (nm_device_wifi_p2p_get_peers (self))); break; @@ -338,23 +329,13 @@ nm_device_wifi_p2p_init (NMDeviceWifiP2P *device) { } -static void -finalize (GObject *object) -{ - NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (object); - - g_free (priv->hw_address); - - G_OBJECT_CLASS (nm_device_wifi_p2p_parent_class)->finalize (object); -} - const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wifip2p = NML_DBUS_META_IFACE_INIT_PROP ( NM_DBUS_INTERFACE_DEVICE_WIFI_P2P, nm_device_wifi_p2p_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( - NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceWifiP2P, _priv.hw_address ), - NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Peers", PROP_PEERS, NMDeviceWifiP2P, _priv.peers, nm_wifi_p2p_peer_get_type, .notify_changed_ao = _property_ao_notify_changed_peers_cb ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), + NML_DBUS_META_PROPERTY_INIT_AO_PROP ("Peers", PROP_PEERS, NMDeviceWifiP2P, _priv.peers, nm_wifi_p2p_peer_get_type, .notify_changed_ao = _property_ao_notify_changed_peers_cb ), ), ); @@ -366,7 +347,6 @@ nm_device_wifi_p2p_class_init (NMDeviceWifiP2PClass *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, NMDeviceWifiP2P); @@ -374,23 +354,9 @@ nm_device_wifi_p2p_class_init (NMDeviceWifiP2PClass *klass) device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; - device_class->get_hw_address = get_hw_address; device_class->get_type_description = get_type_description; /** - * NMDeviceWifiP2P:hw-address: - * - * The hardware (MAC) address of the device. - * - * Since: 1.16 - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_WIFI_P2P_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - /** * NMDeviceWifiP2P:peers: (type GPtrArray(NMWifiP2PPeer)) * * List of all Wi-Fi P2P peers the device can see. diff --git a/libnm/nm-device-wifi-p2p.h b/libnm/nm-device-wifi-p2p.h index 83127575..5daa0ba1 100644 --- a/libnm/nm-device-wifi-p2p.h +++ b/libnm/nm-device-wifi-p2p.h @@ -36,6 +36,7 @@ NM_AVAILABLE_IN_1_16 GType nm_device_wifi_p2p_get_type (void); NM_AVAILABLE_IN_1_16 +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char * nm_device_wifi_p2p_get_hw_address (NMDeviceWifiP2P *device); NM_AVAILABLE_IN_1_16 diff --git a/libnm/nm-device-wifi.c b/libnm/nm-device-wifi.c index 5d8f742c..5c12b676 100644 --- a/libnm/nm-device-wifi.c +++ b/libnm/nm-device-wifi.c @@ -21,7 +21,6 @@ /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_HW_ADDRESS, PROP_PERM_HW_ADDRESS, PROP_MODE, PROP_BITRATE, @@ -34,7 +33,6 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( typedef struct { NMLDBusPropertyAO access_points; NMLDBusPropertyO active_access_point; - char *hw_address; char *perm_hw_address; gint64 last_scan; guint32 mode; @@ -74,13 +72,15 @@ G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE) * * 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 _nml_coerce_property_str_not_empty (NM_DEVICE_WIFI_GET_PRIVATE (device)->hw_address); + return nm_device_get_hw_address (NM_DEVICE (device)); } /** @@ -266,7 +266,7 @@ nm_device_wifi_get_last_scan (NMDeviceWifi *device) * 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 + * Deprecated: 1.22: Use nm_device_wifi_request_scan_async() or GDBusConnection. **/ gboolean nm_device_wifi_request_scan (NMDeviceWifi *device, @@ -296,7 +296,7 @@ nm_device_wifi_request_scan (NMDeviceWifi *device, * * Since: 1.2 * - * Deprecated: 1.22, use nm_device_wifi_request_scan_options_async() or GDBusConnection + * Deprecated: 1.22: Use nm_device_wifi_request_scan_options_async() or GDBusConnection. **/ gboolean nm_device_wifi_request_scan_options (NMDeviceWifi *device, @@ -515,12 +515,6 @@ get_setting_type (NMDevice *device) return NM_TYPE_SETTING_WIRELESS; } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (device)); -} - /*****************************************************************************/ static void @@ -558,9 +552,6 @@ get_property (GObject *object, NMDeviceWifi *self = NM_DEVICE_WIFI (object); switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_wifi_get_hw_address (self)); - break; case PROP_PERM_HW_ADDRESS: g_value_set_string (value, nm_device_wifi_get_permanent_hw_address (self)); break; @@ -593,7 +584,6 @@ finalize (GObject *object) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object); - g_free (priv->hw_address); g_free (priv->perm_hw_address); G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object); @@ -604,14 +594,14 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wireless = NML_DBUS_META_I 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_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceWifi, _priv.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 ), + 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 ), ), ); @@ -632,18 +622,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; - device_class->get_hw_address = get_hw_address; - - /** - * NMDeviceWifi:hw-address: - * - * The hardware (MAC) address of the device. - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_WIFI_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); /** * NMDeviceWifi:perm-hw-address: diff --git a/libnm/nm-device-wifi.h b/libnm/nm-device-wifi.h index c64641d3..e23577a4 100644 --- a/libnm/nm-device-wifi.h +++ b/libnm/nm-device-wifi.h @@ -38,7 +38,9 @@ typedef struct _NMDeviceWifiClass NMDeviceWifiClass; GType nm_device_wifi_get_type (void); +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char * nm_device_wifi_get_hw_address (NMDeviceWifi *device); + const char * nm_device_wifi_get_permanent_hw_address (NMDeviceWifi *device); NM80211Mode nm_device_wifi_get_mode (NMDeviceWifi *device); guint32 nm_device_wifi_get_bitrate (NMDeviceWifi *device); diff --git a/libnm/nm-device-wimax.h b/libnm/nm-device-wimax.h index 10d2cd18..8956715e 100644 --- a/libnm/nm-device-wimax.h +++ b/libnm/nm-device-wimax.h @@ -34,7 +34,7 @@ G_BEGIN_DECLS /** * NMDeviceWimax: * - * Deprecated: 1.22. WiMAX is no longer supported by NetworkManager since 1.2.0 + * Deprecated: 1.22: WiMAX is no longer supported by NetworkManager since 1.2.0. */ typedef struct _NMDeviceWimaxClass NMDeviceWimaxClass; diff --git a/libnm/nm-device-wpan.c b/libnm/nm-device-wpan.c index 5ddd8af3..9cbf4ae0 100644 --- a/libnm/nm-device-wpan.c +++ b/libnm/nm-device-wpan.c @@ -13,17 +13,8 @@ /*****************************************************************************/ -NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_HW_ADDRESS, -); - -typedef struct { - char *hw_address; -} NMDeviceWpanPrivate; - struct _NMDeviceWpan { NMDevice parent; - NMDeviceWpanPrivate _priv; }; struct _NMDeviceWpanClass { @@ -31,9 +22,6 @@ struct _NMDeviceWpanClass { }; G_DEFINE_TYPE (NMDeviceWpan, nm_device_wpan, NM_TYPE_DEVICE) - -#define NM_DEVICE_WPAN_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDeviceWpan, NM_IS_DEVICE_WPAN, NMObject, NMDevice) - /*****************************************************************************/ /** @@ -44,13 +32,15 @@ G_DEFINE_TYPE (NMDeviceWpan, nm_device_wpan, NM_TYPE_DEVICE) * * Returns: the active 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_wpan_get_hw_address (NMDeviceWpan *device) { g_return_val_if_fail (NM_IS_DEVICE_WPAN (device), NULL); - return _nml_coerce_property_str_not_empty (NM_DEVICE_WPAN_GET_PRIVATE (device)->hw_address); + return nm_device_get_hw_address (NM_DEVICE (device)); } static gboolean @@ -74,27 +64,6 @@ get_setting_type (NMDevice *device) return NM_TYPE_SETTING_WPAN; } -static const char * -get_hw_address (NMDevice *device) -{ - return nm_device_wpan_get_hw_address (NM_DEVICE_WPAN (device)); -} - -/*****************************************************************************/ - -static void -get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, nm_device_wpan_get_hw_address (NM_DEVICE_WPAN (object))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - /*****************************************************************************/ static void @@ -102,48 +71,20 @@ nm_device_wpan_init (NMDeviceWpan *device) { } -static void -finalize (GObject *object) -{ - NMDeviceWpanPrivate *priv = NM_DEVICE_WPAN_GET_PRIVATE (object); - - g_free (priv->hw_address); - - G_OBJECT_CLASS (nm_device_wpan_parent_class)->finalize (object); -} - -const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wpan = NML_DBUS_META_IFACE_INIT_PROP ( +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wpan = NML_DBUS_META_IFACE_INIT ( NM_DBUS_INTERFACE_DEVICE_WPAN, nm_device_wpan_get_type, NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH, NML_DBUS_META_IFACE_DBUS_PROPERTIES ( - NML_DBUS_META_PROPERTY_INIT_S ("HwAddress", PROP_HW_ADDRESS, NMDeviceWpan, _priv.hw_address ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), ), ); static void nm_device_wpan_class_init (NMDeviceWpanClass *wpan_class) { - GObjectClass *object_class = G_OBJECT_CLASS (wpan_class); NMDeviceClass *device_class = NM_DEVICE_CLASS (wpan_class); - object_class->get_property = get_property; - object_class->finalize = finalize; - device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; - device_class->get_hw_address = get_hw_address; - - /** - * NMDeviceWpan:hw-address: - * - * The active hardware (MAC) address of the device. - **/ - obj_properties[PROP_HW_ADDRESS] = - g_param_spec_string (NM_DEVICE_WPAN_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device_wpan); } diff --git a/libnm/nm-device-wpan.h b/libnm/nm-device-wpan.h index 43f8b7b3..1ff09794 100644 --- a/libnm/nm-device-wpan.h +++ b/libnm/nm-device-wpan.h @@ -32,6 +32,7 @@ NM_AVAILABLE_IN_1_14 GType nm_device_wpan_get_type (void); NM_AVAILABLE_IN_1_14 +NM_DEPRECATED_IN_1_24_FOR (nm_device_get_hw_address) const char *nm_device_wpan_get_hw_address (NMDeviceWpan *device); G_END_DECLS diff --git a/libnm/nm-device.c b/libnm/nm-device.c index ade67b04..aa8974f6 100644 --- a/libnm/nm-device.c +++ b/libnm/nm-device.c @@ -60,6 +60,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDevice, PROP_IP4_CONNECTIVITY, PROP_IP6_CONNECTIVITY, PROP_INTERFACE_FLAGS, + PROP_HW_ADDRESS, ); enum { @@ -85,6 +86,7 @@ typedef struct _NMDevicePrivate { GPtrArray *lldp_neighbors; char *driver; char *driver_version; + char *hw_address; char *interface; char *ip_interface; char *firmware_version; @@ -105,6 +107,8 @@ typedef struct _NMDevicePrivate { bool managed; bool real; + bool hw_address_is_new:1; + guint32 old_state; struct udev *udev; @@ -158,7 +162,7 @@ _notify_event_state_changed (NMClient *client, gs_unref_object NMDevice *self = notify_event->user_data; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NML_NMCLIENT_LOG_T (_nm_object_get_client (self), + NML_NMCLIENT_LOG_T (client, "[%s] emit Device's StateChanged signal %u -> %u, reason: %u", _nm_object_get_path (self), (guint) priv->old_state, @@ -296,6 +300,7 @@ coerce_type (NMDeviceType type) case NM_DEVICE_TYPE_6LOWPAN: case NM_DEVICE_TYPE_WIREGUARD: case NM_DEVICE_TYPE_WIFI_P2P: + case NM_DEVICE_TYPE_VRF: return type; } return NM_DEVICE_TYPE_UNKNOWN; @@ -324,7 +329,7 @@ finalize (GObject *object) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object); - g_clear_pointer (&priv->lldp_neighbors, g_ptr_array_unref); + nm_clear_pointer (&priv->lldp_neighbors, g_ptr_array_unref); g_free (priv->interface); g_free (priv->ip_interface); @@ -339,6 +344,7 @@ finalize (GObject *object) g_free (priv->bus_name); g_free (priv->type_description); g_free (priv->physical_port_id); + g_free (priv->hw_address); nm_clear_pointer (&priv->udev, udev_unref); @@ -444,6 +450,9 @@ get_property (GObject *object, case PROP_INTERFACE_FLAGS: g_value_set_uint (value, nm_device_get_interface_flags (device)); break; + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_device_get_hw_address (device)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -500,6 +509,7 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device = NML_DBUS_META_IFACE_INIT NML_DBUS_META_PROPERTY_INIT_S ("DriverVersion", PROP_DRIVER_VERSION, NMDevicePrivate, driver_version ), NML_DBUS_META_PROPERTY_INIT_B ("FirmwareMissing", PROP_FIRMWARE_MISSING, NMDevicePrivate, firmware_missing ), NML_DBUS_META_PROPERTY_INIT_S ("FirmwareVersion", PROP_FIRMWARE_VERSION, NMDevicePrivate, firmware_version ), + NML_DBUS_META_PROPERTY_INIT_FCN ("HwAddress", 0, "s", _nm_device_notify_update_prop_hw_address ), NML_DBUS_META_PROPERTY_INIT_S ("Interface", PROP_INTERFACE, NMDevicePrivate, interface ), NML_DBUS_META_PROPERTY_INIT_U ("InterfaceFlags", PROP_INTERFACE_FLAGS, NMDevicePrivate, interface_flags ), NML_DBUS_META_PROPERTY_INIT_IGNORE ("Ip4Address", "u" ), @@ -902,6 +912,19 @@ nm_device_class_init (NMDeviceClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + /** + * NMDevice:hw-address: + * + * The hardware address of the device. + * + * Since: 1.24 + **/ + obj_properties[PROP_HW_ADDRESS] = + g_param_spec_string (NM_DEVICE_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + _nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm_device); /** @@ -1080,6 +1103,50 @@ nm_device_get_type_description (NMDevice *device) return _nml_coerce_property_str_not_empty (priv->type_description); } + NMLDBusNotifyUpdatePropFlags +_nm_device_notify_update_prop_hw_address (NMClient *client, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value) +{ + NMDevice *self = NM_DEVICE (dbobj->nmobj); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + gboolean is_new = (meta_iface == &_nml_dbus_meta_iface_nm_device); + gboolean changed = FALSE; + + if ( !is_new + && priv->hw_address_is_new) { + /* once the instance is marked to honor the new property, the + * changed signal for the old variant gets ignored. */ + goto out; + } + + if (!value) { + if (nm_clear_g_free (&priv->hw_address)) + changed = TRUE; + goto out; + } + + priv->hw_address_is_new = is_new; + + nm_utils_strdup_reset (&priv->hw_address, + _nml_coerce_property_str_not_empty (g_variant_get_string (value, NULL))); + + /* always emit a changed signal here, even if "priv->hw_address" might be unchanged. + * We want to emit the signal because we received a PropertiesChanged signal on D-Bus, + * even if nothing actually changed. */ + changed = TRUE; + +out: + if (changed) { + _nm_client_queue_notify_object (client, + self, + obj_properties[PROP_HW_ADDRESS]); + } + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NONE; +} + /** * nm_device_get_hw_address: * @device: a #NMDevice @@ -1092,12 +1159,15 @@ nm_device_get_type_description (NMDevice *device) const char * nm_device_get_hw_address (NMDevice *device) { + NMDevicePrivate *priv; + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - if (NM_DEVICE_GET_CLASS (device)->get_hw_address) - return NM_DEVICE_GET_CLASS (device)->get_hw_address (device); + priv = NM_DEVICE_GET_PRIVATE (device); + + nm_assert (!nm_streq0 (priv->hw_address, "")); - return NULL; + return priv->hw_address; } /** @@ -1141,8 +1211,9 @@ nm_device_get_managed (NMDevice *device) * * Since: 1.2 * - * Deprecated: 1.22, use nm_device_set_managed_async() or GDBusConnection - * + * Deprecated: 1.22: Use the async command nm_client_dbus_set_property() on + * nm_object_get_path(), interface %NM_DBUS_INTERFACE_DEVICE to set the + * "Managed" property to a "(b)" boolean value. * This function is deprecated because it calls a synchronous D-Bus method * and modifies the content of the NMClient cache client side. Also, it does * not emit a property changed signal. @@ -1152,8 +1223,6 @@ nm_device_set_managed (NMDevice *device, gboolean managed) { g_return_if_fail (NM_IS_DEVICE (device)); - /* FIXME(libnm-async-api): add nm_device_set_managed_async(). */ - managed = !!managed; NM_DEVICE_GET_PRIVATE (device)->managed = managed; @@ -1189,8 +1258,8 @@ nm_device_get_autoconnect (NMDevice *device) * * Enables or disables automatic activation of the #NMDevice. * - * Deprecated: 1.22, use nm_device_set_autoconnect_async() or GDBusConnection - * + * Deprecated: 1.22: Use the async command nm_client_dbus_set_property() on + * nm_object_get_path(), %NM_DBUS_INTERFACE_DEVICE to set "AutoConnect" property to a "(b)" value. * This function is deprecated because it calls a synchronous D-Bus method * and modifies the content of the NMClient cache client side. **/ @@ -1199,8 +1268,6 @@ nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect) { g_return_if_fail (NM_IS_DEVICE (device)); - /* FIXME(libnm-async-api): add nm_device_set_autoconnect_async(). */ - NM_DEVICE_GET_PRIVATE (device)->autoconnect = autoconnect; _nm_client_set_property_sync_legacy (_nm_object_get_client (device), @@ -1505,6 +1572,8 @@ get_type_name (NMDevice *device) return _("WireGuard"); case NM_DEVICE_TYPE_WIFI_P2P: return _("Wi-Fi P2P"); + case NM_DEVICE_TYPE_VRF: + return _("VRF"); case NM_DEVICE_TYPE_GENERIC: case NM_DEVICE_TYPE_UNUSED1: case NM_DEVICE_TYPE_UNUSED2: @@ -1726,7 +1795,7 @@ ensure_description (NMDevice *device) g_object_get (device, "name", &priv->description, NULL); if (priv->description && priv->description[0]) return; - g_clear_pointer (&priv->description, g_free); + nm_clear_g_free (&priv->description); } if (!priv->short_vendor) { @@ -2077,7 +2146,7 @@ nm_device_is_software (NMDevice *device) * * Since: 1.2 * - * Deprecated: 1.22, use nm_device_reapply_async() or GDBusConnection + * Deprecated: 1.22: Use nm_device_reapply_async() or GDBusConnection. **/ gboolean nm_device_reapply (NMDevice *device, @@ -2217,7 +2286,7 @@ nm_device_reapply_finish (NMDevice *device, * * Since: 1.2 * - * Deprecated: 1.22, use nm_device_get_applied_connection_async() or GDBusConnection + * Deprecated: 1.22: Use nm_device_get_applied_connection_async() or GDBusConnection. **/ NMConnection * nm_device_get_applied_connection (NMDevice *device, @@ -2364,7 +2433,7 @@ nm_device_get_applied_connection_finish (NMDevice *device, * * Returns: %TRUE on success, %FALSE on error, in which case @error will be set. * - * Deprecated: 1.22, use nm_device_disconnect_async() or GDBusConnection + * Deprecated: 1.22: Use nm_device_disconnect_async() or GDBusConnection. **/ gboolean nm_device_disconnect (NMDevice *device, @@ -2456,7 +2525,7 @@ nm_device_disconnect_finish (NMDevice *device, * Returns: %TRUE on success, %FALSE on error, in which case @error * will be set. * - * Deprecated: 1.22, use nm_device_delete_async() or GDBusConnection + * Deprecated: 1.22: Use nm_device_delete_async() or GDBusConnection. **/ gboolean nm_device_delete (NMDevice *device, diff --git a/libnm/nm-device.h b/libnm/nm-device.h index 78130c1b..ca359b08 100644 --- a/libnm/nm-device.h +++ b/libnm/nm-device.h @@ -55,6 +55,7 @@ _NM_DEPRECATED_SYNC_WRITABLE_PROPERTY #define NM_DEVICE_IP4_CONNECTIVITY "ip4-connectivity" #define NM_DEVICE_IP6_CONNECTIVITY "ip6-connectivity" #define NM_DEVICE_INTERFACE_FLAGS "interface-flags" +#define NM_DEVICE_HW_ADDRESS "hw-address" /** * NMDevice: diff --git a/libnm/nm-libnm-utils.c b/libnm/nm-libnm-utils.c index 98c7e857..7b4db11e 100644 --- a/libnm/nm-libnm-utils.c +++ b/libnm/nm-libnm-utils.c @@ -89,12 +89,12 @@ _nml_dbus_log (NMLDBusLogLevel level, break; } - ts = nm_utils_clock_gettime_ns (CLOCK_BOOTTIME); + ts = nm_utils_clock_gettime_nsec (CLOCK_BOOTTIME); g_printerr ("libnm-dbus: %s[%"G_GINT64_FORMAT".%05"G_GINT64_FORMAT"] %s\n", prefix, - ts / NM_UTILS_NS_PER_SECOND, - (ts / (NM_UTILS_NS_PER_SECOND / 10000)) % 10000, + ts / NM_UTILS_NSEC_PER_SEC, + (ts / (NM_UTILS_NSEC_PER_SEC / 10000)) % 10000, msg); } @@ -663,88 +663,6 @@ nm_utils_fixup_product_string (const char *desc) /*****************************************************************************/ -NMClientPermission -nm_permission_to_client (const char *nm) -{ - static const struct { - const char *name; - NMClientPermission perm; - } list[] = { - { NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK }, - { NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK, NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK }, - { NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK }, - { NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS, NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS }, - { NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI }, - { NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX, NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX }, - { NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN, NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN }, - { NM_AUTH_PERMISSION_NETWORK_CONTROL, NM_CLIENT_PERMISSION_NETWORK_CONTROL }, - { NM_AUTH_PERMISSION_RELOAD, NM_CLIENT_PERMISSION_RELOAD }, - { NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS, NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS }, - { NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME }, - { NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN, NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN }, - { NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM, NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM }, - { NM_AUTH_PERMISSION_SLEEP_WAKE, NM_CLIENT_PERMISSION_SLEEP_WAKE }, - { NM_AUTH_PERMISSION_WIFI_SCAN, NM_CLIENT_PERMISSION_WIFI_SCAN }, - { NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN }, - { NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED }, - }; - gssize idx; - -#if NM_MORE_ASSERTS > 10 - { - static gboolean checked = FALSE; - int i, j; - - if (!checked) { - checked = TRUE; - - for (i = 0; i < G_N_ELEMENTS (list); i++) { - - nm_assert (list[i].perm != NM_CLIENT_PERMISSION_NONE); - nm_assert (list[i].name && list[i].name[0]); - if (i > 0) { - if (strcmp (list[i - 1].name, list[i].name) >= 0) { - g_error ("list is not sorted by name: #%d (%s) should be after #%d (%s)", - i - 1, list[i - 1].name, i, list[i].name); - } - } - for (j = i + 1; j < G_N_ELEMENTS (list); j++) { - nm_assert (list[i].perm != list[j].perm); - } - } - } - } -#endif - - if (nm) { - idx = nm_utils_array_find_binary_search (list, - sizeof (list[0]), - G_N_ELEMENTS (list), - &nm, - nm_strcmp_p_with_data, - NULL); - if (idx >= 0) - return list[idx].perm; - } - return NM_CLIENT_PERMISSION_NONE; -} - -NMClientPermissionResult -nm_permission_result_to_client (const char *nm) -{ - if (!nm) - return NM_CLIENT_PERMISSION_RESULT_UNKNOWN; - if (nm_streq (nm, "yes")) - return NM_CLIENT_PERMISSION_RESULT_YES; - if (nm_streq (nm, "no")) - return NM_CLIENT_PERMISSION_RESULT_NO; - if (nm_streq (nm, "auth")) - return NM_CLIENT_PERMISSION_RESULT_AUTH; - return NM_CLIENT_PERMISSION_RESULT_UNKNOWN; -} - -/*****************************************************************************/ - const NMLDBusMetaIface *const _nml_dbus_meta_ifaces[] = { &_nml_dbus_meta_iface_nm, &_nml_dbus_meta_iface_nm_accesspoint, @@ -776,6 +694,7 @@ const NMLDBusMetaIface *const _nml_dbus_meta_ifaces[] = { &_nml_dbus_meta_iface_nm_device_tun, &_nml_dbus_meta_iface_nm_device_veth, &_nml_dbus_meta_iface_nm_device_vlan, + &_nml_dbus_meta_iface_nm_device_vrf, &_nml_dbus_meta_iface_nm_device_vxlan, &_nml_dbus_meta_iface_nm_device_wifip2p, &_nml_dbus_meta_iface_nm_device_wireguard, diff --git a/libnm/nm-libnm-utils.h b/libnm/nm-libnm-utils.h index 9138e08c..64ce81ad 100644 --- a/libnm/nm-libnm-utils.h +++ b/libnm/nm-libnm-utils.h @@ -15,12 +15,6 @@ /*****************************************************************************/ -/* Markers for deprecated sync code in internal API. */ -#define _NM_DEPRECATED_SYNC_METHOD_INTERNAL NM_DEPRECATED_IN_1_22 -#define _NM_DEPRECATED_SYNC_WRITABLE_PROPERTY_INTERNAL NM_DEPRECATED_IN_1_22 - -/*****************************************************************************/ - char *nm_utils_fixup_vendor_string (const char *desc); char *nm_utils_fixup_product_string (const char *desc); @@ -30,13 +24,9 @@ gboolean nm_utils_g_param_spec_is_default (const GParamSpec *pspec); /*****************************************************************************/ -NMClientPermission nm_permission_to_client (const char *nm); - -NMClientPermissionResult nm_permission_result_to_client (const char *nm); - -/*****************************************************************************/ - typedef enum { + _NML_DBUS_LOG_LEVEL_NONE = 0x00, + _NML_DBUS_LOG_LEVEL_INITIALIZED = 0x01, _NML_DBUS_LOG_LEVEL_TRACE = 0x02, @@ -89,6 +79,7 @@ nml_dbus_log_enabled (NMLDBusLogLevel level) int l; nm_assert (NM_IN_SET (level, NML_DBUS_LOG_LEVEL_ANY, + _NML_DBUS_LOG_LEVEL_NONE, NML_DBUS_LOG_LEVEL_TRACE, NML_DBUS_LOG_LEVEL_DEBUG, NML_DBUS_LOG_LEVEL_WARN, @@ -110,7 +101,8 @@ void _nml_dbus_log (NMLDBusLogLevel level, #define NML_DBUS_LOG(level, ...) \ G_STMT_START { \ - G_STATIC_ASSERT ( (level) == NML_DBUS_LOG_LEVEL_TRACE \ + G_STATIC_ASSERT ( (level) == _NML_DBUS_LOG_LEVEL_NONE \ + || (level) == NML_DBUS_LOG_LEVEL_TRACE \ || (level) == NML_DBUS_LOG_LEVEL_DEBUG \ || (level) == NML_DBUS_LOG_LEVEL_WARN \ || (level) == NML_DBUS_LOG_LEVEL_ERROR); \ @@ -125,8 +117,19 @@ void _nml_dbus_log (NMLDBusLogLevel level, #define NML_DBUS_LOG_W(...) NML_DBUS_LOG (NML_DBUS_LOG_LEVEL_WARN, __VA_ARGS__) #define NML_DBUS_LOG_E(...) NML_DBUS_LOG (NML_DBUS_LOG_LEVEL_ERROR, __VA_ARGS__) +/* _NML_NMCLIENT_LOG_LEVEL_COERCE is only for printf debugging. You can disable client logging by + * mapping the requested log level to a different one (or disable it altogether). + * That's useful for example if you are interested in *other* trace logging messages from + * libnm and don't want to get flooded by NMClient's trace messages. */ +#define _NML_NMCLIENT_LOG_LEVEL_COERCE(level) \ + /* for example, change condition below to suppress <trace> messages from NMClient. */ \ + (( TRUE \ + || ((level) != NML_DBUS_LOG_LEVEL_TRACE)) \ + ? (level) \ + : _NML_DBUS_LOG_LEVEL_NONE) + #define NML_NMCLIENT_LOG(level, self, ...) \ - NML_DBUS_LOG ((level), \ + NML_DBUS_LOG (_NML_NMCLIENT_LOG_LEVEL_COERCE (level), \ "nmclient["NM_HASH_OBFUSCATE_PTR_FMT"]: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ NM_HASH_OBFUSCATE_PTR (self) \ _NM_UTILS_MACRO_REST (__VA_ARGS__)) @@ -166,6 +169,45 @@ _nml_coerce_property_strv_not_null (char **strv) /*****************************************************************************/ +GQuark nm_context_busy_watcher_quark (void); + +void nm_context_busy_watcher_integrate_source (GMainContext *outer_context, + GMainContext *inner_context, + GObject *context_busy_watcher); + +/*****************************************************************************/ + +typedef struct { + GCancellable *cancellable; + GSource *cancel_on_idle_source; + gulong cancelled_id; + union { + struct { + GTask *task; + } async; + struct { + GMainLoop *main_loop; + GError **error_location; + } sync; + } data; + bool is_sync:1; +} NMLInitData; + +NMLInitData *nml_init_data_new_sync (GCancellable *cancellable, + GMainLoop *main_loop, + GError **error_location); + +NMLInitData *nml_init_data_new_async (GCancellable *cancellable, + GTask *task_take); + +void nml_init_data_return (NMLInitData *init_data, + GError *error_take); + +void nml_cleanup_context_busy_watcher_on_idle (GObject *context_busy_watcher_take, + GMainContext *context); + +/*****************************************************************************/ + typedef struct _NMLDBusObject NMLDBusObject; typedef struct _NMLDBusObjWatcher NMLDBusObjWatcher; typedef struct _NMLDBusMetaIface NMLDBusMetaIface; @@ -185,6 +227,8 @@ typedef enum { /*****************************************************************************/ +#define NM_CLIENT_INSTANCE_FLAGS_ALL ((NMClientInstanceFlags) 0x1) + typedef struct { GType (*get_o_type_fcn) (void); @@ -494,7 +538,7 @@ struct _NMLDBusMetaIface { #define NML_DBUS_META_IFACE_DBUS_PROPERTIES(...) \ .dbus_properties = ((const NMLDBusMetaProperty []) { __VA_ARGS__ }), \ - .n_dbus_properties = sizeof ((const NMLDBusMetaProperty []) { __VA_ARGS__ }) / sizeof (NMLDBusMetaProperty) \ + .n_dbus_properties = (sizeof ((const NMLDBusMetaProperty []) { __VA_ARGS__ }) / sizeof (NMLDBusMetaProperty)) #define NML_DBUS_META_IFACE_INIT(v_dbus_iface_name, \ v_get_type_fcn, \ @@ -507,11 +551,17 @@ struct _NMLDBusMetaIface { ##__VA_ARGS__ \ } -#define NML_DBUS_META_IFACE_INIT_PROP(...) \ - NML_DBUS_META_IFACE_INIT (__VA_ARGS__ \ - NML_DBUS_META_IFACE_OBJ_PROPERTIES ()) +#define NML_DBUS_META_IFACE_INIT_PROP(v_dbus_iface_name, \ + v_get_type_fcn, \ + v_interface_prio, \ + ...) \ + NML_DBUS_META_IFACE_INIT (v_dbus_iface_name, \ + v_get_type_fcn, \ + v_interface_prio, \ + NML_DBUS_META_IFACE_OBJ_PROPERTIES (), \ + ##__VA_ARGS__) -extern const NMLDBusMetaIface *const _nml_dbus_meta_ifaces[43]; +extern const NMLDBusMetaIface *const _nml_dbus_meta_ifaces[44]; extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm; extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_accesspoint; @@ -541,6 +591,7 @@ extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_team; extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_tun; extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_veth; extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_vlan; +extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_vrf; extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_vxlan; extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wifip2p; extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wired; @@ -765,8 +816,6 @@ struct _NMDeviceClass { const char *(*get_type_description) (NMDevice *device); - const char *(*get_hw_address) (NMDevice *device); - GType (*get_setting_type) (NMDevice *device); }; @@ -961,4 +1010,13 @@ void _nm_vpn_connection_state_changed_commit (NMVpnConnection *self, /*****************************************************************************/ +NMLDBusNotifyUpdatePropFlags +_nm_device_notify_update_prop_hw_address (NMClient *client, + NMLDBusObject *dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value); + +/*****************************************************************************/ + #endif /* __NM_LIBNM_UTILS_H__ */ diff --git a/libnm/nm-object.c b/libnm/nm-object.c index 89dc8bb3..d8c4fb41 100644 --- a/libnm/nm-object.c +++ b/libnm/nm-object.c @@ -78,13 +78,40 @@ _nm_object_get_client (gpointer self) * * Returns: the object's path. This is the internal string used by the * object, and must not be modified. + * + * Note that the D-Bus path of an NMObject never changes, even + * if the instance gets removed from the cache. To find out + * whether the object is still alive/cached, check nm_object_get_client(). **/ const char * nm_object_get_path (NMObject *object) { g_return_val_if_fail (NM_IS_OBJECT (object), NULL); - return NM_OBJECT_GET_PRIVATE (object)->dbobj->dbus_path->str; + return _nm_object_get_path (object); +} + +/** + * nm_object_get_client: + * @object: a #NMObject + * + * Returns the #NMClient instance in which object is cached. + * Also, if the object got removed from the client cached, + * this returns %NULL. So it can be used to check whether the + * object is still alive. + * + * Returns: (transfer none): the #NMClient cache in which the + * object can be found, or %NULL if the object is no longer + * cached. + * + * Since: 1.24 + **/ +NMClient * +nm_object_get_client (NMObject *object) +{ + g_return_val_if_fail (NM_IS_OBJECT (object), NULL); + + return _nm_object_get_client (object); } /*****************************************************************************/ diff --git a/libnm/nm-object.h b/libnm/nm-object.h index 88c34a9e..18b44d8a 100644 --- a/libnm/nm-object.h +++ b/libnm/nm-object.h @@ -31,7 +31,10 @@ typedef struct _NMObjectClass NMObjectClass; GType nm_object_get_type (void); -const char *nm_object_get_path (NMObject *object); +const char *nm_object_get_path (NMObject *object); + +NM_AVAILABLE_IN_1_24 +NMClient *nm_object_get_client (NMObject *object); G_END_DECLS diff --git a/libnm/nm-property-docs.xml b/libnm/nm-property-docs.xml index fe5672a1..eb280215 100644 --- a/libnm/nm-property-docs.xml +++ b/libnm/nm-property-docs.xml @@ -43,7 +43,8 @@ <property name="client-cert" name_upper="CLIENT_CERT" type="byte array" description="Contains the client certificate if used by the EAP method specified in the "eap" property. Certificate data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string "file://" and ending with a terminating NUL byte." /> <property name="client-cert-password" name_upper="CLIENT_CERT_PASSWORD" type="string" description="The password used to access the client certificate stored in "client-cert" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login." /> <property name="client-cert-password-flags" name_upper="CLIENT_CERT_PASSWORD_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "client-cert-password" property." /> - <property name="domain-suffix-match" name_upper="DOMAIN_SUFFIX_MATCH" type="string" description="Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison." /> + <property name="domain-match" name_upper="DOMAIN_MATCH" type="string" description="Constraint for server domain name. If set, this list of FQDNs is used as a match requirement for dNSName element(s) of the certificate presented by the authentication server. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using the same comparison. Multiple valid FQDNs can be passed as a ";" delimited list." /> + <property name="domain-suffix-match" name_upper="DOMAIN_SUFFIX_MATCH" type="string" description="Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison. Since version 1.24, multiple valid FQDNs can be passed as a ";" delimited list." /> <property name="eap" name_upper="EAP" type="array of string" description="The allowed EAP method to be used when authenticating to the network with 802.1x. Valid methods are: "leap", "md5", "tls", "peap", "ttls", "pwd", and "fast". Each method requires different configuration using the properties of this setting; refer to wpa_supplicant documentation for the allowed combinations." /> <property name="identity" name_upper="IDENTITY" type="string" description="Identity string for EAP authentication methods. Often the user's user or login name." /> <property name="optional" name_upper="OPTIONAL" type="boolean" default="FALSE" description="Whether the 802.1X authentication is optional. If TRUE, the activation will continue even after a timeout or an authentication failure. Setting the property to TRUE is currently allowed only for Ethernet connections. If set to FALSE, the activation can continue only after a successful authentication." /> @@ -66,7 +67,8 @@ <property name="phase2-client-cert" name_upper="PHASE2_CLIENT_CERT" type="byte array" description="Contains the "phase 2" client certificate if used by the EAP method specified in the "phase2-auth" or "phase2-autheap" properties. Certificate data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string "file://" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended." /> <property name="phase2-client-cert-password" name_upper="PHASE2_CLIENT_CERT_PASSWORD" type="string" description="The password used to access the "phase2" client certificate stored in "phase2-client-cert" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login." /> <property name="phase2-client-cert-password-flags" name_upper="PHASE2_CLIENT_CERT_PASSWORD_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "phase2-client-cert-password" property." /> - <property name="phase2-domain-suffix-match" name_upper="PHASE2_DOMAIN_SUFFIX_MATCH" type="string" description="Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner "phase 2" authentication. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison." /> + <property name="phase2-domain-match" name_upper="PHASE2_DOMAIN_MATCH" type="string" description="Constraint for server domain name. If set, this list of FQDNs is used as a match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner "phase 2" authentication. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using the same comparison. Multiple valid FQDNs can be passed as a ";" delimited list." /> + <property name="phase2-domain-suffix-match" name_upper="PHASE2_DOMAIN_SUFFIX_MATCH" type="string" description="Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner "phase 2" authentication. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison. Since version 1.24, multiple valid FQDNs can be passed as a ";" delimited list." /> <property name="phase2-private-key" name_upper="PHASE2_PRIVATE_KEY" type="byte array" description="Contains the "phase 2" inner private key when the "phase2-auth" or "phase2-autheap" property is set to "tls". Key data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data. When using private keys with the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string "file://" and ending with a terminating NUL byte. When using PKCS#12 format private keys and the blob scheme, this property should be set to the PKCS#12 data and the "phase2-private-key-password" property must be set to password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files and the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string "file://" and ending with a terminating NUL byte, and as with the blob scheme the "phase2-private-key-password" property must be set to the password used to decode the PKCS#12 private key and certificate." /> <property name="phase2-private-key-password" name_upper="PHASE2_PRIVATE_KEY_PASSWORD" type="string" description="The password used to decrypt the "phase 2" private key specified in the "phase2-private-key" property when the private key either uses the path scheme, or is a PKCS#12 format key." /> <property name="phase2-private-key-password-flags" name_upper="PHASE2_PRIVATE_KEY_PASSWORD_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "phase2-private-key-password" property." /> @@ -98,15 +100,21 @@ <setting name="bridge" description="Bridging Settings" name_upper="BRIDGE" > <property name="ageing-time" name_upper="AGEING_TIME" type="uint32" default="300" description="The Ethernet MAC address aging time, in seconds." /> <property name="forward-delay" name_upper="FORWARD_DELAY" type="uint32" default="15" description="The Spanning Tree Protocol (STP) forwarding delay, in seconds." /> + <property name="group-address" name_upper="GROUP_ADDRESS" type="byte array" description="If specified, The MAC address of the multicast group this bridge uses for STP. The address must be a link-local address in standard Ethernet MAC address format, ie an address of the form 01:80:C2:00:00:0X, with X in [0, 4..F]. If not specified the default value is 01:80:C2:00:00:00." /> <property name="group-forward-mask" name_upper="GROUP_FORWARD_MASK" type="uint32" default="0" description="A mask of group addresses to forward. Usually, group addresses in the range from 01:80:C2:00:00:00 to 01:80:C2:00:00:0F are not forwarded according to standards. This property is a mask of 16 bits, each corresponding to a group address in that range that must be forwarded. The mask can't have bits 0, 1 or 2 set because they are used for STP, MAC pause frames and LACP." /> <property name="hello-time" name_upper="HELLO_TIME" type="uint32" default="2" description="The Spanning Tree Protocol (STP) hello time, in seconds." /> <property name="mac-address" name_upper="MAC_ADDRESS" type="byte array" description="If specified, the MAC address of bridge. When creating a new bridge, this MAC address will be set. If this field is left unspecified, the "ethernet.cloned-mac-address" is referred instead to generate the initial MAC address. Note that setting "ethernet.cloned-mac-address" anyway overwrites the MAC address of the bridge later while activating the bridge. Hence, this property is deprecated. Deprecated: 1" /> <property name="max-age" name_upper="MAX_AGE" type="uint32" default="20" description="The Spanning Tree Protocol (STP) maximum message age, in seconds." /> + <property name="multicast-querier" name_upper="MULTICAST_QUERIER" type="boolean" default="FALSE" description="Enable or disable sending of multicast queries by the bridge. If not specified the option is disabled." /> + <property name="multicast-query-use-ifaddr" name_upper="MULTICAST_QUERY_USE_IFADDR" type="boolean" default="FALSE" description="If enabled the bridge's own IP address is used as the source address for IGMP queries otherwise the default of 0.0.0.0 is used." /> + <property name="multicast-router" name_upper="MULTICAST_ROUTER" type="string" description="Sets bridge's multicast router. multicast-snooping must be enabled for this option to work. Supported values are: 'auto', 'disabled', 'enabled'. If not specified the default value is 'auto'." /> <property name="multicast-snooping" name_upper="MULTICAST_SNOOPING" type="boolean" default="TRUE" description="Controls whether IGMP snooping is enabled for this bridge. Note that if snooping was automatically disabled due to hash collisions, the system may refuse to enable the feature until the collisions are resolved." /> <property name="priority" name_upper="PRIORITY" type="uint32" default="32768" description="Sets the Spanning Tree Protocol (STP) priority for this bridge. Lower values are "better"; the lowest priority bridge will be elected the root bridge." /> <property name="stp" name_upper="STP" type="boolean" default="TRUE" description="Controls whether Spanning Tree Protocol (STP) is enabled for this bridge." /> <property name="vlan-default-pvid" name_upper="VLAN_DEFAULT_PVID" type="uint32" default="1" description="The default PVID for the ports of the bridge, that is the VLAN id assigned to incoming untagged frames." /> <property name="vlan-filtering" name_upper="VLAN_FILTERING" type="boolean" default="FALSE" description="Control whether VLAN filtering is enabled on the bridge." /> + <property name="vlan-protocol" name_upper="VLAN_PROTOCOL" type="string" description="If specified, the protocol used for VLAN filtering. Supported values are: '802.1Q', '802.1ad'. If not specified the default value is '802.1Q'." /> + <property name="vlan-stats-enabled" name_upper="VLAN_STATS_ENABLED" type="boolean" default="FALSE" description="Controls whether per-VLAN stats accounting is enabled." /> <property name="vlans" name_upper="VLANS" type="array of vardict" description="Array of bridge VLAN objects. In addition to the VLANs specified here, the bridge will also have the default-pvid VLAN configured by the bridge.vlan-default-pvid property. In nmcli the VLAN list can be specified with the following syntax: $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... where $vid is either a single id between 1 and 4094 or a range, represented as a couple of ids separated by a dash." /> </setting> <setting name="bridge-port" description="Bridge Port Settings" name_upper="BRIDGE_PORT" > @@ -180,7 +188,7 @@ <property name="dhcp-timeout" name_upper="DHCP_TIMEOUT" type="int32" default="0" description="A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity." /> <property name="dns" name_upper="DNS" type="array of uint32" description="Array of IP addresses of DNS servers." /> <property name="dns-options" name_upper="DNS_OPTIONS" type="array of string" description="Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties." /> - <property name="dns-priority" name_upper="DNS_PRIORITY" type="int32" default="0" description="DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored." /> + <property name="dns-priority" name_upper="DNS_PRIORITY" type="int32" default="0" description="DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored." /> <property name="dns-search" name_upper="DNS_SEARCH" type="array of string" description="Array of DNS search domains. Domains starting with a tilde ('~') are considered 'routing' domains and are used only to decide the interface over which a query must be forwarded; they are not used to complete unqualified host names." /> <property name="gateway" name_upper="GATEWAY" type="string" description="The gateway associated with this configuration. This is only meaningful if "addresses" is also set." /> <property name="ignore-auto-dns" name_upper="IGNORE_AUTO_DNS" type="boolean" default="FALSE" description="When "method" is set to "auto" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the "dns" and "dns-search" properties, if any, are used." /> @@ -204,7 +212,7 @@ <property name="dhcp-timeout" name_upper="DHCP_TIMEOUT" type="int32" default="0" description="A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity." /> <property name="dns" name_upper="DNS" type="array of byte array" description="Array of IP addresses of DNS servers." /> <property name="dns-options" name_upper="DNS_OPTIONS" type="array of string" description="Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties." /> - <property name="dns-priority" name_upper="DNS_PRIORITY" type="int32" default="0" description="DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored." /> + <property name="dns-priority" name_upper="DNS_PRIORITY" type="int32" default="0" description="DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored." /> <property name="dns-search" name_upper="DNS_SEARCH" type="array of string" description="Array of DNS search domains. Domains starting with a tilde ('~') are considered 'routing' domains and are used only to decide the interface over which a query must be forwarded; they are not used to complete unqualified host names." /> <property name="gateway" name_upper="GATEWAY" type="string" description="The gateway associated with this configuration. This is only meaningful if "addresses" is also set." /> <property name="ignore-auto-dns" name_upper="IGNORE_AUTO_DNS" type="boolean" default="FALSE" description="When "method" is set to "auto" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the "dns" and "dns-search" properties, if any, are used." /> @@ -251,7 +259,7 @@ <property name="promiscuous" name_upper="PROMISCUOUS" type="boolean" default="TRUE" description="Whether the interface should be put in promiscuous mode." /> <property name="tap" name_upper="TAP" type="boolean" default="FALSE" description="Whether the interface should be a MACVTAP." /> </setting> - <setting name="match" description="Match settings." name_upper="MATCH" > + <setting name="match" description="Match settings" name_upper="MATCH" > <property name="interface-name" name_upper="INTERFACE_NAME" type="array of string" description="A list of interface names to match. Each element is a shell wildcard pattern. When an element is prefixed with exclamation mark (!) the condition is inverted. A candidate interface name is considered matching when both these conditions are satisfied: (a) any of the elements not prefixed with '!' matches or there aren't such elements; (b) none of the elements prefixed with '!' match." /> </setting> <setting name="802-11-olpc-mesh" description="OLPC Wireless Mesh Settings" name_upper="OLPC_MESH" > @@ -323,12 +331,12 @@ <property name="send-delay" name_upper="SEND_DELAY" type="uint64" default="0" description="Time to delay between each byte sent to the modem, in microseconds." /> <property name="stopbits" name_upper="STOPBITS" type="uint32" default="1" description="Number of stop bits for communication on the serial port. Either 1 or 2. The 1 in "8n1" for example." /> </setting> - <setting name="sriov" description="SR-IOV settings." name_upper="SRIOV" > + <setting name="sriov" description="SR-IOV settings" name_upper="SRIOV" > <property name="autoprobe-drivers" name_upper="AUTOPROBE_DRIVERS" type="NMTernary (int32)" description="Whether to autoprobe virtual functions by a compatible driver. If set to NM_TERNARY_TRUE (1), the kernel will try to bind VFs to a compatible driver and if this succeeds a new network interface will be instantiated for each VF. If set to NM_TERNARY_FALSE (0), VFs will not be claimed and no network interfaces will be created for them. When set to NM_TERNARY_DEFAULT (-1), the global default is used; in case the global default is unspecified it is assumed to be NM_TERNARY_TRUE (1)." /> - <property name="total-vfs" name_upper="TOTAL_VFS" type="uint32" default="0" description="The total number of virtual functions to create. Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface also when it is zero. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection." /> + <property name="total-vfs" name_upper="TOTAL_VFS" type="uint32" default="0" description="The total number of virtual functions to create. Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface (also when it is zero) during activation and resets it upon deactivation. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection." /> <property name="vfs" name_upper="VFS" type="array of vardict" description="Array of virtual function descriptors. Each VF descriptor is a dictionary mapping attribute names to GVariant values. The 'index' entry is mandatory for each VF. When represented as string a VF is in the form: "INDEX [ATTR=VALUE[ ATTR=VALUE]...]". for example: "2 mac=00:11:22:33:44:55 spoof-check=true". Multiple VFs can be specified using a comma as separator. Currently the following attributes are supported: mac, spoof-check, trust, min-tx-rate, max-tx-rate, vlans. The "vlans" attribute is represented as a semicolon-separated list of VLAN descriptors, where each descriptor has the form "ID[.PRIORITY[.PROTO]]". PROTO can be either 'q' for 802.1Q (the default) or 'ad' for 802.1ad." /> </setting> - <setting name="tc" description="Linux Traffic Control Settings." name_upper="TC_CONFIG" > + <setting name="tc" description="Linux Traffic Control Settings" name_upper="TC_CONFIG" > <property name="qdiscs" name_upper="QDISCS" type="array of vardict" description="Array of TC queueing disciplines." /> <property name="tfilters" name_upper="TFILTERS" type="array of vardict" description="Array of TC traffic filters." /> </setting> @@ -385,6 +393,9 @@ <property name="timeout" name_upper="TIMEOUT" type="uint32" default="0" description="Timeout for the VPN service to establish the connection. Some services may take quite a long time to connect. Value of 0 means a default timeout, which is 60 seconds (unless overridden by vpn.timeout in configuration file). Values greater than zero mean timeout in seconds." /> <property name="user-name" name_upper="USER_NAME" type="string" description="If the VPN connection requires a user name for authentication, that name should be provided here. If the connection is available to more than one user, and the VPN requires each user to supply a different name, then leave this property empty. If this property is empty, NetworkManager will automatically supply the username of the user which requested the VPN connection." /> </setting> + <setting name="vrf" description="VRF settings" name_upper="VRF" > + <property name="table" name_upper="TABLE" type="uint32" default="0" description="The routing table for this VRF." /> + </setting> <setting name="vxlan" description="VXLAN Settings" name_upper="VXLAN" > <property name="ageing" name_upper="AGEING" type="uint32" default="300" description="Specifies the lifetime in seconds of FDB entries learnt by the kernel." /> <property name="destination-port" name_upper="DESTINATION_PORT" type="uint32" default="8472" description="Specifies the UDP destination port to communicate to the remote VXLAN tunnel endpoint." /> @@ -461,7 +472,7 @@ <property name="auth-alg" name_upper="AUTH_ALG" type="string" description="When WEP is used (ie, key-mgmt = "none" or "ieee8021x") indicate the 802.11 authentication algorithm required by the AP here. One of "open" for Open System, "shared" for Shared Key, or "leap" for Cisco LEAP. When using Cisco LEAP (ie, key-mgmt = "ieee8021x" and auth-alg = "leap") the "leap-username" and "leap-password" properties must be specified." /> <property name="fils" name_upper="FILS" type="int32" default="0" description="Indicates whether Fast Initial Link Setup (802.11ai) must be enabled for the connection. One of NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) (use global default value), NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE (1) (disable FILS), NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL (2) (enable FILS if the supplicant and the access point support it) or NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED (3) (enable FILS and fail if not supported). When set to NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) and no global default is set, FILS will be optionally enabled." /> <property name="group" name_upper="GROUP" type="array of string" description="A list of group/broadcast encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list. For maximum compatibility leave this property empty. Each list element may be one of "wep40", "wep104", "tkip", or "ccmp"." /> - <property name="key-mgmt" name_upper="KEY_MGMT" type="string" description="Key management used for the connection. One of "none" (WEP), "ieee8021x" (Dynamic WEP), "wpa-psk" (infrastructure WPA-PSK), "sae" (SAE) or "wpa-eap" (WPA-Enterprise). This property must be set for any Wi-Fi connection that uses security." /> + <property name="key-mgmt" name_upper="KEY_MGMT" type="string" description="Key management used for the connection. One of "none" (WEP), "ieee8021x" (Dynamic WEP), "wpa-psk" (infrastructure WPA-PSK), "sae" (SAE), "owe" (Opportunistic Wireless Encryption) or "wpa-eap" (WPA-Enterprise). This property must be set for any Wi-Fi connection that uses security." /> <property name="leap-password" name_upper="LEAP_PASSWORD" type="string" description="The login password for legacy LEAP connections (ie, key-mgmt = "ieee8021x" and auth-alg = "leap")." /> <property name="leap-password-flags" name_upper="LEAP_PASSWORD_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "leap-password" property." /> <property name="leap-username" name_upper="LEAP_USERNAME" type="string" description="The login username for legacy LEAP connections (ie, key-mgmt = "ieee8021x" and auth-alg = "leap")." /> diff --git a/libnm/nm-remote-connection.c b/libnm/nm-remote-connection.c index d1cc90d6..b37f5814 100644 --- a/libnm/nm-remote-connection.c +++ b/libnm/nm-remote-connection.c @@ -164,7 +164,7 @@ nm_remote_connection_update2_finish (NMRemoteConnection *connection, * * Returns: %TRUE on success, %FALSE on error, in which case @error will be set. * - * Deprecated: 1.22, use nm_remote_connection_commit_changes_async() or GDBusConnection + * Deprecated: 1.22: Use nm_remote_connection_commit_changes_async() or GDBusConnection. **/ gboolean nm_remote_connection_commit_changes (NMRemoteConnection *connection, @@ -269,7 +269,7 @@ nm_remote_connection_commit_changes_finish (NMRemoteConnection *connection, * * Returns: %TRUE on success, %FALSE on error, in which case @error will be set. * - * Deprecated: 1.22, use nm_remote_connection_save_async() or GDBusConnection + * Deprecated: 1.22: Use nm_remote_connection_save_async() or GDBusConnection. **/ gboolean nm_remote_connection_save (NMRemoteConnection *connection, @@ -359,7 +359,7 @@ nm_remote_connection_save_finish (NMRemoteConnection *connection, * * Returns: %TRUE on success, %FALSE on error, in which case @error will be set. * - * Deprecated: 1.22, use nm_remote_connection_delete_async() or GDBusConnection + * Deprecated: 1.22: Use nm_remote_connection_delete_async() or GDBusConnection. **/ gboolean nm_remote_connection_delete (NMRemoteConnection *connection, @@ -448,7 +448,7 @@ nm_remote_connection_delete_finish (NMRemoteConnection *connection, * Returns: (transfer full): a #GVariant of type %NM_VARIANT_TYPE_CONNECTION containing * @connection's secrets, or %NULL on error. * - * Deprecated: 1.22, use nm_remote_connection_get_secrets_async() or GDBusConnection + * Deprecated: 1.22: Use nm_remote_connection_get_secrets_async() or GDBusConnection. **/ GVariant * nm_remote_connection_get_secrets (NMRemoteConnection *connection, diff --git a/libnm/nm-secret-agent-old.c b/libnm/nm-secret-agent-old.c index f0836b24..d614a34c 100644 --- a/libnm/nm-secret-agent-old.c +++ b/libnm/nm-secret-agent-old.c @@ -12,22 +12,22 @@ #include "nm-dbus-helpers.h" #include "nm-dbus-interface.h" #include "nm-enum-types.h" +#include "nm-glib-aux/nm-c-list.h" #include "nm-glib-aux/nm-dbus-aux.h" #include "nm-glib-aux/nm-time-utils.h" #include "nm-simple-connection.h" -#include "introspection/org.freedesktop.NetworkManager.SecretAgent.h" -#include "introspection/org.freedesktop.NetworkManager.AgentManager.h" - -#define REGISTER_RETRY_TIMEOUT_MSEC 2000 +#define REGISTER_RETRY_TIMEOUT_MSEC 3000 +#define _CALL_REGISTER_TIMEOUT_MSEC 15000 /*****************************************************************************/ typedef struct { - char *path; + char *connection_path; char *setting_name; GDBusMethodInvocation *context; CList gsi_lst; + bool is_cancelling:1; } GetSecretsInfo; NM_GOBJECT_PROPERTIES_DEFINE (NMSecretAgentOld, @@ -35,27 +35,61 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSecretAgentOld, PROP_AUTO_REGISTER, PROP_REGISTERED, PROP_CAPABILITIES, + PROP_DBUS_CONNECTION, ); typedef struct { - GDBusConnection *bus; - NMDBusAgentManager *manager_proxy; - NMDBusSecretAgent *dbus_secret_agent; + GDBusConnection *dbus_connection; + GMainContext *main_context; + GMainContext *dbus_context; + GObject *context_busy_watcher; + GCancellable *name_owner_cancellable; + GCancellable *registering_cancellable; + GSource *registering_retry_source; + + NMLInitData *init_data; - /* GetSecretsInfo structs of in-flight GetSecrets requests */ CList gsi_lst_head; + CList pending_tasks_register_lst_head; + char *identifier; - NMSecretAgentCapabilities capabilities; + NMRefString *name_owner_curr; + NMRefString *name_owner_next; gint64 registering_timeout_msec; - guint registering_try_count; - bool registered:1; + guint name_owner_changed_id; + + guint exported_id; + + guint capabilities; + + guint8 registering_try_count; + + guint8 register_state_change_reenter:2; + bool session_bus:1; + bool auto_register:1; - bool suppress_auto:1; + + bool is_registered:1; + + bool is_enabled:1; + + bool registration_force_unregister:1; + + /* This is true, if we either are in the process of RegisterWithCapabilities() or + * are already successfully registered. + * + * This is only TRUE, if the name owner was authenticated to run as root user. + * + * It also means, we should follow up with an Unregister() call during shutdown. */ + bool registered_against_server:1; + + bool is_initialized:1; + bool is_destroyed:1; } NMSecretAgentOldPrivate; static void nm_secret_agent_old_initable_iface_init (GInitableIface *iface); @@ -66,7 +100,7 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMSecretAgentOld, nm_secret_agent_old, G_TYPE_ G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_secret_agent_old_async_initable_iface_init); ) -#define NM_SECRET_AGENT_OLD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SECRET_AGENT_OLD, NMSecretAgentOldPrivate)) +#define NM_SECRET_AGENT_OLD_GET_PRIVATE(self) (G_TYPE_INSTANCE_GET_PRIVATE ((self), NM_TYPE_SECRET_AGENT_OLD, NMSecretAgentOldPrivate)) /*****************************************************************************/ @@ -78,160 +112,289 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMSecretAgentOld, nm_secret_agent_old, G_TYPE_ /*****************************************************************************/ -static void _register_call_cb (GObject *proxy, - GAsyncResult *result, - gpointer user_data); +static const GDBusInterfaceInfo interface_info = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( + NM_DBUS_INTERFACE_SECRET_AGENT, + .methods = NM_DEFINE_GDBUS_METHOD_INFOS ( + NM_DEFINE_GDBUS_METHOD_INFO ( + "GetSecrets", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("connection", "a{sa{sv}}"), + NM_DEFINE_GDBUS_ARG_INFO ("connection_path", "o"), + NM_DEFINE_GDBUS_ARG_INFO ("setting_name", "s"), + NM_DEFINE_GDBUS_ARG_INFO ("hints", "as"), + NM_DEFINE_GDBUS_ARG_INFO ("flags", "u"), + ), + .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("secrets", "a{sa{sv}}"), + ), + ), + NM_DEFINE_GDBUS_METHOD_INFO ( + "CancelGetSecrets", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("connection_path", "o"), + NM_DEFINE_GDBUS_ARG_INFO ("setting_name", "s"), + ), + ), + NM_DEFINE_GDBUS_METHOD_INFO ( + "SaveSecrets", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("connection", "a{sa{sv}}"), + NM_DEFINE_GDBUS_ARG_INFO ("connection_path", "o"), + ), + ), + NM_DEFINE_GDBUS_METHOD_INFO ( + "DeleteSecrets", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("connection", "a{sa{sv}}"), + NM_DEFINE_GDBUS_ARG_INFO ("connection_path", "o"), + ), + ), + ), +); /*****************************************************************************/ -static void -_internal_unregister (NMSecretAgentOld *self) +static void _register_state_change (NMSecretAgentOld *self); + +static void _register_dbus_call (NMSecretAgentOld *self); + +static void _init_complete (NMSecretAgentOld *self, GError *error_take); + +static void _register_state_complete (NMSecretAgentOld *self); + +/*****************************************************************************/ + +/** + * nm_secret_agent_old_get_dbus_connection: + * @self: the #NMSecretAgentOld instance + * + * Returns: (transfer none): the #GDBusConnection used by the secret agent. + * You may either set this as construct property %NM_SECRET_AGENT_OLD_DBUS_CONNECTION, + * or it will automatically set during initialization. + * + * Since: 1.24 + */ +GDBusConnection * +nm_secret_agent_old_get_dbus_connection (NMSecretAgentOld *self) { - NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (self), NULL); - if (priv->registered) { - g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (priv->dbus_secret_agent)); - priv->registered = FALSE; - priv->registering_timeout_msec = 0; - _notify (self, PROP_REGISTERED); - } + return NM_SECRET_AGENT_OLD_GET_PRIVATE (self)->dbus_connection; +} + +/** + * nm_secret_agent_old_get_main_context: + * @self: the #NMSecretAgentOld instance + * + * Returns: (transfer none): the #GMainContext instance associate with the + * instance. This is the g_main_context_get_thread_default() at the time + * when creating the instance. + * + * Since: 1.24 + */ +GMainContext * +nm_secret_agent_old_get_main_context (NMSecretAgentOld *self) +{ + g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (self), NULL); + + return NM_SECRET_AGENT_OLD_GET_PRIVATE (self)->main_context; +} + +/** + * nm_secret_agent_old_get_context_busy_watcher: + * @self: the #NMSecretAgentOld instance + * + * Returns a #GObject that stays alive as long as there are pending + * requests in the #GDBusConnection. Such requests keep the #GMainContext + * alive, and thus you may want to keep iterating the context as long + * until a weak reference indicates that this object is gone. This is + * useful because even when you destroy the instance right away (and all + * the internally pending requests get cancelled), any pending g_dbus_connection_call() + * requests will still invoke the result on the #GMainContext. Hence, this + * allows you to know how long you must iterate the context to know + * that all remains are cleaned up. + * + * Returns: (transfer none): a #GObject that you may register a weak pointer + * to know that the #GMainContext is still kept busy by @self. + * + * Since: 1.24 + */ +GObject * +nm_secret_agent_old_get_context_busy_watcher (NMSecretAgentOld *self) +{ + g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (self), NULL); + + return NM_SECRET_AGENT_OLD_GET_PRIVATE (self)->context_busy_watcher; +} + +/** + * nm_secret_agent_old_get_dbus_name_owner: + * @self: the #NMSecretAgentOld instance + * + * Returns: the current D-Bus name owner. While this property + * is set while registering, it really only makes sense when + * the nm_secret_agent_old_get_registered() indicates that + * registration is successfull. + * + * Since: 1.24 + */ +const char * +nm_secret_agent_old_get_dbus_name_owner (NMSecretAgentOld *self) +{ + g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (self), NULL); + + return nm_ref_string_get_str (NM_SECRET_AGENT_OLD_GET_PRIVATE (self)->name_owner_curr); } +/** + * nm_secret_agent_old_get_registered: + * @self: a #NMSecretAgentOld + * + * Note that the secret agent transparently registers and re-registers + * as the D-Bus name owner appears. Hence, this property is not really + * useful. Also, to be graceful against races during registration, the + * instance will already accept requests while being in the process of + * registering. + * If you need to avoid races and want to wait until @self is registered, + * call nm_secret_agent_old_register_async(). If that function completes + * with success, you know the instance is registered. + * + * Returns: a %TRUE if the agent is registered, %FALSE if it is not. + **/ +gboolean +nm_secret_agent_old_get_registered (NMSecretAgentOld *self) +{ + g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (self), FALSE); + + return NM_SECRET_AGENT_OLD_GET_PRIVATE (self)->is_registered; +} + +/*****************************************************************************/ + static void -get_secrets_info_free (GetSecretsInfo *info) +get_secret_info_free (GetSecretsInfo *info) { nm_assert (info); + nm_assert (!info->context); c_list_unlink_stale (&info->gsi_lst); - - g_free (info->path); + g_free (info->connection_path); g_free (info->setting_name); - g_slice_free (GetSecretsInfo, info); + nm_g_slice_free (info); } -static gboolean -should_auto_register (NMSecretAgentOld *self) +static void +get_secret_info_complete_and_free (GetSecretsInfo *info, + GVariant *secrets, + GError *error) { - NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - - return ( priv->auto_register - && !priv->suppress_auto - && !priv->registered - && priv->registering_timeout_msec == 0); + if (error) { + if (secrets) + nm_g_variant_unref_floating (secrets); + g_dbus_method_invocation_return_gerror (g_steal_pointer (&info->context), error); + } else { + g_dbus_method_invocation_return_value (g_steal_pointer (&info->context), + g_variant_new ("(@a{sa{sv}})", secrets)); + } + get_secret_info_free (info); } static void -name_owner_changed (GObject *proxy, - GParamSpec *pspec, - gpointer user_data) +get_secret_info_complete_and_free_error (GetSecretsInfo *info, + GQuark error_domain, + int error_code, + const char *error_message) { - NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (user_data); - NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - gs_free char *owner = NULL; - GetSecretsInfo *info; - - owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (proxy)); + g_dbus_method_invocation_return_error_literal (g_steal_pointer (&info->context), error_domain, error_code, error_message); + get_secret_info_free (info); +} - _LOGT ("name owner changed: %s%s%s", NM_PRINT_FMT_QUOTE_STRING (owner)); +/*****************************************************************************/ - if (owner) { - if (should_auto_register (self)) - nm_secret_agent_old_register_async (self, NULL, NULL, NULL); - } else { - while ((info = c_list_first_entry (&priv->gsi_lst_head, GetSecretsInfo, gsi_lst))) { - c_list_unlink (&info->gsi_lst); - NM_SECRET_AGENT_OLD_GET_CLASS (self)->cancel_get_secrets (self, - info->path, - info->setting_name); - } +static void +_dbus_connection_call_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + gs_unref_object GObject *context_busy_watcher = NULL; + GAsyncReadyCallback callback; + gpointer callback_user_data; - _internal_unregister (self); - } + nm_utils_user_data_unpack (user_data, &context_busy_watcher, &callback, &callback_user_data); + callback (source, result, callback_user_data); } -static gboolean -verify_sender (NMSecretAgentOld *self, - GDBusMethodInvocation *context, - GError **error) +static void +_dbus_connection_call (NMSecretAgentOld *self, + const char *bus_name, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + const GVariantType *reply_type, + GDBusCallFlags flags, + int timeout_msec, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - gs_free char *owner = NULL; - const char *sender; - guint32 sender_uid; - gs_unref_variant GVariant *ret = NULL; - gs_free_error GError *local = NULL; - g_return_val_if_fail (context != NULL, FALSE); + nm_assert (nm_g_main_context_is_thread_default (priv->dbus_context)); + + g_dbus_connection_call (priv->dbus_connection, + bus_name, + object_path, + interface_name, + method_name, + parameters, + reply_type, + flags, + timeout_msec, + cancellable, + callback + ? _dbus_connection_call_cb + : NULL, + callback + ? nm_utils_user_data_pack (g_object_ref (priv->context_busy_watcher), callback, user_data) + : NULL); +} - /* Verify that the sender is the same as NetworkManager's bus name owner. */ +/*****************************************************************************/ - owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (priv->manager_proxy)); - if (!owner) { - g_set_error_literal (error, - NM_SECRET_AGENT_ERROR, - NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, - "NetworkManager bus name owner unknown."); - return FALSE; - } +static GetSecretsInfo * +find_get_secrets_info (NMSecretAgentOldPrivate *priv, + const char *connection_path, + const char *setting_name) +{ + GetSecretsInfo *info; - sender = g_dbus_method_invocation_get_sender (context); - if (!sender) { - g_set_error_literal (error, - NM_SECRET_AGENT_ERROR, - NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, - "Failed to get request sender."); - return FALSE; + c_list_for_each_entry (info, &priv->gsi_lst_head, gsi_lst) { + if ( nm_streq (connection_path, info->connection_path) + && nm_streq (setting_name, info->setting_name)) + return info; } + return NULL; +} - if (!nm_streq (sender, owner)) { - g_set_error_literal (error, - NM_SECRET_AGENT_ERROR, - NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, - "Request sender does not match NetworkManager bus name owner."); - return FALSE; - } +static void +_cancel_get_secret_request (NMSecretAgentOld *self, + GetSecretsInfo *info, + const char *message) +{ + c_list_unlink (&info->gsi_lst); + info->is_cancelling = TRUE; - /* If we're connected to the session bus, then this must be a test program, - * so skip the UID check. - */ - if (priv->session_bus) - return TRUE; - - /* Check the UID of the sender */ - ret = g_dbus_connection_call_sync (priv->bus, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS, - "GetConnectionUnixUser", - g_variant_new ("(s)", sender), - G_VARIANT_TYPE ("(u)"), - G_DBUS_CALL_FLAGS_NONE, -1, - NULL, &local); - if (!ret) { - gs_free char *remote_error = NULL; - - remote_error = g_dbus_error_get_remote_error (local); - g_dbus_error_strip_remote_error (local); - g_set_error (error, - NM_SECRET_AGENT_ERROR, - NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, - "Failed to request unix user: (%s) %s.", - remote_error ?: "", - local->message); - return FALSE; - } - g_variant_get (ret, "(u)", &sender_uid); + _LOGT ("cancel get-secrets request \"%s\", \"%s\": %s", info->connection_path, info->setting_name, message); - /* We only accept requests from NM, which always runs as root */ - if (sender_uid != 0) { - g_set_error_literal (error, - NM_SECRET_AGENT_ERROR, - NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, - "Request sender is not root."); - return FALSE; - } + NM_SECRET_AGENT_OLD_GET_CLASS (self)->cancel_get_secrets (self, + info->connection_path, + info->setting_name); - return TRUE; + get_secret_info_complete_and_free_error (info, + NM_SECRET_AGENT_ERROR, + NM_SECRET_AGENT_ERROR_AGENT_CANCELED, + message); } static gboolean @@ -245,15 +408,7 @@ verify_request (NMSecretAgentOld *self, gs_unref_object NMConnection *connection = NULL; gs_free_error GError *local = NULL; - if (!verify_sender (self, context, error)) - return FALSE; - - /* No connection? If the sender verified, then we allow the request */ - if (connection_dict == NULL) - return TRUE; - - /* If we have a connection dictionary, we require a path too */ - if (connection_path == NULL) { + if (!nm_dbus_path_not_empty (connection_path)) { g_set_error_literal (error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_INVALID_CONNECTION, @@ -261,7 +416,6 @@ verify_request (NMSecretAgentOld *self, return FALSE; } - /* Make sure the given connection is valid */ connection = _nm_simple_connection_new_from_dbus (connection_dict, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &local); if (!connection) { g_set_error (error, @@ -285,102 +439,99 @@ get_secrets_cb (NMSecretAgentOld *self, { GetSecretsInfo *info = user_data; - if (error) - g_dbus_method_invocation_return_gerror (info->context, error); - else { - g_variant_take_ref (secrets); - g_dbus_method_invocation_return_value (info->context, - g_variant_new ("(@a{sa{sv}})", secrets)); + if (info->is_cancelling) { + if (secrets) + nm_g_variant_unref_floating (secrets); + return; } - get_secrets_info_free (info); + _LOGT ("request: get-secrets request \"%s\", \"%s\" complete with %s%s%s", + info->connection_path, + info->setting_name, + NM_PRINT_FMT_QUOTED (error, "error: ", error->message, "", "success")); + + get_secret_info_complete_and_free (info, secrets, error); } static void -impl_secret_agent_old_get_secrets (NMSecretAgentOld *self, - GDBusMethodInvocation *context, - GVariant *connection_dict, - const char *connection_path, - const char *setting_name, - const char * const *hints, - guint flags, - gpointer user_data) +impl_get_secrets (NMSecretAgentOld *self, + GVariant *parameters, + GDBusMethodInvocation *context) { NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); GError *error = NULL; gs_unref_object NMConnection *connection = NULL; GetSecretsInfo *info; - - /* Make sure the request comes from NetworkManager and is valid */ - if (!verify_request (self, context, connection_dict, connection_path, &connection, &error)) { + gs_unref_variant GVariant *arg_connection = NULL; + const char *arg_connection_path; + const char *arg_setting_name; + gs_free const char **arg_hints = NULL; + guint32 arg_flags; + + g_variant_get (parameters, + "(@a{sa{sv}}&o&s^a&su)", + &arg_connection, + &arg_connection_path, + &arg_setting_name, + &arg_hints, + &arg_flags); + + if (!verify_request (self, context, arg_connection, arg_connection_path, &connection, &error)) { g_dbus_method_invocation_take_error (context, error); return; } + _LOGT ("request: get-secrets(\"%s\", \"%s\")", arg_connection_path, arg_setting_name); + + info = find_get_secrets_info (priv, arg_connection_path, arg_setting_name); + if (info) + _cancel_get_secret_request (self, info, "Request aborted due to new request"); + info = g_slice_new (GetSecretsInfo); *info = (GetSecretsInfo) { - .path = g_strdup (connection_path), - .setting_name = g_strdup (setting_name), - .context = context, + .context = context, + .connection_path = g_strdup (arg_connection_path), + .setting_name = g_strdup (arg_setting_name), }; c_list_link_tail (&priv->gsi_lst_head, &info->gsi_lst); NM_SECRET_AGENT_OLD_GET_CLASS (self)->get_secrets (self, connection, - connection_path, - setting_name, - (const char **) hints, - flags, + info->connection_path, + info->setting_name, + arg_hints, + arg_flags, get_secrets_cb, info); } -static GetSecretsInfo * -find_get_secrets_info (NMSecretAgentOldPrivate *priv, - const char *path, - const char *setting_name) -{ - GetSecretsInfo *info; - - c_list_for_each_entry (info, &priv->gsi_lst_head, gsi_lst) { - if ( nm_streq0 (path, info->path) - && nm_streq0 (setting_name, info->setting_name)) - return info; - } - return NULL; -} - static void -impl_secret_agent_old_cancel_get_secrets (NMSecretAgentOld *self, - GDBusMethodInvocation *context, - const char *connection_path, - const char *setting_name, - gpointer user_data) +impl_cancel_get_secrets (NMSecretAgentOld *self, + GVariant *parameters, + GDBusMethodInvocation *context) { NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - GError *error = NULL; GetSecretsInfo *info; + const char *arg_connection_path; + const char *arg_setting_name; - /* Make sure the request comes from NetworkManager and is valid */ - if (!verify_request (self, context, NULL, NULL, NULL, &error)) { - g_dbus_method_invocation_take_error (context, error); - return; - } + g_variant_get (parameters, + "(&o&s)", + &arg_connection_path, + &arg_setting_name); - info = find_get_secrets_info (priv, connection_path, setting_name); + info = find_get_secrets_info (priv, arg_connection_path, arg_setting_name); if (!info) { - g_dbus_method_invocation_return_error (context, - NM_SECRET_AGENT_ERROR, - NM_SECRET_AGENT_ERROR_FAILED, - "No secrets request in progress for this connection."); + g_dbus_method_invocation_return_error_literal (context, + NM_SECRET_AGENT_ERROR, + NM_SECRET_AGENT_ERROR_FAILED, + "No secrets request in progress for this connection."); return; } - c_list_unlink (&info->gsi_lst); - - NM_SECRET_AGENT_OLD_GET_CLASS (self)->cancel_get_secrets (self, - info->path, - info->setting_name); + _cancel_get_secret_request (self, + info, + "Request cancelled by NetworkManager"); g_dbus_method_invocation_return_value (context, NULL); } @@ -400,24 +551,30 @@ save_secrets_cb (NMSecretAgentOld *self, } static void -impl_secret_agent_old_save_secrets (NMSecretAgentOld *self, - GDBusMethodInvocation *context, - GVariant *connection_dict, - const char *connection_path, - gpointer user_data) +impl_save_secrets (NMSecretAgentOld *self, + GVariant *parameters, + GDBusMethodInvocation *context) { gs_unref_object NMConnection *connection = NULL; + gs_unref_variant GVariant *arg_connection = NULL; + const char *arg_connection_path; GError *error = NULL; - /* Make sure the request comes from NetworkManager and is valid */ - if (!verify_request (self, context, connection_dict, connection_path, &connection, &error)) { + g_variant_get (parameters, + "(@a{sa{sv}}&o)", + &arg_connection, + &arg_connection_path); + + if (!verify_request (self, context, arg_connection, arg_connection_path, &connection, &error)) { g_dbus_method_invocation_take_error (context, error); return; } + _LOGT ("request: save-secrets(\"%s\")", arg_connection_path); + NM_SECRET_AGENT_OLD_GET_CLASS (self)->save_secrets (self, connection, - connection_path, + arg_connection_path, save_secrets_cb, context); } @@ -437,64 +594,124 @@ delete_secrets_cb (NMSecretAgentOld *self, } static void -impl_secret_agent_old_delete_secrets (NMSecretAgentOld *self, - GDBusMethodInvocation *context, - GVariant *connection_dict, - const char *connection_path, - gpointer user_data) +impl_delete_secrets (NMSecretAgentOld *self, + GVariant *parameters, + GDBusMethodInvocation *context) { gs_unref_object NMConnection *connection = NULL; + gs_unref_variant GVariant *arg_connection = NULL; + const char *arg_connection_path; GError *error = NULL; - /* Make sure the request comes from NetworkManager and is valid */ - if (!verify_request (self, context, connection_dict, connection_path, &connection, &error)) { + g_variant_get (parameters, + "(@a{sa{sv}}&o)", + &arg_connection, + &arg_connection_path); + + if (!verify_request (self, context, arg_connection, arg_connection_path, &connection, &error)) { g_dbus_method_invocation_take_error (context, error); return; } + _LOGT ("request: delete-secrets(\"%s\")", arg_connection_path); + NM_SECRET_AGENT_OLD_GET_CLASS (self)->delete_secrets (self, connection, - connection_path, + arg_connection_path, delete_secrets_cb, context); } /*****************************************************************************/ -static gboolean -check_nm_running (NMSecretAgentOld *self, GError **error) +/** + * nm_secret_agent_old_enable: + * @self: the #NMSecretAgentOld instance + * @enable: whether to enable or disable the listener. + * + * This has the same effect as setting %NM_SECRET_AGENT_OLD_AUTO_REGISTER + * property. + * + * Unlike most other functions, you may already call this function before + * initialization completes. + * + * Since: 1.24 + */ +void +nm_secret_agent_old_enable (NMSecretAgentOld *self, + gboolean enable) { - NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - gs_free char *owner = NULL; + NMSecretAgentOldPrivate *priv; + + g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self)); + + priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (priv->manager_proxy)); - if (owner) - return TRUE; + enable = (!!enable); - g_set_error (error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED, - "NetworkManager is not running"); - return FALSE; + if (priv->auto_register != enable) { + priv->auto_register = enable; + priv->is_enabled = enable; + _notify (self, PROP_AUTO_REGISTER); + } + _register_state_change (self); } -/*****************************************************************************/ +static void +_secret_agent_old_destroy (NMSecretAgentOld *self) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); -static gboolean -_register_should_retry (NMSecretAgentOldPrivate *priv, - guint *out_timeout_msec) + priv->is_destroyed = TRUE; + + if (priv->exported_id != 0) { + g_dbus_connection_unregister_object (priv->dbus_connection, + nm_steal_int (&priv->exported_id)); + } + + _register_state_change (self); + + nm_assert (!priv->name_owner_changed_id); + nm_assert (!priv->name_owner_curr); + nm_assert (!priv->name_owner_next); + nm_assert (!priv->name_owner_cancellable); + nm_assert (!priv->registering_retry_source); + nm_assert (!priv->registering_cancellable); + nm_assert (!priv->init_data); + nm_assert (c_list_is_empty (&priv->gsi_lst_head)); + nm_assert (c_list_is_empty (&priv->pending_tasks_register_lst_head)); +} + +/** + * nm_secret_agent_old_destroy: + * @self: the #NMSecretAgentOld instance. + * + * Since 1.24, the instance will already register a D-Bus object on the + * D-Bus connection during initialization. That object will stay registered + * until @self gets unrefed (destroyed) or this function is called. This + * function performs the necessary cleanup to tear down the instance. Afterwards, + * the function can not longer be used. This is optional, but necessary to + * ensure unregistering the D-Bus object at a define point, when other users + * might still have a reference on @self. + * + * You may call this function any time and repeatedly. However, after destroying + * the instance, it is a bug to still use the instance for other purposes. The + * instance becomes defunct and cannot re-register. + * + * Since: 1.24 + */ +void +nm_secret_agent_old_destroy (NMSecretAgentOld *self) { - guint timeout_msec; + g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self)); - if (priv->registering_try_count++ == 0) - timeout_msec = 0; - else if (nm_utils_get_monotonic_timestamp_ms () < priv->registering_timeout_msec) - timeout_msec = 1ULL * (1ULL << NM_MIN (7, priv->registering_try_count)); - else - return FALSE; + _LOGT ("destroying"); - *out_timeout_msec = timeout_msec; - return TRUE; + _secret_agent_old_destroy (self); } +/*****************************************************************************/ + /** * nm_secret_agent_old_register: * @self: a #NMSecretAgentOld @@ -505,10 +722,17 @@ _register_should_retry (NMSecretAgentOldPrivate *priv, * indicating to NetworkManager that the agent is able to provide and save * secrets for connections on behalf of its user. * - * It is a programmer error to attempt to register an agent that is already - * registered, or in the process of registering. - * * Returns: %TRUE if registration was successful, %FALSE on error. + * + * Since 1.24, this can no longer fail unless the @cancellable gets + * cancelled. Contrary to nm_secret_agent_old_register_async(), this also + * does not wait for the registration to succeed. You cannot synchronously + * (without iterating the caller's GMainContext) wait for registration. + * + * Since 1.24, registration is idempotent. It has the same effect as setting + * %NM_SECRET_AGENT_OLD_AUTO_REGISTER to %TRUE or nm_secret_agent_old_enable(). + * + * Deprecated: 1.24: Use nm_secret_agent_old_enable() or nm_secret_agent_old_register_async(). **/ gboolean nm_secret_agent_old_register (NMSecretAgentOld *self, @@ -516,206 +740,59 @@ nm_secret_agent_old_register (NMSecretAgentOld *self, GError **error) { NMSecretAgentOldPrivate *priv; - NMSecretAgentOldClass *class; g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (self), FALSE); + g_return_val_if_fail (!error || !*error, FALSE); priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - g_return_val_if_fail (priv->registered == FALSE, FALSE); - g_return_val_if_fail (priv->registering_timeout_msec == 0, FALSE); - g_return_val_if_fail (priv->bus != NULL, FALSE); - g_return_val_if_fail (priv->manager_proxy != NULL, FALSE); + g_return_val_if_fail (priv->is_initialized && !priv->is_destroyed, FALSE); - /* Also make sure the subclass can actually respond to secrets requests */ - class = NM_SECRET_AGENT_OLD_GET_CLASS (self); - g_return_val_if_fail (class->get_secrets != NULL, FALSE); - g_return_val_if_fail (class->save_secrets != NULL, FALSE); - g_return_val_if_fail (class->delete_secrets != NULL, FALSE); + priv->is_enabled = TRUE; + _register_state_change (self); - if (!check_nm_running (self, error)) + if (g_cancellable_set_error_if_cancelled (cancellable, error)) return FALSE; - priv->suppress_auto = FALSE; - - /* Export our secret agent interface before registering with the manager */ - if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_secret_agent), - priv->bus, - NM_DBUS_PATH_SECRET_AGENT, - error)) - return FALSE; - - priv->registering_timeout_msec = nm_utils_get_monotonic_timestamp_ms () + REGISTER_RETRY_TIMEOUT_MSEC; - priv->registering_try_count = 0; - - while (TRUE) { - gs_free_error GError *local = NULL; - - nmdbus_agent_manager_call_register_with_capabilities_sync (priv->manager_proxy, - priv->identifier, - priv->capabilities, - cancellable, - &local); - if (nm_dbus_error_is (local, NM_DBUS_ERROR_NAME_UNKNOWN_METHOD)) { - guint timeout_msec; - - if (_register_should_retry (priv, &timeout_msec)) { - if (timeout_msec > 0) - g_usleep (timeout_msec * 1000LU); - continue; - } - } - - priv->registering_timeout_msec = 0; - - if (local) { - g_dbus_error_strip_remote_error (local); - g_propagate_error (error, g_steal_pointer (&local)); - _internal_unregister (self); - return FALSE; - } - - priv->registered = TRUE; - _notify (self, PROP_REGISTERED); - return TRUE; - } -} - -/*****************************************************************************/ - -typedef struct { - GCancellable *cancellable; - GSource *timeout_source; - gulong cancellable_signal_id; -} RegisterData; - -static void -_register_data_free (RegisterData *register_data) -{ - nm_clear_g_cancellable_disconnect (register_data->cancellable, ®ister_data->cancellable_signal_id); - nm_clear_g_source_inst (®ister_data->timeout_source); - g_clear_object (®ister_data->cancellable); - nm_g_slice_free (register_data); -} - -static gboolean -_register_retry_cb (gpointer user_data) -{ - gs_unref_object GTask *task = user_data; - NMSecretAgentOld *self = g_task_get_source_object (task); - NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - GCancellable *cancellable; - - _LOGT ("register: retry registration..."); - - g_task_set_task_data (task, NULL, NULL); - - cancellable = g_task_get_cancellable (task); - - nmdbus_agent_manager_call_register_with_capabilities (priv->manager_proxy, - priv->identifier, - priv->capabilities, - cancellable, - _register_call_cb, - g_steal_pointer (&task)); - return G_SOURCE_REMOVE; -} - -static void -_register_cancelled_cb (GCancellable *cancellable, - gpointer user_data) -{ - gs_unref_object GTask *task = user_data; - NMSecretAgentOld *self = g_task_get_source_object (task); - RegisterData *register_data = g_task_get_task_data (task); - GError *error = NULL; - - nm_clear_g_signal_handler (register_data->cancellable, ®ister_data->cancellable_signal_id); - g_task_set_task_data (task, NULL, NULL); - - _LOGT ("register: registration cancelled. Stop waiting..."); - - nm_utils_error_set_cancelled (&error, FALSE, NULL); - g_task_return_error (task, error); + /* This is a synchronous function, meaning: we are not allowed to iterate + * the caller's GMainContext. This is a catch 22, because we don't want + * to perform synchronous calls that bypasses the ordering of our otherwise + * asynchronous mode of operation. Hence, we always signal success. + * That's why this function is deprecated. + * + * So despite claiming success, we might still be in the process of registering + * or NetworkManager might not be available. + * + * This is a change in behavior with respect to libnm before 1.24. + */ + return TRUE; } static void -_register_call_cb (GObject *proxy, - GAsyncResult *result, - gpointer user_data) +_register_cancelled_cb (GObject *object, gpointer user_data) { - gs_unref_object GTask *task = user_data; - NMSecretAgentOld *self = g_task_get_source_object (task); + GTask *task0 = user_data; + gs_unref_object GTask *task = NULL; + NMSecretAgentOld *self = g_task_get_source_object (task0); NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + gulong *p_cancelled_id; + NMCListElem *elem; gs_free_error GError *error = NULL; - nmdbus_agent_manager_call_register_with_capabilities_finish (NMDBUS_AGENT_MANAGER (proxy), result, &error); + elem = nm_c_list_elem_find_first (&priv->pending_tasks_register_lst_head, x, x == task0); - if (nm_utils_error_is_cancelled (error, FALSE)) { - /* FIXME: we should unregister right away. For now, don't do that, likely the - * application is anyway about to exit. */ - } else if (nm_dbus_error_is (error, NM_DBUS_ERROR_NAME_UNKNOWN_METHOD)) { - gboolean already_cancelled = FALSE; - RegisterData *register_data; - guint timeout_msec; - - if (!_register_should_retry (priv, &timeout_msec)) - goto done; - - _LOGT ("register: registration failed with error \"%s\". Retry in %u msec...", error->message, timeout_msec); - nm_assert (G_IS_TASK (task)); - nm_assert (!g_task_get_task_data (task)); - - register_data = g_slice_new (RegisterData); - - *register_data = (RegisterData) { - .cancellable = nm_g_object_ref (g_task_get_cancellable (task)), - }; - - g_task_set_task_data (task, - register_data, - (GDestroyNotify) _register_data_free); - - if (register_data->cancellable) { - register_data->cancellable_signal_id = g_cancellable_connect (register_data->cancellable, - G_CALLBACK (_register_cancelled_cb), - task, - NULL); - if (register_data->cancellable_signal_id == 0) - already_cancelled = TRUE; - } - - if (!already_cancelled) { - register_data->timeout_source = nm_g_source_attach (nm_g_timeout_source_new (timeout_msec, - g_task_get_priority (task), - _register_retry_cb, - task, - NULL), - g_task_get_context (task)); - } - - /* The reference of the task is owned by the _register_cancelled_cb and _register_retry_cb actions. - * Whichever completes first, will consume it. */ - g_steal_pointer (&task); - return; - } + g_return_if_fail (elem); -done: - priv->registering_timeout_msec = 0; + task = nm_c_list_elem_free_steal (elem); - if (error) { - _LOGT ("register: registration failed with error \"%s\"", error->message); - g_dbus_error_strip_remote_error (error); - _internal_unregister (self); - g_task_return_error (task, g_steal_pointer (&error)); - return; + p_cancelled_id = g_task_get_task_data (task); + if (p_cancelled_id) { + g_signal_handler_disconnect (g_task_get_cancellable (task), *p_cancelled_id); + g_task_set_task_data (task, NULL, NULL); } - _LOGT ("register: registration succeeded"); - priv->registered = TRUE; - _notify (self, PROP_REGISTERED); - - g_task_return_boolean (task, TRUE); + nm_utils_error_set_cancelled (&error, FALSE, NULL); + g_task_return_error (task, error); } /** @@ -729,8 +806,16 @@ done: * manager, indicating to NetworkManager that the agent is able to provide and * save secrets for connections on behalf of its user. * - * It is a programmer error to attempt to register an agent that is already - * registered, or in the process of registering. + * Since 1.24, registration cannot fail and is idempotent. It has + * the same effect as setting %NM_SECRET_AGENT_OLD_AUTO_REGISTER to %TRUE + * or nm_secret_agent_old_enable(). + * + * Since 1.24, the asynchronous result indicates whether the instance is successfully + * registered. In any case, this call enables the agent and it will automatically + * try to register and handle secret requests. A failure of this function only indicates + * that currently the instance might not be ready (but since it will automatically + * try to recover, it might be ready in a moment afterwards). Use this function if + * you want to check and ensure that the agent is registered. **/ void nm_secret_agent_old_register_async (NMSecretAgentOld *self, @@ -739,54 +824,39 @@ nm_secret_agent_old_register_async (NMSecretAgentOld *self, gpointer user_data) { NMSecretAgentOldPrivate *priv; - NMSecretAgentOldClass *class; - gs_unref_object GTask *task = NULL; - gs_free_error GError *error = NULL; g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self)); + g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - g_return_if_fail (priv->registered == FALSE); - g_return_if_fail (priv->registering_timeout_msec == 0); - g_return_if_fail (priv->bus != NULL); - g_return_if_fail (priv->manager_proxy != NULL); + g_return_if_fail (priv->is_initialized && !priv->is_destroyed); - /* Also make sure the subclass can actually respond to secrets requests */ - class = NM_SECRET_AGENT_OLD_GET_CLASS (self); - g_return_if_fail (class->get_secrets != NULL); - g_return_if_fail (class->save_secrets != NULL); - g_return_if_fail (class->delete_secrets != NULL); + if (callback) { + GTask *task; - task = nm_g_task_new (self, cancellable, nm_secret_agent_old_register_async, callback, user_data); + task = nm_g_task_new (self, cancellable, nm_secret_agent_old_register_async, callback, user_data); - if (!check_nm_running (self, &error)) { - _LOGT ("register: failed because NetworkManager is not running"); - g_task_return_error (task, g_steal_pointer (&error)); - return; - } + c_list_link_tail (&priv->pending_tasks_register_lst_head, + &nm_c_list_elem_new_stale (task)->lst); - /* Export our secret agent interface before registering with the manager */ - if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_secret_agent), - priv->bus, - NM_DBUS_PATH_SECRET_AGENT, - &error)) { - _LOGT ("register: failed to export D-Bus service: %s", error->message); - g_task_return_error (task, g_steal_pointer (&error)); - return; - } + if (cancellable) { + gulong cancelled_id; - priv->suppress_auto = FALSE; - priv->registering_timeout_msec = nm_utils_get_monotonic_timestamp_ms () + REGISTER_RETRY_TIMEOUT_MSEC; - priv->registering_try_count = 0; + cancelled_id = g_cancellable_connect (cancellable, + G_CALLBACK (_register_cancelled_cb), + task, + NULL); + if (cancelled_id != 0) { + g_task_set_task_data (task, + g_memdup (&cancelled_id, sizeof (cancelled_id)), + g_free); + } + } + } - _LOGT ("register: starting asynchronous registration..."); - nmdbus_agent_manager_call_register_with_capabilities (priv->manager_proxy, - priv->identifier, - priv->capabilities, - cancellable, - _register_call_cb, - g_steal_pointer (&task)); + priv->is_enabled = TRUE; + _register_state_change (self); } /** @@ -798,6 +868,10 @@ nm_secret_agent_old_register_async (NMSecretAgentOld *self, * Gets the result of a call to nm_secret_agent_old_register_async(). * * Returns: %TRUE if registration was successful, %FALSE on error. + * + * Since 1.24, registration cannot fail and is idempotent. It has + * the same effect as setting %NM_SECRET_AGENT_OLD_AUTO_REGISTER to %TRUE + * or nm_secret_agent_old_enable(). **/ gboolean nm_secret_agent_old_register_finish (NMSecretAgentOld *self, @@ -821,6 +895,12 @@ nm_secret_agent_old_register_finish (NMSecretAgentOld *self, * store secrets on behalf of this user. * * Returns: %TRUE if unregistration was successful, %FALSE on error + * + * Since 1.24, registration cannot fail and is idempotent. It has + * the same effect as setting %NM_SECRET_AGENT_OLD_AUTO_REGISTER to %FALSE + * or nm_secret_agent_old_enable(). + * + * Deprecated: 1.24: Use nm_secret_agent_old_enable(). **/ gboolean nm_secret_agent_old_unregister (NMSecretAgentOld *self, @@ -828,43 +908,19 @@ nm_secret_agent_old_unregister (NMSecretAgentOld *self, GError **error) { NMSecretAgentOldPrivate *priv; - gboolean success; g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (self), FALSE); + g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE); + g_return_val_if_fail (!error || !*error, FALSE); priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - g_return_val_if_fail (priv->bus != NULL, FALSE); - g_return_val_if_fail (priv->manager_proxy != NULL, FALSE); - - priv->suppress_auto = TRUE; + g_return_val_if_fail (priv->is_initialized && !priv->is_destroyed, FALSE); - success = nmdbus_agent_manager_call_unregister_sync (priv->manager_proxy, cancellable, error); - if (error && *error) - g_dbus_error_strip_remote_error (*error); - _internal_unregister (self); + priv->is_enabled = FALSE; + _register_state_change (self); - return success; -} - -static void -unregister_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) -{ - gs_unref_object GTask *task = user_data; - NMSecretAgentOld *self = g_task_get_source_object (task); - gs_free_error GError *error = NULL; - - _internal_unregister (self); - - if (!nmdbus_agent_manager_call_unregister_finish (NMDBUS_AGENT_MANAGER (proxy), - result, - &error)) { - g_dbus_error_strip_remote_error (error); - g_task_return_error (task, g_steal_pointer (&error)); - return; - } - - g_task_return_boolean (task, TRUE); + return !g_cancellable_set_error_if_cancelled (cancellable, error); } /** @@ -877,6 +933,12 @@ unregister_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) * Asynchronously unregisters the #NMSecretAgentOld with the NetworkManager secret * manager, indicating to NetworkManager that the agent will no longer provide * or store secrets on behalf of this user. + * + * Since 1.24, registration cannot fail and is idempotent. It has + * the same effect as setting %NM_SECRET_AGENT_OLD_AUTO_REGISTER to %FALSE + * or nm_secret_agent_old_enable(). + * + * Deprecated: 1.24: Use nm_secret_agent_old_enable(). **/ void nm_secret_agent_old_unregister_async (NMSecretAgentOld *self, @@ -885,29 +947,23 @@ nm_secret_agent_old_unregister_async (NMSecretAgentOld *self, gpointer user_data) { NMSecretAgentOldPrivate *priv; - gs_unref_object GTask *task = NULL; - gs_free_error GError *error = NULL; g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self)); + g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - g_return_if_fail (priv->bus != NULL); - g_return_if_fail (priv->manager_proxy != NULL); + g_return_if_fail (priv->is_initialized && !priv->is_destroyed); - task = nm_g_task_new (self, cancellable, nm_secret_agent_old_unregister_async, callback, user_data); + if (callback) { + gs_unref_object GTask *task = NULL; - if (!check_nm_running (self, &error)) { - g_task_return_error (task, g_steal_pointer (&error)); - return; + task = nm_g_task_new (self, cancellable, nm_secret_agent_old_unregister_async, callback, user_data); + g_task_return_boolean (task, TRUE); } - priv->suppress_auto = TRUE; - - nmdbus_agent_manager_call_unregister (priv->manager_proxy, - cancellable, - unregister_cb, - g_steal_pointer (&task)); + priv->is_enabled = FALSE; + _register_state_change (self); } /** @@ -919,6 +975,12 @@ nm_secret_agent_old_unregister_async (NMSecretAgentOld *self, * Gets the result of a call to nm_secret_agent_old_unregister_async(). * * Returns: %TRUE if unregistration was successful, %FALSE on error. + * + * Since 1.24, registration cannot fail and is idempotent. It has + * the same effect as setting %NM_SECRET_AGENT_OLD_AUTO_REGISTER to %FALSE + * or nm_secret_agent_old_enable(). + * + * Deprecated: 1.24: Use nm_secret_agent_old_enable(). **/ gboolean nm_secret_agent_old_unregister_finish (NMSecretAgentOld *self, @@ -931,20 +993,6 @@ nm_secret_agent_old_unregister_finish (NMSecretAgentOld *self, return g_task_propagate_boolean (G_TASK (result), error); } -/** - * nm_secret_agent_old_get_registered: - * @self: a #NMSecretAgentOld - * - * Returns: a %TRUE if the agent is registered, %FALSE if it is not. - **/ -gboolean -nm_secret_agent_old_get_registered (NMSecretAgentOld *self) -{ - g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (self), FALSE); - - return NM_SECRET_AGENT_OLD_GET_PRIVATE (self)->registered; -} - /*****************************************************************************/ /** @@ -1074,83 +1122,675 @@ validate_identifier (const char *identifier) /*****************************************************************************/ +static gboolean +_register_retry_cb (gpointer user_data) +{ + NMSecretAgentOld *self = user_data; + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + nm_auto_pop_gmaincontext GMainContext *dbus_context = NULL; + + dbus_context = nm_g_main_context_push_thread_default_if_necessary (priv->dbus_context); + + nm_clear_g_source_inst (&priv->registering_retry_source); + _register_dbus_call (self); + return G_SOURCE_CONTINUE; +} + +static void +_register_call_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + NMSecretAgentOld *self = user_data; + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + gs_unref_variant GVariant *ret = NULL; + gs_free_error GError *error = NULL; + + ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); + + if (nm_utils_error_is_cancelled (error)) + return; + + nm_assert (!priv->registering_retry_source); + nm_assert (!priv->is_registered); + nm_assert (priv->registering_cancellable); + + if ( nm_dbus_error_is (error, NM_DBUS_ERROR_NAME_UNKNOWN_METHOD) + && nm_utils_get_monotonic_timestamp_msec () < priv->registering_timeout_msec) { + guint timeout_msec; + + timeout_msec = (2u << NM_MIN (6u, ++priv->registering_try_count)); + + _LOGT ("register: registration failed with error \"%s\". Retry in %u msec...", error->message, timeout_msec); + + priv->registering_retry_source = nm_g_source_attach (nm_g_timeout_source_new (timeout_msec, + G_PRIORITY_DEFAULT, + _register_retry_cb, + self, + NULL), + priv->dbus_context); + return; + } + + g_clear_object (&priv->registering_cancellable); + + if (error) { + /* registration apparently failed. However we still keep priv->registered_against_server TRUE, because + * + * - eventually we want to still make an Unregister() call. Even if it probably has no effect, + * better be sure. + * + * - we actually accept secret request (from the right name owner). We register so that + * NetworkManager knows that we are here. We don't require the registration to succeed + * for our purpose. If NetworkManager makes requests for us, despite the registration + * failing, that is fine. */ + _LOGT ("register: registration failed with error \"%s\"", error->message); + goto out; + } + + _LOGT ("register: registration succeeded"); + priv->is_registered = TRUE; + _notify (self, PROP_REGISTERED); + +out: + _register_state_complete (self); +} + static void -init_common (NMSecretAgentOld *self) +_register_dbus_call (NMSecretAgentOld *self) { NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - priv->session_bus = _nm_dbus_bus_type () == G_BUS_TYPE_SESSION; + _dbus_connection_call (self, + nm_ref_string_get_str (priv->name_owner_curr), + NM_DBUS_PATH_AGENT_MANAGER, + NM_DBUS_INTERFACE_AGENT_MANAGER, + "RegisterWithCapabilities", + g_variant_new ("(su)", + priv->identifier, + (guint32) priv->capabilities), + G_VARIANT_TYPE ("()"), + G_DBUS_CALL_FLAGS_NONE, + _CALL_REGISTER_TIMEOUT_MSEC, + priv->registering_cancellable, + _register_call_cb, + self); +} - g_signal_connect (priv->manager_proxy, "notify::g-name-owner", - G_CALLBACK (name_owner_changed), self); +static void +_get_connection_unix_user_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + NMSecretAgentOld *self; + NMSecretAgentOldPrivate *priv; + gs_unref_variant GVariant *ret = NULL; + gs_free_error GError *error = NULL; + guint32 sender_uid = 0; + + ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); + if (nm_utils_error_is_cancelled (error)) + return; + + self = user_data; + priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + nm_assert (priv->registering_cancellable); + nm_assert (!priv->registered_against_server); + + if (ret) + g_variant_get (ret, "(u)", &sender_uid); + + if ( ret + && sender_uid == 0) + _LOGT ("register: peer %s is owned by root. Validated to accept requests.", priv->name_owner_curr->str); + else if ( ret + && priv->session_bus) { + _LOGT ("register: peer %s is owned by user %d for session bus. Validated to accept requests.", priv->name_owner_curr->str, sender_uid); + } else { + /* the peer is not validated. We don't actually register. */ + if (ret) + _LOGT ("register: peer %s is owned by user %u. Not validated as NetworkManager service.", priv->name_owner_curr->str, sender_uid); + else + _LOGT ("register: failed to get user id for peer %s: %s. Not validated as NetworkManager service.", priv->name_owner_curr->str, error->message); + + /* we actually don't do anything and keep the agent unregistered. + * + * We keep priv->registering_cancellable set to not retry this again, until we loose the + * name owner. But the state of the agent is lingering and won't accept any requests. */ + return; + } + + priv->registering_timeout_msec = nm_utils_get_monotonic_timestamp_msec () + REGISTER_RETRY_TIMEOUT_MSEC; + priv->registering_try_count = 0; + priv->registered_against_server = TRUE; + _register_dbus_call (self); } +/*****************************************************************************/ + static void -init_async_registered (GObject *object, GAsyncResult *result, gpointer user_data) +_name_owner_changed (NMSecretAgentOld *self, + const char *name_owner, + gboolean is_event) { - gs_unref_object GTask *task = user_data; - NMSecretAgentOld *self = g_task_get_source_object (task); - GError *error = NULL; + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - nm_secret_agent_old_register_finish (self, result, &error); + if (is_event) { + if (priv->name_owner_cancellable) { + /* we are still fetching the name-owner. Ignore this event. */ + return; + } + } else + g_clear_object (&priv->name_owner_cancellable); - if (error) - g_task_return_error (task, error); + nm_ref_string_unref (priv->name_owner_next); + priv->name_owner_next = nm_ref_string_new (nm_str_not_empty (name_owner)); + + _LOGT ("name-owner changed: %s%s%s -> %s%s%s", + NM_PRINT_FMT_QUOTED (priv->name_owner_curr, "\"", priv->name_owner_curr->str, "\"", "(null)"), + NM_PRINT_FMT_QUOTED (priv->name_owner_next, "\"", priv->name_owner_next->str, "\"", "(null)")); + + _register_state_change (self); +} + +static void +_name_owner_changed_cb (GDBusConnection *connection, + const char *sender_name, + const char *object_path, + const char *interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) +{ + NMSecretAgentOld *self = user_data; + const char *new_owner; + + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sss)"))) + return; + + g_variant_get (parameters, + "(&s&s&s)", + NULL, + NULL, + &new_owner); + + _name_owner_changed (self, new_owner, TRUE); +} + +static void +_name_owner_get_cb (const char *name_owner, + GError *error, + gpointer user_data) +{ + if ( name_owner + || !nm_utils_error_is_cancelled (error)) + _name_owner_changed (user_data, name_owner, FALSE); +} + +/*****************************************************************************/ + +static void +_method_call (GDBusConnection *connection, + const char *sender, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + GDBusMethodInvocation *context, + gpointer user_data) +{ + NMSecretAgentOld *self = user_data; + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + nm_assert (nm_streq0 (object_path, NM_DBUS_PATH_SECRET_AGENT)); + nm_assert (nm_streq0 (interface_name, NM_DBUS_INTERFACE_SECRET_AGENT)); + nm_assert (sender); + nm_assert (nm_streq0 (sender, g_dbus_method_invocation_get_sender (context))); + + if ( !priv->name_owner_curr + || !priv->registered_against_server) { + /* priv->registered_against_server means that we started to register, but not necessarily + * that the registration fully succeeded. However, we already authenticated the request + * and so we accept it, even if the registration is not yet complete. */ + g_dbus_method_invocation_return_error_literal (context, + NM_SECRET_AGENT_ERROR, + NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, + "Request by non authenticated peer rejected"); + return; + } + + if (nm_streq (method_name, "GetSecrets")) + impl_get_secrets (self, parameters, context); + else if (nm_streq (method_name, "CancelGetSecrets")) + impl_cancel_get_secrets (self, parameters, context); + else if (nm_streq (method_name, "SaveSecrets")) + impl_save_secrets (self, parameters, context); + else if (nm_streq (method_name, "DeleteSecrets")) + impl_delete_secrets (self, parameters, context); else - g_task_return_boolean (task, TRUE); + nm_assert_not_reached (); } +/*****************************************************************************/ + static void -init_async_got_proxy (GObject *object, GAsyncResult *result, gpointer user_data) +_register_state_complete (NMSecretAgentOld *self) { - gs_unref_object GTask *task = user_data; - NMSecretAgentOld *self = g_task_get_source_object (task); NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - GError *error = NULL; + NMCListElem *elem; + gboolean any_tasks_to_complete = FALSE; + + if (!c_list_is_empty (&priv->pending_tasks_register_lst_head)) { + /* add a dummy sentinel. We want to complete all the task we started + * so far, but as we invoke user callbacks, the user might register + * new tasks. Those we don't complete in this run. */ + g_object_ref (self); + any_tasks_to_complete = TRUE; + c_list_link_tail (&priv->pending_tasks_register_lst_head, + &nm_c_list_elem_new_stale (&any_tasks_to_complete)->lst); + } + + _init_complete (self, NULL); + + if (any_tasks_to_complete) { + while ((elem = c_list_first_entry (&priv->pending_tasks_register_lst_head, NMCListElem, lst))) { + gpointer data = nm_c_list_elem_free_steal (elem); + gs_unref_object GTask *task = NULL; + + if (data == &any_tasks_to_complete) { + any_tasks_to_complete = FALSE; + break; + } + + task = data; + + if (!priv->is_registered) { + g_task_return_error (task, + g_error_new_literal (NM_SECRET_AGENT_ERROR, + NM_SECRET_AGENT_ERROR_FAILED, + _("registration failed"))); + continue; + } + g_task_return_boolean (task, TRUE); + } + nm_assert (!any_tasks_to_complete); + g_object_unref (self); + } +} + +static void +_register_state_change_do (NMSecretAgentOld *self) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + if (priv->is_destroyed) + priv->is_enabled = FALSE; + + if ( !priv->is_enabled + || priv->registration_force_unregister + || priv->name_owner_curr != priv->name_owner_next) { + GetSecretsInfo *info; - priv->manager_proxy = nmdbus_agent_manager_proxy_new_finish (result, &error); - if (!priv->manager_proxy) { - g_task_return_error (task, error); + while ((info = c_list_first_entry (&priv->gsi_lst_head, GetSecretsInfo, gsi_lst))) { + _cancel_get_secret_request (self, info, "The secret agent is going away"); + _register_state_change (self); + return; + } + + priv->registration_force_unregister = FALSE; + + nm_clear_g_cancellable (&priv->registering_cancellable); + nm_clear_g_source_inst (&priv->registering_retry_source); + + if (priv->registered_against_server) { + priv->registered_against_server = FALSE; + if (priv->name_owner_curr) { + _LOGT ("register: unregister from %s", priv->name_owner_curr->str); + _dbus_connection_call (self, + priv->name_owner_curr->str, + NM_DBUS_PATH_AGENT_MANAGER, + NM_DBUS_INTERFACE_AGENT_MANAGER, + "Unregister", + g_variant_new ("()"), + G_VARIANT_TYPE ("()"), + G_DBUS_CALL_FLAGS_NONE, + _CALL_REGISTER_TIMEOUT_MSEC, + NULL, + NULL, + NULL); + } + } + + if (!priv->is_enabled) { + nm_clear_g_cancellable (&priv->name_owner_cancellable); + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->name_owner_changed_id); + nm_clear_pointer (&priv->name_owner_curr, nm_ref_string_unref); + nm_clear_pointer (&priv->name_owner_next, nm_ref_string_unref); + } + + if (priv->is_registered) { + priv->is_registered = FALSE; + if (!priv->is_destroyed) { + _LOGT ("register: now unregistered"); + _notify (self, PROP_REGISTERED); + _register_state_change (self); + return; + } + } + + if (!priv->is_enabled) { + _register_state_complete (self); + return; + } + + if (priv->name_owner_curr != priv->name_owner_next) { + nm_ref_string_unref (priv->name_owner_curr); + priv->name_owner_curr = nm_ref_string_ref (priv->name_owner_next); + } + } + + if (priv->name_owner_changed_id == 0) { + nm_assert (!priv->name_owner_cancellable); + nm_assert (!priv->name_owner_curr); + nm_assert (!priv->name_owner_next); + priv->name_owner_cancellable = g_cancellable_new (); + priv->name_owner_changed_id = nm_dbus_connection_signal_subscribe_name_owner_changed (priv->dbus_connection, + NM_DBUS_SERVICE, + _name_owner_changed_cb, + self, + NULL); + nm_dbus_connection_call_get_name_owner (priv->dbus_connection, + NM_DBUS_SERVICE, + -1, + priv->name_owner_cancellable, + _name_owner_get_cb, + self); return; } - init_common (self); + if (priv->name_owner_cancellable) { + /* we still wait for the name owner. Nothing to do for now. */ + return; + } - if (!priv->auto_register) { - g_task_return_boolean (task, TRUE); + if (!priv->name_owner_curr) { + /* we don't have a name owner. We are done and wait. */ + _register_state_complete (self); return; } - nm_secret_agent_old_register_async (self, - g_task_get_cancellable (task), - init_async_registered, - task); - g_steal_pointer (&task); + if (priv->registering_cancellable) { + /* we are already registering... wait longer. */ + return; + } + + nm_assert (!priv->registering_retry_source); + + if (!priv->is_registered) { + /* start registering... */ + priv->registering_cancellable = g_cancellable_new (); + _dbus_connection_call (self, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "GetConnectionUnixUser", + g_variant_new ("(s)", priv->name_owner_curr->str), + G_VARIANT_TYPE ("(u)"), + G_DBUS_CALL_FLAGS_NONE, + _CALL_REGISTER_TIMEOUT_MSEC, + priv->registering_cancellable, + _get_connection_unix_user_cb, + self); + return; + } + + /* we are fully registered and done. */ + _register_state_complete (self); } static void -init_async_got_bus (GObject *initable, GAsyncResult *result, gpointer user_data) +_register_state_change (NMSecretAgentOld *self) { - gs_unref_object GTask *task = user_data; - NMSecretAgentOld *self = g_task_get_source_object (task); + _nm_unused gs_unref_object NMSecretAgentOld *self_keep_alive = g_object_ref (self); NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - GError *error = NULL; + nm_auto_pop_gmaincontext GMainContext *dbus_context = NULL; + + if (priv->register_state_change_reenter == 0) { + /* We are not yet initialized. Do nothing. */ + return; + } - priv->bus = g_bus_get_finish (result, &error); - if (!priv->bus) { - g_task_return_error (task, error); + if (priv->register_state_change_reenter != 1) { + /* Recursive calls are prevented. Do nothing for now, but repeat + * the state change afterwards. */ + priv->register_state_change_reenter = 3; return; } - nmdbus_agent_manager_proxy_new (priv->bus, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES - | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, - NM_DBUS_SERVICE, - NM_DBUS_PATH_AGENT_MANAGER, - g_task_get_cancellable (task), - init_async_got_proxy, - task); - g_steal_pointer (&task); + dbus_context = nm_g_main_context_push_thread_default_if_necessary (priv->dbus_context); + +again: + priv->register_state_change_reenter = 2; + + _register_state_change_do (self); + + if (priv->register_state_change_reenter != 2) + goto again; + + priv->register_state_change_reenter = 1; +} + +/*****************************************************************************/ + +static void +_init_complete (NMSecretAgentOld *self, + GError *error_take) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + gs_free_error GError *error = g_steal_pointer (&error_take); + GError *error_cancelled = NULL; + + if (!priv->init_data) + return; + + if (g_cancellable_set_error_if_cancelled (priv->init_data->cancellable, &error_cancelled)) { + g_clear_error (&error); + g_propagate_error (&error, error_cancelled); + } + + priv->is_initialized = (!error); + + _LOGT ("%s init complete with %s%s%s", + priv->init_data->is_sync ? "sync" : "async", + NM_PRINT_FMT_QUOTED (error_take, "error: ", error_take->message, "", "success")); + + nml_init_data_return (g_steal_pointer (&priv->init_data), + g_steal_pointer (&error)); +} + +static void +_init_register_object (NMSecretAgentOld *self) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + gs_free_error GError *error = NULL; + GDBusInterfaceVTable interface_vtable = { + .method_call = _method_call, + }; + + if (g_cancellable_set_error_if_cancelled (priv->init_data->cancellable, &error)) { + _init_complete (self, g_steal_pointer (&error)); + return; + } + + priv->exported_id = g_dbus_connection_register_object (priv->dbus_connection, + NM_DBUS_PATH_SECRET_AGENT, + (GDBusInterfaceInfo*) &interface_info, + &interface_vtable, + self, + NULL, + &error); + if (priv->exported_id == 0) { + _init_complete (self, g_steal_pointer (&error)); + return; + } + + priv->register_state_change_reenter = 1; + + _register_state_change (self); +} + +static void +_init_got_bus (GObject *initable, GAsyncResult *result, gpointer user_data) +{ + NMSecretAgentOld *self = user_data; + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + gs_free_error GError *error = NULL; + + priv->dbus_connection = g_bus_get_finish (result, &error); + if (!priv->dbus_connection) { + _init_complete (self, g_steal_pointer (&error)); + return; + } + + _LOGT ("init: got GDBusConnection"); + + _notify (self, PROP_DBUS_CONNECTION); + + _init_register_object (self); +} + +static void +_init_start (NMSecretAgentOld *self) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + if (!priv->dbus_connection) { + GBusType bus_type; + + bus_type = _nm_dbus_bus_type (); + + priv->session_bus = (bus_type == G_BUS_TYPE_SESSION); + + g_bus_get (bus_type, + priv->init_data->cancellable, + _init_got_bus, + self); + return; + } + + _init_register_object (self); +} + +static void +init_async (GAsyncInitable *initable, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMSecretAgentOld *self; + NMSecretAgentOldClass *klass; + NMSecretAgentOldPrivate *priv; + nm_auto_pop_gmaincontext GMainContext *dbus_context = NULL; + gs_unref_object GTask *task = NULL; + + g_return_if_fail (NM_IS_SECRET_AGENT_OLD (initable)); + + self = NM_SECRET_AGENT_OLD (initable); + priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + g_return_if_fail (!priv->dbus_context); + g_return_if_fail (!priv->is_destroyed); + + klass = NM_SECRET_AGENT_OLD_GET_CLASS (self); + g_return_if_fail (klass->get_secrets); + g_return_if_fail (klass->cancel_get_secrets); + g_return_if_fail (klass->save_secrets); + g_return_if_fail (klass->delete_secrets); + + _LOGT ("init-async starting..."); + + priv->dbus_context = g_main_context_ref (priv->main_context); + + dbus_context = nm_g_main_context_push_thread_default_if_necessary (priv->dbus_context); + + task = nm_g_task_new (self, cancellable, init_async, callback, user_data); + g_task_set_priority (task, io_priority); + + priv->init_data = nml_init_data_new_async (cancellable, g_steal_pointer (&task)); + + _init_start (self); +} + +static gboolean +init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) +{ + g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (initable), FALSE); + g_return_val_if_fail (nm_g_task_is_valid (result, initable, init_async), FALSE); + + return g_task_propagate_boolean (G_TASK (result), error); +} + +/*****************************************************************************/ + +static gboolean +init_sync (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + gs_unref_object NMSecretAgentOld *self = NULL; + NMSecretAgentOldPrivate *priv; + NMSecretAgentOldClass *klass; + GMainLoop *main_loop; + GError *local_error = NULL; + + g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (initable), FALSE); + + self = g_object_ref (NM_SECRET_AGENT_OLD (initable)); + priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + g_return_val_if_fail (!priv->dbus_context, FALSE); + g_return_val_if_fail (!priv->is_destroyed, FALSE); + + klass = NM_SECRET_AGENT_OLD_GET_CLASS (self); + g_return_val_if_fail (klass->get_secrets, FALSE); + g_return_val_if_fail (klass->cancel_get_secrets, FALSE); + g_return_val_if_fail (klass->save_secrets, FALSE); + g_return_val_if_fail (klass->delete_secrets, FALSE); + + _LOGT ("init-sync"); + + /* See NMClient's sync-init method for explanation about why we create + * an internal GMainContext priv->dbus_context. */ + + priv->dbus_context = g_main_context_new (); + + g_main_context_push_thread_default (priv->dbus_context); + + main_loop = g_main_loop_new (priv->dbus_context, FALSE); + + priv->init_data = nml_init_data_new_sync (cancellable, main_loop, &local_error); + + _init_start (self); + + g_main_loop_run (main_loop); + + g_main_loop_unref (main_loop); + + g_main_context_pop_thread_default (priv->dbus_context); + + nm_context_busy_watcher_integrate_source (priv->main_context, + priv->dbus_context, + priv->context_busy_watcher); + + if (local_error) { + g_propagate_error (error, local_error); + return FALSE; + } + + return TRUE; } /*****************************************************************************/ @@ -1164,6 +1804,9 @@ get_property (GObject *object, NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (object); switch (prop_id) { + case PROP_DBUS_CONNECTION: + g_value_set_object (value, priv->dbus_connection); + break; case PROP_IDENTIFIER: g_value_set_string (value, priv->identifier); break; @@ -1171,7 +1814,7 @@ get_property (GObject *object, g_value_set_boolean (value, priv->auto_register); break; case PROP_REGISTERED: - g_value_set_boolean (value, priv->registered); + g_value_set_boolean (value, priv->is_registered); break; case PROP_CAPABILITIES: g_value_set_flags (value, priv->capabilities); @@ -1188,23 +1831,34 @@ set_property (GObject *object, const GValue *value, GParamSpec *pspec) { - NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (object); - const char *identifier; + NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (object); + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + guint u; switch (prop_id) { + case PROP_DBUS_CONNECTION: + /* construct-only */ + priv->dbus_connection = g_value_dup_object (value); + break; case PROP_IDENTIFIER: - identifier = g_value_get_string (value); - - g_return_if_fail (validate_identifier (identifier)); - - g_free (priv->identifier); - priv->identifier = g_strdup (identifier); + /* construct-only */ + priv->identifier = g_value_dup_string (value); + g_return_if_fail (validate_identifier (priv->identifier)); break; case PROP_AUTO_REGISTER: + /* construct */ priv->auto_register = g_value_get_boolean (value); + priv->is_enabled = priv->auto_register; + _register_state_change (self); break; case PROP_CAPABILITIES: - priv->capabilities = g_value_get_flags (value); + /* construct */ + u = g_value_get_flags (value); + if (u != priv->capabilities) { + priv->capabilities = u; + priv->registration_force_unregister = TRUE; + _register_state_change (self); + } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1222,94 +1876,46 @@ nm_secret_agent_old_init (NMSecretAgentOld *self) _LOGT ("create new instance"); c_list_init (&priv->gsi_lst_head); - priv->dbus_secret_agent = nmdbus_secret_agent_skeleton_new (); - _nm_dbus_bind_properties (self, priv->dbus_secret_agent); - _nm_dbus_bind_methods (self, priv->dbus_secret_agent, - "GetSecrets", impl_secret_agent_old_get_secrets, - "CancelGetSecrets", impl_secret_agent_old_cancel_get_secrets, - "DeleteSecrets", impl_secret_agent_old_delete_secrets, - "SaveSecrets", impl_secret_agent_old_save_secrets, - NULL); -} - -static gboolean -init_sync (GInitable *initable, GCancellable *cancellable, GError **error) -{ - NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (initable); - NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - - _LOGT ("init-sync"); + c_list_init (&priv->pending_tasks_register_lst_head); - priv->bus = g_bus_get_sync (_nm_dbus_bus_type (), cancellable, error); - if (!priv->bus) - return FALSE; - - priv->manager_proxy = nmdbus_agent_manager_proxy_new_sync (priv->bus, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES - | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, - NM_DBUS_SERVICE, - NM_DBUS_PATH_AGENT_MANAGER, - cancellable, - error); - if (!priv->manager_proxy) - return FALSE; - - init_common (self); - - if (priv->auto_register) - return nm_secret_agent_old_register (self, cancellable, error); - else - return TRUE; + priv->main_context = g_main_context_ref_thread_default (); + priv->context_busy_watcher = g_object_new (G_TYPE_OBJECT, NULL); } static void -init_async (GAsyncInitable *initable, int io_priority, - GCancellable *cancellable, GAsyncReadyCallback callback, - gpointer user_data) +dispose (GObject *object) { - NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (initable); - GTask *task; + NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (object); - _LOGT ("init-async starting..."); + _LOGT ("disposing"); - task = g_task_new (self, cancellable, callback, user_data); - g_task_set_priority (task, io_priority); + _secret_agent_old_destroy (self); - g_bus_get (_nm_dbus_bus_type (), - cancellable, - init_async_got_bus, - task); + G_OBJECT_CLASS (nm_secret_agent_old_parent_class)->dispose (object); } static void -dispose (GObject *object) +finalize (GObject *object) { NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (object); NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); - GetSecretsInfo *info; - _LOGT ("disposing"); + _LOGT ("finalizing"); - if (priv->registered) { - priv->registered = FALSE; - nm_secret_agent_old_unregister_async (self, NULL, NULL, NULL); + if (priv->dbus_context) { + nml_cleanup_context_busy_watcher_on_idle (g_steal_pointer (&priv->context_busy_watcher), + priv->dbus_context); } - nm_clear_g_free (&priv->identifier); + g_clear_object (&priv->dbus_connection); + nm_clear_pointer (&priv->dbus_context, g_main_context_unref); + nm_clear_pointer (&priv->main_context, g_main_context_unref); - while ((info = c_list_first_entry (&priv->gsi_lst_head, GetSecretsInfo, gsi_lst))) - get_secrets_info_free (info); + g_clear_object (&priv->context_busy_watcher); - if (priv->dbus_secret_agent) { - g_signal_handlers_disconnect_matched (priv->dbus_secret_agent, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, self); - g_clear_object (&priv->dbus_secret_agent); - } + g_free (priv->identifier); - g_clear_object (&priv->manager_proxy); - g_clear_object (&priv->bus); - - G_OBJECT_CLASS (nm_secret_agent_old_parent_class)->dispose (object); + G_OBJECT_CLASS (nm_secret_agent_old_parent_class)->finalize (object); } static void @@ -1319,9 +1925,26 @@ nm_secret_agent_old_class_init (NMSecretAgentOldClass *class) g_type_class_add_private (class, sizeof (NMSecretAgentOldPrivate)); - object_class->dispose = dispose; object_class->get_property = get_property; object_class->set_property = set_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + /** + * NMSecretAgentOld:dbus-connection: + * + * The #GDBusConnection used by the instance. You may either set this + * as construct-only property, or otherwise #NMSecretAgentOld will choose + * a connection via g_bus_get() during initialization. + * + * Since: 1.24 + **/ + obj_properties[PROP_DBUS_CONNECTION] = + g_param_spec_object (NM_SECRET_AGENT_OLD_DBUS_CONNECTION, "", "", + G_TYPE_DBUS_CONNECTION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); /** * NMSecretAgentOld:identifier: @@ -1350,17 +1973,17 @@ nm_secret_agent_old_class_init (NMSecretAgentOldClass *class) * * In particular, if this property is %TRUE at construct time, then the * agent will register itself with NetworkManager during - * construction/initialization, and initialization will fail with an error - * if the agent is unable to register itself. + * construction/initialization and initialization will only complete + * after registration is completed (either successfully or unsucessfully). + * Since 1.24, a failure to register will no longer cause initialization + * of #NMSecretAgentOld to fail. * * If the property is %FALSE, the agent will not automatically register with - * NetworkManager, and nm_secret_agent_old_register() or + * NetworkManager, and nm_secret_agent_old_enable() or * nm_secret_agent_old_register_async() must be called to register it. * - * Calling nm_secret_agent_old_unregister() will suppress auto-registration - * until nm_secret_agent_old_register() is called, which re-enables - * auto-registration. This ensures that the agent remains un-registered when - * you expect it to be unregistered. + * Calling nm_secret_agent_old_enable() has the same effect as setting this + * property. **/ obj_properties[PROP_AUTO_REGISTER] = g_param_spec_boolean (NM_SECRET_AGENT_OLD_AUTO_REGISTER, "", "", @@ -1384,6 +2007,9 @@ nm_secret_agent_old_class_init (NMSecretAgentOldClass *class) * NMSecretAgentOld:capabilities: * * A bitfield of %NMSecretAgentCapabilities. + * + * Changing this property is possible at any time. In case the secret + * agent is currently registered, this will cause a re-registration. **/ obj_properties[PROP_CAPABILITIES] = g_param_spec_flags (NM_SECRET_AGENT_OLD_CAPABILITIES, "", "", @@ -1405,6 +2031,6 @@ nm_secret_agent_old_initable_iface_init (GInitableIface *iface) static void nm_secret_agent_old_async_initable_iface_init (GAsyncInitableIface *iface) { - iface->init_async = init_async; - /* Use default implementation for init_finish */ + iface->init_async = init_async; + iface->init_finish = init_finish; } diff --git a/libnm/nm-secret-agent-old.h b/libnm/nm-secret-agent-old.h index af0dabe7..07deee2c 100644 --- a/libnm/nm-secret-agent-old.h +++ b/libnm/nm-secret-agent-old.h @@ -21,6 +21,7 @@ G_BEGIN_DECLS #define NM_SECRET_AGENT_OLD_AUTO_REGISTER "auto-register" #define NM_SECRET_AGENT_OLD_REGISTERED "registered" #define NM_SECRET_AGENT_OLD_CAPABILITIES "capabilities" +#define NM_SECRET_AGENT_OLD_DBUS_CONNECTION "dbus-connection" /** * NMSecretAgentOld: @@ -126,9 +127,12 @@ typedef struct { /* Called when the subclass should retrieve and return secrets. Subclass * must copy or reference any arguments it may require after returning from * this method, as the arguments will freed (except for 'self', 'callback', - * and 'user_data' of course). If the request is canceled, the callback - * should still be called, but with the - * NM_SECRET_AGENT_OLD_ERROR_AGENT_CANCELED error. + * and 'user_data' of course). + * + * Before version 1.24, if the request is canceled, the callback + * should still be called, but with the NM_SECRET_AGENT_ERROR_AGENT_CANCELED + * error. Since 1.24, invoking the callback has no effect during cancellation + * and may be omitted. */ void (*get_secrets) (NMSecretAgentOld *self, NMConnection *connection, @@ -140,10 +144,12 @@ typedef struct { gpointer user_data); /* Called when the subclass should cancel an outstanding request to - * get secrets for a given connection. Canceling the request MUST - * call the callback that was passed along with the initial get_secrets - * call, sending the NM_SECRET_AGENT_OLD_ERROR/ - * NM_SECRET_AGENT_OLD_ERROR_AGENT_CANCELED error to that callback. + * get secrets for a given connection. + * + * Before version 1.24, canceling the request MUST call the callback that was + * passed along with the initial get_secrets call, sending the NM_SECRET_AGENT_ERROR/ + * NM_SECRET_AGENT_ERROR_AGENT_CANCELED error to that callback. Since 1.24, + * the get_secrets callback will be ignored during cancellation and may be omitted. */ void (*cancel_get_secrets) (NMSecretAgentOld *self, const char *connection_path, @@ -179,9 +185,26 @@ typedef struct { GType nm_secret_agent_old_get_type (void); -gboolean nm_secret_agent_old_register (NMSecretAgentOld *self, - GCancellable *cancellable, - GError **error); +NM_AVAILABLE_IN_1_24 +GDBusConnection *nm_secret_agent_old_get_dbus_connection (NMSecretAgentOld *self); + +NM_AVAILABLE_IN_1_24 +GMainContext *nm_secret_agent_old_get_main_context (NMSecretAgentOld *self); + +NM_AVAILABLE_IN_1_24 +GObject *nm_secret_agent_old_get_context_busy_watcher (NMSecretAgentOld *self); + +NM_AVAILABLE_IN_1_24 +const char *nm_secret_agent_old_get_dbus_name_owner (NMSecretAgentOld *self); + +gboolean nm_secret_agent_old_get_registered (NMSecretAgentOld *self); + +/*****************************************************************************/ + +NM_AVAILABLE_IN_1_24 +void nm_secret_agent_old_enable (NMSecretAgentOld *self, + gboolean enable); + void nm_secret_agent_old_register_async (NMSecretAgentOld *self, GCancellable *cancellable, GAsyncReadyCallback callback, @@ -190,18 +213,33 @@ gboolean nm_secret_agent_old_register_finish (NMSecretAgentOld *self, GAsyncResult *result, GError **error); +NM_AVAILABLE_IN_1_24 +void nm_secret_agent_old_destroy (NMSecretAgentOld *self); + +/*****************************************************************************/ + +NM_DEPRECATED_IN_1_24_FOR (nm_secret_agent_old_enable) +gboolean nm_secret_agent_old_register (NMSecretAgentOld *self, + GCancellable *cancellable, + GError **error); + +NM_DEPRECATED_IN_1_24_FOR (nm_secret_agent_old_enable) gboolean nm_secret_agent_old_unregister (NMSecretAgentOld *self, GCancellable *cancellable, GError **error); + +NM_DEPRECATED_IN_1_24_FOR (nm_secret_agent_old_enable) void nm_secret_agent_old_unregister_async (NMSecretAgentOld *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); + +NM_DEPRECATED_IN_1_24_FOR (nm_secret_agent_old_enable) gboolean nm_secret_agent_old_unregister_finish (NMSecretAgentOld *self, GAsyncResult *result, GError **error); -gboolean nm_secret_agent_old_get_registered (NMSecretAgentOld *self); +/*****************************************************************************/ void nm_secret_agent_old_get_secrets (NMSecretAgentOld *self, NMConnection *connection, diff --git a/libnm/nm-settings-docs-overrides.xml b/libnm/nm-settings-docs-overrides.xml index 019dfc64..7442dbd0 100644 --- a/libnm/nm-settings-docs-overrides.xml +++ b/libnm/nm-settings-docs-overrides.xml @@ -162,6 +162,8 @@ vlan's interface name."/> </setting> <setting name="vpn"> </setting> +<setting name="vrf"> +</setting> <setting name="vxlan"> </setting> <setting name="wifi-p2p"> diff --git a/libnm/nm-settings-docs.xml b/libnm/nm-settings-docs.xml index 68f09cdb..9a139a16 100644 --- a/libnm/nm-settings-docs.xml +++ b/libnm/nm-settings-docs.xml @@ -43,7 +43,8 @@ <property name="client-cert" name_upper="CLIENT_CERT" type="byte array" description="Contains the client certificate if used by the EAP method specified in the "eap" property. Certificate data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string "file://" and ending with a terminating NUL byte." /> <property name="client-cert-password" name_upper="CLIENT_CERT_PASSWORD" type="string" description="The password used to access the client certificate stored in "client-cert" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login." /> <property name="client-cert-password-flags" name_upper="CLIENT_CERT_PASSWORD_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "client-cert-password" property." /> - <property name="domain-suffix-match" name_upper="DOMAIN_SUFFIX_MATCH" type="string" description="Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison." /> + <property name="domain-match" name_upper="DOMAIN_MATCH" type="string" description="Constraint for server domain name. If set, this list of FQDNs is used as a match requirement for dNSName element(s) of the certificate presented by the authentication server. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using the same comparison. Multiple valid FQDNs can be passed as a ";" delimited list." /> + <property name="domain-suffix-match" name_upper="DOMAIN_SUFFIX_MATCH" type="string" description="Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison. Since version 1.24, multiple valid FQDNs can be passed as a ";" delimited list." /> <property name="eap" name_upper="EAP" type="array of string" description="The allowed EAP method to be used when authenticating to the network with 802.1x. Valid methods are: "leap", "md5", "tls", "peap", "ttls", "pwd", and "fast". Each method requires different configuration using the properties of this setting; refer to wpa_supplicant documentation for the allowed combinations." /> <property name="identity" name_upper="IDENTITY" type="string" description="Identity string for EAP authentication methods. Often the user's user or login name." /> <property name="optional" name_upper="OPTIONAL" type="boolean" default="FALSE" description="Whether the 802.1X authentication is optional. If TRUE, the activation will continue even after a timeout or an authentication failure. Setting the property to TRUE is currently allowed only for Ethernet connections. If set to FALSE, the activation can continue only after a successful authentication." /> @@ -66,7 +67,8 @@ <property name="phase2-client-cert" name_upper="PHASE2_CLIENT_CERT" type="byte array" description="Contains the "phase 2" client certificate if used by the EAP method specified in the "phase2-auth" or "phase2-autheap" properties. Certificate data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string "file://" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended." /> <property name="phase2-client-cert-password" name_upper="PHASE2_CLIENT_CERT_PASSWORD" type="string" description="The password used to access the "phase2" client certificate stored in "phase2-client-cert" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login." /> <property name="phase2-client-cert-password-flags" name_upper="PHASE2_CLIENT_CERT_PASSWORD_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "phase2-client-cert-password" property." /> - <property name="phase2-domain-suffix-match" name_upper="PHASE2_DOMAIN_SUFFIX_MATCH" type="string" description="Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner "phase 2" authentication. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison." /> + <property name="phase2-domain-match" name_upper="PHASE2_DOMAIN_MATCH" type="string" description="Constraint for server domain name. If set, this list of FQDNs is used as a match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner "phase 2" authentication. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using the same comparison. Multiple valid FQDNs can be passed as a ";" delimited list." /> + <property name="phase2-domain-suffix-match" name_upper="PHASE2_DOMAIN_SUFFIX_MATCH" type="string" description="Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner "phase 2" authentication. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison. Since version 1.24, multiple valid FQDNs can be passed as a ";" delimited list." /> <property name="phase2-private-key" name_upper="PHASE2_PRIVATE_KEY" type="byte array" description="Contains the "phase 2" inner private key when the "phase2-auth" or "phase2-autheap" property is set to "tls". Key data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data. When using private keys with the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string "file://" and ending with a terminating NUL byte. When using PKCS#12 format private keys and the blob scheme, this property should be set to the PKCS#12 data and the "phase2-private-key-password" property must be set to password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files and the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string "file://" and ending with a terminating NUL byte, and as with the blob scheme the "phase2-private-key-password" property must be set to the password used to decode the PKCS#12 private key and certificate." /> <property name="phase2-private-key-password" name_upper="PHASE2_PRIVATE_KEY_PASSWORD" type="string" description="The password used to decrypt the "phase 2" private key specified in the "phase2-private-key" property when the private key either uses the path scheme, or is a PKCS#12 format key." /> <property name="phase2-private-key-password-flags" name_upper="PHASE2_PRIVATE_KEY_PASSWORD_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "phase2-private-key-password" property." /> @@ -99,16 +101,22 @@ <setting name="bridge" description="Bridging Settings" name_upper="BRIDGE" > <property name="ageing-time" name_upper="AGEING_TIME" type="uint32" default="300" description="The Ethernet MAC address aging time, in seconds." /> <property name="forward-delay" name_upper="FORWARD_DELAY" type="uint32" default="15" description="The Spanning Tree Protocol (STP) forwarding delay, in seconds." /> + <property name="group-address" name_upper="GROUP_ADDRESS" type="byte array" description="If specified, The MAC address of the multicast group this bridge uses for STP. The address must be a link-local address in standard Ethernet MAC address format, ie an address of the form 01:80:C2:00:00:0X, with X in [0, 4..F]. If not specified the default value is 01:80:C2:00:00:00." /> <property name="group-forward-mask" name_upper="GROUP_FORWARD_MASK" type="uint32" default="0" description="A mask of group addresses to forward. Usually, group addresses in the range from 01:80:C2:00:00:00 to 01:80:C2:00:00:0F are not forwarded according to standards. This property is a mask of 16 bits, each corresponding to a group address in that range that must be forwarded. The mask can't have bits 0, 1 or 2 set because they are used for STP, MAC pause frames and LACP." /> <property name="hello-time" name_upper="HELLO_TIME" type="uint32" default="2" description="The Spanning Tree Protocol (STP) hello time, in seconds." /> <property name="interface-name" name_upper="INTERFACE_NAME" type="string" description="Deprecated in favor of connection.interface-name, but can be used for backward-compatibility with older daemons, to set the bridge's interface name." /> <property name="mac-address" name_upper="MAC_ADDRESS" type="byte array" description="If specified, the MAC address of bridge. When creating a new bridge, this MAC address will be set. If this field is left unspecified, the "ethernet.cloned-mac-address" is referred instead to generate the initial MAC address. Note that setting "ethernet.cloned-mac-address" anyway overwrites the MAC address of the bridge later while activating the bridge. Hence, this property is deprecated. Deprecated: 1" /> <property name="max-age" name_upper="MAX_AGE" type="uint32" default="20" description="The Spanning Tree Protocol (STP) maximum message age, in seconds." /> + <property name="multicast-querier" name_upper="MULTICAST_QUERIER" type="boolean" default="FALSE" description="Enable or disable sending of multicast queries by the bridge. If not specified the option is disabled." /> + <property name="multicast-query-use-ifaddr" name_upper="MULTICAST_QUERY_USE_IFADDR" type="boolean" default="FALSE" description="If enabled the bridge's own IP address is used as the source address for IGMP queries otherwise the default of 0.0.0.0 is used." /> + <property name="multicast-router" name_upper="MULTICAST_ROUTER" type="string" description="Sets bridge's multicast router. multicast-snooping must be enabled for this option to work. Supported values are: 'auto', 'disabled', 'enabled'. If not specified the default value is 'auto'." /> <property name="multicast-snooping" name_upper="MULTICAST_SNOOPING" type="boolean" default="TRUE" description="Controls whether IGMP snooping is enabled for this bridge. Note that if snooping was automatically disabled due to hash collisions, the system may refuse to enable the feature until the collisions are resolved." /> <property name="priority" name_upper="PRIORITY" type="uint32" default="32768" description="Sets the Spanning Tree Protocol (STP) priority for this bridge. Lower values are "better"; the lowest priority bridge will be elected the root bridge." /> <property name="stp" name_upper="STP" type="boolean" default="TRUE" description="Controls whether Spanning Tree Protocol (STP) is enabled for this bridge." /> <property name="vlan-default-pvid" name_upper="VLAN_DEFAULT_PVID" type="uint32" default="1" description="The default PVID for the ports of the bridge, that is the VLAN id assigned to incoming untagged frames." /> <property name="vlan-filtering" name_upper="VLAN_FILTERING" type="boolean" default="FALSE" description="Control whether VLAN filtering is enabled on the bridge." /> + <property name="vlan-protocol" name_upper="VLAN_PROTOCOL" type="string" description="If specified, the protocol used for VLAN filtering. Supported values are: '802.1Q', '802.1ad'. If not specified the default value is '802.1Q'." /> + <property name="vlan-stats-enabled" name_upper="VLAN_STATS_ENABLED" type="boolean" default="FALSE" description="Controls whether per-VLAN stats accounting is enabled." /> <property name="vlans" name_upper="VLANS" type="array of vardict" description="Array of bridge VLAN objects. In addition to the VLANs specified here, the bridge will also have the default-pvid VLAN configured by the bridge.vlan-default-pvid property. In nmcli the VLAN list can be specified with the following syntax: $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... where $vid is either a single id between 1 and 4094 or a range, represented as a couple of ids separated by a dash." /> </setting> <setting name="bridge-port" description="Bridge Port Settings" name_upper="BRIDGE_PORT" > @@ -183,7 +191,7 @@ <property name="dhcp-timeout" name_upper="DHCP_TIMEOUT" type="int32" default="0" description="A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity." /> <property name="dns" name_upper="DNS" type="array of uint32" description="Array of IP addresses of DNS servers (as network-byte-order integers)" /> <property name="dns-options" name_upper="DNS_OPTIONS" type="array of string" description="Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties." /> - <property name="dns-priority" name_upper="DNS_PRIORITY" type="int32" default="0" description="DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored." /> + <property name="dns-priority" name_upper="DNS_PRIORITY" type="int32" default="0" description="DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored." /> <property name="dns-search" name_upper="DNS_SEARCH" type="array of string" description="Array of DNS search domains. Domains starting with a tilde ('~') are considered 'routing' domains and are used only to decide the interface over which a query must be forwarded; they are not used to complete unqualified host names." /> <property name="gateway" name_upper="GATEWAY" type="string" description="The gateway associated with this configuration. This is only meaningful if "addresses" is also set." /> <property name="ignore-auto-dns" name_upper="IGNORE_AUTO_DNS" type="boolean" default="FALSE" description="When "method" is set to "auto" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the "dns" and "dns-search" properties, if any, are used." /> @@ -209,7 +217,7 @@ <property name="dhcp-timeout" name_upper="DHCP_TIMEOUT" type="int32" default="0" description="A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity." /> <property name="dns" name_upper="DNS" type="array of byte array" description="Array of IP addresses of DNS servers (in network byte order)" /> <property name="dns-options" name_upper="DNS_OPTIONS" type="array of string" description="Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties." /> - <property name="dns-priority" name_upper="DNS_PRIORITY" type="int32" default="0" description="DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored." /> + <property name="dns-priority" name_upper="DNS_PRIORITY" type="int32" default="0" description="DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored." /> <property name="dns-search" name_upper="DNS_SEARCH" type="array of string" description="Array of DNS search domains. Domains starting with a tilde ('~') are considered 'routing' domains and are used only to decide the interface over which a query must be forwarded; they are not used to complete unqualified host names." /> <property name="gateway" name_upper="GATEWAY" type="string" description="The gateway associated with this configuration. This is only meaningful if "addresses" is also set." /> <property name="ignore-auto-dns" name_upper="IGNORE_AUTO_DNS" type="boolean" default="FALSE" description="When "method" is set to "auto" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the "dns" and "dns-search" properties, if any, are used." /> @@ -257,7 +265,7 @@ <property name="promiscuous" name_upper="PROMISCUOUS" type="boolean" default="TRUE" description="Whether the interface should be put in promiscuous mode." /> <property name="tap" name_upper="TAP" type="boolean" default="FALSE" description="Whether the interface should be a MACVTAP." /> </setting> - <setting name="match" description="Match settings." name_upper="MATCH" > + <setting name="match" description="Match settings" name_upper="MATCH" > <property name="interface-name" name_upper="INTERFACE_NAME" type="array of string" description="A list of interface names to match. Each element is a shell wildcard pattern. When an element is prefixed with exclamation mark (!) the condition is inverted. A candidate interface name is considered matching when both these conditions are satisfied: (a) any of the elements not prefixed with '!' matches or there aren't such elements; (b) none of the elements prefixed with '!' match." /> </setting> <setting name="802-11-olpc-mesh" description="OLPC Wireless Mesh Settings" name_upper="OLPC_MESH" > @@ -329,12 +337,12 @@ <property name="send-delay" name_upper="SEND_DELAY" type="uint64" default="0" description="Time to delay between each byte sent to the modem, in microseconds." /> <property name="stopbits" name_upper="STOPBITS" type="uint32" default="1" description="Number of stop bits for communication on the serial port. Either 1 or 2. The 1 in "8n1" for example." /> </setting> - <setting name="sriov" description="SR-IOV settings." name_upper="SRIOV" > + <setting name="sriov" description="SR-IOV settings" name_upper="SRIOV" > <property name="autoprobe-drivers" name_upper="AUTOPROBE_DRIVERS" type="NMTernary (int32)" description="Whether to autoprobe virtual functions by a compatible driver. If set to NM_TERNARY_TRUE (1), the kernel will try to bind VFs to a compatible driver and if this succeeds a new network interface will be instantiated for each VF. If set to NM_TERNARY_FALSE (0), VFs will not be claimed and no network interfaces will be created for them. When set to NM_TERNARY_DEFAULT (-1), the global default is used; in case the global default is unspecified it is assumed to be NM_TERNARY_TRUE (1)." /> - <property name="total-vfs" name_upper="TOTAL_VFS" type="uint32" default="0" description="The total number of virtual functions to create. Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface also when it is zero. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection." /> + <property name="total-vfs" name_upper="TOTAL_VFS" type="uint32" default="0" description="The total number of virtual functions to create. Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface (also when it is zero) during activation and resets it upon deactivation. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection." /> <property name="vfs" name_upper="VFS" type="array of vardict" description="Array of virtual function descriptors. Each VF descriptor is a dictionary mapping attribute names to GVariant values. The 'index' entry is mandatory for each VF. When represented as string a VF is in the form: "INDEX [ATTR=VALUE[ ATTR=VALUE]...]". for example: "2 mac=00:11:22:33:44:55 spoof-check=true". Multiple VFs can be specified using a comma as separator. Currently the following attributes are supported: mac, spoof-check, trust, min-tx-rate, max-tx-rate, vlans. The "vlans" attribute is represented as a semicolon-separated list of VLAN descriptors, where each descriptor has the form "ID[.PRIORITY[.PROTO]]". PROTO can be either 'q' for 802.1Q (the default) or 'ad' for 802.1ad." /> </setting> - <setting name="tc" description="Linux Traffic Control Settings." name_upper="TC_CONFIG" > + <setting name="tc" description="Linux Traffic Control Settings" name_upper="TC_CONFIG" > <property name="qdiscs" name_upper="QDISCS" type="array of vardict" description="Array of TC queueing disciplines." /> <property name="tfilters" name_upper="TFILTERS" type="array of vardict" description="Array of TC traffic filters." /> </setting> @@ -393,6 +401,9 @@ <property name="timeout" name_upper="TIMEOUT" type="uint32" default="0" description="Timeout for the VPN service to establish the connection. Some services may take quite a long time to connect. Value of 0 means a default timeout, which is 60 seconds (unless overridden by vpn.timeout in configuration file). Values greater than zero mean timeout in seconds." /> <property name="user-name" name_upper="USER_NAME" type="string" description="If the VPN connection requires a user name for authentication, that name should be provided here. If the connection is available to more than one user, and the VPN requires each user to supply a different name, then leave this property empty. If this property is empty, NetworkManager will automatically supply the username of the user which requested the VPN connection." /> </setting> + <setting name="vrf" description="VRF settings" name_upper="VRF" > + <property name="table" name_upper="TABLE" type="uint32" default="0" description="The routing table for this VRF." /> + </setting> <setting name="vxlan" description="VXLAN Settings" name_upper="VXLAN" > <property name="ageing" name_upper="AGEING" type="uint32" default="300" description="Specifies the lifetime in seconds of FDB entries learnt by the kernel." /> <property name="destination-port" name_upper="DESTINATION_PORT" type="uint32" default="8472" description="Specifies the UDP destination port to communicate to the remote VXLAN tunnel endpoint." /> @@ -473,7 +484,7 @@ <property name="auth-alg" name_upper="AUTH_ALG" type="string" description="When WEP is used (ie, key-mgmt = "none" or "ieee8021x") indicate the 802.11 authentication algorithm required by the AP here. One of "open" for Open System, "shared" for Shared Key, or "leap" for Cisco LEAP. When using Cisco LEAP (ie, key-mgmt = "ieee8021x" and auth-alg = "leap") the "leap-username" and "leap-password" properties must be specified." /> <property name="fils" name_upper="FILS" type="int32" default="0" description="Indicates whether Fast Initial Link Setup (802.11ai) must be enabled for the connection. One of NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) (use global default value), NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE (1) (disable FILS), NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL (2) (enable FILS if the supplicant and the access point support it) or NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED (3) (enable FILS and fail if not supported). When set to NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) and no global default is set, FILS will be optionally enabled." /> <property name="group" name_upper="GROUP" type="array of string" description="A list of group/broadcast encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list. For maximum compatibility leave this property empty. Each list element may be one of "wep40", "wep104", "tkip", or "ccmp"." /> - <property name="key-mgmt" name_upper="KEY_MGMT" type="string" description="Key management used for the connection. One of "none" (WEP), "ieee8021x" (Dynamic WEP), "wpa-psk" (infrastructure WPA-PSK), "sae" (SAE) or "wpa-eap" (WPA-Enterprise). This property must be set for any Wi-Fi connection that uses security." /> + <property name="key-mgmt" name_upper="KEY_MGMT" type="string" description="Key management used for the connection. One of "none" (WEP), "ieee8021x" (Dynamic WEP), "wpa-psk" (infrastructure WPA-PSK), "sae" (SAE), "owe" (Opportunistic Wireless Encryption) or "wpa-eap" (WPA-Enterprise). This property must be set for any Wi-Fi connection that uses security." /> <property name="leap-password" name_upper="LEAP_PASSWORD" type="string" description="The login password for legacy LEAP connections (ie, key-mgmt = "ieee8021x" and auth-alg = "leap")." /> <property name="leap-password-flags" name_upper="LEAP_PASSWORD_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "leap-password" property." /> <property name="leap-username" name_upper="LEAP_USERNAME" type="string" description="The login username for legacy LEAP connections (ie, key-mgmt = "ieee8021x" and auth-alg = "leap")." /> diff --git a/libnm/nm-settings-ifcfg-rh-docs.xml b/libnm/nm-settings-ifcfg-rh-docs.xml index 9934e4de..fcc91bc3 100644 --- a/libnm/nm-settings-ifcfg-rh-docs.xml +++ b/libnm/nm-settings-ifcfg-rh-docs.xml @@ -15,6 +15,7 @@ <property name="subject-match" variable="IEEE_8021X_SUBJECT_MATCH(+)" format="" values="" default="" example="IEEE_8021X_SUBJECT_MATCH="Red Hat"" description="Substring to match subject of server certificate against."/> <property name="altsubject-matches" variable="IEEE_8021X_ALTSUBJECT_MATCHES(+)" format="" values="" default="" example="IEEE_8021X_ALTSUBJECT_MATCHES="s1.domain.cc"" description="List of strings to be matched against the altSubjectName."/> <property name="domain-suffix-match" variable="IEEE_8021X_DOMAIN_SUFFIX_MATCH(+)" format="" values="" default="" example="" description="Suffix to match domain of server certificate against."/> +<property name="domain-match" variable="IEEE_8021X_DOMAIN_MATCH(+)" format="" values="" default="" example="" description="Value to match domain of server certificate against."/> <property name="client-cert" variable="IEEE_8021X_CLIENT_CERT(+)" format="" values="" default="" example="IEEE_8021X_CLIENT_CERT=/home/joe/mycert.crt" description="Client certificate for EAP."/> <property name="phase1-peapver" variable="IEEE_8021X_PEAP_VERSION(+)" format="" values="0, 1" default="" example="" description="Use to force a specific PEAP version."/> <property name="phase1-peaplabel" variable="IEEE_8021X_PEAP_FORCE_NEW_LABEL(+)" format="" values="yes, no" default="no" example="" description="Use to force the new PEAP label during key derivation."/> @@ -27,6 +28,7 @@ IEEE_8021X_INNER_AUTH_METHODS is also used for 'phase2-auth' values."/ <property name="phase2-subject-match" variable="IEEE_8021X_PHASE2_SUBJECT_MATCH(+)" format="" values="" default="" example="IEEE_8021X_PHASE2_SUBJECT_MATCH="Red Hat"" description="Substring to match subject of server certificate against."/> <property name="phase2-altsubject-matches" variable="IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES(+)" format="" values="" default="" example="" description=""/> <property name="phase2-domain-suffix-match" variable="IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH(+)" format="" values="" default="" example="" description="Suffix to match domain of server certificate for phase 2 against."/> +<property name="phase2-domain-match" variable="IEEE_8021X_PHASE2_DOMAIN_MATCH(+)" format="" values="" default="" example="" description="Value to match domain of server certificate for phase 2 against."/> <property name="phase2-client-cert" variable="IEEE_8021X_INNER_CLIENT_CERT(+)" format="" values="" default="" example="IEEE_8021X_INNER_CLIENT_CERT=/home/joe/mycert.crt" description="Client certificate for inner EAP method."/> <property name="password" variable="IEEE_8021X_PASSWORD(+)" format="" values="" default="" example="" description="UTF-8 encoded password used for EAP. It can also go to "key-" lookaside file, or it can be owned by a secret agent."/> @@ -76,6 +78,12 @@ BRIDGE_MACADDR for bridges is an NM extension."/> <property name="vlan-filtering" variable="BRIDGING_OPTS: vlan_filtering=" format="" values="0 or 1" default="0" example="" description="VLAN filtering support."/> <property name="vlan-default-pvid" variable="BRIDGING_OPTS: default_pvid=" format="" values="0 - 4094" default="1" example="" description="default VLAN PVID."/> <property name="vlans" variable="BRIDGE_VLANS" format="" values="" default="" example="BRIDGE_VLANS="1 pvid untagged,20,300-400 untagged"" description="List of VLANs on the bridge"/> +<property name="group-address" variable="BRIDGING_OPTS: group_address=" format="" values="" default="" example="BRIDGING_OPTS="group_address=01:80:C2:00:00:0A"" description="STP group address."/> +<property name="vlan-protocol" variable="BRIDGING_OPTS: vlan_protocol=" format="" values="" default="" example="BRIDGING_OPTS="vlan_protocol=802.1Q"" description="VLAN filtering protocol."/> +<property name="vlan-stats-enabled" variable="BRIDGING_OPTS: vlan_stats_enabled=" format="" values="" default="0" example="BRIDGING_OPTS="vlan_stats_enabled=1"" description=""/> +<property name="multicast-router" variable="BRIDGING_OPTS: multicast_router=" format="" values="auto, enabled, disabled" default="auto" example="BRIDGING_OPTS="multicast_router=enabled"" description=""/> +<property name="multicast-query-use-ifaddr" variable="BRIDGING_OPTS: multicast_query_use_ifaddr=" format="" values="" default="0" example="BRIDGING_OPTS="multicast_query-use_ifaddr=1"" description=""/> +<property name="multicast-querier" variable="BRIDGING_OPTS: multicast_querier=" format="" values="" default="0" example="BRIDGING_OPTS="multicast_querier=1"" description=""/> </setting> <setting name="cdma"> </setting> @@ -97,7 +105,7 @@ specified users is logged into an active session."/> higher numbers are preferred when selecting profiles for automatic activation."/> <property name="autoconnect-retries" variable="AUTOCONNECT_RETRIES(+)" format="" values="-1 (use global default), 0 (forever) or a positive value" default="" example="AUTOCONNECT_RETRIES=1" description="The number of times a connection should be autoactivated before giving up and switching to the next one."/> -<property name="multi-connect" variable="MULTI_CONNECT(+)" format="" values="" default="" example="ZONE=3" description="whether the profile can be active on multiple devices at a given +<property name="multi-connect" variable="MULTI_CONNECT(+)" format="" values="" default="" example="MULTI_CONNECT=3" description="whether the profile can be active on multiple devices at a given moment. The values are numbers corresponding to #NMConnectionMultiConnect enum."/> <property name="zone" variable="ZONE(+)" format="" values="" default="" example="ZONE=Work" description="Trust level of this connection. The string is usually used for a firewall."/> @@ -311,6 +319,8 @@ but VLAN id from DEVICE takes precedence over VLAN_ID."/> </setting> <setting name="vpn"> </setting> +<setting name="vrf"> +</setting> <setting name="vxlan"> </setting> <setting name="wifi-p2p"> diff --git a/libnm/nm-settings-keyfile-docs.xml b/libnm/nm-settings-keyfile-docs.xml index 1a88f78c..3a1891e8 100644 --- a/libnm/nm-settings-keyfile-docs.xml +++ b/libnm/nm-settings-keyfile-docs.xml @@ -102,6 +102,8 @@ under [vpn] section."/> <property name="secrets" variable="separate variables named after keys of the dictionary" format="" values="" default="" example="password=Popocatepetl" description="The keys of the secrets dictionary are used as variable names directly under [vpn-secrets] section."/> </setting> +<setting name="vrf"> +</setting> <setting name="vxlan"> </setting> <setting name="wifi-p2p"> diff --git a/libnm/nm-types.h b/libnm/nm-types.h index 11e9f055..d390e61a 100644 --- a/libnm/nm-types.h +++ b/libnm/nm-types.h @@ -37,6 +37,7 @@ typedef struct _NMDevicePpp NMDevicePpp; typedef struct _NMDeviceTeam NMDeviceTeam; typedef struct _NMDeviceTun NMDeviceTun; typedef struct _NMDeviceVlan NMDeviceVlan; +typedef struct _NMDeviceVrf NMDeviceVrf; typedef struct _NMDeviceVxlan NMDeviceVxlan; typedef struct _NMDeviceWifi NMDeviceWifi; typedef struct _NMDeviceWifiP2P NMDeviceWifiP2P; diff --git a/libnm/nm-vpn-plugin-old.c b/libnm/nm-vpn-plugin-old.c index 782fd80d..5de25b25 100644 --- a/libnm/nm-vpn-plugin-old.c +++ b/libnm/nm-vpn-plugin-old.c @@ -92,7 +92,7 @@ nm_vpn_plugin_old_set_connection (NMVpnPluginOld *plugin, * * Returns: (transfer full): * - * Deprecated: 1.2: replaced by NMVpnServicePlugin + * Deprecated: 1.2: Replaced by NMVpnServicePlugin. */ GDBusConnection * nm_vpn_plugin_old_get_connection (NMVpnPluginOld *plugin) @@ -112,7 +112,7 @@ nm_vpn_plugin_old_get_connection (NMVpnPluginOld *plugin) /** * nm_vpn_plugin_old_get_state: * - * Deprecated: 1.2: replaced by NMVpnServicePlugin + * Deprecated: 1.2: Replaced by NMVpnServicePlugin. */ NMVpnServiceState nm_vpn_plugin_old_get_state (NMVpnPluginOld *plugin) @@ -125,7 +125,7 @@ nm_vpn_plugin_old_get_state (NMVpnPluginOld *plugin) /** * nm_vpn_plugin_old_set_state: * - * Deprecated: 1.2: replaced by NMVpnServicePlugin + * Deprecated: 1.2: Replaced by NMVpnServicePlugin. */ void nm_vpn_plugin_old_set_state (NMVpnPluginOld *plugin, @@ -145,7 +145,7 @@ nm_vpn_plugin_old_set_state (NMVpnPluginOld *plugin, /** * nm_vpn_plugin_old_set_login_banner: * - * Deprecated: 1.2: replaced by NMVpnServicePlugin + * Deprecated: 1.2: Replaced by NMVpnServicePlugin. */ void nm_vpn_plugin_old_set_login_banner (NMVpnPluginOld *plugin, @@ -160,7 +160,7 @@ nm_vpn_plugin_old_set_login_banner (NMVpnPluginOld *plugin, /** * nm_vpn_plugin_old_failure: * - * Deprecated: 1.2: replaced by NMVpnServicePlugin + * Deprecated: 1.2: Replaced by NMVpnServicePlugin. */ void nm_vpn_plugin_old_failure (NMVpnPluginOld *plugin, @@ -174,7 +174,7 @@ nm_vpn_plugin_old_failure (NMVpnPluginOld *plugin, /** * nm_vpn_plugin_old_disconnect: * - * Deprecated: 1.2: replaced by NMVpnServicePlugin + * Deprecated: 1.2: Replaced by NMVpnServicePlugin. */ gboolean nm_vpn_plugin_old_disconnect (NMVpnPluginOld *plugin, GError **err) @@ -288,7 +288,7 @@ schedule_fail_stop (NMVpnPluginOld *plugin, guint timeout_secs) /** * nm_vpn_plugin_old_set_config: * - * Deprecated: 1.2: replaced by NMVpnServicePlugin + * Deprecated: 1.2: Replaced by NMVpnServicePlugin. */ void nm_vpn_plugin_old_set_config (NMVpnPluginOld *plugin, @@ -332,7 +332,7 @@ nm_vpn_plugin_old_set_config (NMVpnPluginOld *plugin, /** * nm_vpn_plugin_old_set_ip4_config: * - * Deprecated: 1.2: replaced by NMVpnServicePlugin + * Deprecated: 1.2: Replaced by NMVpnServicePlugin. */ void nm_vpn_plugin_old_set_ip4_config (NMVpnPluginOld *plugin, @@ -392,7 +392,7 @@ nm_vpn_plugin_old_set_ip4_config (NMVpnPluginOld *plugin, /** * nm_vpn_plugin_old_set_ip6_config: * - * Deprecated: 1.2: replaced by NMVpnServicePlugin + * Deprecated: 1.2: Replaced by NMVpnServicePlugin. */ void nm_vpn_plugin_old_set_ip6_config (NMVpnPluginOld *plugin, @@ -637,7 +637,7 @@ impl_vpn_plugin_old_new_secrets (NMVpnPluginOld *plugin, * are insufficient, or the VPN process indicates that it needs additional * information to complete the request. * - * Deprecated: 1.2: replaced by NMVpnServicePlugin + * Deprecated: 1.2: Replaced by NMVpnServicePlugin. */ void nm_vpn_plugin_old_secrets_required (NMVpnPluginOld *plugin, @@ -677,7 +677,7 @@ nm_vpn_plugin_old_secrets_required (NMVpnPluginOld *plugin, * * Returns: %TRUE if reading values was successful, %FALSE if not * - * Deprecated: 1.2: replaced by NMVpnServicePlugin + * Deprecated: 1.2: Replaced by NMVpnServicePlugin. **/ gboolean nm_vpn_plugin_old_read_vpn_details (int fd, @@ -700,7 +700,7 @@ nm_vpn_plugin_old_read_vpn_details (int fd, * Returns: %TRUE if the flag data item was found and successfully converted * to flags, %FALSE if not * - * Deprecated: 1.2: replaced by NMVpnServicePlugin + * Deprecated: 1.2: Replaced by NMVpnServicePlugin. **/ gboolean nm_vpn_plugin_old_get_secret_flags (GHashTable *data, @@ -963,10 +963,10 @@ finalize (GObject *object) nm_vpn_plugin_old_set_connection (plugin, NULL); g_free (priv->dbus_service_name); - g_clear_pointer (&priv->banner, g_variant_unref); - g_clear_pointer (&priv->tundev, g_variant_unref); - g_clear_pointer (&priv->gateway, g_variant_unref); - g_clear_pointer (&priv->mtu, g_variant_unref); + nm_clear_pointer (&priv->banner, g_variant_unref); + nm_clear_pointer (&priv->tundev, g_variant_unref); + nm_clear_pointer (&priv->gateway, g_variant_unref); + nm_clear_pointer (&priv->mtu, g_variant_unref); G_OBJECT_CLASS (nm_vpn_plugin_old_parent_class)->finalize (object); } @@ -1012,7 +1012,7 @@ nm_vpn_plugin_old_class_init (NMVpnPluginOldClass *plugin_class) * * The D-Bus service name of this plugin. * - * Deprecated: 1.2: replaced by NMVpnServicePlugin + * Deprecated: 1.2: Replaced by NMVpnServicePlugin. */ obj_properties[PROP_DBUS_SERVICE_NAME] = g_param_spec_string (NM_VPN_PLUGIN_OLD_DBUS_SERVICE_NAME, "", "", @@ -1026,7 +1026,7 @@ nm_vpn_plugin_old_class_init (NMVpnPluginOldClass *plugin_class) * * The state of the plugin. * - * Deprecated: 1.2: replaced by NMVpnServicePlugin + * Deprecated: 1.2: Replaced by NMVpnServicePlugin. */ obj_properties[PROP_STATE] = g_param_spec_enum (NM_VPN_PLUGIN_OLD_STATE, "", "", diff --git a/libnm/nm-vpn-service-plugin.c b/libnm/nm-vpn-service-plugin.c index a0df8402..c0b11db9 100644 --- a/libnm/nm-vpn-service-plugin.c +++ b/libnm/nm-vpn-service-plugin.c @@ -1145,10 +1145,10 @@ finalize (GObject *object) nm_vpn_service_plugin_set_connection (plugin, NULL); g_free (priv->dbus_service_name); - g_clear_pointer (&priv->banner, g_variant_unref); - g_clear_pointer (&priv->tundev, g_variant_unref); - g_clear_pointer (&priv->gateway, g_variant_unref); - g_clear_pointer (&priv->mtu, g_variant_unref); + nm_clear_pointer (&priv->banner, g_variant_unref); + nm_clear_pointer (&priv->tundev, g_variant_unref); + nm_clear_pointer (&priv->gateway, g_variant_unref); + nm_clear_pointer (&priv->mtu, g_variant_unref); G_OBJECT_CLASS (nm_vpn_service_plugin_parent_class)->finalize (object); } diff --git a/libnm/nm-wimax-nsp.c b/libnm/nm-wimax-nsp.c index d8472838..00ed636c 100644 --- a/libnm/nm-wimax-nsp.c +++ b/libnm/nm-wimax-nsp.c @@ -37,7 +37,7 @@ G_DEFINE_TYPE (NMWimaxNsp, nm_wimax_nsp, NM_TYPE_OBJECT) * * Returns: the name * - * Deprecated: 1.22. WiMAX is no longer supported by NetworkManager since 1.2.0 + * Deprecated: 1.22: WiMAX is no longer supported by NetworkManager since 1.2.0. **/ const char * nm_wimax_nsp_get_name (NMWimaxNsp *nsp) @@ -53,7 +53,7 @@ nm_wimax_nsp_get_name (NMWimaxNsp *nsp) * * Returns: the signal quality * - * Deprecated: 1.22. WiMAX is no longer supported by NetworkManager since 1.2.0 + * Deprecated: 1.22: WiMAX is no longer supported by NetworkManager since 1.2.0. **/ guint32 nm_wimax_nsp_get_signal_quality (NMWimaxNsp *nsp) @@ -69,7 +69,7 @@ nm_wimax_nsp_get_signal_quality (NMWimaxNsp *nsp) * * Returns: the network type * - * Deprecated: 1.22. WiMAX is no longer supported by NetworkManager since 1.2.0 + * Deprecated: 1.22: WiMAX is no longer supported by NetworkManager since 1.2.0. **/ NMWimaxNspNetworkType nm_wimax_nsp_get_network_type (NMWimaxNsp *nsp) @@ -89,7 +89,7 @@ nm_wimax_nsp_get_network_type (NMWimaxNsp *nsp) * Returns: %TRUE if the connection may be activated with this WiMAX NSP, * %FALSE if it cannot be. * - * Deprecated: 1.22. WiMAX is no longer supported by NetworkManager since 1.2.0 + * Deprecated: 1.22: WiMAX is no longer supported by NetworkManager since 1.2.0. **/ gboolean nm_wimax_nsp_connection_valid (NMWimaxNsp *nsp, NMConnection *connection) @@ -111,7 +111,7 @@ nm_wimax_nsp_connection_valid (NMWimaxNsp *nsp, NMConnection *connection) * #NMConnections that could be activated with the given @nsp. The array should * be freed with g_ptr_array_unref() when it is no longer required. * - * Deprecated: 1.22. WiMAX is no longer supported by NetworkManager since 1.2.0 + * Deprecated: 1.22: WiMAX is no longer supported by NetworkManager since 1.2.0. **/ GPtrArray * nm_wimax_nsp_filter_connections (NMWimaxNsp *nsp, const GPtrArray *connections) @@ -148,7 +148,7 @@ nm_wimax_nsp_class_init (NMWimaxNspClass *nsp_class) * * The name of the WiMAX NSP. * - * Deprecated: 1.22. WiMAX is no longer supported by NetworkManager since 1.2.0 + * Deprecated: 1.22: WiMAX is no longer supported by NetworkManager since 1.2.0. **/ obj_properties[PROP_NAME] = g_param_spec_string (NM_WIMAX_NSP_NAME, "", "", @@ -161,7 +161,7 @@ nm_wimax_nsp_class_init (NMWimaxNspClass *nsp_class) * * The signal quality of the WiMAX NSP. * - * Deprecated: 1.22. WiMAX is no longer supported by NetworkManager since 1.2.0 + * Deprecated: 1.22: WiMAX is no longer supported by NetworkManager since 1.2.0. **/ obj_properties[PROP_SIGNAL_QUALITY] = g_param_spec_uint (NM_WIMAX_NSP_SIGNAL_QUALITY, "", "", @@ -174,7 +174,7 @@ nm_wimax_nsp_class_init (NMWimaxNspClass *nsp_class) * * The network type of the WiMAX NSP. * - * Deprecated: 1.22. WiMAX is no longer supported by NetworkManager since 1.2.0 + * Deprecated: 1.22: WiMAX is no longer supported by NetworkManager since 1.2.0. **/ obj_properties[PROP_NETWORK_TYPE] = g_param_spec_enum (NM_WIMAX_NSP_NETWORK_TYPE, "", "", diff --git a/libnm/nm-wimax-nsp.h b/libnm/nm-wimax-nsp.h index 17a10b7d..1fd95821 100644 --- a/libnm/nm-wimax-nsp.h +++ b/libnm/nm-wimax-nsp.h @@ -29,7 +29,7 @@ G_BEGIN_DECLS /** * NMWimaxNsp: * - * Deprecated: 1.22. WiMAX is no longer supported by NetworkManager since 1.2.0 + * Deprecated: 1.22: WiMAX is no longer supported by NetworkManager since 1.2.0. */ typedef struct _NMWimaxNspClass NMWimaxNspClass; diff --git a/libnm/tests/meson.build b/libnm/tests/meson.build index 76c3b287..59fb771d 100644 --- a/libnm/tests/meson.build +++ b/libnm/tests/meson.build @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1+ + test_units = [ ['test-libnm', 30], ['test-nm-client', 90], diff --git a/libnm/tests/test-libnm.c b/libnm/tests/test-libnm.c index 345fbb07..90d0cf0d 100644 --- a/libnm/tests/test-libnm.c +++ b/libnm/tests/test-libnm.c @@ -22,6 +22,7 @@ #include "nm-libnm-utils.h" #include "nm-object.h" #include "nm-vpn-service-plugin.h" +#include "nm-libnm-core-intern/nm-libnm-core-utils.h" #include "nm-utils/nm-test-utils.h" @@ -3064,6 +3065,49 @@ test_dbus_meta_types (void) g_assert (meta_iface->get_type_fcn() == d->gtype); } } + +/*****************************************************************************/ + +static void +test_nm_auth_permissions (void) +{ + int i, j; + + G_STATIC_ASSERT (G_N_ELEMENTS (nm_auth_permission_names_by_idx) == NM_CLIENT_PERMISSION_LAST); + G_STATIC_ASSERT (G_N_ELEMENTS (nm_auth_permission_sorted) == NM_CLIENT_PERMISSION_LAST); + + for (i = 0; i < NM_CLIENT_PERMISSION_LAST; i++) { + g_assert (nm_auth_permission_names_by_idx[i]); + g_assert (NM_STR_HAS_PREFIX (nm_auth_permission_names_by_idx[i], "org.freedesktop.NetworkManager.")); + g_assert_cmpint (nm_auth_permission_sorted[i], >, 0); + g_assert_cmpint (nm_auth_permission_sorted[i], <=, NM_CLIENT_PERMISSION_LAST); + for (j = i + 1; j < NM_CLIENT_PERMISSION_LAST; j++) { + g_assert_cmpint (nm_auth_permission_sorted[i], !=, nm_auth_permission_sorted[j]); + g_assert_cmpstr (nm_auth_permission_names_by_idx[i], !=, nm_auth_permission_names_by_idx[j]); + } + } + for (i = 1; i < NM_CLIENT_PERMISSION_LAST; i++) { + NMClientPermission a = nm_auth_permission_sorted[i - 1]; + NMClientPermission b = nm_auth_permission_sorted[i]; + const char *s_a = nm_auth_permission_names_by_idx[a - 1]; + const char *s_b = nm_auth_permission_names_by_idx[b - 1]; + + g_assert_cmpstr (s_a, <, s_b); + g_assert (a != b); + g_assert (s_a != s_b); + } + for (i = 1; i <= NM_CLIENT_PERMISSION_LAST; i++) { + const char *s = nm_auth_permission_to_string (i); + + g_assert_cmpstr (s, ==, nm_auth_permission_names_by_idx[i - 1]); + g_assert (s == nm_auth_permission_names_by_idx[i - 1]); + g_assert_cmpint (nm_auth_permission_from_string (s), ==, i); + } + return; + for (i = 0; i < NM_CLIENT_PERMISSION_LAST; i++) + g_assert_cmpint (nm_auth_permission_from_string (nm_auth_permission_names_by_idx[i]), ==, i + 1); +} + /*****************************************************************************/ NMTST_DEFINE (); @@ -3078,6 +3122,7 @@ int main (int argc, char **argv) g_test_add_func ("/libnm/general/test_types", test_types); g_test_add_func ("/libnm/general/test_nml_dbus_meta", test_nml_dbus_meta); g_test_add_func ("/libnm/general/test_dbus_meta_types", test_dbus_meta_types); + g_test_add_func ("/libnm/general/test_nm_auth_permissions", test_nm_auth_permissions); return g_test_run (); } diff --git a/libnm/tests/test-nm-client.c b/libnm/tests/test-nm-client.c index afcc4962..3d63e1ce 100644 --- a/libnm/tests/test-nm-client.c +++ b/libnm/tests/test-nm-client.c @@ -364,7 +364,7 @@ test_wifi_ap_added_removed (void) NULL, &error); g_assert_no_error (error); - g_clear_pointer (&ret, g_variant_unref); + nm_clear_pointer (&ret, g_variant_unref); g_signal_connect (wifi, "access-point-removed", @@ -590,7 +590,7 @@ test_client_nm_running (void) g_source_remove (quit_id); /* And kill it */ - g_clear_pointer (&sinfo, nmtstc_service_cleanup); + nm_clear_pointer (&sinfo, nmtstc_service_cleanup); g_assert (nm_client_get_nm_running (client1)); diff --git a/libnm/tests/test-remote-settings-client.c b/libnm/tests/test-remote-settings-client.c index 8483eca8..f8771a98 100644 --- a/libnm/tests/test-remote-settings-client.c +++ b/libnm/tests/test-remote-settings-client.c @@ -62,7 +62,7 @@ test_add_connection (void) add_cb, &done); - nmtst_main_context_iterate_until (NULL, 5000, done); + nmtst_main_context_iterate_until_assert (NULL, 5000, done); g_assert (gl.remote != NULL); @@ -151,7 +151,7 @@ test_make_invisible (void) set_visible_cb, NULL); /* Wait for the connection to be removed */ - nmtst_main_context_iterate_until (NULL, 5000, visible_changed && connection_removed); + nmtst_main_context_iterate_until_assert (NULL, 5000, visible_changed && connection_removed); g_signal_handlers_disconnect_by_func (gl.remote, G_CALLBACK (visible_changed_cb), &visible_changed); g_signal_handlers_disconnect_by_func (gl.client, G_CALLBACK (connection_removed_cb), &connection_removed); @@ -225,7 +225,7 @@ test_make_visible (void) set_visible_cb, NULL); /* Wait for the settings service to announce the connection again */ - nmtst_main_context_iterate_until (NULL, 5000, new); + nmtst_main_context_iterate_until_assert (NULL, 5000, new); /* Ensure the new connection is the same as the one we made visible again */ g_assert (new == gl.remote); @@ -313,7 +313,7 @@ test_remove_connection (void) NULL, deleted_cb, NULL); - nmtst_main_context_iterate_until (NULL, 5000, done && !gl.remote); + nmtst_main_context_iterate_until_assert (NULL, 5000, done && !gl.remote); /* Ensure NMClient no longer has the connection */ conns = nm_client_get_connections (gl.client); @@ -378,7 +378,7 @@ test_add_remove_connection (void) add_remove_cb, &done); - nmtst_main_context_iterate_until (NULL, 5000, done); + nmtst_main_context_iterate_until_assert (NULL, 5000, done); } /*****************************************************************************/ @@ -417,7 +417,7 @@ test_add_bad_connection (void) &done); g_clear_object (&connection); - nmtst_main_context_iterate_until (NULL, 5000, done); + nmtst_main_context_iterate_until_assert (NULL, 5000, done); g_assert (gl.remote == NULL); } @@ -454,12 +454,12 @@ test_save_hostname (void) nm_client_save_hostname_async (gl.client, "example.com", NULL, save_hostname_cb, &done); - until_ts = nm_utils_get_monotonic_timestamp_ms () + 5000; + until_ts = nm_utils_get_monotonic_timestamp_msec () + 5000; while (TRUE) { g_main_context_iteration (NULL, FALSE); if (done) break; - if (nm_utils_get_monotonic_timestamp_ms () >= until_ts) + if (nm_utils_get_monotonic_timestamp_msec () >= until_ts) g_assert_not_reached (); } diff --git a/libnm/tests/test-secret-agent.c b/libnm/tests/test-secret-agent.c index fef6071d..97953b6d 100644 --- a/libnm/tests/test-secret-agent.c +++ b/libnm/tests/test-secret-agent.c @@ -16,22 +16,17 @@ enum { SECRET_REQUESTED, - - LAST_SIGNAL + LAST_SIGNAL, }; static guint signals[LAST_SIGNAL] = { 0 }; -typedef NMSecretAgentOld TestSecretAgent; +typedef NMSecretAgentOld TestSecretAgent; typedef NMSecretAgentOldClass TestSecretAgentClass; GType test_secret_agent_get_type (void); -G_DEFINE_TYPE (TestSecretAgent, test_secret_agent, NM_TYPE_SECRET_AGENT_OLD) -static void -test_secret_agent_init (TestSecretAgent *agent) -{ -} +G_DEFINE_TYPE (TestSecretAgent, test_secret_agent, NM_TYPE_SECRET_AGENT_OLD) static void test_secret_agent_get_secrets (NMSecretAgentOld *agent, @@ -89,7 +84,7 @@ test_secret_agent_get_secrets (NMSecretAgentOld *agent, done: callback (agent, connection, secrets, error, callback_data); g_clear_error (&error); - g_clear_pointer (&secrets, g_variant_unref); + nm_clear_pointer (&secrets, g_variant_unref); g_free (secret); } @@ -122,42 +117,41 @@ test_secret_agent_delete_secrets (NMSecretAgentOld *agent, } static void +test_secret_agent_init (TestSecretAgent *agent) +{ +} + +static NMSecretAgentOld * +test_secret_agent_new (gboolean auto_register) +{ + return nmtstc_context_object_new (test_secret_agent_get_type (), + TRUE, + NM_SECRET_AGENT_OLD_IDENTIFIER, "test-secret-agent", + NM_SECRET_AGENT_OLD_AUTO_REGISTER, auto_register, + NULL); +} + +static void test_secret_agent_class_init (TestSecretAgentClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); NMSecretAgentOldClass *agent_class = NM_SECRET_AGENT_OLD_CLASS (klass); - agent_class->get_secrets = test_secret_agent_get_secrets; + agent_class->get_secrets = test_secret_agent_get_secrets; agent_class->cancel_get_secrets = test_secret_agent_cancel_get_secrets; - agent_class->save_secrets = test_secret_agent_save_secrets; - agent_class->delete_secrets = test_secret_agent_delete_secrets; + agent_class->save_secrets = test_secret_agent_save_secrets; + agent_class->delete_secrets = test_secret_agent_delete_secrets; signals[SECRET_REQUESTED] = - g_signal_new ("secret-requested", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_STRING, 4, - NM_TYPE_CONNECTION, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING); - -} - -static NMSecretAgentOld * -test_secret_agent_new (void) -{ - NMSecretAgentOld *agent; - GError *error = NULL; - - agent = g_initable_new (test_secret_agent_get_type (), NULL, &error, - NM_SECRET_AGENT_OLD_IDENTIFIER, "test-secret-agent", - NM_SECRET_AGENT_OLD_AUTO_REGISTER, FALSE, - NULL); - g_assert_no_error (error); - - return agent; + g_signal_new ("secret-requested", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_STRING, 4, + NM_TYPE_CONNECTION, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); } /*****************************************************************************/ @@ -171,7 +165,7 @@ typedef struct { NMConnection *connection; GMainLoop *loop; - guint timeout_id; + GSource *timeout_source; char *ifname; char *con_id; @@ -179,12 +173,6 @@ typedef struct { int secrets_requested; } TestSecretAgentData; -static gboolean -timeout_assert (gpointer user_data) -{ - g_assert_not_reached (); -} - static void connection_added_cb (GObject *s, GAsyncResult *result, @@ -221,33 +209,40 @@ register_cb (GObject *object, GAsyncResult *result, gpointer user_data) static void test_setup (TestSecretAgentData *sadata, gconstpointer test_data) { - static int counter = 0; - const char *agent_notes = test_data; + static int static_counter = 0; + const int counter = static_counter++; + const char *create_agent = test_data; NMConnection *connection; NMSettingConnection *s_con; NMSettingWireless *s_wireless; GBytes *ssid; NMSetting *s_wsec; - GError *error = NULL; + gs_free_error GError *error = NULL; sadata->sinfo = nmtstc_service_init (); if (!sadata->sinfo) return; - g_assert (g_main_context_get_thread_default () == NULL); + g_assert (nm_g_main_context_is_thread_default (NULL)); sadata->client = nmtstc_client_new (TRUE); + g_assert (nm_g_main_context_is_thread_default (NULL)); + g_assert (nm_g_main_context_is_thread_default (nm_client_get_main_context (sadata->client))); + sadata->loop = g_main_loop_new (NULL, FALSE); - sadata->timeout_id = g_timeout_add_seconds (5, timeout_assert, NULL); + + sadata->timeout_source = g_timeout_source_new_seconds (5); + g_source_set_callback (sadata->timeout_source, nmtst_g_source_assert_not_called, NULL, NULL); + g_source_attach (sadata->timeout_source, NULL); sadata->ifname = g_strdup_printf ("wlan%d", counter); sadata->con_id = g_strdup_printf ("%s-%d", TEST_CON_ID_PREFIX, counter); - counter++; - /* Create the device */ - sadata->device = nmtstc_service_add_device (sadata->sinfo, sadata->client, - "AddWifiDevice", sadata->ifname); + sadata->device = nmtstc_service_add_device (sadata->sinfo, + sadata->client, + "AddWifiDevice", + sadata->ifname); /* Create the connection */ connection = nmtst_create_minimal_connection (sadata->con_id, NULL, NM_SETTING_WIRELESS_SETTING_NAME, &s_con); @@ -278,18 +273,25 @@ test_setup (TestSecretAgentData *sadata, gconstpointer test_data) g_main_loop_run (sadata->loop); g_assert (sadata->connection); - if (agent_notes) { - sadata->agent = test_secret_agent_new (); + if (nm_streq (create_agent, "1")) { + gboolean auto_register = nmtst_get_rand_bool (); + + sadata->agent = test_secret_agent_new (auto_register); - if (!strcmp (agent_notes, "sync")) { + if (auto_register) { + g_assert (nm_secret_agent_old_get_registered (sadata->agent)); nm_secret_agent_old_register (sadata->agent, NULL, &error); g_assert_no_error (error); - g_assert (nm_secret_agent_old_get_registered (sadata->agent)); } else { - nm_secret_agent_old_register_async (sadata->agent, NULL, - register_cb, sadata); + g_assert (!nm_secret_agent_old_get_registered (sadata->agent)); + nm_secret_agent_old_register_async (sadata->agent, + NULL, + register_cb, + sadata); g_main_loop_run (sadata->loop); } + + g_assert (nm_secret_agent_old_get_registered (sadata->agent)); } } @@ -298,11 +300,22 @@ test_cleanup (TestSecretAgentData *sadata, gconstpointer test_data) { GVariant *ret; GError *error = NULL; + NMTstContextBusyWatcherData watcher_data = { }; + + g_assert (nm_g_main_context_is_thread_default (NULL)); if (!sadata->sinfo) return; + g_assert (nm_g_main_context_is_thread_default (nm_client_get_main_context (sadata->client))); + + nmtst_context_busy_watcher_add (&watcher_data, + nm_client_get_context_busy_watcher (sadata->client)); + if (sadata->agent) { + nmtst_context_busy_watcher_add (&watcher_data, + nm_secret_agent_old_get_context_busy_watcher (sadata->agent)); + if (nm_secret_agent_old_get_registered (sadata->agent)) { nm_secret_agent_old_unregister (sadata->agent, NULL, &error); g_assert_no_error (error); @@ -325,11 +338,21 @@ test_cleanup (TestSecretAgentData *sadata, gconstpointer test_data) nmtstc_service_cleanup (sadata->sinfo); - g_source_remove (sadata->timeout_id); + nm_clear_g_source_inst (&sadata->timeout_source); + g_main_loop_unref (sadata->loop); g_free (sadata->ifname); g_free (sadata->con_id); + + *sadata = (TestSecretAgentData) { }; + + nmtst_context_busy_watcher_wait (&watcher_data); + + while (g_main_context_iteration (NULL, FALSE)) { + } + + nmtst_main_context_assert_no_dispatch (NULL, nmtst_get_rand_uint32 () % 500); } /*****************************************************************************/ @@ -529,17 +552,18 @@ test_secret_agent_good (TestSecretAgentData *sadata, gconstpointer test_data) g_assert_cmpint (sadata->secrets_requested, ==, 1); } +/*****************************************************************************/ + static void async_init_cb (GObject *object, GAsyncResult *result, gpointer user_data) { GMainLoop *loop = user_data; - GError *error = NULL; - GObject *agent; + gs_free_error GError *error = NULL; + gs_unref_object GObject *agent = NULL; agent = g_async_initable_new_finish (G_ASYNC_INITABLE (object), result, &error); - g_assert_error (error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED); - g_assert (agent == NULL); - g_clear_error (&error); + nmtst_assert_success (NM_IS_SECRET_AGENT_OLD (agent), error); + g_assert (!nm_secret_agent_old_get_registered (NM_SECRET_AGENT_OLD (agent))); g_main_loop_quit (loop); } @@ -547,89 +571,151 @@ async_init_cb (GObject *object, GAsyncResult *result, gpointer user_data) static void test_secret_agent_nm_not_running (void) { - NMSecretAgentOld *agent; - GMainLoop *loop; + gs_unref_object NMSecretAgentOld *agent = NULL; + nm_auto_unref_gmainloop GMainLoop *loop = NULL; GError *error = NULL; - agent = g_initable_new (test_secret_agent_get_type (), NULL, &error, + agent = g_initable_new (test_secret_agent_get_type (), + NULL, + &error, NM_SECRET_AGENT_OLD_IDENTIFIER, "test-secret-agent", NULL); - g_assert_error (error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED); - g_assert (agent == NULL); - g_clear_error (&error); + nmtst_assert_success (NM_IS_SECRET_AGENT_OLD (agent), error); + g_assert (!nm_secret_agent_old_get_registered (agent)); + g_clear_object (&agent); loop = g_main_loop_new (NULL, FALSE); g_async_initable_new_async (test_secret_agent_get_type (), G_PRIORITY_DEFAULT, - NULL, async_init_cb, loop, + NULL, + async_init_cb, + loop, NM_SECRET_AGENT_OLD_IDENTIFIER, "test-secret-agent", NULL); g_main_loop_run (loop); - g_main_loop_unref (loop); } +/*****************************************************************************/ + +typedef struct { + int step; + int invoke_count; +} AutoRegisterData; + static void registered_changed (GObject *object, GParamSpec *pspec, gpointer user_data) { - GMainLoop *loop = user_data; - - g_main_loop_quit (loop); + NMSecretAgentOld *agent = NM_SECRET_AGENT_OLD (object); + AutoRegisterData *data = user_data; + + g_assert (data); + g_assert (NM_IS_SECRET_AGENT_OLD (agent)); + + data->invoke_count++; + g_assert_cmpint (data->invoke_count, ==, data->step); + + switch (data->step) { + case 1: + case 3: + g_assert (nm_secret_agent_old_get_registered (agent)); + break; + case 2: + case 4: + g_assert (!nm_secret_agent_old_get_registered (agent)); + break; + default: + g_assert_not_reached (); + } } static void test_secret_agent_auto_register (void) { NMTstcServiceInfo *sinfo; - NMSecretAgentOld *agent; - GMainLoop *loop; + gs_unref_object NMSecretAgentOld *agent = NULL; GError *error = NULL; + AutoRegisterData auto_register_data = { + .step = 0, + .invoke_count = 0, + }; + gulong signal_id; + NMTstContextBusyWatcherData watcher_data = { }; sinfo = nmtstc_service_init (); if (!nmtstc_service_available (sinfo)) return; - loop = g_main_loop_new (NULL, FALSE); + agent = test_secret_agent_new (FALSE); + g_assert (!nm_secret_agent_old_get_registered (agent)); - agent = test_secret_agent_new (); - g_object_set (agent, - NM_SECRET_AGENT_OLD_AUTO_REGISTER, TRUE, - NULL); - g_signal_connect (agent, "notify::" NM_SECRET_AGENT_OLD_REGISTERED, - G_CALLBACK (registered_changed), loop); + signal_id = g_signal_connect (agent, "notify::" NM_SECRET_AGENT_OLD_REGISTERED, + G_CALLBACK (registered_changed), &auto_register_data); + if (nmtst_get_rand_bool ()) { + g_object_set (agent, + NM_SECRET_AGENT_OLD_AUTO_REGISTER, TRUE, + NULL); + } else + nm_secret_agent_old_enable (agent, TRUE); g_assert (!nm_secret_agent_old_get_registered (agent)); + nm_secret_agent_old_register (agent, NULL, &error); g_assert_no_error (error); - g_assert (nm_secret_agent_old_get_registered (agent)); + g_assert (!nm_secret_agent_old_get_registered (agent)); - /* The GLib ObjectManager doesn't like when we drop the service - * in between it sees the service disappear and the call to - * GetManagedObjects. Give it a chance to do its business. - * Arguably a bug. */ - g_main_context_iteration (NULL, FALSE); + auto_register_data.step = 1; + nmtst_main_context_iterate_until_assert (NULL, + 1000, + nm_secret_agent_old_get_registered (agent)); + + auto_register_data.step = 2; + nm_secret_agent_old_enable (agent, FALSE); + g_assert (!nm_secret_agent_old_get_registered (agent)); + + nmtst_main_context_iterate_until (NULL, + nmtst_get_rand_uint32 () % 200, + FALSE); + + g_assert (!nm_secret_agent_old_get_registered (agent)); - /* Shut down test service */ nmtstc_service_cleanup (sinfo); - g_main_loop_run (loop); + + g_assert (!nm_secret_agent_old_get_registered (agent)); + + nm_secret_agent_old_enable (agent, TRUE); + + g_assert (!nm_secret_agent_old_get_registered (agent)); + + nmtst_main_context_iterate_until (NULL, + nmtst_get_rand_uint32 () % 200, + FALSE); + g_assert (!nm_secret_agent_old_get_registered (agent)); - /* Restart test service */ sinfo = nmtstc_service_init (); g_assert (nmtstc_service_available (sinfo)); - g_main_loop_run (loop); - g_assert (nm_secret_agent_old_get_registered (agent)); - - /* Let ObjectManager initialize (see above). */ - g_main_context_iteration (NULL, FALSE); + auto_register_data.step = 3; + nmtst_main_context_iterate_until_assert (NULL, + 1000, + nm_secret_agent_old_get_registered (agent)); - /* Shut down test service again */ nmtstc_service_cleanup (sinfo); - g_main_loop_run (loop); - g_assert (!nm_secret_agent_old_get_registered (agent)); - g_object_unref (agent); - g_main_loop_unref (loop); + auto_register_data.step = 4; + nmtst_main_context_iterate_until_assert (NULL, + 1000, + !nm_secret_agent_old_get_registered (agent)); + + nm_clear_g_signal_handler (agent, &signal_id); + + nmtst_context_busy_watcher_add (&watcher_data, nm_secret_agent_old_get_context_busy_watcher (agent)); + + g_clear_object (&agent); + + nmtst_context_busy_watcher_wait (&watcher_data); + + nmtst_main_context_assert_no_dispatch (NULL, nmtst_get_rand_uint32 () % 500); } /*****************************************************************************/ @@ -639,25 +725,16 @@ NMTST_DEFINE (); int main (int argc, char **argv) { - int ret; - g_setenv ("LIBNM_USE_SESSION_BUS", "1", TRUE); nmtst_init (&argc, &argv, TRUE); - g_test_add ("/libnm/secret-agent/none", TestSecretAgentData, NULL, - test_setup, test_secret_agent_none, test_cleanup); - g_test_add ("/libnm/secret-agent/no-secrets", TestSecretAgentData, "sync", - test_setup, test_secret_agent_no_secrets, test_cleanup); - g_test_add ("/libnm/secret-agent/cancel", TestSecretAgentData, "async", - test_setup, test_secret_agent_cancel, test_cleanup); - g_test_add ("/libnm/secret-agent/good", TestSecretAgentData, "async", - test_setup, test_secret_agent_good, test_cleanup); + g_test_add ("/libnm/secret-agent/none", TestSecretAgentData, "0", test_setup, test_secret_agent_none, test_cleanup); + g_test_add ("/libnm/secret-agent/no-secrets", TestSecretAgentData, "1", test_setup, test_secret_agent_no_secrets, test_cleanup); + g_test_add ("/libnm/secret-agent/cancel", TestSecretAgentData, "1", test_setup, test_secret_agent_cancel, test_cleanup); + g_test_add ("/libnm/secret-agent/good", TestSecretAgentData, "1", test_setup, test_secret_agent_good, test_cleanup); g_test_add_func ("/libnm/secret-agent/nm-not-running", test_secret_agent_nm_not_running); g_test_add_func ("/libnm/secret-agent/auto-register", test_secret_agent_auto_register); - ret = g_test_run (); - - return ret; + return g_test_run (); } - |