diff options
Diffstat (limited to 'libnm-core')
77 files changed, 3356 insertions, 2447 deletions
diff --git a/libnm-core/crypto.h b/libnm-core/crypto.h index 8c4cfefe..e89f0919 100644 --- a/libnm-core/crypto.h +++ b/libnm-core/crypto.h @@ -24,6 +24,10 @@ #ifndef __CRYPTO_H__ #define __CRYPTO_H__ +#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) +#error Cannot use this header. +#endif + #define MD5_HASH_LEN 20 #define CIPHER_DES_EDE3_CBC "DES-EDE3-CBC" #define CIPHER_DES_CBC "DES-CBC" diff --git a/libnm-core/meson.build b/libnm-core/meson.build new file mode 100644 index 00000000..7b143706 --- /dev/null +++ b/libnm-core/meson.build @@ -0,0 +1,202 @@ +libnm_core_inc = include_directories('.') + +libnm_core_headers = files( + 'nm-connection.h', + 'nm-core-types.h', + 'nm-dbus-interface.h', + 'nm-errors.h', + 'nm-setting-8021x.h', + 'nm-setting-adsl.h', + 'nm-setting-bluetooth.h', + 'nm-setting-bond.h', + 'nm-setting-bridge-port.h', + 'nm-setting-bridge.h', + 'nm-setting-cdma.h', + 'nm-setting-connection.h', + 'nm-setting-dcb.h', + 'nm-setting-dummy.h', + 'nm-setting-generic.h', + 'nm-setting-gsm.h', + 'nm-setting-infiniband.h', + 'nm-setting-ip-config.h', + 'nm-setting-ip-tunnel.h', + 'nm-setting-ip4-config.h', + 'nm-setting-ip6-config.h', + 'nm-setting-macsec.h', + 'nm-setting-macvlan.h', + 'nm-setting-olpc-mesh.h', + 'nm-setting-ovs-bridge.h', + 'nm-setting-ovs-interface.h', + 'nm-setting-ovs-patch.h', + 'nm-setting-ovs-port.h', + 'nm-setting-ppp.h', + 'nm-setting-pppoe.h', + 'nm-setting-proxy.h', + 'nm-setting-serial.h', + 'nm-setting-tc-config.h', + 'nm-setting-team-port.h', + 'nm-setting-team.h', + 'nm-setting-tun.h', + 'nm-setting-user.h', + 'nm-setting-vlan.h', + 'nm-setting-vpn.h', + 'nm-setting-vxlan.h', + 'nm-setting-wimax.h', + 'nm-setting-wired.h', + 'nm-setting-wireless-security.h', + 'nm-setting-wireless.h', + 'nm-setting.h', + 'nm-simple-connection.h', + 'nm-utils.h', + 'nm-version.h', + 'nm-vpn-dbus-interface.h', + 'nm-vpn-editor-plugin.h', + 'nm-vpn-plugin-info.h' +) + +libnm_core_settings_sources = files( + 'nm-setting-8021x.c', + 'nm-setting-adsl.c', + 'nm-setting-bluetooth.c', + 'nm-setting-bond.c', + 'nm-setting-bridge-port.c', + 'nm-setting-bridge.c', + 'nm-setting-cdma.c', + 'nm-setting-connection.c', + 'nm-setting-dcb.c', + 'nm-setting-dummy.c', + 'nm-setting-generic.c', + 'nm-setting-gsm.c', + 'nm-setting-infiniband.c', + 'nm-setting-ip-config.c', + 'nm-setting-ip-tunnel.c', + 'nm-setting-ip4-config.c', + 'nm-setting-ip6-config.c', + 'nm-setting-macsec.c', + 'nm-setting-macvlan.c', + 'nm-setting-olpc-mesh.c', + 'nm-setting-ovs-bridge.c', + 'nm-setting-ovs-interface.c', + 'nm-setting-ovs-patch.c', + 'nm-setting-ovs-port.c', + 'nm-setting-ppp.c', + 'nm-setting-pppoe.c', + 'nm-setting-proxy.c', + 'nm-setting-serial.c', + 'nm-setting-tc-config.c', + 'nm-setting-team-port.c', + 'nm-setting-team.c', + 'nm-setting-tun.c', + 'nm-setting-user.c', + 'nm-setting-vlan.c', + 'nm-setting-vpn.c', + 'nm-setting-vxlan.c', + 'nm-setting-wimax.c', + 'nm-setting-wired.c', + 'nm-setting-wireless-security.c', + 'nm-setting-wireless.c' +) + +libnm_core_sources = libnm_core_settings_sources + files( + 'crypto.c', + 'crypto_' + crypto + '.c', + 'nm-connection.c', + 'nm-dbus-utils.c', + 'nm-errors.c', + 'nm-keyfile.c', + 'nm-keyfile-utils.c', + 'nm-property-compare.c', + 'nm-setting.c', + 'nm-simple-connection.c', + 'nm-utils.c', + 'nm-vpn-editor-plugin.c', + 'nm-vpn-plugin-info.c' +) + +enum_headers = libnm_core_headers + [version_header] +enum_types = 'nm-core-enum-types' + +libnm_core_enum = gnome.mkenums( + enum_types, + sources: enum_headers, + identifier_prefix: nm_id_prefix, + c_template: enum_types + '.c.template', + h_template: enum_types + '.h.template', + install_header: true, + install_dir: libnm_pkgincludedir +) + +deps = [ + crypto_dep, + dl_dep, + libudev_dep, + shared_dep, + uuid_dep, + shared_c_siphash_dep, +] + +cflags = [ + '-DG_LOG_DOMAIN="@0@"'.format(libnm_name), + '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIBNM_CORE', + '-DLIBEXECDIR="@0@"'.format(nm_libexecdir), + '-DNMLOCALEDIR="@0@"'.format(nm_localedir), + '-DNMCONFDIR="@0@"'.format(nm_pkgconfdir), + '-DNMLIBDIR="@0@"'.format(nm_pkglibdir), + '-DNMPLUGINDIR="@0@"'.format(nm_plugindir), + '-DNMVPNDIR="@0@"'.format(nm_vpndir) +] + +if enable_json_validation + libnm_core_sources += files('nm-json.c') + deps += jansson_dep +endif + +libnm_core_sources_all = libnm_core_sources +libnm_core_sources_all += libnm_core_enum +libnm_core_sources_all += shared_nm_utils_nm_meta_setting_c +libnm_core_sources_all += shared_files_libnm_core +libnm_core_sources_all += [version_header] + +libnm_core = static_library( + 'nm-core', + sources: libnm_core_sources_all, + dependencies: deps, + c_args: cflags +) + +nm_core_dep = declare_dependency( + sources: libnm_core_enum[1], + include_directories: libnm_core_inc, + dependencies: [ + shared_dep, + shared_c_siphash_dep, + ], +) + +enums_to_docbook = join_paths(meson.source_root(), 'tools', 'enums-to-docbook.pl') + +docbooks = [ + ['nm-dbus-types', 'nm-dbus-interface.h', 'NetworkManager D-Bus API Types'], + ['nm-vpn-dbus-types', 'nm-vpn-dbus-interface.h', 'VPN Plugin D-Bus API Types'] +] + +foreach docbook: docbooks + output = docbook[0] + '.xml' + + xml = custom_target( + output, + input: docbook[1], + output: output, + capture: true, + command: [perl, enums_to_docbook, docbook[0], docbook[2], '@INPUT@'], + # FIXME: gtkdoc does not depend directly on this. + # https://github.com/mesonbuild/meson/pull/2806 + build_by_default: true + ) + + content_files += xml.full_path() +endforeach + +if enable_tests + subdir('tests') +endif diff --git a/libnm-core/nm-connection-private.h b/libnm-core/nm-connection-private.h index ee2d7264..3ff7c57d 100644 --- a/libnm-core/nm-connection-private.h +++ b/libnm-core/nm-connection-private.h @@ -21,6 +21,10 @@ #ifndef __NM_CONNECTION_PRIVATE_H__ #define __NM_CONNECTION_PRIVATE_H__ +#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) +#error Cannot use this header. +#endif + #include "nm-setting.h" #include "nm-connection.h" diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index f70be09f..790e98b8 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -515,7 +515,6 @@ nm_connection_compare (NMConnection *a, return TRUE; } - static gboolean diff_one_connection (NMConnection *a, NMConnection *b, @@ -587,7 +586,7 @@ nm_connection_diff (NMConnection *a, if (a == b) return TRUE; - diffs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_destroy); + diffs = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_destroy); /* Diff A to B, then B to A to capture keys in B that aren't in A */ if (diff_one_connection (a, b, flags, FALSE, diffs)) @@ -959,7 +958,7 @@ _normalize_infiniband_mtu (NMConnection *self, GHashTable *parameters) max_mtu = 65520; if (max_mtu && nm_setting_infiniband_get_mtu (s_infini) > max_mtu) { - g_object_set (s_infini, NM_SETTING_INFINIBAND_MTU, max_mtu, NULL); + g_object_set (s_infini, NM_SETTING_INFINIBAND_MTU, (guint) max_mtu, NULL); return TRUE; } } @@ -1370,7 +1369,7 @@ nm_connection_verify_secrets (NMConnection *connection, GError **error) * @parameters: (allow-none) (element-type utf8 gpointer): a #GHashTable with * normalization parameters to allow customization of the normalization by providing * specific arguments. Unknown arguments will be ignored and the default will be - * used. The keys must be strings, hashed by g_str_hash() and g_str_equal() functions. + * used. The keys must be strings compared with g_str_equal() function. * The values are opaque and depend on the parameter name. * @modified: (out) (allow-none): outputs whether any settings were modified. * @error: location to store error, or %NULL. Contains the reason, @@ -1531,7 +1530,7 @@ nm_connection_update_secrets (NMConnection *connection, g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection); success_detail = _nm_setting_update_secrets (setting, - setting_dict ? setting_dict : secrets, + setting_dict ?: secrets, error); g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection); @@ -2447,7 +2446,7 @@ nm_connection_get_setting_ovs_patch (NMConnection *connection) { return _connection_get_setting_check (connection, NM_TYPE_SETTING_OVS_PATCH); } - + /** * nm_connection_get_setting_ovs_port: * @connection: the #NMConnection @@ -2530,7 +2529,7 @@ nm_connection_get_setting_serial (NMConnection *connection) * * Returns: (transfer none): an #NMSettingTCConfig if the connection contains one, otherwise %NULL * - * Since: 1.10.2 + * Since: 1.12 **/ NMSettingTCConfig * nm_connection_get_setting_tc_config (NMConnection *connection) @@ -2724,7 +2723,7 @@ nm_connection_get_private (NMConnection *connection) priv, (GDestroyNotify) nm_connection_private_free); priv->self = connection; - priv->settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); + priv->settings = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, g_object_unref); } return priv; diff --git a/libnm-core/nm-connection.h b/libnm-core/nm-connection.h index 95e11f1f..6d23cfdb 100644 --- a/libnm-core/nm-connection.h +++ b/libnm-core/nm-connection.h @@ -229,7 +229,7 @@ NMSettingPppoe * nm_connection_get_setting_pppoe (NMConnec NM_AVAILABLE_IN_1_6 NMSettingProxy * nm_connection_get_setting_proxy (NMConnection *connection); NMSettingSerial * nm_connection_get_setting_serial (NMConnection *connection); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMSettingTCConfig * nm_connection_get_setting_tc_config (NMConnection *connection); NMSettingTun * nm_connection_get_setting_tun (NMConnection *connection); NMSettingVpn * nm_connection_get_setting_vpn (NMConnection *connection); diff --git a/libnm-core/nm-core-enum-types.c.template b/libnm-core/nm-core-enum-types.c.template new file mode 100644 index 00000000..9c08f526 --- /dev/null +++ b/libnm-core/nm-core-enum-types.c.template @@ -0,0 +1,86 @@ +/*** BEGIN file-header ***/ +#include "config.h" + +#include "nm-core-enum-types.h" +#include "nm-default.h" + +#include "nm-version-macros.h" +#include "nm-connection.h" +#include "nm-core-types.h" +#include "nm-dbus-interface.h" +#include "nm-errors.h" +#include "nm-setting-8021x.h" +#include "nm-setting-adsl.h" +#include "nm-setting-bluetooth.h" +#include "nm-setting-bond.h" +#include "nm-setting-bridge-port.h" +#include "nm-setting-bridge.h" +#include "nm-setting-cdma.h" +#include "nm-setting-connection.h" +#include "nm-setting-dcb.h" +#include "nm-setting-dummy.h" +#include "nm-setting-generic.h" +#include "nm-setting-gsm.h" +#include "nm-setting-infiniband.h" +#include "nm-setting-ip-config.h" +#include "nm-setting-ip-tunnel.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-ip6-config.h" +#include "nm-setting-macsec.h" +#include "nm-setting-macvlan.h" +#include "nm-setting-olpc-mesh.h" +#include "nm-setting-ovs-bridge.h" +#include "nm-setting-ovs-interface.h" +#include "nm-setting-ovs-patch.h" +#include "nm-setting-ovs-port.h" +#include "nm-setting-ppp.h" +#include "nm-setting-pppoe.h" +#include "nm-setting-proxy.h" +#include "nm-setting-serial.h" +#include "nm-setting-team-port.h" +#include "nm-setting-team.h" +#include "nm-setting-tun.h" +#include "nm-setting-user.h" +#include "nm-setting-vlan.h" +#include "nm-setting-vpn.h" +#include "nm-setting-vxlan.h" +#include "nm-setting-wimax.h" +#include "nm-setting-wired.h" +#include "nm-setting-wireless-security.h" +#include "nm-setting-wireless.h" +#include "nm-setting.h" +#include "nm-simple-connection.h" +#include "nm-utils.h" +#include "nm-version.h" +#include "nm-vpn-dbus-interface.h" +#include "nm-vpn-editor-plugin.h" +#include "nm-vpn-plugin-info.h" +/*** END file-header ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} + +/*** END value-tail ***/ diff --git a/libnm-core/nm-core-enum-types.h.template b/libnm-core/nm-core-enum-types.h.template new file mode 100644 index 00000000..0f1be1e1 --- /dev/null +++ b/libnm-core/nm-core-enum-types.h.template @@ -0,0 +1,21 @@ +/*** BEGIN file-header ***/ +#ifndef __NM_CORE_ENUM_TYPES_H__ +#define __NM_CORE_ENUM_TYPES_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +/*** END file-header ***/ + +/*** BEGIN enumeration-production ***/ +GType @enum_name@_get_type (void) G_GNUC_CONST; +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) + +/*** END enumeration-production ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* __NM_CORE_ENUM_TYPES_H__ */ +/*** END file-tail ***/ diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 15e5dc2a..cace423a 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -31,7 +31,9 @@ * statically against libnm-core. This basically means libnm-core, libnm, NetworkManager * and some test programs. **/ - +#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL) +#error Cannot use this header. +#endif #include "nm-connection.h" #include "nm-core-enum-types.h" @@ -114,7 +116,6 @@ */ #define NM_SETTING_COMPARE_FLAG_NONE ((NMSettingCompareFlags) 0) - #define NM_SETTING_SECRET_FLAGS_ALL \ (NM_SETTING_SECRET_FLAG_NONE | \ NM_SETTING_SECRET_FLAG_AGENT_OWNED | \ @@ -209,6 +210,7 @@ guint8 *_nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize buffer_le const char *nm_utils_hwaddr_ntoa_buf (gconstpointer addr, gsize addr_len, gboolean upper_case, char *buf, gsize buf_len); char *_nm_utils_bin2str (gconstpointer addr, gsize length, gboolean upper_case); +void _nm_utils_bin2str_full (gconstpointer addr, gsize length, const char delimiter, gboolean upper_case, char *out); GSList * _nm_utils_hash_values_to_slist (GHashTable *hash); @@ -216,6 +218,8 @@ GHashTable *_nm_utils_copy_strdict (GHashTable *strdict); typedef gpointer (*NMUtilsCopyFunc) (gpointer); +const char **_nm_ip_address_get_attribute_names (const NMIPAddress *addr, gboolean sorted, guint *out_length); + gboolean _nm_ip_route_attribute_validate_all (const NMIPRoute *route); const char **_nm_ip_route_get_attribute_names (const NMIPRoute *route, gboolean sorted, guint *out_length); GHashTable *_nm_ip_route_get_attributes_direct (NMIPRoute *route); @@ -491,4 +495,17 @@ gboolean _nm_utils_string_append_tc_tfilter_rest (GString *string, /*****************************************************************************/ +static inline gboolean +_nm_connection_type_is_master (const char *type) +{ + return (NM_IN_STRSET (type, + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BRIDGE_SETTING_NAME, + NM_SETTING_TEAM_SETTING_NAME, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + NM_SETTING_OVS_PORT_SETTING_NAME)); +} + +/*****************************************************************************/ + #endif diff --git a/libnm-core/nm-core-types-internal.h b/libnm-core/nm-core-types-internal.h index 442a10a3..4d43aaf4 100644 --- a/libnm-core/nm-core-types-internal.h +++ b/libnm-core/nm-core-types-internal.h @@ -22,9 +22,22 @@ #ifndef NM_CORE_TYPES_INTERNAL_H #define NM_CORE_TYPES_INTERNAL_H +#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL) +#error Cannot use this header. +#endif + typedef struct { guint32 from; guint32 to; } NMVlanQosMapping; +#define _NM_IP_TUNNEL_FLAG_ALL_IP6TNL \ + ( NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT \ + | NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS \ + | NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL \ + | NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV \ + | NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY \ + | NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK \ + ) + #endif /* NM_CORE_TYPES_INTERNAL_H */ diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index 33e4850c..ba31a379 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -76,6 +76,7 @@ #define NM_DBUS_INTERFACE_DEVICE_GRE NM_DBUS_INTERFACE_DEVICE ".Gre" #define NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL NM_DBUS_INTERFACE_DEVICE ".IPTunnel" #define NM_DBUS_INTERFACE_DEVICE_STATISTICS NM_DBUS_INTERFACE_DEVICE ".Statistics" +#define NM_DBUS_INTERFACE_CHECKPOINT NM_DBUS_INTERFACE ".Checkpoint" #define NM_DBUS_INTERFACE_SETTINGS "org.freedesktop.NetworkManager.Settings" #define NM_DBUS_PATH_SETTINGS "/org/freedesktop/NetworkManager/Settings" @@ -295,7 +296,6 @@ typedef enum { /*< flags >*/ NM_WIFI_DEVICE_CAP_FREQ_5GHZ = 0x00000400, } NMDeviceWifiCapabilities; - /** * NM80211ApFlags: * @NM_802_11_AP_FLAGS_NONE: access point has no special capabilities @@ -831,7 +831,6 @@ typedef enum { NM_IP_TUNNEL_MODE_VTI6 = 9, } NMIPTunnelMode; - /** * NMCheckpointCreateFlags: * @NM_CHECKPOINT_CREATE_FLAG_NONE: no flags @@ -841,16 +840,29 @@ typedef enum { * delete any new connection added after the checkpoint (Since: 1.6) * @NM_CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES: upon rollback, * disconnect any new device appeared after the checkpoint (Since: 1.6) + * @NM_CHECKPOINT_CREATE_FLAG_ALLOW_OVERLAPPING: by default, creating + * a checkpoint fails if there are already existing checkoints that + * reference the same devices. With this flag, creation of such + * checkpoints is allowed, however, if an older checkpoint + * that references overlapping devices gets rolled back, it will + * automatically destroy this checkpoint during rollback. This + * allows to create several overlapping checkpoints in parallel, + * and rollback to them at will. With the special case that + * rolling back to an older checkpoint will invalidate all + * overlapping younger checkpoints. This opts-in that the + * checkpoint can be automatically destroyed by the rollback + * of an older checkpoint. (Since: 1.12) * * The flags for CheckpointCreate call * - * Since: 1.4 + * Since: 1.4 (gi flags generated since 1.12) */ -typedef enum { /*< skip >*/ +typedef enum { /*< flags >*/ NM_CHECKPOINT_CREATE_FLAG_NONE = 0, NM_CHECKPOINT_CREATE_FLAG_DESTROY_ALL = 0x01, NM_CHECKPOINT_CREATE_FLAG_DELETE_NEW_CONNECTIONS = 0x02, NM_CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES = 0x04, + NM_CHECKPOINT_CREATE_FLAG_ALLOW_OVERLAPPING = 0x08, } NMCheckpointCreateFlags; /** @@ -872,6 +884,34 @@ typedef enum { /*< skip >*/ } NMRollbackResult; /** + * NMSettingsConnectionFlags: + * @NM_SETTINGS_CONNECTION_FLAG_NONE: an alias for numeric zero, no flags set. + * @NM_SETTINGS_CONNECTION_FLAG_UNSAVED: the connection is not saved to disk. + * That either means, that the connection is in-memory only and currently + * is not backed by a file. Or, that the connection is backed by a file, + * but has modifications in-memory that were not persisted to disk. + * @NM_SETTINGS_CONNECTION_FLAG_NM_GENERATED: A connection is "nm-generated" if + * it was generated by NetworkManger. If the connection gets modified or saved + * by the user, the flag gets cleared. A nm-generated is also unsaved + * and has no backing file as it is in-memory only. + * @NM_SETTINGS_CONNECTION_FLAG_VOLATILE: The connection will be deleted + * when it disconnects. That is for in-memory connections (unsaved), which are + * currently active but deleted on disconnect. Volatile connections are + * always unsaved, but they are also no backing file on disk and are entirely + * in-memory only. + * + * Flags describing the current activation state. + * + * Since: 1.12 + **/ +typedef enum { /*< flags >*/ + NM_SETTINGS_CONNECTION_FLAG_NONE = 0, + NM_SETTINGS_CONNECTION_FLAG_UNSAVED = 0x01, + NM_SETTINGS_CONNECTION_FLAG_NM_GENERATED = 0x02, + NM_SETTINGS_CONNECTION_FLAG_VOLATILE = 0x04, +} NMSettingsConnectionFlags; + +/** * NMActivationStateFlags: * @NM_ACTIVATION_STATE_FLAG_NONE: an alias for numeric zero, no flags set. * @NM_ACTIVATION_STATE_FLAG_IS_MASTER: the device is a master. @@ -929,7 +969,7 @@ typedef enum { /*< flags >*/ * right away. Setting this flag, disables autoconnect until the connection * is manually activated. * - * Since: 1.10.2 + * Since: 1.12 */ typedef enum { /*< flags >*/ NM_SETTINGS_UPDATE2_FLAG_NONE = 0, diff --git a/libnm-core/nm-dbus-types.xml b/libnm-core/nm-dbus-types.xml index b8c5d84f..cdb2021e 100644 --- a/libnm-core/nm-dbus-types.xml +++ b/libnm-core/nm-dbus-types.xml @@ -1483,7 +1483,7 @@ <indexterm zone="NMCheckpointCreateFlags"> <primary>NMCheckpointCreateFlags</primary> </indexterm> - <para><para>The flags for CheckpointCreate call</para><para>Since: 1.4</para><para></para></para> + <para><para>The flags for CheckpointCreate call</para><para>Since: 1.4 (gi flags generated since 1.12)</para><para></para></para> <refsect3 role="enum_members"> <title>Values</title> <informaltable role="enum_members_table" pgwide="1" frame="none"> @@ -1512,6 +1512,11 @@ <entry role="enum_member_value"><para>= <literal>0x04</literal></para><para></para></entry> <entry role="enum_member_description"><para>upon rollback, disconnect any new device appeared after the checkpoint (Since: 1.6)</para><para></para></entry> </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CHECKPOINT_CREATE_FLAG_ALLOW_OVERLAPPING</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>0x08</literal></para><para></para></entry> + <entry role="enum_member_description"><para>by default, creating a checkpoint fails if there are already existing checkoints that reference the same devices. With this flag, creation of such checkpoints is allowed, however, if an older checkpoint that references overlapping devices gets rolled back, it will automatically destroy this checkpoint during rollback. This allows to create several overlapping checkpoints in parallel, and rollback to them at will. With the special case that rolling back to an older checkpoint will invalidate all overlapping younger checkpoints. This opts-in that the checkpoint can be automatically destroyed by the rollback of an older checkpoint. (Since: 1.12)</para><para></para></entry> + </row> </tbody> </tgroup> </informaltable> @@ -1558,6 +1563,46 @@ </refsect3> </refsect2> + <refsect2 id="NMSettingsConnectionFlags" role="enum"> + <title>enum NMSettingsConnectionFlags</title> + <indexterm zone="NMSettingsConnectionFlags"> + <primary>NMSettingsConnectionFlags</primary> + </indexterm> + <para><para>Flags describing the current activation state.</para><para>Since: 1.12</para><para></para></para> + <refsect3 role="enum_members"> + <title>Values</title> + <informaltable role="enum_members_table" pgwide="1" frame="none"> + <tgroup cols="4"> + <colspec colname="enum_members_name" colwidth="300px" /> + <colspec colname="enum_members_value" colwidth="100px"/> + <colspec colname="enum_members_description" /> + <tbody> + <row role="constant"> + <entry role="enum_member_name"><para>NM_SETTINGS_CONNECTION_FLAG_NONE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>0</literal></para><para></para></entry> + <entry role="enum_member_description"><para>an alias for numeric zero, no flags set.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_SETTINGS_CONNECTION_FLAG_UNSAVED</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>0x01</literal></para><para></para></entry> + <entry role="enum_member_description"><para>the connection is not saved to disk. That either means, that the connection is in-memory only and currently is not backed by a file. Or, that the connection is backed by a file, but has modifications in-memory that were not persisted to disk.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_SETTINGS_CONNECTION_FLAG_NM_GENERATED</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>0x02</literal></para><para></para></entry> + <entry role="enum_member_description"><para>A connection is "nm-generated" if it was generated by NetworkManger. If the connection gets modified or saved by the user, the flag gets cleared. A nm-generated is also unsaved and has no backing file as it is in-memory only.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_SETTINGS_CONNECTION_FLAG_VOLATILE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>0x04</literal></para><para></para></entry> + <entry role="enum_member_description"><para>The connection will be deleted when it disconnects. That is for in-memory connections (unsaved), which are currently active but deleted on disconnect. Volatile connections are always unsaved, but they are also no backing file on disk and are entirely in-memory only.</para><para></para></entry> + </row> + </tbody> + </tgroup> + </informaltable> + </refsect3> + </refsect2> + <refsect2 id="NMActivationStateFlags" role="enum"> <title>enum NMActivationStateFlags</title> <indexterm zone="NMActivationStateFlags"> @@ -1618,7 +1663,7 @@ <indexterm zone="NMSettingsUpdate2Flags"> <primary>NMSettingsUpdate2Flags</primary> </indexterm> - <para><para>Since: 1.10.2</para><para></para></para> + <para><para>Since: 1.12</para><para></para></para> <refsect3 role="enum_members"> <title>Values</title> <informaltable role="enum_members_table" pgwide="1" frame="none"> diff --git a/libnm-core/nm-dbus-utils.c b/libnm-core/nm-dbus-utils.c index 79020b2d..8389bf36 100644 --- a/libnm-core/nm-dbus-utils.c +++ b/libnm-core/nm-dbus-utils.c @@ -174,13 +174,14 @@ _nm_dbus_signal_connect_data (GDBusProxy *proxy, * Returns: the signal handler ID, as with _nm_signal_connect_data(). */ - static void -typecheck_response (GVariant **response, - const GVariantType *reply_type, - GError **error) +typecheck_response (GVariant **response, + const GVariantType *reply_type, + GError **error) { - if (*response && reply_type && !g_variant_is_of_type (*response, reply_type)) { + if ( *response + && reply_type + && !g_variant_is_of_type (*response, reply_type)) { /* This is the same error code that g_dbus_connection_call() returns if * @reply_type doesn't match. */ diff --git a/libnm-core/nm-json.c b/libnm-core/nm-json.c index f9042b1f..aa181a4a 100644 --- a/libnm-core/nm-json.c +++ b/libnm-core/nm-json.c @@ -44,7 +44,6 @@ void *_nm_jansson_json_true; void *_nm_jansson_json_object_size; void *_nm_jansson_json_object_set_new; void *_nm_jansson_json_object_iter; -void *_nm_jansson_json_object_iter_at; void *_nm_jansson_json_integer_value; void *_nm_jansson_json_string_value; @@ -80,7 +79,6 @@ bind_symbols (void *handle) TRY_BIND_SYMBOL (json_object_size); TRY_BIND_SYMBOL (json_object_set_new); TRY_BIND_SYMBOL (json_object_iter); - TRY_BIND_SYMBOL (json_object_iter_at); TRY_BIND_SYMBOL (json_integer_value); TRY_BIND_SYMBOL (json_string_value); @@ -96,6 +94,7 @@ nm_jansson_load (void) MISSING, } state = UNKNOWN; void *handle; + int mode; if (G_LIKELY (state != UNKNOWN)) goto out; @@ -104,7 +103,13 @@ nm_jansson_load (void) if (!bind_symbols (RTLD_DEFAULT)) goto out; - handle = dlopen (JANSSON_SONAME, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE | RTLD_DEEPBIND); + mode = RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE | RTLD_DEEPBIND; +#if defined (ASAN_BUILD) + /* Address sanitizer is incompatible with RTLD_DEEPBIND. */ + mode &= ~RTLD_DEEPBIND; +#endif + handle = dlopen (JANSSON_SONAME, mode); + if (!handle) goto out; diff --git a/libnm-core/nm-json.h b/libnm-core/nm-json.h index 513b8d36..560b827a 100644 --- a/libnm-core/nm-json.h +++ b/libnm-core/nm-json.h @@ -42,9 +42,10 @@ gboolean nm_jansson_load (void); #define json_object_size (*_nm_jansson_json_object_size) #define json_object_set_new (*_nm_jansson_json_object_set_new) #define json_object_iter (*_nm_jansson_json_object_iter) -#define json_object_iter_at (*_nm_jansson_json_object_iter_at) #define json_integer_value (*_nm_jansson_json_integer_value) #define json_string_value (*_nm_jansson_json_string_value) + +#include "nm-utils/nm-jansson.h" #endif #endif /* __NM_JSON_H__ */ diff --git a/libnm-core/nm-keyfile-internal.h b/libnm-core/nm-keyfile-internal.h index 5b709c02..d6a14711 100644 --- a/libnm-core/nm-keyfile-internal.h +++ b/libnm-core/nm-keyfile-internal.h @@ -22,6 +22,10 @@ #ifndef __NM_KEYFILE_INTERNAL_H__ #define __NM_KEYFILE_INTERNAL_H__ +#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL) +#error Cannot use this header. +#endif + #include <sys/types.h> #include "nm-connection.h" @@ -90,7 +94,6 @@ typedef struct { const char *message; } NMKeyfileReadTypeDataWarn; - NMConnection *nm_keyfile_read (GKeyFile *keyfile, const char *keyfile_name, const char *base_dir, @@ -145,7 +148,6 @@ typedef struct { NMSetting8021x *setting; } NMKeyfileWriteTypeDataCert; - GKeyFile *nm_keyfile_write (NMConnection *connection, NMKeyfileWriteHandler handler, void *user_data, @@ -161,5 +163,4 @@ gboolean _nm_keyfile_a_contains_all_in_b (GKeyFile *kf_a, GKeyFile *kf_b); gboolean _nm_keyfile_equals (GKeyFile *kf_a, GKeyFile *kf_b, gboolean consider_order); gboolean _nm_keyfile_has_values (GKeyFile *keyfile); - #endif /* __NM_KEYFILE_INTERNAL_H__ */ diff --git a/libnm-core/nm-keyfile-utils.c b/libnm-core/nm-keyfile-utils.c index 88583319..5000b583 100644 --- a/libnm-core/nm-keyfile-utils.c +++ b/libnm-core/nm-keyfile-utils.c @@ -106,7 +106,7 @@ nm_keyfile_plugin_kf_set_##stype##_list (GKeyFile *kf, \ const char *alias; \ \ alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \ - g_key_file_set_##stype##_list (kf, alias ? alias : group, key, list, length); \ + g_key_file_set_##stype##_list (kf, alias ?: group, key, list, length); \ } DEFINE_KF_LIST_WRAPPER(integer, gint*, gint); @@ -170,7 +170,7 @@ nm_keyfile_plugin_kf_set_##stype (GKeyFile *kf, \ const char *alias; \ \ alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \ - g_key_file_set_##stype (kf, alias ? alias : group, key, value); \ + g_key_file_set_##stype (kf, alias ?: group, key, value); \ } DEFINE_KF_WRAPPER(string, gchar*, const gchar*); @@ -179,7 +179,6 @@ DEFINE_KF_WRAPPER(uint64, guint64, guint64); DEFINE_KF_WRAPPER(boolean, gboolean, gboolean); DEFINE_KF_WRAPPER(value, gchar*, const gchar*); - gchar ** nm_keyfile_plugin_kf_get_keys (GKeyFile *kf, const char *group, @@ -195,7 +194,7 @@ nm_keyfile_plugin_kf_get_keys (GKeyFile *kf, alias = nm_keyfile_plugin_get_alias_for_setting_name (group); if (alias) { g_clear_error (&local); - keys = g_key_file_get_keys (kf, alias, out_length, &local); + keys = g_key_file_get_keys (kf, alias, out_length, error ? &local : NULL); } } if (local) @@ -288,7 +287,6 @@ _nm_keyfile_a_contains_all_in_b (GKeyFile *kf_a, GKeyFile *kf_b) return TRUE; } - static gboolean _nm_keyfile_equals_ordered (GKeyFile *kf_a, GKeyFile *kf_b) { diff --git a/libnm-core/nm-keyfile-utils.h b/libnm-core/nm-keyfile-utils.h index 1f63af8c..832ad0b4 100644 --- a/libnm-core/nm-keyfile-utils.h +++ b/libnm-core/nm-keyfile-utils.h @@ -21,7 +21,9 @@ #ifndef __NM_KEYFILE_UTILS_H__ #define __NM_KEYFILE_UTILS_H__ -#include <glib.h> +#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) +#error Cannot use this header. +#endif #define NM_KEYFILE_GROUP_VPN_SECRETS "vpn-secrets" diff --git a/libnm-core/nm-keyfile-writer.c b/libnm-core/nm-keyfile-writer.c deleted file mode 100644 index 0333b644..00000000 --- a/libnm-core/nm-keyfile-writer.c +++ /dev/null @@ -1,882 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager system settings service - keyfile plugin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2008 Novell, Inc. - * Copyright (C) 2008 - 2017 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-keyfile-internal.h" - -#include <stdlib.h> -#include <sys/stat.h> -#include <unistd.h> -#include <stdio.h> -#include <errno.h> -#include <arpa/inet.h> -#include <string.h> - -#include "nm-core-internal.h" -#include "nm-keyfile-utils.h" - -typedef struct { - NMConnection *connection; - GKeyFile *keyfile; - GError *error; - NMKeyfileWriteHandler handler; - void *user_data; -} KeyfileWriterInfo; - - -/* Some setting properties also contain setting names, such as - * NMSettingConnection's 'type' property (which specifies the base type of the - * connection, eg ethernet or wifi) or the 802-11-wireless setting's - * 'security' property which specifies whether or not the AP requires - * encryption. This function handles translating those properties' values - * from the real setting name to the more-readable alias. - */ -static void -setting_alias_writer (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value) -{ - const char *str, *alias; - - str = g_value_get_string (value); - alias = nm_keyfile_plugin_get_alias_for_setting_name (str); - nm_keyfile_plugin_kf_set_string (info->keyfile, - nm_setting_get_name (setting), - key, - alias ? alias : str); -} - -static void -write_array_of_uint (GKeyFile *file, - NMSetting *setting, - const char *key, - const GValue *value) -{ - GArray *array; - guint i; - gs_free int *tmp_array = NULL; - - array = (GArray *) g_value_get_boxed (value); - if (!array || !array->len) - return; - - g_return_if_fail (g_array_get_element_size (array) == sizeof (guint)); - - tmp_array = g_new (gint, array->len); - for (i = 0; i < array->len; i++) { - guint v = g_array_index (array, guint, i); - - if (v > G_MAXINT) - g_return_if_reached (); - tmp_array[i] = (int) v; - } - - nm_keyfile_plugin_kf_set_integer_list (file, nm_setting_get_name (setting), key, tmp_array, array->len); -} - -static void -dns_writer (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value) -{ - char **list; - - list = g_value_get_boxed (value); - if (list && list[0]) { - nm_keyfile_plugin_kf_set_string_list (info->keyfile, nm_setting_get_name (setting), key, - (const char **) list, g_strv_length (list)); - } -} - -static void -ip6_addr_gen_mode_writer (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value) -{ - NMSettingIP6ConfigAddrGenMode addr_gen_mode; - gs_free char *str = NULL; - - addr_gen_mode = (NMSettingIP6ConfigAddrGenMode) g_value_get_int (value); - str = nm_utils_enum_to_str (nm_setting_ip6_config_addr_gen_mode_get_type (), - addr_gen_mode); - nm_keyfile_plugin_kf_set_string (info->keyfile, - nm_setting_get_name (setting), - key, - str); -} - -static void -write_ip_values (GKeyFile *file, - const char *setting_name, - GPtrArray *array, - const char *gateway, - gboolean is_route) -{ - GString *output; - int family, i; - const char *addr, *gw; - guint32 plen; - char key_name[64], *key_name_idx; - - if (!array->len) - return; - - family = !strcmp (setting_name, NM_SETTING_IP4_CONFIG_SETTING_NAME) ? AF_INET : AF_INET6; - - strcpy (key_name, is_route ? "route" : "address"); - key_name_idx = key_name + strlen (key_name); - - output = g_string_sized_new (2*INET_ADDRSTRLEN + 10); - for (i = 0; i < array->len; i++) { - gint64 metric = -1; - - if (is_route) { - NMIPRoute *route = array->pdata[i]; - - addr = nm_ip_route_get_dest (route); - plen = nm_ip_route_get_prefix (route); - gw = nm_ip_route_get_next_hop (route); - metric = nm_ip_route_get_metric (route); - } else { - NMIPAddress *address = array->pdata[i]; - - addr = nm_ip_address_get_address (address); - plen = nm_ip_address_get_prefix (address); - gw = i == 0 ? gateway : NULL; - } - - g_string_set_size (output, 0); - g_string_append_printf (output, "%s/%u", addr, plen); - if ( metric != -1 - || gw) { - /* Older versions of the plugin do not support the form - * "a.b.c.d/plen,,metric", so, we always have to write the - * gateway, even if there isn't one. - * The current version supports reading of the above form. - */ - if (!gw) { - if (family == AF_INET) - gw = "0.0.0.0"; - else - gw = "::"; - } - - g_string_append_printf (output, ",%s", gw); - if (is_route && metric != -1) - g_string_append_printf (output, ",%lu", (unsigned long) metric); - } - - sprintf (key_name_idx, "%d", i + 1); - nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, output->str); - - if (is_route) { - gs_free char *attributes = NULL; - GHashTable *hash; - - hash = _nm_ip_route_get_attributes_direct (array->pdata[i]); - attributes = nm_utils_format_variant_attributes (hash, ',', '='); - if (attributes) { - g_strlcat (key_name, "_options", sizeof (key_name)); - nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, attributes); - } - } - } - g_string_free (output, TRUE); -} - -static void -addr_writer (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value) -{ - GPtrArray *array; - const char *setting_name = nm_setting_get_name (setting); - const char *gateway = nm_setting_ip_config_get_gateway (NM_SETTING_IP_CONFIG (setting)); - - array = (GPtrArray *) g_value_get_boxed (value); - if (array && array->len) - write_ip_values (info->keyfile, setting_name, array, gateway, FALSE); -} - -static void -ip4_addr_label_writer (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value) -{ - /* skip */ -} - -static void -gateway_writer (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value) -{ - /* skip */ -} - -static void -route_writer (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value) -{ - GPtrArray *array; - const char *setting_name = nm_setting_get_name (setting); - - array = (GPtrArray *) g_value_get_boxed (value); - if (array && array->len) - write_ip_values (info->keyfile, setting_name, array, NULL, TRUE); -} - -static void -qdisc_writer (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value) -{ - gsize i; - GPtrArray *array; - - array = (GPtrArray *) g_value_get_boxed (value); - if (!array || !array->len) - return; - - for (i = 0; i < array->len; i++) { - NMTCQdisc *qdisc = array->pdata[i]; - GString *key_name = g_string_sized_new (16); - GString *value_str = g_string_sized_new (60); - - g_string_append (key_name, "qdisc."); - _nm_utils_string_append_tc_parent (key_name, NULL, - nm_tc_qdisc_get_parent (qdisc)); - _nm_utils_string_append_tc_qdisc_rest (value_str, qdisc); - - nm_keyfile_plugin_kf_set_string (info->keyfile, - NM_SETTING_TC_CONFIG_SETTING_NAME, - key_name->str, - value_str->str); - - g_string_free (key_name, TRUE); - g_string_free (value_str, TRUE); - } -} - -static void -tfilter_writer (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value) -{ - gsize i; - GPtrArray *array; - - array = (GPtrArray *) g_value_get_boxed (value); - if (!array || !array->len) - return; - - for (i = 0; i < array->len; i++) { - NMTCTfilter *tfilter = array->pdata[i]; - GString *key_name = g_string_sized_new (16); - GString *value_str = g_string_sized_new (60); - - g_string_append (key_name, "tfilter."); - _nm_utils_string_append_tc_parent (key_name, NULL, - nm_tc_tfilter_get_parent (tfilter)); - _nm_utils_string_append_tc_tfilter_rest (value_str, tfilter, NULL); - - nm_keyfile_plugin_kf_set_string (info->keyfile, - NM_SETTING_TC_CONFIG_SETTING_NAME, - key_name->str, - value_str->str); - - g_string_free (key_name, TRUE); - g_string_free (value_str, TRUE); - } -} - -static void -write_hash_of_string (GKeyFile *file, - NMSetting *setting, - const char *key, - const GValue *value) -{ - GHashTable *hash; - const char *group_name = nm_setting_get_name (setting); - gboolean vpn_secrets = FALSE; - gs_free const char **keys = NULL; - guint i, l; - - /* Write VPN secrets out to a different group to keep them separate */ - if (NM_IS_SETTING_VPN (setting) && !strcmp (key, NM_SETTING_VPN_SECRETS)) { - group_name = NM_KEYFILE_GROUP_VPN_SECRETS; - vpn_secrets = TRUE; - } - - hash = g_value_get_boxed (value); - keys = (const char **) g_hash_table_get_keys_as_array (hash, &l); - if (!keys) - return; - - g_qsort_with_data (keys, l, sizeof (const char *), nm_strcmp_p_with_data, NULL); - - for (i = 0; keys[i]; i++) { - const char *property, *data; - gboolean write_item = TRUE; - - property = keys[i]; - - /* Handle VPN secrets specially; they are nested in the property's hash; - * we don't want to write them if the secret is not saved, not required, - * or owned by a user's secret agent. - */ - if (vpn_secrets) { - NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; - - nm_setting_get_secret_flags (setting, property, &secret_flags, NULL); - if (secret_flags != NM_SETTING_SECRET_FLAG_NONE) - write_item = FALSE; - } - - if (write_item) { - gs_free char *to_free = NULL; - - data = g_hash_table_lookup (hash, property); - nm_keyfile_plugin_kf_set_string (file, group_name, - nm_keyfile_key_encode (property, &to_free), - data); - } - } -} - -static void -ssid_writer (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value) -{ - GBytes *bytes; - const guint8 *ssid_data; - gsize ssid_len; - const char *setting_name = nm_setting_get_name (setting); - gboolean new_format = TRUE; - gsize semicolons = 0; - gsize i; - - g_return_if_fail (G_VALUE_HOLDS (value, G_TYPE_BYTES)); - - bytes = g_value_get_boxed (value); - if (!bytes) - return; - ssid_data = g_bytes_get_data (bytes, &ssid_len); - if (!ssid_data || !ssid_len) { - nm_keyfile_plugin_kf_set_string (info->keyfile, setting_name, key, ""); - return; - } - - /* Check whether each byte is printable. If not, we have to use an - * integer list, otherwise we can just use a string. - */ - for (i = 0; i < ssid_len; i++) { - const char c = ssid_data[i]; - - if (!g_ascii_isprint (c)) { - new_format = FALSE; - break; - } - if (c == ';') - semicolons++; - } - - if (new_format) { - gs_free char *ssid = NULL; - - if (semicolons == 0) - ssid = g_strndup ((char *) ssid_data, ssid_len); - else { - /* Escape semicolons with backslashes to make strings - * containing ';', such as '16;17;' unambiguous */ - gsize j = 0; - - ssid = g_malloc (ssid_len + semicolons + 1); - for (i = 0; i < ssid_len; i++) { - if (ssid_data[i] == ';') - ssid[j++] = '\\'; - ssid[j++] = ssid_data[i]; - } - ssid[j] = '\0'; - } - nm_keyfile_plugin_kf_set_string (info->keyfile, setting_name, key, ssid); - } else - nm_keyfile_plugin_kf_set_integer_list_uint8 (info->keyfile, setting_name, key, ssid_data, ssid_len); -} - -static void -password_raw_writer (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value) -{ - const char *setting_name = nm_setting_get_name (setting); - GBytes *array; - gsize len; - const guint8 *data; - - g_return_if_fail (G_VALUE_HOLDS (value, G_TYPE_BYTES)); - - array = (GBytes *) g_value_get_boxed (value); - if (!array) - return; - data = g_bytes_get_data (array, &len); - if (!data) - len = 0; - nm_keyfile_plugin_kf_set_integer_list_uint8 (info->keyfile, setting_name, key, data, len); -} - -/*****************************************************************************/ - -static void -cert_writer_default (NMConnection *connection, - GKeyFile *file, - NMKeyfileWriteTypeDataCert *cert_data) -{ - const char *setting_name = nm_setting_get_name (NM_SETTING (cert_data->setting)); - NMSetting8021xCKScheme scheme; - - scheme = cert_data->vtable->scheme_func (cert_data->setting); - if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { - const char *path; - char *path_free = NULL, *tmp; - gs_free char *base_dir = NULL; - - path = cert_data->vtable->path_func (cert_data->setting); - g_assert (path); - - /* If the path is relative, make it an absolute path. - * Relative paths make a keyfile not easily usable in another - * context. */ - if (path[0] && path[0] != '/') { - base_dir = g_get_current_dir (); - path = path_free = g_strconcat (base_dir, "/", path, NULL); - } else - base_dir = g_path_get_dirname (path); - - /* path cannot start with "file://" or "data:;base64,", because it is an absolute path. - * Still, make sure that a prefix-less path will be recognized. This can happen - * for example if the path is longer then 500 chars. */ - tmp = nm_keyfile_detect_unqualified_path_scheme (base_dir, path, -1, FALSE, NULL); - if (tmp) - g_clear_pointer (&tmp, g_free); - else - path = tmp = g_strconcat (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, path, NULL); - - /* Path contains at least a '/', hence it cannot be recognized as the old - * binary format consisting of a list of integers. */ - - nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->vtable->setting_key, path); - g_free (tmp); - g_free (path_free); - } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { - GBytes *blob; - const guint8 *blob_data; - gsize blob_len; - char *blob_base64, *val; - - blob = cert_data->vtable->blob_func (cert_data->setting); - g_assert (blob); - blob_data = g_bytes_get_data (blob, &blob_len); - - blob_base64 = g_base64_encode (blob_data, blob_len); - val = g_strconcat (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB, blob_base64, NULL); - - nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->vtable->setting_key, val); - g_free (val); - g_free (blob_base64); - } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { - nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->vtable->setting_key, - cert_data->vtable->uri_func (cert_data->setting)); - } else { - /* scheme_func() returns UNKNOWN in all other cases. The only valid case - * where a scheme is allowed to be UNKNOWN, is unsetting the value. In this - * case, we don't expect the writer to be called, because the default value - * will not be serialized. - * The only other reason for the scheme to be UNKNOWN is an invalid cert. - * But our connection verifies, so that cannot happen either. */ - g_return_if_reached (); - } -} - -static void -cert_writer (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value) -{ - const NMSetting8021xSchemeVtable *objtype = NULL; - guint i; - NMKeyfileWriteTypeDataCert type_data = { 0 }; - - for (i = 0; nm_setting_8021x_scheme_vtable[i].setting_key; i++) { - if (g_strcmp0 (nm_setting_8021x_scheme_vtable[i].setting_key, key) == 0) { - objtype = &nm_setting_8021x_scheme_vtable[i]; - break; - } - } - if (!objtype) - g_return_if_reached (); - - type_data.setting = NM_SETTING_802_1X (setting); - type_data.vtable = objtype; - - if (info->handler) { - if (info->handler (info->connection, - info->keyfile, - NM_KEYFILE_WRITE_TYPE_CERT, - &type_data, - info->user_data, - &info->error)) - return; - if (info->error) - return; - } - - cert_writer_default (info->connection, info->keyfile, &type_data); -} - -static void -null_writer (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value) -{ - /* skip */ -} - -/*****************************************************************************/ - -typedef struct { - const char *setting_name; - const char *key; - void (*writer) (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value); -} KeyWriter; - -/* A table of keys that require further parsing/conversion because they are - * stored in a format that can't be automatically read using the key's type. - * i.e. IPv4 addresses, which are stored in NetworkManager as guint32, but are - * stored in keyfiles as strings, eg "10.1.1.2" or IPv6 addresses stored - * in struct in6_addr internally, but as string in keyfiles. - */ -static KeyWriter key_writers[] = { - { NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_TYPE, - setting_alias_writer }, - { NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_ADDRESSES, - addr_writer }, - { NM_SETTING_IP4_CONFIG_SETTING_NAME, - "address-labels", - ip4_addr_label_writer }, - { NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_ADDRESSES, - addr_writer }, - { NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_GATEWAY, - gateway_writer }, - { NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_GATEWAY, - gateway_writer }, - { NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_ROUTES, - route_writer }, - { NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_ROUTES, - route_writer }, - { NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_DNS, - dns_writer }, - { NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_DNS, - dns_writer }, - { NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, - ip6_addr_gen_mode_writer }, - { NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_SSID, - ssid_writer }, - { NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PASSWORD_RAW, - password_raw_writer }, - { NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_CA_CERT, - cert_writer }, - { NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_CLIENT_CERT, - cert_writer }, - { NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PRIVATE_KEY, - cert_writer }, - { NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_CA_CERT, - cert_writer }, - { NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_CLIENT_CERT, - cert_writer }, - { NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, - cert_writer }, - { NM_SETTING_TC_CONFIG_SETTING_NAME, - NM_SETTING_TC_CONFIG_QDISCS, - qdisc_writer }, - { NM_SETTING_TC_CONFIG_SETTING_NAME, - NM_SETTING_TC_CONFIG_TFILTERS, - tfilter_writer }, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_NOTIFY_PEERS_COUNT, - null_writer}, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL, - null_writer}, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_MCAST_REJOIN_COUNT, - null_writer}, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL, - null_writer}, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_RUNNER, - null_writer}, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_RUNNER_HWADDR_POLICY, - null_writer}, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_RUNNER_TX_HASH, - null_writer}, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_RUNNER_TX_BALANCER, - null_writer}, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL, - null_writer}, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_RUNNER_ACTIVE, - null_writer}, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_RUNNER_FAST_RATE, - null_writer}, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_RUNNER_SYS_PRIO, - null_writer}, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_RUNNER_MIN_PORTS, - null_writer}, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY, - null_writer}, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_LINK_WATCHERS, - null_writer}, - { NM_SETTING_TEAM_PORT_SETTING_NAME, - NM_SETTING_TEAM_PORT_QUEUE_ID, - null_writer}, - { NM_SETTING_TEAM_PORT_SETTING_NAME, - NM_SETTING_TEAM_PORT_PRIO, - null_writer}, - { NM_SETTING_TEAM_PORT_SETTING_NAME, - NM_SETTING_TEAM_PORT_STICKY, - null_writer}, - { NM_SETTING_TEAM_PORT_SETTING_NAME, - NM_SETTING_TEAM_PORT_LACP_PRIO, - null_writer}, - { NM_SETTING_TEAM_PORT_SETTING_NAME, - NM_SETTING_TEAM_PORT_LACP_KEY, - null_writer}, - { NM_SETTING_TEAM_PORT_SETTING_NAME, - NM_SETTING_TEAM_PORT_LINK_WATCHERS, - null_writer}, - { NULL, NULL, NULL } -}; - -static gboolean -can_omit_default_value (NMSetting *setting, const char *property) -{ - if (NM_IS_SETTING_VLAN (setting)) { - if (!strcmp (property, NM_SETTING_VLAN_FLAGS)) - return FALSE; - } else if (NM_IS_SETTING_IP6_CONFIG (setting)) { - if (!strcmp (property, NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE)) - return FALSE; - } - - return TRUE; -} - -static void -write_setting_value (NMSetting *setting, - const char *key, - const GValue *value, - GParamFlags flag, - gpointer user_data) -{ - KeyfileWriterInfo *info = user_data; - const char *setting_name; - GType type = G_VALUE_TYPE (value); - KeyWriter *writer = &key_writers[0]; - GParamSpec *pspec; - - if (info->error) - return; - - /* Setting name gets picked up from the keyfile's section name instead */ - if (!strcmp (key, NM_SETTING_NAME)) - return; - - /* Don't write the NMSettingConnection object's 'read-only' property */ - if ( NM_IS_SETTING_CONNECTION (setting) - && !strcmp (key, NM_SETTING_CONNECTION_READ_ONLY)) - return; - - setting_name = nm_setting_get_name (setting); - - /* If the value is the default value, remove the item from the keyfile */ - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key); - if (pspec) { - if ( can_omit_default_value (setting, key) - && g_param_value_defaults (pspec, (GValue *) value)) { - g_key_file_remove_key (info->keyfile, setting_name, key, NULL); - return; - } - } - - /* Don't write secrets that are owned by user secret agents or aren't - * supposed to be saved. VPN secrets are handled specially though since - * the secret flags there are in a third-level hash in the 'secrets' - * property. - */ - if (pspec && (pspec->flags & NM_SETTING_PARAM_SECRET) && !NM_IS_SETTING_VPN (setting)) { - NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; - - if (!nm_setting_get_secret_flags (setting, key, &secret_flags, NULL)) - g_assert_not_reached (); - if (secret_flags != NM_SETTING_SECRET_FLAG_NONE) - return; - } - - /* Look through the list of handlers for non-standard format key values */ - while (writer->setting_name) { - if (!strcmp (writer->setting_name, setting_name) && !strcmp (writer->key, key)) { - (*writer->writer) (info, setting, key, value); - return; - } - writer++; - } - - if (type == G_TYPE_STRING) { - const char *str; - - str = g_value_get_string (value); - if (str) - nm_keyfile_plugin_kf_set_string (info->keyfile, setting_name, key, str); - } else if (type == G_TYPE_UINT) - nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (int) g_value_get_uint (value)); - else if (type == G_TYPE_INT) - nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, g_value_get_int (value)); - else if (type == G_TYPE_UINT64) { - char *numstr; - - numstr = g_strdup_printf ("%" G_GUINT64_FORMAT, g_value_get_uint64 (value)); - nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr); - g_free (numstr); - } else if (type == G_TYPE_INT64) { - char *numstr; - - numstr = g_strdup_printf ("%" G_GINT64_FORMAT, g_value_get_int64 (value)); - nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr); - g_free (numstr); - } else if (type == G_TYPE_BOOLEAN) { - nm_keyfile_plugin_kf_set_boolean (info->keyfile, setting_name, key, g_value_get_boolean (value)); - } else if (type == G_TYPE_CHAR) { - nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (int) g_value_get_schar (value)); - } else if (type == G_TYPE_BYTES) { - GBytes *bytes; - const guint8 *data; - gsize len = 0; - - bytes = g_value_get_boxed (value); - data = bytes ? g_bytes_get_data (bytes, &len) : NULL; - - if (data != NULL && len > 0) - nm_keyfile_plugin_kf_set_integer_list_uint8 (info->keyfile, setting_name, key, data, len); - } else if (type == G_TYPE_STRV) { - char **array; - - array = (char **) g_value_get_boxed (value); - nm_keyfile_plugin_kf_set_string_list (info->keyfile, setting_name, key, (const gchar **const) array, g_strv_length (array)); - } else if (type == G_TYPE_HASH_TABLE) { - write_hash_of_string (info->keyfile, setting, key, value); - } else if (type == G_TYPE_ARRAY) { - write_array_of_uint (info->keyfile, setting, key, value); - } else if (G_VALUE_HOLDS_FLAGS (value)) { - /* Flags are guint but GKeyFile has no uint reader, just uint64 */ - nm_keyfile_plugin_kf_set_uint64 (info->keyfile, setting_name, key, (guint64) g_value_get_flags (value)); - } else if (G_VALUE_HOLDS_ENUM (value)) - nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (gint) g_value_get_enum (value)); - else - g_warn_if_reached (); -} - -GKeyFile * -nm_keyfile_write (NMConnection *connection, - NMKeyfileWriteHandler handler, - void *user_data, - GError **error) -{ - KeyfileWriterInfo info = { 0 }; - - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - g_return_val_if_fail (!error || !*error, NULL); - - if (!nm_connection_verify (connection, error)) - return NULL; - - info.connection = connection; - info.keyfile = g_key_file_new (); - info.error = NULL; - info.handler = handler; - info.user_data = user_data; - nm_connection_for_each_setting_value (connection, write_setting_value, &info); - - if (info.error) { - g_propagate_error (error, info.error); - g_key_file_unref (info.keyfile); - return NULL; - } - return info.keyfile; -} - diff --git a/libnm-core/nm-keyfile-reader.c b/libnm-core/nm-keyfile.c index 20b5a3fc..5c94c35c 100644 --- a/libnm-core/nm-keyfile-reader.c +++ b/libnm-core/nm-keyfile.c @@ -25,6 +25,7 @@ #include <errno.h> #include <stdlib.h> +#include <stdio.h> #include <sys/stat.h> #include <unistd.h> #include <sys/types.h> @@ -38,6 +39,8 @@ #include "nm-setting-user.h" +/*****************************************************************************/ + typedef struct { NMConnection *connection; GKeyFile *keyfile; @@ -49,6 +52,15 @@ typedef struct { NMSetting *setting; } KeyfileReaderInfo; +typedef struct { + NMConnection *connection; + GKeyFile *keyfile; + GError *error; + NMKeyfileWriteHandler handler; + void *user_data; +} KeyfileWriterInfo; + +/*****************************************************************************/ static void _handle_warn (KeyfileReaderInfo *info, @@ -100,7 +112,7 @@ setting_alias_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *k if (s) { key_setting_name = nm_keyfile_plugin_get_setting_name_for_alias (s); g_object_set (G_OBJECT (setting), - key, key_setting_name ? key_setting_name : s, + key, key_setting_name ?: s, NULL); g_free (s); } @@ -301,7 +313,6 @@ read_field (char **current, const char **out_err_str, const char *characters, co #define DIGITS "0123456789" #define DELIMITERS "/;," - /* The following IPv4 and IPv6 address formats are supported: * * address (DEPRECATED) @@ -347,7 +358,7 @@ read_one_ip_address_or_route (KeyfileReaderInfo *info, gs_free char *value = NULL; gs_free char *value_orig = NULL; -#define VALUE_ORIG() (value_orig ? value_orig : (value_orig = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key_name, NULL))) +#define VALUE_ORIG() (value_orig ?: (value_orig = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key_name, NULL))) value = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key_name, NULL); if (!value) @@ -432,8 +443,8 @@ read_one_ip_address_or_route (KeyfileReaderInfo *info, address_str, plen, property_name); if (!result) return NULL; - if (out_gateway && gateway_str) - *out_gateway = g_strdup (gateway_str); + if (gateway_str) + NM_SET_OUT (out_gateway, g_strdup (gateway_str)); } #undef VALUE_ORIG @@ -466,146 +477,239 @@ fill_route_attributes (GKeyFile *kf, NMIPRoute *route, const char *setting, cons } } -static void -ip_address_or_route_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char *setting_name = nm_setting_get_name (setting); - gboolean ipv6 = !strcmp (setting_name, "ipv6"); - gboolean routes = !strcmp (key, "routes"); - static const char *key_names_routes[] = { "route", "routes", NULL }; - static const char *key_names_addresses[] = { "address", "addresses", NULL }; - const char **key_names = routes ? key_names_routes : key_names_addresses; - char *gateway = NULL; - GPtrArray *list; - GDestroyNotify free_func; - int i; +typedef struct { + const char *s_key; + gint32 key_idx; + gint8 key_type; +} IPAddrRouteBuildListData; - if (routes) - free_func = (GDestroyNotify) nm_ip_route_unref; - else - free_func = (GDestroyNotify) nm_ip_address_unref; - list = g_ptr_array_new_with_free_func (free_func); +static int +_ip_addrroute_build_lst_data_cmp (gconstpointer p_a, gconstpointer p_b, gpointer user_data) +{ + const IPAddrRouteBuildListData *a = p_a; + const IPAddrRouteBuildListData *b = p_b; - for (i = -1; i < 1000; i++) { - const char **key_basename; + NM_CMP_FIELD (a, b, key_idx); + NM_CMP_FIELD (a, b, key_type); + NM_CMP_FIELD_STR (a, b, s_key); + return 0; +} - for (key_basename = key_names; *key_basename; key_basename++) { - char *key_name; - gpointer item; - char options_key[128]; +static gboolean +ip_addrroute_match_key_w_name_ (const char *key, + const char *base_name, + gsize base_name_l, + gint32 *out_key_idx) +{ + gint64 v; - /* -1 means no suffix */ - if (i >= 0) - key_name = g_strdup_printf ("%s%d", *key_basename, i); - else - key_name = g_strdup (*key_basename); - - item = read_one_ip_address_or_route (info, key, setting_name, key_name, ipv6, routes, - gateway ? NULL : &gateway, setting); - if (item && routes) { - nm_sprintf_buf (options_key, "%s_options", key_name); - fill_route_attributes (info->keyfile, item, setting_name, options_key, ipv6 ? AF_INET6 : AF_INET); - } + /* some very strict parsing. */ - g_free (key_name); + /* the key must start with base_name. */ + if (strncmp (key, base_name, base_name_l) != 0) + return FALSE; - if (info->error) { - g_ptr_array_unref (list); - g_free (gateway); - return; - } - if (item) - g_ptr_array_add (list, item); + key += base_name_l; + if (key[0] == '\0') { + /* if key is identical to base_name, that's good. */ + NM_SET_OUT (out_key_idx, -1); + return TRUE; + } - } + /* if base_name is followed by a zero, then it must be + * only a zero, nothing else. */ + if (key[0] == '0') { + if (key[1] != '\0') + return FALSE; + NM_SET_OUT (out_key_idx, 0); + return TRUE; } - if (list->len >= 1) - g_object_set (setting, key, list, NULL); + /* otherwise, it can only be followed by a non-zero decimal. */ + if (!(key[0] >= '1' && key[0] <= '9')) + return FALSE; + /* and all remaining chars must be decimals too. */ + if (!NM_STRCHAR_ALL (&key[1], ch, g_ascii_isdigit (ch))) + return FALSE; - if (gateway) { - g_object_set (setting, "gateway", gateway, NULL); - g_free (gateway); - } + /* and it must be convertible to a (positive) int. */ + v = _nm_utils_ascii_str_to_int64 (key, 10, 0, G_MAXINT32, -1); + if (v < 0) + return FALSE; + + /* good */ + NM_SET_OUT (out_key_idx, v); + return TRUE; +} - g_ptr_array_unref (list); +static gboolean +ip_addrroute_match_key (const char *key, + gboolean is_routes, + gint32 *out_key_idx, + gint8 *out_key_type) +{ +#define ip_addrroute_match_key_w_name(key, base_name, out_key_idx) \ + ip_addrroute_match_key_w_name_ (key, base_name, NM_STRLEN (base_name), out_key_idx) + + if (is_routes) { + if (ip_addrroute_match_key_w_name (key, "route", out_key_idx)) + NM_SET_OUT (out_key_type, 0); + else if (ip_addrroute_match_key_w_name (key, "routes", out_key_idx)) + NM_SET_OUT (out_key_type, 1); + else + return FALSE; + } else { + if (ip_addrroute_match_key_w_name (key, "address", out_key_idx)) + NM_SET_OUT (out_key_type, 0); + else if (ip_addrroute_match_key_w_name (key, "addresses", out_key_idx)) + NM_SET_OUT (out_key_type, 1); + else + return FALSE; + } + return TRUE; } static void -ip4_dns_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) +ip_address_or_route_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *setting_key) { const char *setting_name = nm_setting_get_name (setting); - GPtrArray *array; - gsize length; - char **list, **iter; - int ret; + gboolean is_ipv6 = nm_streq (setting_name, "ipv6"); + gboolean is_routes = nm_streq (setting_key, "routes"); + gs_free char *gateway = NULL; + gs_unref_ptrarray GPtrArray *list = NULL; + gs_strfreev char **keys = NULL; + gsize i_keys, keys_len; + gs_free IPAddrRouteBuildListData *build_list = NULL; + gsize i_build_list, build_list_len = 0; - list = nm_keyfile_plugin_kf_get_string_list (info->keyfile, setting_name, key, &length, NULL); - if (!list || !g_strv_length (list)) + keys = nm_keyfile_plugin_kf_get_keys (info->keyfile, setting_name, &keys_len, NULL); + + if (keys_len == 0) return; - array = g_ptr_array_sized_new (length + 1); - for (iter = list; *iter; iter++) { - guint32 addr; + /* first create a list of all relevant keys, and sort them. */ + for (i_keys = 0; i_keys < keys_len; i_keys++) { + const char *s_key = keys[i_keys]; + gint32 key_idx; + gint8 key_type; - ret = inet_pton (AF_INET, *iter, &addr); - if (ret <= 0) { - if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid DNS server IPv4 address '%s'"), - *iter)) { - g_ptr_array_unref (array); - g_strfreev (list); - return; - } + if (!ip_addrroute_match_key (s_key, is_routes, &key_idx, &key_type)) + continue; + + if (G_UNLIKELY (!build_list)) + build_list = g_new (IPAddrRouteBuildListData, keys_len - i_keys); + + build_list[build_list_len].s_key = s_key; + build_list[build_list_len].key_idx = key_idx; + build_list[build_list_len].key_type = key_type; + build_list_len++; + } + + if (build_list_len == 0) + return; + + g_qsort_with_data (build_list, + build_list_len, + sizeof (IPAddrRouteBuildListData), + _ip_addrroute_build_lst_data_cmp, + NULL); + + list = g_ptr_array_new_with_free_func (is_routes + ? (GDestroyNotify) nm_ip_route_unref + : (GDestroyNotify) nm_ip_address_unref); + + for (i_build_list = 0; i_build_list < build_list_len; i_build_list++) { + const IPAddrRouteBuildListData *build_data = &build_list[i_build_list]; + gpointer item; + + if ( i_build_list + 1 < build_list_len + && build_data->key_idx == build_data[1].key_idx + && build_data->key_type == build_data[1].key_type + && nm_streq (build_data->s_key, build_data[1].s_key)) { + /* the keyfile contains duplicate keys, which are both returned + * by g_key_file_get_keys() (WHY??). + * + * Skip the earlier one. */ continue; } - g_ptr_array_add (array, *iter); + item = read_one_ip_address_or_route (info, + setting_key, + setting_name, + build_data->s_key, + is_ipv6, + is_routes, + gateway ? NULL : &gateway, + setting); + if (item && is_routes) { + char options_key[128]; + + nm_sprintf_buf (options_key, "%s_options", build_data->s_key); + fill_route_attributes (info->keyfile, + item, + setting_name, + options_key, + is_ipv6 ? AF_INET6 : AF_INET); + } + + if (info->error) + return; + + if (item) + g_ptr_array_add (list, item); } - g_ptr_array_add (array, NULL); - g_object_set (setting, key, array->pdata, NULL); - g_ptr_array_unref (array); - g_strfreev (list); + if (list->len >= 1) + g_object_set (setting, setting_key, list, NULL); + + if (gateway) + g_object_set (setting, "gateway", gateway, NULL); } static void -ip6_dns_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) +ip_dns_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) { - const char *setting_name = nm_setting_get_name (setting); - GPtrArray *array = NULL; - gsize length; - char **list, **iter; - int ret; - - list = nm_keyfile_plugin_kf_get_string_list (info->keyfile, setting_name, key, &length, NULL); - if (!list || !g_strv_length (list)) + int addr_family; + gs_strfreev char **list = NULL; + gsize i, n, length; + + nm_assert (NM_IS_SETTING_IP4_CONFIG (setting) || NM_IS_SETTING_IP6_CONFIG (setting)); + + list = nm_keyfile_plugin_kf_get_string_list (info->keyfile, + nm_setting_get_name (setting), + key, + &length, + NULL); + nm_assert (length == NM_PTRARRAY_LEN (list)); + if (length == 0) return; - array = g_ptr_array_sized_new (length + 1); + addr_family = NM_IS_SETTING_IP4_CONFIG (setting) ? AF_INET : AF_INET6; - for (iter = list; *iter; iter++) { - struct in6_addr addr; + n = 0; + for (i = 0; i < length; i++) { + NMIPAddr addr; - ret = inet_pton (AF_INET6, *iter, &addr); - if (ret <= 0) { + if (inet_pton (addr_family, list[i], &addr) <= 0) { if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid DNS server IPv6 address '%s'"), - *iter)) { - g_ptr_array_unref (array); - g_strfreev (list); + _("ignoring invalid DNS server IPv%c address '%s'"), + nm_utils_addr_family_to_char (addr_family), + list[i])) { + do { + nm_clear_g_free (&list[i]); + } while (++i < length); return; } + nm_clear_g_free (&list[i]); continue; } - g_ptr_array_add (array, *iter); + if (n != i) + list[n] = g_steal_pointer (&list[i]); + n++; } - g_ptr_array_add (array, NULL); - g_object_set (setting, key, array->pdata, NULL); - g_ptr_array_unref (array); - g_strfreev (list); + g_object_set (setting, key, list, NULL); } static void @@ -764,7 +868,7 @@ read_hash_of_string (GKeyFile *file, NMSetting *setting, const char *key) if (NM_IS_SETTING_USER (setting)) { gs_unref_hashtable GHashTable *data = NULL; - data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + data = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free); for (iter = (const char *const*) keys; *iter; iter++) { gs_free char *to_free = NULL; char *value = NULL; @@ -990,116 +1094,6 @@ has_cert_ext (const char *path) return FALSE; } -static gboolean -handle_as_scheme (KeyfileReaderInfo *info, GBytes *bytes, NMSetting *setting, const char *key) -{ - const char *data; - gsize data_len, bin_len; - - data = g_bytes_get_data (bytes, &data_len); - - g_return_val_if_fail (data && data_len > 0, FALSE); - - /* to be a scheme, @data must be a zero terminated string, which is counted by @data_len */ - if (data[data_len - 1] != '\0') - return FALSE; - data_len--; - - /* It's the PATH scheme, can just set plain data. - * In this case, @data_len includes */ - if ( data_len >= NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) - && g_str_has_prefix (data, NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)) { - if (nm_setting_802_1x_check_cert_scheme (data, data_len + 1, NULL) == NM_SETTING_802_1X_CK_SCHEME_PATH) { - const char *path = &data[NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)]; - gs_free char *path_free = NULL; - - if (path[0] != '/') { - /* we want to read absolute paths because we use keyfile as exchange - * between different processes which might not have the same cwd. */ - path = path_free = get_cert_path (info->base_dir, (const guint8 *) path, - data_len - NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)); - } - - g_object_set (setting, key, bytes, NULL); - if (!g_file_test (path, G_FILE_TEST_EXISTS)) { - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE, - _("certificate or key file '%s' does not exist"), - path); - } - } else { - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid key/cert value path \"%s\""), data); - } - return TRUE; - } - if ( data_len >= NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PKCS11) - && g_str_has_prefix (data, NM_KEYFILE_CERT_SCHEME_PREFIX_PKCS11)) { - if (nm_setting_802_1x_check_cert_scheme (data, data_len + 1, NULL) == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { - g_object_set (setting, key, bytes, NULL); - } else { - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid PKCS#11 URI \"%s\""), data); - } - return TRUE; - } - if ( data_len > NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB) - && g_str_has_prefix (data, NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB)) { - const char *cdata = data + NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB); - guchar *bin; - GBytes *bytes2; - gsize i; - gboolean valid_base64; - - data_len -= NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB); - - /* Let's be strict here. We expect valid base64, no funny stuff!! - * We didn't write such invalid data ourselfes and refuse to read it as blob. */ - if ((valid_base64 = (data_len % 4 == 0))) { - for (i = 0; i < data_len; i++) { - char c = cdata[i]; - - if (!( (c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || (c >= '0' && c <= '9') - || (c == '+' || c == '/'))) { - if (c != '=' || i < data_len - 2) - valid_base64 = FALSE; - else { - for (; i < data_len; i++) { - if (cdata[i] != '=') - valid_base64 = FALSE; - } - } - break; - } - } - } - if (!valid_base64) { - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid key/cert value data:;base64, is not base64")); - return TRUE; - } - - bin = g_base64_decode (cdata, &bin_len); - - g_return_val_if_fail (bin_len > 0, FALSE); - if (nm_setting_802_1x_check_cert_scheme (bin, bin_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_BLOB) { - /* The blob probably starts with "file://". Setting the cert data will confuse NMSetting8021x. - * In fact this is a limitation of NMSetting8021x which does not support setting blobs that start - * with file://. Just warn and return TRUE to signal that we ~handled~ the setting. */ - g_free (bin); - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid key/cert value data:;base64,file://")); - } else { - bytes2 = g_bytes_new_take (bin, bin_len); - g_object_set (setting, key, bytes2, NULL); - g_bytes_unref (bytes2); - } - return TRUE; - } - return FALSE; -} - char * nm_keyfile_detect_unqualified_path_scheme (const char *base_dir, gconstpointer pdata, @@ -1109,9 +1103,8 @@ nm_keyfile_detect_unqualified_path_scheme (const char *base_dir, { const char *data = pdata; gboolean exists = FALSE; - gboolean success = FALSE; gsize validate_len; - char *path; + gs_free char *path = NULL; GByteArray *tmp; g_return_val_if_fail (base_dir && base_dir[0] == '/', NULL); @@ -1143,106 +1136,187 @@ nm_keyfile_detect_unqualified_path_scheme (const char *base_dir, if ( !memchr (data, '/', data_len) && !has_cert_ext (path)) { if (!consider_exists) - goto out; + return NULL; exists = g_file_test (path, G_FILE_TEST_EXISTS); if (!exists) - goto out; + return NULL; } else if (out_exists) exists = g_file_test (path, G_FILE_TEST_EXISTS); - /* Construct the proper value as required for the PATH scheme */ + /* Construct the proper value as required for the PATH scheme. + * + * When returning TRUE, we must also be sure that @data_len does not look like + * the deprecated format of list of integers. With this implementation that is the + * case, as long as @consider_exists is FALSE. */ tmp = g_byte_array_sized_new (strlen (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) + strlen (path) + 1); g_byte_array_append (tmp, (const guint8 *) NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, strlen (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)); g_byte_array_append (tmp, (const guint8 *) path, strlen (path) + 1); - if (nm_setting_802_1x_check_cert_scheme (tmp->data, tmp->len, NULL) == NM_SETTING_802_1X_CK_SCHEME_PATH) { - g_free (path); - path = (char *) g_byte_array_free (tmp, FALSE); - /* when returning TRUE, we must also be sure that @data_len does not look like - * the deprecated format of list of integers. With this implementation that is the - * case, as long as @consider_exists is FALSE. */ - success = TRUE; - } else + if (nm_setting_802_1x_check_cert_scheme (tmp->data, tmp->len, NULL) != NM_SETTING_802_1X_CK_SCHEME_PATH) { g_byte_array_unref (tmp); - -out: - if (!success) { - g_free (path); return NULL; } - if (out_exists) - *out_exists = exists; - return path; -} - -static gboolean -handle_as_path (KeyfileReaderInfo *info, - GBytes *bytes, - NMSetting *setting, - const char *key) -{ - const guint8 *data; - gsize data_len; - char *path; - gboolean exists = FALSE; - GBytes *val; - - data = g_bytes_get_data (bytes, &data_len); - - path = nm_keyfile_detect_unqualified_path_scheme (info->base_dir, data, data_len, TRUE, &exists); - if (!path) - return FALSE; - - /* Construct the proper value as required for the PATH scheme */ - val = g_bytes_new_take (path, strlen (path) + 1); - g_object_set (setting, key, val, NULL); - - /* Warn if the certificate didn't exist */ - if (!exists) { - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE, - _("certificate or key file '%s' does not exist"), - path); - } - g_bytes_unref (val); + g_free (path); + path = (char *) g_byte_array_free (tmp, FALSE); - return TRUE; + NM_SET_OUT (out_exists, exists); + return g_steal_pointer (&path); } +#define HAS_SCHEME_PREFIX(bin, bin_len, scheme) \ + ({ \ + const char *const _bin = (bin); \ + const gsize _bin_len = (bin_len); \ + \ + nm_assert (_bin && _bin_len > 0); \ + \ + ( _bin_len > NM_STRLEN (scheme) + 1 \ + && _bin[_bin_len - 1] == '\0' \ + && memcmp (_bin, scheme, NM_STRLEN (scheme)) == 0); \ + }) + static void cert_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) { const char *setting_name = nm_setting_get_name (setting); gs_unref_bytes GBytes *bytes = NULL; - gsize bin_len; - const char *bin; + const char *bin = NULL; + gsize bin_len = 0; + char *path; + gboolean path_exists; bytes = get_bytes (info, setting_name, key, TRUE, FALSE); - if (bytes) { - /* Try as a path + scheme (ie, starts with "file://") */ - if (handle_as_scheme (info, bytes, setting, key)) - return; - if (info->error) + if (bytes) + bin = g_bytes_get_data (bytes, &bin_len); + if (bin_len == 0) { + if (!info->error) { + handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid key/cert value")); + } + return; + } + + if (HAS_SCHEME_PREFIX (bin, bin_len, NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)) { + const char *path2 = &bin[NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)]; + gs_free char *path2_free = NULL; + + if (nm_setting_802_1x_check_cert_scheme (bin, bin_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_PATH) { + handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid key/cert value path \"%s\""), bin); return; + } + + g_object_set (setting, key, bytes, NULL); - /* If not, it might be a plain path */ - if (handle_as_path (info, bytes, setting, key)) + if (path2[0] != '/') { + /* we want to read absolute paths because we use keyfile as exchange + * between different processes which might not have the same cwd. */ + path2_free = get_cert_path (info->base_dir, (const guint8 *) path2, + bin_len - NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) - 1); + path2 = path2_free; + } + + if (!g_file_test (path2, G_FILE_TEST_EXISTS)) { + handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE, + _("certificate or key file '%s' does not exist"), + path2); + } + return; + } + + if (HAS_SCHEME_PREFIX (bin, bin_len, NM_KEYFILE_CERT_SCHEME_PREFIX_PKCS11)) { + if (nm_setting_802_1x_check_cert_scheme (bin, bin_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_PKCS11) { + handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid PKCS#11 URI \"%s\""), bin); return; - if (info->error) + } + + g_object_set (setting, key, bytes, NULL); + return; + } + + if (HAS_SCHEME_PREFIX (bin, bin_len, NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB)) { + const char *cdata = bin + NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB); + gsize cdata_len = bin_len - NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB) - 1; + gs_free guchar *bin_decoded = NULL; + gsize bin_decoded_len = 0; + gsize i; + gboolean valid_base64; + gs_unref_bytes GBytes *val = NULL; + + /* Let's be strict here. We expect valid base64, no funny stuff!! + * We didn't write such invalid data ourselfes and refuse to read it as blob. */ + if ((valid_base64 = (cdata_len % 4 == 0))) { + for (i = 0; i < cdata_len; i++) { + char c = cdata[i]; + + if (!( (c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || (c >= '0' && c <= '9') + || (c == '+' || c == '/'))) { + if (c != '=' || i < cdata_len - 2) + valid_base64 = FALSE; + else { + for (; i < cdata_len; i++) { + if (cdata[i] != '=') + valid_base64 = FALSE; + } + } + break; + } + } + } + if (valid_base64) + bin_decoded = g_base64_decode (cdata, &bin_decoded_len); + + if (bin_decoded_len == 0) { + handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid key/cert value data:;base64, is not base64")); return; + } - bin = g_bytes_get_data (bytes, &bin_len); - if (nm_setting_802_1x_check_cert_scheme (bin, bin_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_BLOB) { - /* The blob probably starts with "file://" but contains invalid characters for a path. - * Setting the cert data will confuse NMSetting8021x. - * In fact, NMSetting8021x does not support setting such binary data, so just warn and - * continue. */ + if (nm_setting_802_1x_check_cert_scheme (bin_decoded, bin_decoded_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_BLOB) { + /* The blob probably starts with "file://". Setting the cert data will confuse NMSetting8021x. + * In fact this is a limitation of NMSetting8021x which does not support setting blobs that start + * with file://. Just warn and return TRUE to signal that we ~handled~ the setting. */ handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid key/cert value is not a valid blob")); - } else - g_object_set (setting, key, bytes, NULL); - } else if (!info->error) { + _("invalid key/cert value data:;base64,file://")); + return; + } + + val = g_bytes_new_take (g_steal_pointer (&bin_decoded), bin_decoded_len); + g_object_set (setting, key, val, NULL); + return; + } + + /* If not, it might be a plain path */ + path = nm_keyfile_detect_unqualified_path_scheme (info->base_dir, bin, bin_len, TRUE, &path_exists); + if (path) { + gs_unref_bytes GBytes *val = NULL; + + /* Construct the proper value as required for the PATH scheme */ + val = g_bytes_new_take (path, strlen (path) + 1); + g_object_set (setting, key, val, NULL); + + /* Warn if the certificate didn't exist */ + if (!path_exists) { + handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE, + _("certificate or key file '%s' does not exist"), + path); + } + return; + } + + if (nm_setting_802_1x_check_cert_scheme (bin, bin_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_BLOB) { + /* The blob probably starts with "file://" but contains invalid characters for a path. + * Setting the cert data will confuse NMSetting8021x. + * In fact, NMSetting8021x does not support setting such binary data, so just warn and + * continue. */ handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid key/cert value")); + _("invalid key/cert value is not a valid blob")); + return; } + + g_object_set (setting, key, bytes, NULL); } static void @@ -1289,7 +1363,7 @@ parity_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) default: handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("invalid parity value '%s'"), - str_val ? str_val : ""); + str_val ?: ""); return; } @@ -1410,149 +1484,927 @@ tfilter_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) g_ptr_array_unref (tfilters); } +/*****************************************************************************/ + +/* Some setting properties also contain setting names, such as + * NMSettingConnection's 'type' property (which specifies the base type of the + * connection, eg ethernet or wifi) or the 802-11-wireless setting's + * 'security' property which specifies whether or not the AP requires + * encryption. This function handles translating those properties' values + * from the real setting name to the more-readable alias. + */ +static void +setting_alias_writer (KeyfileWriterInfo *info, + NMSetting *setting, + const char *key, + const GValue *value) +{ + const char *str, *alias; + + str = g_value_get_string (value); + alias = nm_keyfile_plugin_get_alias_for_setting_name (str); + nm_keyfile_plugin_kf_set_string (info->keyfile, + nm_setting_get_name (setting), + key, + alias ?: str); +} + +static void +write_array_of_uint (GKeyFile *file, + NMSetting *setting, + const char *key, + const GValue *value) +{ + GArray *array; + guint i; + gs_free int *tmp_array = NULL; + + array = (GArray *) g_value_get_boxed (value); + if (!array || !array->len) + return; + + g_return_if_fail (g_array_get_element_size (array) == sizeof (guint)); + + tmp_array = g_new (gint, array->len); + for (i = 0; i < array->len; i++) { + guint v = g_array_index (array, guint, i); + + if (v > G_MAXINT) + g_return_if_reached (); + tmp_array[i] = (int) v; + } + + nm_keyfile_plugin_kf_set_integer_list (file, nm_setting_get_name (setting), key, tmp_array, array->len); +} + +static void +dns_writer (KeyfileWriterInfo *info, + NMSetting *setting, + const char *key, + const GValue *value) +{ + char **list; + + list = g_value_get_boxed (value); + if (list && list[0]) { + nm_keyfile_plugin_kf_set_string_list (info->keyfile, nm_setting_get_name (setting), key, + (const char **) list, g_strv_length (list)); + } +} + +static void +ip6_addr_gen_mode_writer (KeyfileWriterInfo *info, + NMSetting *setting, + const char *key, + const GValue *value) +{ + NMSettingIP6ConfigAddrGenMode addr_gen_mode; + gs_free char *str = NULL; + + addr_gen_mode = (NMSettingIP6ConfigAddrGenMode) g_value_get_int (value); + str = nm_utils_enum_to_str (nm_setting_ip6_config_addr_gen_mode_get_type (), + addr_gen_mode); + nm_keyfile_plugin_kf_set_string (info->keyfile, + nm_setting_get_name (setting), + key, + str); +} + +static void +write_ip_values (GKeyFile *file, + const char *setting_name, + GPtrArray *array, + const char *gateway, + gboolean is_route) +{ + GString *output; + int family, i; + const char *addr, *gw; + guint32 plen; + char key_name[64], *key_name_idx; + + if (!array->len) + return; + + family = !strcmp (setting_name, NM_SETTING_IP4_CONFIG_SETTING_NAME) ? AF_INET : AF_INET6; + + strcpy (key_name, is_route ? "route" : "address"); + key_name_idx = key_name + strlen (key_name); + + output = g_string_sized_new (2*INET_ADDRSTRLEN + 10); + for (i = 0; i < array->len; i++) { + gint64 metric = -1; + + if (is_route) { + NMIPRoute *route = array->pdata[i]; + + addr = nm_ip_route_get_dest (route); + plen = nm_ip_route_get_prefix (route); + gw = nm_ip_route_get_next_hop (route); + metric = nm_ip_route_get_metric (route); + } else { + NMIPAddress *address = array->pdata[i]; + + addr = nm_ip_address_get_address (address); + plen = nm_ip_address_get_prefix (address); + gw = i == 0 ? gateway : NULL; + } + + g_string_set_size (output, 0); + g_string_append_printf (output, "%s/%u", addr, plen); + if ( metric != -1 + || gw) { + /* Older versions of the plugin do not support the form + * "a.b.c.d/plen,,metric", so, we always have to write the + * gateway, even if there isn't one. + * The current version supports reading of the above form. + */ + if (!gw) { + if (family == AF_INET) + gw = "0.0.0.0"; + else + gw = "::"; + } + + g_string_append_printf (output, ",%s", gw); + if (is_route && metric != -1) + g_string_append_printf (output, ",%lu", (unsigned long) metric); + } + + sprintf (key_name_idx, "%d", i + 1); + nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, output->str); + + if (is_route) { + gs_free char *attributes = NULL; + GHashTable *hash; + + hash = _nm_ip_route_get_attributes_direct (array->pdata[i]); + attributes = nm_utils_format_variant_attributes (hash, ',', '='); + if (attributes) { + g_strlcat (key_name, "_options", sizeof (key_name)); + nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, attributes); + } + } + } + g_string_free (output, TRUE); +} + +static void +addr_writer (KeyfileWriterInfo *info, + NMSetting *setting, + const char *key, + const GValue *value) +{ + GPtrArray *array; + const char *setting_name = nm_setting_get_name (setting); + const char *gateway = nm_setting_ip_config_get_gateway (NM_SETTING_IP_CONFIG (setting)); + + array = (GPtrArray *) g_value_get_boxed (value); + if (array && array->len) + write_ip_values (info->keyfile, setting_name, array, gateway, FALSE); +} + +static void +route_writer (KeyfileWriterInfo *info, + NMSetting *setting, + const char *key, + const GValue *value) +{ + GPtrArray *array; + const char *setting_name = nm_setting_get_name (setting); + + array = (GPtrArray *) g_value_get_boxed (value); + if (array && array->len) + write_ip_values (info->keyfile, setting_name, array, NULL, TRUE); +} + +static void +qdisc_writer (KeyfileWriterInfo *info, + NMSetting *setting, + const char *key, + const GValue *value) +{ + gsize i; + GPtrArray *array; + + array = (GPtrArray *) g_value_get_boxed (value); + if (!array || !array->len) + return; + + for (i = 0; i < array->len; i++) { + NMTCQdisc *qdisc = array->pdata[i]; + GString *key_name = g_string_sized_new (16); + GString *value_str = g_string_sized_new (60); + + g_string_append (key_name, "qdisc."); + _nm_utils_string_append_tc_parent (key_name, NULL, + nm_tc_qdisc_get_parent (qdisc)); + _nm_utils_string_append_tc_qdisc_rest (value_str, qdisc); + + nm_keyfile_plugin_kf_set_string (info->keyfile, + NM_SETTING_TC_CONFIG_SETTING_NAME, + key_name->str, + value_str->str); + + g_string_free (key_name, TRUE); + g_string_free (value_str, TRUE); + } +} + +static void +tfilter_writer (KeyfileWriterInfo *info, + NMSetting *setting, + const char *key, + const GValue *value) +{ + gsize i; + GPtrArray *array; + + array = (GPtrArray *) g_value_get_boxed (value); + if (!array || !array->len) + return; + + for (i = 0; i < array->len; i++) { + NMTCTfilter *tfilter = array->pdata[i]; + GString *key_name = g_string_sized_new (16); + GString *value_str = g_string_sized_new (60); + + g_string_append (key_name, "tfilter."); + _nm_utils_string_append_tc_parent (key_name, NULL, + nm_tc_tfilter_get_parent (tfilter)); + _nm_utils_string_append_tc_tfilter_rest (value_str, tfilter, NULL); + + nm_keyfile_plugin_kf_set_string (info->keyfile, + NM_SETTING_TC_CONFIG_SETTING_NAME, + key_name->str, + value_str->str); + + g_string_free (key_name, TRUE); + g_string_free (value_str, TRUE); + } +} + +static void +write_hash_of_string (GKeyFile *file, + NMSetting *setting, + const char *key, + const GValue *value) +{ + GHashTable *hash; + const char *group_name = nm_setting_get_name (setting); + gboolean vpn_secrets = FALSE; + gs_free const char **keys = NULL; + guint i, l; + + /* Write VPN secrets out to a different group to keep them separate */ + if (NM_IS_SETTING_VPN (setting) && !strcmp (key, NM_SETTING_VPN_SECRETS)) { + group_name = NM_KEYFILE_GROUP_VPN_SECRETS; + vpn_secrets = TRUE; + } + + hash = g_value_get_boxed (value); + + keys = nm_utils_strdict_get_keys (hash, TRUE, &l); + for (i = 0; i < l; i++) { + const char *property, *data; + gboolean write_item = TRUE; + + property = keys[i]; + + /* Handle VPN secrets specially; they are nested in the property's hash; + * we don't want to write them if the secret is not saved, not required, + * or owned by a user's secret agent. + */ + if (vpn_secrets) { + NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; + + nm_setting_get_secret_flags (setting, property, &secret_flags, NULL); + if (secret_flags != NM_SETTING_SECRET_FLAG_NONE) + write_item = FALSE; + } + + if (write_item) { + gs_free char *to_free = NULL; + + data = g_hash_table_lookup (hash, property); + nm_keyfile_plugin_kf_set_string (file, group_name, + nm_keyfile_key_encode (property, &to_free), + data); + } + } +} + +static void +ssid_writer (KeyfileWriterInfo *info, + NMSetting *setting, + const char *key, + const GValue *value) +{ + GBytes *bytes; + const guint8 *ssid_data; + gsize ssid_len; + const char *setting_name = nm_setting_get_name (setting); + gboolean new_format = TRUE; + gsize semicolons = 0; + gsize i; + + g_return_if_fail (G_VALUE_HOLDS (value, G_TYPE_BYTES)); + + bytes = g_value_get_boxed (value); + if (!bytes) + return; + ssid_data = g_bytes_get_data (bytes, &ssid_len); + if (!ssid_data || !ssid_len) { + nm_keyfile_plugin_kf_set_string (info->keyfile, setting_name, key, ""); + return; + } + + /* Check whether each byte is printable. If not, we have to use an + * integer list, otherwise we can just use a string. + */ + for (i = 0; i < ssid_len; i++) { + const char c = ssid_data[i]; + + if (!g_ascii_isprint (c)) { + new_format = FALSE; + break; + } + if (c == ';') + semicolons++; + } + + if (new_format) { + gs_free char *ssid = NULL; + + if (semicolons == 0) + ssid = g_strndup ((char *) ssid_data, ssid_len); + else { + /* Escape semicolons with backslashes to make strings + * containing ';', such as '16;17;' unambiguous */ + gsize j = 0; + + ssid = g_malloc (ssid_len + semicolons + 1); + for (i = 0; i < ssid_len; i++) { + if (ssid_data[i] == ';') + ssid[j++] = '\\'; + ssid[j++] = ssid_data[i]; + } + ssid[j] = '\0'; + } + nm_keyfile_plugin_kf_set_string (info->keyfile, setting_name, key, ssid); + } else + nm_keyfile_plugin_kf_set_integer_list_uint8 (info->keyfile, setting_name, key, ssid_data, ssid_len); +} + +static void +password_raw_writer (KeyfileWriterInfo *info, + NMSetting *setting, + const char *key, + const GValue *value) +{ + const char *setting_name = nm_setting_get_name (setting); + GBytes *array; + gsize len; + const guint8 *data; + + g_return_if_fail (G_VALUE_HOLDS (value, G_TYPE_BYTES)); + + array = (GBytes *) g_value_get_boxed (value); + if (!array) + return; + data = g_bytes_get_data (array, &len); + if (!data) + len = 0; + nm_keyfile_plugin_kf_set_integer_list_uint8 (info->keyfile, setting_name, key, data, len); +} + +/*****************************************************************************/ + +static void +cert_writer_default (NMConnection *connection, + GKeyFile *file, + NMKeyfileWriteTypeDataCert *cert_data) +{ + const char *setting_name = nm_setting_get_name (NM_SETTING (cert_data->setting)); + NMSetting8021xCKScheme scheme; + + scheme = cert_data->vtable->scheme_func (cert_data->setting); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { + const char *path; + char *path_free = NULL, *tmp; + gs_free char *base_dir = NULL; + + path = cert_data->vtable->path_func (cert_data->setting); + g_assert (path); + + /* If the path is relative, make it an absolute path. + * Relative paths make a keyfile not easily usable in another + * context. */ + if (path[0] && path[0] != '/') { + base_dir = g_get_current_dir (); + path = path_free = g_strconcat (base_dir, "/", path, NULL); + } else + base_dir = g_path_get_dirname (path); + + /* path cannot start with "file://" or "data:;base64,", because it is an absolute path. + * Still, make sure that a prefix-less path will be recognized. This can happen + * for example if the path is longer then 500 chars. */ + tmp = nm_keyfile_detect_unqualified_path_scheme (base_dir, path, -1, FALSE, NULL); + if (tmp) + g_clear_pointer (&tmp, g_free); + else + path = tmp = g_strconcat (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, path, NULL); + + /* Path contains at least a '/', hence it cannot be recognized as the old + * binary format consisting of a list of integers. */ + + nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->vtable->setting_key, path); + g_free (tmp); + g_free (path_free); + } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { + GBytes *blob; + const guint8 *blob_data; + gsize blob_len; + char *blob_base64, *val; + + blob = cert_data->vtable->blob_func (cert_data->setting); + g_assert (blob); + blob_data = g_bytes_get_data (blob, &blob_len); + + blob_base64 = g_base64_encode (blob_data, blob_len); + val = g_strconcat (NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB, blob_base64, NULL); + + nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->vtable->setting_key, val); + g_free (val); + g_free (blob_base64); + } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { + nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->vtable->setting_key, + cert_data->vtable->uri_func (cert_data->setting)); + } else { + /* scheme_func() returns UNKNOWN in all other cases. The only valid case + * where a scheme is allowed to be UNKNOWN, is unsetting the value. In this + * case, we don't expect the writer to be called, because the default value + * will not be serialized. + * The only other reason for the scheme to be UNKNOWN is an invalid cert. + * But our connection verifies, so that cannot happen either. */ + g_return_if_reached (); + } +} + +static void +cert_writer (KeyfileWriterInfo *info, + NMSetting *setting, + const char *key, + const GValue *value) +{ + const NMSetting8021xSchemeVtable *objtype = NULL; + guint i; + NMKeyfileWriteTypeDataCert type_data = { 0 }; + + for (i = 0; nm_setting_8021x_scheme_vtable[i].setting_key; i++) { + if (g_strcmp0 (nm_setting_8021x_scheme_vtable[i].setting_key, key) == 0) { + objtype = &nm_setting_8021x_scheme_vtable[i]; + break; + } + } + if (!objtype) + g_return_if_reached (); + + type_data.setting = NM_SETTING_802_1X (setting); + type_data.vtable = objtype; + + if (info->handler) { + if (info->handler (info->connection, + info->keyfile, + NM_KEYFILE_WRITE_TYPE_CERT, + &type_data, + info->user_data, + &info->error)) + return; + if (info->error) + return; + } + + cert_writer_default (info->connection, info->keyfile, &type_data); +} + +/*****************************************************************************/ + +typedef struct { + const char *property_name; + void (*parser) (KeyfileReaderInfo *info, + NMSetting *setting, + const char *key); + void (*writer) (KeyfileWriterInfo *info, + NMSetting *setting, + const char *key, + const GValue *value); + bool parser_skip; + bool parser_no_check_key:1; + bool writer_skip:1; + + /* usually, we skip to write values that have their + * default value. By setting this flag to TRUE, also + * default values are written. */ + bool writer_persist_default:1; +} ParseInfoProperty; + +#define PARSE_INFO_PROPERTY(_property_name, ...) \ + (&((const ParseInfoProperty) { \ + .property_name = _property_name, \ + __VA_ARGS__ \ + })) + +#define PARSE_INFO_PROPERTIES(...) \ + .properties = ((const ParseInfoProperty*const[]) { \ + __VA_ARGS__ \ + NULL, \ + }) + typedef struct { const char *setting_name; - const char *key; - gboolean check_for_key; - void (*parser) (KeyfileReaderInfo *info, NMSetting *setting, const char *key); -} KeyParser; - -/* A table of keys that require further parsing/conversion because they are - * stored in a format that can't be automatically read using the key's type. - * i.e. IPv4 addresses, which are stored in NetworkManager as guint32, but are - * stored in keyfiles as strings, eg "10.1.1.2" or IPv6 addresses stored - * in struct in6_addr internally, but as string in keyfiles. - */ -static KeyParser key_parsers[] = { - { NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_TYPE, - TRUE, - setting_alias_parser }, - { NM_SETTING_BRIDGE_SETTING_NAME, - NM_SETTING_BRIDGE_MAC_ADDRESS, - TRUE, - mac_address_parser_ETHER }, - { NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_ADDRESSES, - FALSE, - ip_address_or_route_parser }, - { NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_ADDRESSES, - FALSE, - ip_address_or_route_parser }, - { NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_ROUTES, - FALSE, - ip_address_or_route_parser }, - { NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_ROUTES, - FALSE, - ip_address_or_route_parser }, - { NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_DNS, - FALSE, - ip4_dns_parser }, - { NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_DNS, - FALSE, - ip6_dns_parser }, - { NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, - FALSE, - ip6_addr_gen_mode_parser }, - { NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_MAC_ADDRESS, - TRUE, - mac_address_parser_ETHER }, - { NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_CLONED_MAC_ADDRESS, - TRUE, - mac_address_parser_ETHER_cloned }, - { NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_MAC_ADDRESS, - TRUE, - mac_address_parser_ETHER }, - { NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, - TRUE, - mac_address_parser_ETHER_cloned }, - { NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_BSSID, - TRUE, - mac_address_parser_ETHER }, - { NM_SETTING_BLUETOOTH_SETTING_NAME, - NM_SETTING_BLUETOOTH_BDADDR, - TRUE, - mac_address_parser_ETHER }, - { NM_SETTING_INFINIBAND_SETTING_NAME, - NM_SETTING_INFINIBAND_MAC_ADDRESS, - TRUE, - mac_address_parser_INFINIBAND }, - { NM_SETTING_WIMAX_SETTING_NAME, - NM_SETTING_WIMAX_MAC_ADDRESS, - TRUE, - mac_address_parser_ETHER }, - { NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_SSID, - TRUE, - ssid_parser }, - { NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PASSWORD_RAW, - TRUE, - password_raw_parser }, - { NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_CA_CERT, - TRUE, - cert_parser }, - { NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_CLIENT_CERT, - TRUE, - cert_parser }, - { NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PRIVATE_KEY, - TRUE, - cert_parser }, - { NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_CA_CERT, - TRUE, - cert_parser }, - { NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_CLIENT_CERT, - TRUE, - cert_parser }, - { NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, - TRUE, - cert_parser }, - { NM_SETTING_SERIAL_SETTING_NAME, - NM_SETTING_SERIAL_PARITY, - TRUE, - parity_parser }, - { NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TEAM_CONFIG, - TRUE, - team_config_parser }, - { NM_SETTING_TEAM_PORT_SETTING_NAME, - NM_SETTING_TEAM_CONFIG, - TRUE, - team_config_parser }, - { NM_SETTING_TC_CONFIG_SETTING_NAME, - NM_SETTING_TC_CONFIG_QDISCS, - FALSE, - qdisc_parser }, - { NM_SETTING_TC_CONFIG_SETTING_NAME, - NM_SETTING_TC_CONFIG_TFILTERS, - FALSE, - tfilter_parser }, - { NULL, NULL, FALSE } + const ParseInfoProperty*const*properties; +} ParseInfoSetting; + +#define PARSE_INFO_SETTING(_setting_name, ...) \ + { \ + .setting_name = _setting_name, \ + __VA_ARGS__ \ + } + +static const ParseInfoSetting parse_infos[] = { + PARSE_INFO_SETTING (NM_SETTING_WIRELESS_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_WIRELESS_BSSID, + .parser = mac_address_parser_ETHER, + ), + PARSE_INFO_PROPERTY (NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, + .parser = mac_address_parser_ETHER_cloned, + ), + PARSE_INFO_PROPERTY (NM_SETTING_WIRELESS_MAC_ADDRESS, + .parser = mac_address_parser_ETHER, + ), + PARSE_INFO_PROPERTY (NM_SETTING_WIRELESS_SSID, + .parser = ssid_parser, + .writer = ssid_writer, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_802_1X_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_802_1X_CA_CERT, + .parser = cert_parser, + .writer = cert_writer, + ), + PARSE_INFO_PROPERTY (NM_SETTING_802_1X_CLIENT_CERT, + .parser = cert_parser, + .writer = cert_writer, + ), + PARSE_INFO_PROPERTY (NM_SETTING_802_1X_PASSWORD_RAW, + .parser = password_raw_parser, + .writer = password_raw_writer, + ), + PARSE_INFO_PROPERTY (NM_SETTING_802_1X_PHASE2_CA_CERT, + .parser = cert_parser, + .writer = cert_writer, + ), + PARSE_INFO_PROPERTY (NM_SETTING_802_1X_PHASE2_CLIENT_CERT, + .parser = cert_parser, + .writer = cert_writer, + ), + PARSE_INFO_PROPERTY (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, + .parser = cert_parser, + .writer = cert_writer, + ), + PARSE_INFO_PROPERTY (NM_SETTING_802_1X_PRIVATE_KEY, + .parser = cert_parser, + .writer = cert_writer, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_WIRED_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_WIRED_CLONED_MAC_ADDRESS, + .parser = mac_address_parser_ETHER_cloned, + ), + PARSE_INFO_PROPERTY (NM_SETTING_WIRED_MAC_ADDRESS, + .parser = mac_address_parser_ETHER, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_BLUETOOTH_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_BLUETOOTH_BDADDR, + .parser = mac_address_parser_ETHER, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_BOND_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_BOND_OPTIONS, + .parser_no_check_key = TRUE, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_BRIDGE_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_BRIDGE_MAC_ADDRESS, + .parser = mac_address_parser_ETHER, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_CONNECTION_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_CONNECTION_READ_ONLY, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_CONNECTION_TYPE, + .parser = setting_alias_parser, + .writer = setting_alias_writer, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_INFINIBAND_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_INFINIBAND_MAC_ADDRESS, + .parser = mac_address_parser_INFINIBAND, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_IP4_CONFIG_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_IP_CONFIG_ADDRESSES, + .parser_no_check_key = TRUE, + .parser = ip_address_or_route_parser, + .writer = addr_writer, + ), + PARSE_INFO_PROPERTY (NM_SETTING_IP_CONFIG_DNS, + .parser_no_check_key = TRUE, + .parser = ip_dns_parser, + .writer = dns_writer, + ), + PARSE_INFO_PROPERTY (NM_SETTING_IP_CONFIG_GATEWAY, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_IP_CONFIG_ROUTES, + .parser_no_check_key = TRUE, + .parser = ip_address_or_route_parser, + .writer = route_writer, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_IP6_CONFIG_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, + .parser_no_check_key = TRUE, + .parser = ip6_addr_gen_mode_parser, + .writer = ip6_addr_gen_mode_writer, + .writer_persist_default = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_IP_CONFIG_ADDRESSES, + .parser_no_check_key = TRUE, + .parser = ip_address_or_route_parser, + .writer = addr_writer, + ), + PARSE_INFO_PROPERTY (NM_SETTING_IP_CONFIG_DNS, + .parser_no_check_key = TRUE, + .parser = ip_dns_parser, + .writer = dns_writer, + ), + PARSE_INFO_PROPERTY (NM_SETTING_IP_CONFIG_GATEWAY, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_IP_CONFIG_ROUTES, + .parser_no_check_key = TRUE, + .parser = ip_address_or_route_parser, + .writer = route_writer, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_SERIAL_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_SERIAL_PARITY, + .parser = parity_parser, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_TC_CONFIG_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_TC_CONFIG_QDISCS, + .parser_no_check_key = TRUE, + .parser = qdisc_parser, + .writer = qdisc_writer, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TC_CONFIG_TFILTERS, + .parser_no_check_key = TRUE, + .parser = tfilter_parser, + .writer = tfilter_writer, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_TEAM_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_CONFIG, + .parser = team_config_parser, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_LINK_WATCHERS, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_MCAST_REJOIN_COUNT, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_NOTIFY_PEERS_COUNT, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_RUNNER, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_RUNNER_ACTIVE, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_RUNNER_FAST_RATE, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_RUNNER_HWADDR_POLICY, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_RUNNER_MIN_PORTS, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_RUNNER_SYS_PRIO, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_RUNNER_TX_BALANCER, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_RUNNER_TX_HASH, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_TEAM_PORT_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_CONFIG, + .parser = team_config_parser, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_PORT_LACP_KEY, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_PORT_LACP_PRIO, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_PORT_LINK_WATCHERS, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_PORT_PRIO, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_PORT_QUEUE_ID, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_TEAM_PORT_STICKY, + .parser_skip = TRUE, + .writer_skip = TRUE, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_USER_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_USER_DATA, + .parser_no_check_key = TRUE, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_VLAN_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_VLAN_FLAGS, + .writer_persist_default = TRUE, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_VPN_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_VPN_DATA, + .parser_no_check_key = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_VPN_PERSISTENT, + .parser_no_check_key = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_VPN_SECRETS, + .parser_no_check_key = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_VPN_SERVICE_TYPE, + .parser_no_check_key = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_VPN_TIMEOUT, + .parser_no_check_key = TRUE, + ), + PARSE_INFO_PROPERTY (NM_SETTING_VPN_USER_NAME, + .parser_no_check_key = TRUE, + ), + ), + ), + PARSE_INFO_SETTING (NM_SETTING_WIMAX_SETTING_NAME, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_WIMAX_MAC_ADDRESS, + .parser = mac_address_parser_ETHER, + ), + ), + ), }; -static void -set_default_for_missing_key (NMSetting *setting, const char *property) +static const ParseInfoProperty * +_parse_info_find (const char *setting_name, const char *property_name) { - /* Set a value different from the default value of the property's spec */ + gssize idx; + +#if NM_MORE_ASSERTS > 5 + { + guint i, j; + + for (i = 0; i < G_N_ELEMENTS (parse_infos); i++) { + const ParseInfoSetting *pis = &parse_infos[i]; + + g_assert (pis->setting_name); + if ( i > 0 + && strcmp (pis[-1].setting_name, pis->setting_name) >= 0) + g_error ("Wrong order at index #%d: \"%s\" before \"%s\"", i - 1, pis[-1].setting_name, pis->setting_name); + g_assert (pis->properties); + g_assert (pis->properties[0]); + for (j = 0; pis->properties[j]; j++) { + const ParseInfoProperty *pip0; + const ParseInfoProperty *pip = pis->properties[j]; + + g_assert (pip->property_name); + if ( j > 0 + && (pip0 = pis->properties[j - 1]) + && strcmp (pip0->property_name, pip->property_name) >= 0) + g_error ("Wrong order at index #%d.%d: \"%s.%s\" before \"%s.%s\"", i, j - 1, pis->setting_name, pip0->property_name, pis->setting_name, pip->property_name); + } + } + } +#endif + + G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (ParseInfoSetting, setting_name) == 0); + idx = _nm_utils_array_find_binary_search (parse_infos, + sizeof (ParseInfoSetting), + G_N_ELEMENTS (parse_infos), + &setting_name, + nm_strcmp_p_with_data, + NULL); + if (idx >= 0) { + const ParseInfoSetting *pis = &parse_infos[idx]; + + nm_assert (nm_streq (pis->setting_name, setting_name)); + idx = _nm_utils_ptrarray_find_binary_search ((gconstpointer *) pis->properties, + NM_PTRARRAY_LEN (pis->properties), + &property_name, + nm_strcmp_p_with_data, + NULL, + NULL, + NULL); + if (idx >= 0) + return pis->properties[idx]; + } + + return NULL; } +/*****************************************************************************/ + static void read_one_setting_value (NMSetting *setting, const char *key, @@ -1566,85 +2418,54 @@ read_one_setting_value (NMSetting *setting, int errsv; GType type; gs_free_error GError *err = NULL; - gboolean check_for_key = TRUE; - KeyParser *parser = &key_parsers[0]; + const ParseInfoProperty *pip; if (info->error) return; - /* Property is not writable */ if (!(flags & G_PARAM_WRITABLE)) return; - /* Setting name gets picked up from the keyfile's section name instead */ - if (!strcmp (key, NM_SETTING_NAME)) - return; + setting_name = nm_setting_get_name (setting); - /* Don't read the NMSettingConnection object's 'read-only' property */ - if ( NM_IS_SETTING_CONNECTION (setting) - && !strcmp (key, NM_SETTING_CONNECTION_READ_ONLY)) - return; + pip = _parse_info_find (setting_name, key); - if ( ( NM_IS_SETTING_TEAM (setting) - || NM_IS_SETTING_TEAM_PORT (setting)) - && !NM_IN_STRSET (key, NM_SETTING_TEAM_CONFIG)) { - /* silently ignore all team properties (except "config"). */ + if ( !pip + && nm_streq (key, NM_SETTING_NAME)) return; - } - - setting_name = nm_setting_get_name (setting); - - /* Look through the list of handlers for non-standard format key values */ - while (parser->setting_name) { - if (!strcmp (parser->setting_name, setting_name) && !strcmp (parser->key, key)) { - check_for_key = parser->check_for_key; - break; - } - parser++; - } - if (NM_IS_SETTING_VPN (setting)) - check_for_key = FALSE; - else if (NM_IS_SETTING_USER (setting)) - check_for_key = FALSE; - else if (NM_IS_SETTING_BOND (setting)) - check_for_key = FALSE; + if (pip && pip->parser_skip) + return; /* Check for the exact key in the GKeyFile if required. Most setting * properties map 1:1 to a key in the GKeyFile, but for those properties * like IP addresses and routes where more than one value is actually * encoded by the setting property, this won't be true. */ - if (check_for_key && !nm_keyfile_plugin_kf_has_key (keyfile, setting_name, key, &err)) { + if ( (!pip || !pip->parser_no_check_key) + && !nm_keyfile_plugin_kf_has_key (keyfile, setting_name, key, &err)) { /* Key doesn't exist or an error ocurred, thus nothing to do. */ if (err) { if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("error loading setting value: %s"), err->message)) - goto out_error; + return; } - - /* Allow default values different than in property spec */ - set_default_for_missing_key (setting, key); return; } - /* If there's a custom parser for this key, handle that before the generic - * parsers below. - */ - if (parser->setting_name) { - (*parser->parser) (info, setting, key); + if (pip && pip->parser) { + pip->parser (info, setting, key); return; } type = G_VALUE_TYPE (value); if (type == G_TYPE_STRING) { - char *str_val; + gs_free char *str_val = NULL; str_val = nm_keyfile_plugin_kf_get_string (keyfile, setting_name, key, NULL); g_object_set (setting, key, str_val, NULL); - g_free (str_val); } else if (type == G_TYPE_UINT) { int int_val; @@ -1653,7 +2474,7 @@ read_one_setting_value (NMSetting *setting, if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("invalid negative value (%i)"), int_val)) - goto out_error; + return; } g_object_set (setting, key, int_val, NULL); } else if (type == G_TYPE_INT) { @@ -1674,17 +2495,16 @@ read_one_setting_value (NMSetting *setting, if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("invalid char value (%i)"), int_val)) - goto out_error; + return; } g_object_set (setting, key, int_val, NULL); } else if (type == G_TYPE_UINT64) { - char *tmp_str; + gs_free char *tmp_str = NULL; guint64 uint_val; tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_name, key, NULL); uint_val = g_ascii_strtoull (tmp_str, NULL, 10); - g_free (tmp_str); g_object_set (setting, key, uint_val, NULL); } else if (type == G_TYPE_INT64) { gs_free char *tmp_str = NULL; @@ -1697,7 +2517,7 @@ read_one_setting_value (NMSetting *setting, if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("invalid int64 value (%s)"), tmp_str)) - goto out_error; + return; } else g_object_set (setting, key, int_val, NULL); } else if (type == G_TYPE_BYTES) { @@ -1722,7 +2542,7 @@ read_one_setting_value (NMSetting *setting, val)) { g_byte_array_unref (array); g_free (tmp); - goto out_error; + return; } already_warned = TRUE; } else @@ -1756,7 +2576,7 @@ read_one_setting_value (NMSetting *setting, if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("too large FLAGS property '%s' (%llu)"), G_VALUE_TYPE_NAME (value), (unsigned long long) uint_val)) - goto out_error; + return; } } } else if (G_VALUE_HOLDS_ENUM (value)) { @@ -1769,10 +2589,8 @@ read_one_setting_value (NMSetting *setting, if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("unhandled setting property type '%s'"), G_VALUE_TYPE_NAME (value))) - goto out_error; + return; } -out_error: - return; } static NMSetting * @@ -1807,7 +2625,8 @@ read_setting (KeyfileReaderInfo *info) static void read_vpn_secrets (KeyfileReaderInfo *info, NMSettingVpn *s_vpn) { - char **keys, **iter; + gs_strfreev char **keys = NULL; + char **iter; keys = nm_keyfile_plugin_kf_get_keys (info->keyfile, NM_KEYFILE_GROUP_VPN_SECRETS, NULL, NULL); for (iter = keys; *iter; iter++) { @@ -1819,7 +2638,6 @@ read_vpn_secrets (KeyfileReaderInfo *info, NMSettingVpn *s_vpn) g_free (secret); } } - g_strfreev (keys); } /** @@ -1853,7 +2671,7 @@ nm_keyfile_read (GKeyFile *keyfile, void *user_data, GError **error) { - NMConnection *connection = NULL; + gs_unref_object NMConnection *connection = NULL; NMSettingConnection *s_con; NMSetting *setting; gchar **groups; @@ -1887,8 +2705,6 @@ nm_keyfile_read (GKeyFile *keyfile, info.user_data = user_data; groups = g_key_file_get_groups (keyfile, &length); - if (!groups) - length = 0; for (i = 0; i < length; i++) { /* Only read out secrets when needed */ if (!strcmp (groups[i], NM_KEYFILE_GROUP_VPN_SECRETS)) { @@ -1899,8 +2715,10 @@ nm_keyfile_read (GKeyFile *keyfile, info.group = groups[i]; setting = read_setting (&info); info.group = NULL; - if (info.error) - goto out_error; + if (info.error) { + g_propagate_error (error, info.error); + return NULL; + } if (setting) nm_connection_add_setting (connection, setting); } @@ -1915,21 +2733,19 @@ nm_keyfile_read (GKeyFile *keyfile, /* Make sure that we have 'id' even if not explictly specified in the keyfile */ if ( keyfile_name && !nm_setting_connection_get_id (s_con)) { - char *base_name; + gs_free char *base_name = NULL; base_name = g_path_get_basename (keyfile_name); g_object_set (s_con, NM_SETTING_CONNECTION_ID, base_name, NULL); - g_free (base_name); } /* Make sure that we have 'uuid' even if not explictly specified in the keyfile */ if ( keyfile_name && !nm_setting_connection_get_uuid (s_con)) { - char *hashed_uuid; + gs_free char *hashed_uuid = NULL; hashed_uuid = _nm_utils_uuid_generate_from_strings ("keyfile", keyfile_name, NULL); g_object_set (s_con, NM_SETTING_CONNECTION_UUID, hashed_uuid, NULL); - g_free (hashed_uuid); } /* Make sure that we have 'interface-name' even if it was specified in the @@ -1956,14 +2772,152 @@ nm_keyfile_read (GKeyFile *keyfile, s_vpn = nm_connection_get_setting_vpn (connection); if (s_vpn) { read_vpn_secrets (&info, s_vpn); - if (info.error) - goto out_error; + if (info.error) { + g_propagate_error (error, info.error); + return NULL; + } } } - return connection; -out_error: - g_propagate_error (error, info.error); - g_free (connection); - return NULL; + return g_steal_pointer (&connection); +} + +/*****************************************************************************/ + +static void +write_setting_value (NMSetting *setting, + const char *key, + const GValue *value, + GParamFlags flag, + gpointer user_data) +{ + KeyfileWriterInfo *info = user_data; + const char *setting_name; + GType type; + const ParseInfoProperty *pip; + GParamSpec *pspec; + + if (info->error) + return; + + setting_name = nm_setting_get_name (setting); + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key); + nm_assert (pspec); + + pip = _parse_info_find (setting_name, key); + + if ( !pip + && nm_streq (key, NM_SETTING_NAME)) + return; + + if (pip && pip->writer_skip) + return; + + /* Don't write secrets that are owned by user secret agents or aren't + * supposed to be saved. VPN secrets are handled specially though since + * the secret flags there are in a third-level hash in the 'secrets' + * property. + */ + if ( (pspec->flags & NM_SETTING_PARAM_SECRET) + && !NM_IS_SETTING_VPN (setting)) { + NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; + + if (!nm_setting_get_secret_flags (setting, key, &secret_flags, NULL)) + g_assert_not_reached (); + if (secret_flags != NM_SETTING_SECRET_FLAG_NONE) + return; + } + + if ( (!pip || !pip->writer_persist_default) + && g_param_value_defaults (pspec, (GValue *) value)) { + nm_assert (!g_key_file_has_key (info->keyfile, setting_name, key, NULL)); + return; + } + + if (pip && pip->writer) { + pip->writer (info, setting, key, value); + return; + } + + type = G_VALUE_TYPE (value); + if (type == G_TYPE_STRING) { + const char *str; + + str = g_value_get_string (value); + if (str) + nm_keyfile_plugin_kf_set_string (info->keyfile, setting_name, key, str); + } else if (type == G_TYPE_UINT) + nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (int) g_value_get_uint (value)); + else if (type == G_TYPE_INT) + nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, g_value_get_int (value)); + else if (type == G_TYPE_UINT64) { + char numstr[30]; + + nm_sprintf_buf (numstr, "%" G_GUINT64_FORMAT, g_value_get_uint64 (value)); + nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr); + } else if (type == G_TYPE_INT64) { + char numstr[30]; + + nm_sprintf_buf (numstr, "%" G_GINT64_FORMAT, g_value_get_int64 (value)); + nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr); + } else if (type == G_TYPE_BOOLEAN) { + nm_keyfile_plugin_kf_set_boolean (info->keyfile, setting_name, key, g_value_get_boolean (value)); + } else if (type == G_TYPE_CHAR) { + nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (int) g_value_get_schar (value)); + } else if (type == G_TYPE_BYTES) { + GBytes *bytes; + const guint8 *data; + gsize len = 0; + + bytes = g_value_get_boxed (value); + data = bytes ? g_bytes_get_data (bytes, &len) : NULL; + + if (data != NULL && len > 0) + nm_keyfile_plugin_kf_set_integer_list_uint8 (info->keyfile, setting_name, key, data, len); + } else if (type == G_TYPE_STRV) { + char **array; + + array = (char **) g_value_get_boxed (value); + nm_keyfile_plugin_kf_set_string_list (info->keyfile, setting_name, key, (const gchar **const) array, g_strv_length (array)); + } else if (type == G_TYPE_HASH_TABLE) { + write_hash_of_string (info->keyfile, setting, key, value); + } else if (type == G_TYPE_ARRAY) { + write_array_of_uint (info->keyfile, setting, key, value); + } else if (G_VALUE_HOLDS_FLAGS (value)) { + /* Flags are guint but GKeyFile has no uint reader, just uint64 */ + nm_keyfile_plugin_kf_set_uint64 (info->keyfile, setting_name, key, (guint64) g_value_get_flags (value)); + } else if (G_VALUE_HOLDS_ENUM (value)) + nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (gint) g_value_get_enum (value)); + else + g_warn_if_reached (); +} + +GKeyFile * +nm_keyfile_write (NMConnection *connection, + NMKeyfileWriteHandler handler, + void *user_data, + GError **error) +{ + KeyfileWriterInfo info = { 0 }; + + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + g_return_val_if_fail (!error || !*error, NULL); + + if (!nm_connection_verify (connection, error)) + return NULL; + + info.connection = connection; + info.keyfile = g_key_file_new (); + info.error = NULL; + info.handler = handler; + info.user_data = user_data; + nm_connection_for_each_setting_value (connection, write_setting_value, &info); + + if (info.error) { + g_propagate_error (error, info.error); + g_key_file_unref (info.keyfile); + return NULL; + } + return info.keyfile; } diff --git a/libnm-core/nm-property-compare.h b/libnm-core/nm-property-compare.h index b859989f..da2aaf2c 100644 --- a/libnm-core/nm-property-compare.h +++ b/libnm-core/nm-property-compare.h @@ -23,6 +23,10 @@ #ifndef __NM_PROPERTY_COMPARE_H__ #define __NM_PROPERTY_COMPARE_H__ +#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) +#error Cannot use this header. +#endif + int nm_property_compare (GVariant *value1, GVariant *value2); #endif /* __NM_PROPERTY_COMPARE_H__ */ diff --git a/libnm-core/nm-setting-8021x.c b/libnm-core/nm-setting-8021x.c index af195211..3b4240e6 100644 --- a/libnm-core/nm-setting-8021x.c +++ b/libnm-core/nm-setting-8021x.c @@ -1686,7 +1686,6 @@ nm_setting_802_1x_remove_phase2_altsubject_match (NMSetting8021x *setting, guint g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES); } - /** * nm_setting_802_1x_remove_phase2_altsubject_match_by_value: * @setting: the #NMSetting8021x @@ -2247,7 +2246,7 @@ nm_setting_802_1x_set_private_key (NMSetting8021x *setting, { NMSetting8021xPrivate *priv; NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - gboolean key_cleared = FALSE, password_cleared = FALSE; + gboolean password_changed = FALSE; GError *local_err = NULL; g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE); @@ -2281,39 +2280,35 @@ nm_setting_802_1x_set_private_key (NMSetting8021x *setting, priv = NM_SETTING_802_1X_GET_PRIVATE (setting); - /* Clear out any previous private key data */ - if (priv->private_key) { - g_bytes_unref (priv->private_key); - priv->private_key = NULL; - key_cleared = TRUE; - } - - if (priv->private_key_password) { - g_free (priv->private_key_password); - priv->private_key_password = NULL; - password_cleared = TRUE; - } - if (value == NULL) { - if (key_cleared) + if (priv->private_key) { + g_clear_pointer (&priv->private_key, g_bytes_unref); g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY); - if (password_cleared) + } + if (nm_clear_g_free (&priv->private_key_password)) g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); return TRUE; } - priv->private_key_password = g_strdup (password); + /* this makes password self-assignment safe. */ + if (!nm_streq0 (priv->private_key_password, password)) { + g_free (priv->private_key_password); + priv->private_key_password = g_strdup (password); + password_changed = TRUE; + } + + g_bytes_unref (priv->private_key); if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { /* FIXME: potential race after verifying the private key above */ /* FIXME: ensure blob doesn't start with file:// */ priv->private_key = file_to_secure_bytes (value); - g_assert (priv->private_key); + nm_assert (priv->private_key); } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) priv->private_key = path_to_scheme_value (value); - else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) + else { + nm_assert (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11); priv->private_key = g_bytes_new (value, strlen (value) + 1); - else - g_assert_not_reached (); + } /* As required by NM and wpa_supplicant, set the client-cert * property to the same PKCS#12 data. @@ -2326,11 +2321,10 @@ nm_setting_802_1x_set_private_key (NMSetting8021x *setting, } g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY); - if (password_cleared || password) + if (password_changed) g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); - if (out_format) - *out_format = (NMSetting8021xCKFormat) format; + NM_SET_OUT (out_format, (NMSetting8021xCKFormat) format); return priv->private_key != NULL; } @@ -2594,7 +2588,7 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting, { NMSetting8021xPrivate *priv; NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - gboolean key_cleared = FALSE, password_cleared = FALSE; + gboolean password_changed = FALSE; GError *local_err = NULL; g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE); @@ -2628,39 +2622,34 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting, priv = NM_SETTING_802_1X_GET_PRIVATE (setting); - /* Clear out any previous private key data */ - if (priv->phase2_private_key) { - g_bytes_unref (priv->phase2_private_key); - priv->phase2_private_key = NULL; - key_cleared = TRUE; - } - - if (priv->phase2_private_key_password) { - g_free (priv->phase2_private_key_password); - priv->phase2_private_key_password = NULL; - password_cleared = TRUE; - } - if (value == NULL) { - if (key_cleared) + if (priv->phase2_private_key) { + g_clear_pointer (&priv->phase2_private_key, g_bytes_unref); g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); - if (password_cleared) + } + if (nm_clear_g_free (&priv->phase2_private_key_password)) g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD); return TRUE; } - priv->phase2_private_key_password = g_strdup (password); + /* this makes password self-assignment safe. */ + if (!nm_streq0 (priv->phase2_private_key_password, password)) { + g_free (priv->phase2_private_key_password); + priv->phase2_private_key_password = g_strdup (password); + password_changed = TRUE; + } + if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { /* FIXME: potential race after verifying the private key above */ /* FIXME: ensure blob doesn't start with file:// */ priv->phase2_private_key = file_to_secure_bytes (value); - g_assert (priv->phase2_private_key); + nm_assert (priv->phase2_private_key); } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) priv->phase2_private_key = path_to_scheme_value (value); - else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) + else { + nm_assert (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11); priv->phase2_private_key = g_bytes_new (value, strlen (value) + 1); - else - g_assert_not_reached (); + } /* As required by NM and wpa_supplicant, set the client-cert * property to the same PKCS#12 data. @@ -2674,11 +2663,10 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting, } g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); - if (password_cleared || password) + if (password_changed) g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD); - if (out_format) - *out_format = (NMSetting8021xCKFormat) format; + NM_SET_OUT (out_format, (NMSetting8021xCKFormat) format); return priv->phase2_private_key != NULL; } @@ -3071,7 +3059,6 @@ static void need_secrets_phase2 (NMSetting8021x *self, GPtrArray *secrets, gboolean phase2); - typedef void (*EAPMethodNeedSecretsFunc) (NMSetting8021x *self, GPtrArray *secrets, gboolean phase2); @@ -3137,7 +3124,6 @@ need_secrets_phase2 (NMSetting8021x *self, } } - static GPtrArray * need_secrets (NMSetting *setting) { @@ -4434,9 +4420,6 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - - /** * NMSetting8021x:phase2-client-cert-password: * diff --git a/libnm-core/nm-setting-8021x.h b/libnm-core/nm-setting-8021x.h index e1631e2d..986d0488 100644 --- a/libnm-core/nm-setting-8021x.h +++ b/libnm-core/nm-setting-8021x.h @@ -280,7 +280,6 @@ gboolean nm_setting_802_1x_set_phase2_ca_cert (NMSetting8 NMSetting8021xCKFormat *out_format, GError **error); - NM_AVAILABLE_IN_1_8 const char * nm_setting_802_1x_get_phase2_ca_cert_password (NMSetting8021x *setting); NM_AVAILABLE_IN_1_8 diff --git a/libnm-core/nm-setting-adsl.c b/libnm-core/nm-setting-adsl.c index 8be288b6..c2eb5db4 100644 --- a/libnm-core/nm-setting-adsl.c +++ b/libnm-core/nm-setting-adsl.c @@ -206,7 +206,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' is not a valid value for the property"), - priv->protocol ? priv->protocol : "(null)"); + priv->protocol ?: "(null)"); g_prefix_error (error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_PROTOCOL); return FALSE; } diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c index a44972cf..9b4b3641 100644 --- a/libnm-core/nm-setting-bond.c +++ b/libnm-core/nm-setting-bond.c @@ -159,9 +159,7 @@ nm_setting_bond_get_option (NMSettingBond *setting, const char **out_value) { NMSettingBondPrivate *priv; - guint i, len; - GHashTableIter iter; - const char *key, *value; + guint len; g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE); @@ -171,23 +169,8 @@ nm_setting_bond_get_option (NMSettingBond *setting, if (idx >= len) return FALSE; - if (!G_UNLIKELY (priv->options_idx_cache)) { - NMUtilsNamedValue *options; - - i = 0; - options = g_new (NMUtilsNamedValue, len); - g_hash_table_iter_init (&iter, priv->options); - while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) { - options[i].name = key; - options[i].value_str = value; - i++; - } - nm_assert (i == len); - - g_qsort_with_data (options, len, sizeof (options[0]), - nm_utils_named_entry_cmp_with_data, NULL); - priv->options_idx_cache = options; - } + if (!G_UNLIKELY (priv->options_idx_cache)) + priv->options_idx_cache = nm_utils_named_values_from_str_dict (priv->options, NULL); NM_SET_OUT (out_name, priv->options_idx_cache[idx].name); NM_SET_OUT (out_value, priv->options_idx_cache[idx].value_str); @@ -554,7 +537,7 @@ _nm_setting_bond_option_supported (const char *option, NMBondMode mode) for (i = 0; i < G_N_ELEMENTS (bond_unsupp_modes); i++) { if (nm_streq (option, bond_unsupp_modes[i].option)) - return !NM_FLAGS_HAS (bond_unsupp_modes[i].unsupp_modes, BIT (mode)); + return !NM_FLAGS_ANY (bond_unsupp_modes[i].unsupp_modes, BIT (mode)); } return TRUE; @@ -947,7 +930,7 @@ nm_setting_bond_init (NMSettingBond *setting) { NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting); - priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + priv->options = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free); /* Default values: */ nm_setting_bond_add_option (setting, NM_SETTING_BOND_OPTION_MODE, "balance-rr"); @@ -994,13 +977,11 @@ nm_setting_bond_class_init (NMSettingBondClass *setting_class) /* Properties */ /** - * NMSettingBond:options: + * NMSettingBond:options: (type GHashTable(utf8,utf8)): * * Dictionary of key/value pairs of bonding options. Both keys and values * must be strings. Option names must contain only alphanumeric characters * (ie, [a-zA-Z0-9]). - * - * Type: GHashTable(utf8,utf8) **/ /* ---ifcfg-rh--- * property: options diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c index 152cdf65..112b499f 100644 --- a/libnm-core/nm-setting-bridge.c +++ b/libnm-core/nm-setting-bridge.c @@ -418,6 +418,8 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class) * "ethernet.cloned-mac-address" anyway overwrites the MAC address of * the bridge later while activating the bridge. Hence, this property * is deprecated. + * + * Deprecated: 1.12: Use the ethernet.cloned-mac-address property instead. **/ /* ---keyfile--- * property: mac-address diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c index 24c65e7c..f8f1b017 100644 --- a/libnm-core/nm-setting-connection.c +++ b/libnm-core/nm-setting-connection.c @@ -81,6 +81,7 @@ typedef struct { NMMetered metered; NMSettingConnectionLldp lldp; gint auth_retries; + int mdns; } NMSettingConnectionPrivate; enum { @@ -103,6 +104,7 @@ enum { PROP_GATEWAY_PING_TIMEOUT, PROP_METERED, PROP_LLDP, + PROP_MDNS, PROP_STABLE_ID, PROP_AUTH_RETRIES, @@ -286,7 +288,6 @@ nm_setting_connection_get_connection_type (NMSettingConnection *setting) return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->type; } - /** * nm_setting_connection_get_num_permissions: * @setting: the #NMSettingConnection @@ -862,6 +863,23 @@ nm_setting_connection_get_lldp (NMSettingConnection *setting) return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->lldp; } +/** + * nm_setting_connection_get_mdns: + * @setting: the #NMSettingConnection + * + * Returns: the #NMSettingConnection:mdns property of the setting. + * + * Since: 1.12 + **/ +NMSettingConnectionMdns +nm_setting_connection_get_mdns (NMSettingConnection *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), + NM_SETTING_CONNECTION_MDNS_DEFAULT); + + return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->mdns; +} + static void _set_error_missing_base_setting (GError **error, const char *type) { @@ -1057,6 +1075,17 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + if ( priv->mdns < NM_SETTING_CONNECTION_MDNS_DEFAULT + || priv->mdns > NM_SETTING_CONNECTION_MDNS_YES) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("mdns value %d is not valid"), priv->mdns); + g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_MDNS); + return FALSE; + } + /* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */ if (!priv->uuid) { @@ -1214,6 +1243,9 @@ compare_property (NMSetting *setting, static void nm_setting_connection_init (NMSettingConnection *setting) { + NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting); + + priv->mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; } static void @@ -1332,6 +1364,9 @@ set_property (GObject *object, guint prop_id, case PROP_AUTH_RETRIES: priv->auth_retries = g_value_get_int (value); break; + case PROP_MDNS: + priv->mdns = g_value_get_int (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1420,6 +1455,9 @@ get_property (GObject *object, guint prop_id, case PROP_AUTH_RETRIES: g_value_set_int (value, priv->auth_retries); break; + case PROP_MDNS: + g_value_set_int (value, priv->mdns); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1497,32 +1535,39 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) /** * NMSettingConnection:stable-id: * - * Token to generate stable IDs for the connection. + * This represents the identity of the connection used for various purposes. + * It allows to configure multiple profiles to share the identity. Also, + * the stable-id can contain placeholders that are substituted dynamically and + * deterministically depending on the context. * * The stable-id is used for generating IPv6 stable private addresses * with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the * generated cloned MAC address for ethernet.cloned-mac-address=stable - * and wifi.cloned-mac-address=stable. Note that also the interface name - * of the activating connection and a per-host secret key is included - * into the address generation so that the same stable-id on different - * hosts/devices yields different addresses. + * and wifi.cloned-mac-address=stable. It is also used as DHCP client + * identifier with ipv4.dhcp-client-id=stable. * - * If the value is unset, an ID unique for the connection is used. - * Specifying a stable-id allows multiple connections to generate the - * same addresses. Another use is to generate IDs at runtime via - * dynamic substitutions. + * Note that depending on the context where it is used, other parameters are + * also seeded into the generation algorithm. For example, a per-host key + * is commonly also included, so that different systems end up generating + * different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's + * name is included, so that different interfaces yield different addresses. * * The '$' character is treated special to perform dynamic substitutions - * at runtime. Currently supported are "${CONNECTION}", "${BOOT}", "${RANDOM}". - * These effectively create unique IDs per-connection, per-boot, or every time. + * at runtime. Currently supported are "${CONNECTION}", "${DEVICE}", + * "${BOOT}", "${RANDOM}". + * These effectively create unique IDs per-connection, per-device, per-boot, + * or every time. Note that "${DEVICE}" corresponds the the interface name of the + * device. * Any unrecognized patterns following '$' are treated verbatim, however * are reserved for future use. You are thus advised to avoid '$' or * escape it as "$$". - * For example, set it to "${CONNECTION}/${BOOT}" to create a unique id for - * this connection that changes with every reboot. + * For example, set it to "${CONNECTION}-${BOOT}-${DEVICE}" to create a unique id for + * this connection that changes with every reboot and differs depending on the + * interface where the profile activates. * - * Note that two connections only use the same effective id if - * their stable-id is also identical before performing dynamic substitutions. + * If the value is unset, a global connection default is consulted. If the + * value is still unset, the default is similar to "${CONNECTION}" and uses + * a unique, fixed ID for the connection. * * Since: 1.4 **/ @@ -1641,6 +1686,10 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) * NetworkManager when the resources for the connection are available. * %TRUE to automatically activate the connection, %FALSE to require manual * intervention to activate the connection. + * + * Note that autoconnect is not implemented for VPN profiles. See + * #NMSettingConnection:secondaries as an alternative to automatically + * connect VPN profiles. **/ /* ---ifcfg-rh--- * property: autoconnect @@ -1686,7 +1735,6 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); - /** * NMSettingConnection:autoconnect-retries: * @@ -1833,7 +1881,9 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) * * Whether or not slaves of this connection should be automatically brought up * when NetworkManager activates this connection. This only has a real effect - * for master connections. + * for master connections. The properties #NMSettingConnection:autoconnect, + * #NMSettingConnection:autoconnect-priority and #NMSettingConnection:autoconnect-retries + * are unrelated to this setting. * The permitted values are: 0: leave slave connections untouched, * 1: activate all the slave connections with this connection, -1: default. * If -1 (default) is set, global connection.autoconnect-slaves is read to @@ -1982,4 +2032,37 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingConnection:mdns: + * + * Whether mDNS is enabled for the connection. + * + * The permitted values are: yes: register hostname and resolving + * for the connection, no: disable mDNS for the interface, resolve: + * do not register hostname but allow resolving of mDNS host names. + * When updating this property on a currently activated connection, + * the change takes effect immediately. + * + * This feature requires a plugin which supports mDNS. One such + * plugin is dns-systemd-resolved. + * + * Since: 1.12 + **/ + /* ---ifcfg-rh--- + * property: mdns + * variable: CONNECTION_MDNS(+) + * values: yes,no,resolve + * default: missing variable means global default + * description: Whether or not mDNS is enabled for the connection + * example: CONNECTION_MDNS=yes + * ---end--- + */ + g_object_class_install_property + (object_class, PROP_MDNS, + g_param_spec_int (NM_SETTING_CONNECTION_MDNS, "", "", + G_MININT32, G_MAXINT32, + NM_SETTING_CONNECTION_MDNS_DEFAULT, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); } diff --git a/libnm-core/nm-setting-connection.h b/libnm-core/nm-setting-connection.h index 02a7f5b1..cf083a48 100644 --- a/libnm-core/nm-setting-connection.h +++ b/libnm-core/nm-setting-connection.h @@ -64,6 +64,7 @@ G_BEGIN_DECLS #define NM_SETTING_CONNECTION_METERED "metered" #define NM_SETTING_CONNECTION_LLDP "lldp" #define NM_SETTING_CONNECTION_AUTH_RETRIES "auth-retries" +#define NM_SETTING_CONNECTION_MDNS "mdns" /* Types for property values */ /** @@ -98,6 +99,24 @@ typedef enum { } NMSettingConnectionLldp; /** + * NMSettingConnectionMdns: + * @NM_SETTING_CONNECTION_MDNS_DEFAULT: default value + * @NM_SETTING_CONNECTION_MDNS_NO: disable mDNS + * @NM_SETTING_CONNECTION_MDNS_RESOLVE: support only resolving, do not register hostname + * @NM_SETTING_CONNECTION_MDNS_YES: enable mDNS + * + * #NMSettingConnectionMdns values indicate whether mDNS should be enabled. + * + * Since: 1.12 + */ +typedef enum { + NM_SETTING_CONNECTION_MDNS_DEFAULT = -1, + NM_SETTING_CONNECTION_MDNS_NO = 0, + NM_SETTING_CONNECTION_MDNS_RESOLVE = 1, + NM_SETTING_CONNECTION_MDNS_YES = 2, +} NMSettingConnectionMdns; + +/** * NMSettingConnection: * * General Connection Profile Settings @@ -170,6 +189,8 @@ NMSettingConnectionLldp nm_setting_connection_get_lldp (NMSettingConnection *set NM_AVAILABLE_IN_1_10 gint nm_setting_connection_get_auth_retries (NMSettingConnection *setting); +NM_AVAILABLE_IN_1_12 +NMSettingConnectionMdns nm_setting_connection_get_mdns (NMSettingConnection *setting); G_END_DECLS #endif /* __NM_SETTING_CONNECTION_H__ */ diff --git a/libnm-core/nm-setting-dcb.c b/libnm-core/nm-setting-dcb.c index 24d461a1..491d9151 100644 --- a/libnm-core/nm-setting-dcb.c +++ b/libnm-core/nm-setting-dcb.c @@ -1099,13 +1099,11 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) G_PARAM_STATIC_STRINGS)); /** - * NMSettingDcb:priority-flow-control: + * NMSettingDcb:priority-flow-control: (type GArray(gboolean)) * * An array of 8 boolean values, where the array index corresponds to the User * Priority (0 - 7) and the value indicates whether or not the corresponding * priority should transmit priority pause. - * - * Element-type: gboolean **/ /* ---ifcfg-rh--- * property: priority-flow-control @@ -1149,13 +1147,11 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) G_PARAM_STATIC_STRINGS)); /** - * NMSettingDcb:priority-group-id: + * NMSettingDcb:priority-group-id: (type GArray(guint)) * * An array of 8 uint values, where the array index corresponds to the User * Priority (0 - 7) and the value indicates the Priority Group ID. Allowed * Priority Group ID values are 0 - 7 or 15 for the unrestricted group. - * - * Element-type: guint **/ /* ---ifcfg-rh--- * property: priority-group-id @@ -1177,14 +1173,12 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) _nm_setting_dcb_uint_array_from_dbus); /** - * NMSettingDcb:priority-group-bandwidth: + * NMSettingDcb:priority-group-bandwidth: (type GArray(guint)) * * An array of 8 uint values, where the array index corresponds to the * Priority Group ID (0 - 7) and the value indicates the percentage of link * bandwidth allocated to that group. Allowed values are 0 - 100, and the * sum of all values must total 100 percents. - * - * Element-type: guint **/ /* ---ifcfg-rh--- * property: priority-group-bandwidth @@ -1205,15 +1199,13 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) _nm_setting_dcb_uint_array_from_dbus); /** - * NMSettingDcb:priority-bandwidth: + * NMSettingDcb:priority-bandwidth: (type GArray(guint)) * * An array of 8 uint values, where the array index corresponds to the User * Priority (0 - 7) and the value indicates the percentage of bandwidth of * the priority's assigned group that the priority may use. The sum of all * percentages for priorities which belong to the same group must total 100 * percents. - * - * Element-type: guint **/ /* ---ifcfg-rh--- * property: priority-bandwidth @@ -1235,13 +1227,11 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) _nm_setting_dcb_uint_array_from_dbus); /** - * NMSettingDcb:priority-strict-bandwidth: + * NMSettingDcb:priority-strict-bandwidth: (type GArray(gboolean)) * * An array of 8 boolean values, where the array index corresponds to the User * Priority (0 - 7) and the value indicates whether or not the priority may * use all of the bandwidth allocated to its assigned group. - * - * Element-type: gboolean **/ /* ---ifcfg-rh--- * property: priority-strict-bandwidth @@ -1263,13 +1253,11 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) _nm_setting_dcb_uint_array_from_dbus); /** - * NMSettingDcb:priority-traffic-class: + * NMSettingDcb:priority-traffic-class: (type GArray(guint)) * * An array of 8 uint values, where the array index corresponds to the User * Priority (0 - 7) and the value indicates the traffic class (0 - 7) to * which the priority is mapped. - * - * Element-type: guint **/ /* ---ifcfg-rh--- * property: priority-traffic-class diff --git a/libnm-core/nm-setting-dcb.h b/libnm-core/nm-setting-dcb.h index d2a364a2..51a883fb 100644 --- a/libnm-core/nm-setting-dcb.h +++ b/libnm-core/nm-setting-dcb.h @@ -70,7 +70,6 @@ typedef enum { /*< flags >*/ */ #define NM_SETTING_DCB_FCOE_MODE_VN2VN "vn2vn" - /* Properties */ #define NM_SETTING_DCB_APP_FCOE_FLAGS "app-fcoe-flags" #define NM_SETTING_DCB_APP_FCOE_PRIORITY "app-fcoe-priority" diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c index 779d4428..c7f8c555 100644 --- a/libnm-core/nm-setting-ip-config.c +++ b/libnm-core/nm-setting-ip-config.c @@ -526,6 +526,14 @@ nm_ip_address_set_prefix (NMIPAddress *address, address->prefix = prefix; } +const char ** +_nm_ip_address_get_attribute_names (const NMIPAddress *address, gboolean sorted, guint *out_length) +{ + nm_assert (address); + + return nm_utils_strdict_get_keys (address->attributes, sorted, out_length); +} + /** * nm_ip_address_get_attribute_names: * @address: the #NMIPAddress @@ -537,22 +545,12 @@ nm_ip_address_set_prefix (NMIPAddress *address, char ** nm_ip_address_get_attribute_names (NMIPAddress *address) { - GHashTableIter iter; - const char *key; - GPtrArray *names; - - g_return_val_if_fail (address != NULL, NULL); + const char **names; - names = g_ptr_array_new (); + g_return_val_if_fail (address, NULL); - if (address->attributes) { - g_hash_table_iter_init (&iter, address->attributes); - while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL)) - g_ptr_array_add (names, g_strdup (key)); - } - g_ptr_array_add (names, NULL); - - return (char **) g_ptr_array_free (names, FALSE); + names = _nm_ip_address_get_attribute_names (address, TRUE, NULL); + return nm_utils_strv_make_deep_copied_nonnull (names); } /** @@ -593,7 +591,7 @@ nm_ip_address_set_attribute (NMIPAddress *address, const char *name, GVariant *v g_return_if_fail (strcmp (name, "address") != 0 && strcmp (name, "prefix") != 0); if (!address->attributes) { - address->attributes = g_hash_table_new_full (g_str_hash, g_str_equal, + address->attributes = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); } @@ -1131,33 +1129,14 @@ _nm_ip_route_get_attributes_direct (NMIPRoute *route) * * Returns: (array length=out_length) (transfer container): a %NULL-terminated array * of attribute names or %NULL if there are no attributes. The order of the returned - * names is undefined. + * names depends on @sorted. **/ const char ** _nm_ip_route_get_attribute_names (const NMIPRoute *route, gboolean sorted, guint *out_length) { - const char **names; - guint length; - - g_return_val_if_fail (route != NULL, NULL); - - if ( !route->attributes - || !g_hash_table_size (route->attributes)) { - NM_SET_OUT (out_length, 0); - return NULL; - } + nm_assert (route); - names = (const char **) g_hash_table_get_keys_as_array (route->attributes, &length); - if ( sorted - && length > 1) { - g_qsort_with_data (names, - length, - sizeof (char *), - nm_strcmp_p_with_data, - NULL); - } - NM_SET_OUT (out_length, length); - return names; + return nm_utils_strdict_get_keys (route->attributes, sorted, out_length); } /** @@ -1171,21 +1150,12 @@ _nm_ip_route_get_attribute_names (const NMIPRoute *route, gboolean sorted, guint char ** nm_ip_route_get_attribute_names (NMIPRoute *route) { - char **names; - guint i, len; + const char **names; g_return_val_if_fail (route != NULL, NULL); - names = (char **) _nm_ip_route_get_attribute_names (route, TRUE, &len); - if (!names) - return g_new0 (char *, 1); - - nm_assert (len > 0 && names && names[len] == NULL); - for (i = 0; i < len; i++) { - nm_assert (names[i]); - names[i] = g_strdup (names[i]); - } - return names; + names = _nm_ip_route_get_attribute_names (route, TRUE, NULL); + return nm_utils_strv_make_deep_copied_nonnull (names); } /** @@ -1227,7 +1197,7 @@ nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value) && strcmp (name, "next-hop") != 0 && strcmp (name, "metric") != 0); if (!route->attributes) { - route->attributes = g_hash_table_new_full (g_str_hash, g_str_equal, + route->attributes = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); } @@ -2553,7 +2523,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - label = nm_ip_address_get_attribute (addr, "label"); + label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); if (label) { if (!g_variant_is_of_type (label, G_VARIANT_TYPE_STRING)) { g_set_error (error, @@ -2960,7 +2930,10 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) /** * NMSettingIPConfig:dns-search: * - * Array of DNS search domains. + * 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. **/ g_object_class_install_property (object_class, PROP_DNS_SEARCH, @@ -2990,24 +2963,34 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) /** * NMSettingIPConfig:dns-priority: * - * Intra-connection DNS priority. + * DNS servers priority. + * + * The relative priority for DNS servers specified by this setting. A lower + * value is better (higher priority). Zero selects the default value, which + * is 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. * - * The relative priority to be used when determining the order of DNS - * servers in resolv.conf. A lower value means that servers will be on top - * of the file. Zero selects the default value, which is 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. For that, - * just specify the DNS servers in the desired order. - * When multiple devices have configurations with the same priority, the - * one with an active default route will be preferred. - * Note that when using dns=dnsmasq the order is meaningless - * since dnsmasq forwards queries to all known servers at the same time. + * 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, the one with an + * active default route will be preferred. Negative values have the special + * effect of excluding other configurations with a greater priority value; + * so in presence of at least a negative priority, only DNS servers from + * connections with the lowest priority value will be used. * - * Negative values have the special effect of excluding other configurations - * with a greater priority value; so in presence of at least a negative - * priority, only DNS servers from connections with the lowest priority - * value will be used. + * When using a DNS resolver that supports split-DNS 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. * * Since: 1.4 **/ @@ -3020,11 +3003,9 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) G_PARAM_STATIC_STRINGS)); /** - * NMSettingIPConfig:addresses: + * NMSettingIPConfig:addresses: (type GPtrArray(NMIPAddress)) * * Array of IP addresses. - * - * Element-Type: NMIPAddress **/ g_object_class_install_property (object_class, PROP_ADDRESSES, @@ -3061,11 +3042,9 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) NULL); /** - * NMSettingIPConfig:routes: + * NMSettingIPConfig:routes: (type GPtrArray(NMIPRoute)) * * Array of IP routes. - * - * Element-Type: NMIPRoute **/ g_object_class_install_property (object_class, PROP_ROUTES, @@ -3232,9 +3211,11 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) * addresses on the network. If an address conflict is detected, the * activation will fail. A zero value means that no duplicate address * detection is performed, -1 means the default value (either configuration - * ipvx.dad-timeout override or 3 seconds). A value greater than zero is a + * ipvx.dad-timeout override or zero). A value greater than zero is a * timeout in milliseconds. * + * The property is currently implemented only for IPv4. + * * Since: 1.2 **/ g_object_class_install_property diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h index 96e61bb5..8b3c85de 100644 --- a/libnm-core/nm-setting-ip-config.h +++ b/libnm-core/nm-setting-ip-config.h @@ -32,6 +32,8 @@ G_BEGIN_DECLS +#define NM_IP_ADDRESS_ATTRIBUTE_LABEL "label" + typedef struct NMIPAddress NMIPAddress; GType nm_ip_address_get_type (void); @@ -70,7 +72,6 @@ void nm_ip_address_set_attribute (NMIPAddress *address, const char *name, GVariant *value); - typedef struct NMIPRoute NMIPRoute; GType nm_ip_route_get_type (void); diff --git a/libnm-core/nm-setting-ip-tunnel.c b/libnm-core/nm-setting-ip-tunnel.c index fa8d4a7a..c9cb97df 100644 --- a/libnm-core/nm-setting-ip-tunnel.c +++ b/libnm-core/nm-setting-ip-tunnel.c @@ -49,6 +49,7 @@ typedef struct { guint encapsulation_limit; guint flow_label; guint mtu; + guint32 flags; } NMSettingIPTunnelPrivate; enum { @@ -65,6 +66,7 @@ enum { PROP_ENCAPSULATION_LIMIT, PROP_FLOW_LABEL, PROP_MTU, + PROP_FLAGS, LAST_PROP }; @@ -285,6 +287,24 @@ nm_setting_ip_tunnel_get_mtu (NMSettingIPTunnel *setting) return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->mtu; } +/* + * nm_setting_ip_tunnel_get_flags: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:flags property of the setting. + * + * Returns: the tunnel flags + * + * Since: 1.12 + **/ +NMIPTunnelFlags +nm_setting_ip_tunnel_get_flags (NMSettingIPTunnel *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), NM_IP_TUNNEL_FLAG_NONE); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->flags; +} + /*****************************************************************************/ static gboolean @@ -292,6 +312,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting); int family = AF_UNSPEC; + guint32 flags; switch (priv->mode) { case NM_IP_TUNNEL_MODE_IPIP: @@ -419,6 +440,20 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + flags = priv->flags; + if (NM_IN_SET (priv->mode, NM_IP_TUNNEL_MODE_IPIP6, NM_IP_TUNNEL_MODE_IP6IP6)) + flags &= (guint32) (~_NM_IP_TUNNEL_FLAG_ALL_IP6TNL); + if (flags) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("some flags are invalid for the select mode: %s"), + nm_utils_enum_to_str (nm_ip_tunnel_flags_get_type (), flags)); + g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_FLAGS); + return FALSE; + } + return TRUE; } @@ -491,6 +526,9 @@ set_property (GObject *object, guint prop_id, case PROP_MTU: priv->mtu = g_value_get_uint (value); break; + case PROP_FLAGS: + priv->flags = g_value_get_uint (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -541,6 +579,9 @@ get_property (GObject *object, guint prop_id, case PROP_MTU: g_value_set_uint (value, priv->mtu); break; + case PROP_FLAGS: + g_value_set_uint (value, priv->flags); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -773,4 +814,23 @@ nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingIPTunnel:flags: + * + * Tunnel flags. Currently the following values are supported: + * %NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT, %NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS, + * %NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL, %NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV, + * %NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY, %NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK. + * They are valid only for IPv6 tunnels. + * + * Since: 1.12 + **/ + g_object_class_install_property + (object_class, PROP_FLAGS, + g_param_spec_uint (NM_SETTING_IP_TUNNEL_FLAGS, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | + NM_SETTING_PARAM_FUZZY_IGNORE | + G_PARAM_STATIC_STRINGS)); } diff --git a/libnm-core/nm-setting-ip-tunnel.h b/libnm-core/nm-setting-ip-tunnel.h index dfa62116..efa754a8 100644 --- a/libnm-core/nm-setting-ip-tunnel.h +++ b/libnm-core/nm-setting-ip-tunnel.h @@ -50,6 +50,7 @@ G_BEGIN_DECLS #define NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT "encapsulation-limit" #define NM_SETTING_IP_TUNNEL_FLOW_LABEL "flow-label" #define NM_SETTING_IP_TUNNEL_MTU "mtu" +#define NM_SETTING_IP_TUNNEL_FLAGS "flags" /** * NMSettingIPTunnel: @@ -67,6 +68,33 @@ typedef struct { gpointer padding[4]; } NMSettingIPTunnelClass; +/* + * NMIPTunnelFlags: + * @NM_IP_TUNNEL_FLAG_NONE: no flag + * @NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT: don't add encapsulation limit + * if one isn't present in inner packet + * @NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS: copy the traffic class field + * from the inner packet + * @NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL: copy the flowlabel from the + * inner packet + * @NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV: used for Mobile IPv6 + * @NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY: copy DSCP from the outer packet + * @NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK: copy fwmark from inner packet + * + * IP tunnel flags. + * + * Since: 1.12 + */ +typedef enum { /*< flags, prefix=NM_IP_TUNNEL_FLAG >*/ + NM_IP_TUNNEL_FLAG_NONE = 0x0, + NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT = 0x1, + NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS = 0x2, + NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL = 0x4, + NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV = 0x8, + NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY = 0x10, + NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK = 0x20, +} NMIPTunnelFlags; + NM_AVAILABLE_IN_1_2 GType nm_setting_ip_tunnel_get_type (void); @@ -97,6 +125,8 @@ NM_AVAILABLE_IN_1_2 guint nm_setting_ip_tunnel_get_flow_label (NMSettingIPTunnel *setting); NM_AVAILABLE_IN_1_2 guint nm_setting_ip_tunnel_get_mtu (NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_12 +NMIPTunnelFlags nm_setting_ip_tunnel_get_flags (NMSettingIPTunnel *setting); G_END_DECLS diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c index d9c0cbb1..0c668d8c 100644 --- a/libnm-core/nm-setting-ip4-config.c +++ b/libnm-core/nm-setting-ip4-config.c @@ -363,7 +363,7 @@ ip4_addresses_set (NMSetting *setting, if (g_variant_lookup (s_ip4, "address-labels", "^as", &labels)) { for (i = 0; i < addrs->len && labels[i]; i++) if (*labels[i]) - nm_ip_address_set_attribute (addrs->pdata[i], "label", g_variant_new_string (labels[i])); + nm_ip_address_set_attribute (addrs->pdata[i], NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string (labels[i])); g_strfreev (labels); } g_variant_unref (s_ip4); @@ -391,7 +391,7 @@ ip4_address_labels_get (NMSetting *setting, num_addrs = nm_setting_ip_config_get_num_addresses (s_ip); for (i = 0; i < num_addrs; i++) { NMIPAddress *addr = nm_setting_ip_config_get_address (s_ip, i); - GVariant *label = nm_ip_address_get_attribute (addr, "label"); + GVariant *label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); if (label) { have_labels = TRUE; @@ -404,7 +404,7 @@ ip4_address_labels_get (NMSetting *setting, labels = g_ptr_array_sized_new (num_addrs); for (i = 0; i < num_addrs; i++) { NMIPAddress *addr = nm_setting_ip_config_get_address (s_ip, i); - GVariant *label = nm_ip_address_get_attribute (addr, "label"); + GVariant *label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); g_ptr_array_add (labels, (char *) (label ? g_variant_get_string (label, NULL) : "")); } @@ -524,7 +524,6 @@ ip4_route_data_set (NMSetting *setting, return TRUE; } - static void nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) { @@ -719,13 +718,24 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) * ARP type and the rest is a MAC address). * If the property is not a hex string it is considered as a * non-hardware-address client ID and the 'type' field is set to 0. + * + * The special values "mac" and "perm-mac" are supported, which use the + * current or permanent MAC address of the device to generate a client identifier + * with type ethernet type (01). Currently, these options only work for ethernet + * type of links. + * + * The special value "stable" is supported to generate a type 0 client identifier based + * on the stable-id (see connection.stable-id) and a per-host key. + * + * If unset, a globally configured default is used. If still unset, the + * client-id from the last lease is reused. **/ /* ---ifcfg-rh--- * property: dhcp-client-id * variable: DHCP_CLIENT_ID(+) * description: A string sent to the DHCP server to identify the local machine. * A binary value can be specified using hex notation ('aa:bb:cc'). - * example: DHCP_CLIENT_ID=ax-srv-1; DHCP_CLIENT_ID=01:44:44:44:44:44:44" + * example: DHCP_CLIENT_ID=ax-srv-1; DHCP_CLIENT_ID=01:44:44:44:44:44:44 * ---end--- */ g_object_class_install_property @@ -737,11 +747,12 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) /* ---ifcfg-rh--- * property: dad-timeout - * variable: ARPING_WAIT - * default: missing variable means global default (config override or 3) - * description: Timeout (in seconds) for performing DAD before configuring - * IPv4 addresses. 0 turns off the DAD completely, -1 means default value. - * example: ARPING_WAIT=2 + * variable: ACD_TIMEOUT, ARPING_WAIT + * default: missing variable means global default (config override or zero) + * description: Timeout (in milliseconds for ACD_TIMEOUT or in seconds + * for ARPING_WAIT) for address conflict detection before configuring + * IPv4 addresses. 0 turns off the ACD completely, -1 means default value. + * example: ACD_TIMEOUT=2000 or ARPING_WAIT=2 * ---end--- */ diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c index 00e9391d..7c2b45f2 100644 --- a/libnm-core/nm-setting-ip6-config.c +++ b/libnm-core/nm-setting-ip6-config.c @@ -63,7 +63,6 @@ typedef struct { char *token; } NMSettingIP6ConfigPrivate; - enum { PROP_0, PROP_IP6_PRIVACY, @@ -281,7 +280,6 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return TRUE; } - static void nm_setting_ip6_config_init (NMSettingIP6Config *setting) { @@ -784,14 +782,13 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) * example: IPV6_TOKEN=::53 * ---end--- */ - g_object_class_install_property - (object_class, PROP_TOKEN, - g_param_spec_string (NM_SETTING_IP6_CONFIG_TOKEN, "", "", - NULL, - G_PARAM_READWRITE | - NM_SETTING_PARAM_INFERRABLE | - G_PARAM_STATIC_STRINGS)); - + g_object_class_install_property + (object_class, PROP_TOKEN, + g_param_spec_string (NM_SETTING_IP6_CONFIG_TOKEN, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); /* IP6-specific property overrides */ diff --git a/libnm-core/nm-setting-macvlan.c b/libnm-core/nm-setting-macvlan.c index d684e58d..6fea8b0d 100644 --- a/libnm-core/nm-setting-macvlan.c +++ b/libnm-core/nm-setting-macvlan.c @@ -147,16 +147,12 @@ static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE (setting); - NMSettingConnection *s_con; NMSettingWired *s_wired; - if (connection) { - s_con = nm_connection_get_setting_connection (connection); + if (connection) s_wired = nm_connection_get_setting_wired (connection); - } else { - s_con = NULL; + else s_wired = NULL; - } if (priv->parent) { if ( !nm_utils_is_uuid (priv->parent) diff --git a/libnm-core/nm-setting-ovs-interface.c b/libnm-core/nm-setting-ovs-interface.c index f06db32a..73e1cfc6 100644 --- a/libnm-core/nm-setting-ovs-interface.c +++ b/libnm-core/nm-setting-ovs-interface.c @@ -244,7 +244,6 @@ normalize: return TRUE; } - static int verify (NMSetting *setting, NMConnection *connection, GError **error) { diff --git a/libnm-core/nm-setting-ovs-patch.c b/libnm-core/nm-setting-ovs-patch.c index 9e380914..3689aecf 100644 --- a/libnm-core/nm-setting-ovs-patch.c +++ b/libnm-core/nm-setting-ovs-patch.c @@ -83,7 +83,6 @@ static int verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingOvsPatch *self = NM_SETTING_OVS_PATCH (setting); - int family = AF_UNSPEC; if (!_nm_connection_verify_required_interface_name (connection, error)) return FALSE; @@ -99,11 +98,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (nm_utils_ipaddr_valid (AF_INET, self->peer)) - family = AF_INET; - else if (nm_utils_ipaddr_valid (AF_INET6, self->peer)) - family = AF_INET6; - else { + if ( !nm_utils_ipaddr_valid (AF_INET, self->peer) + && !nm_utils_ipaddr_valid (AF_INET6, self->peer)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, diff --git a/libnm-core/nm-setting-ovs-port.c b/libnm-core/nm-setting-ovs-port.c index 456e3fbc..72722b15 100644 --- a/libnm-core/nm-setting-ovs-port.c +++ b/libnm-core/nm-setting-ovs-port.c @@ -436,7 +436,6 @@ nm_setting_ovs_port_class_init (NMSettingOvsPortClass *setting_class) NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - /** * NMSettingOvsPort:bond-updelay: * diff --git a/libnm-core/nm-setting-private.h b/libnm-core/nm-setting-private.h index 30e2a160..863ea9f3 100644 --- a/libnm-core/nm-setting-private.h +++ b/libnm-core/nm-setting-private.h @@ -21,6 +21,10 @@ #ifndef __NM_SETTING_PRIVATE_H__ #define __NM_SETTING_PRIVATE_H__ +#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) +#error Cannot use this header. +#endif + #include "nm-setting.h" #include "nm-connection.h" #include "nm-core-enum-types.h" @@ -54,7 +58,6 @@ gboolean _nm_setting_clear_secrets_with_flags (NMSetting *setting, NMSettingClearSecretsWithFlagsFn func, gpointer user_data); - /* The property of the #NMSetting should be considered during comparisons that * use the %NM_SETTING_COMPARE_FLAG_INFERRABLE flag. Properties that don't have * this flag, are ignored when doing an infrerrable comparison. This flag should @@ -85,7 +88,7 @@ gboolean _nm_setting_clear_secrets_with_flags (NMSetting *setting, /* Ensure the setting's GType is registered at library load time */ #define NM_SETTING_REGISTER_TYPE(x) \ static void __attribute__((constructor)) register_setting (void) \ -{ nm_g_type_init (); g_type_ensure (x); } +{ g_type_ensure (x); } GVariant *_nm_setting_get_deprecated_virtual_interface_name (NMSetting *setting, NMConnection *connection, diff --git a/libnm-core/nm-setting-serial.c b/libnm-core/nm-setting-serial.c index e0da89aa..e86988b5 100644 --- a/libnm-core/nm-setting-serial.c +++ b/libnm-core/nm-setting-serial.c @@ -51,7 +51,6 @@ typedef struct { guint64 send_delay; } NMSettingSerialPrivate; - enum { PROP_0, PROP_BAUD, diff --git a/libnm-core/nm-setting-tc-config.c b/libnm-core/nm-setting-tc-config.c index a4960038..e801e4fd 100644 --- a/libnm-core/nm-setting-tc-config.c +++ b/libnm-core/nm-setting-tc-config.c @@ -52,7 +52,7 @@ struct NMTCQdisc { * * Returns: (transfer full): the new #NMTCQdisc object, or %NULL on error * - * Since: 1.10.2 + * Since: 1.12 **/ NMTCQdisc * nm_tc_qdisc_new (const char *kind, @@ -92,7 +92,7 @@ nm_tc_qdisc_new (const char *kind, * * Increases the reference count of the object. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_tc_qdisc_ref (NMTCQdisc *qdisc) @@ -110,7 +110,7 @@ nm_tc_qdisc_ref (NMTCQdisc *qdisc) * Decreases the reference count of the object. If the reference count * reaches zero, the object will be destroyed. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_tc_qdisc_unref (NMTCQdisc *qdisc) @@ -135,7 +135,7 @@ nm_tc_qdisc_unref (NMTCQdisc *qdisc) * * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_tc_qdisc_equal (NMTCQdisc *qdisc, NMTCQdisc *other) @@ -162,7 +162,7 @@ nm_tc_qdisc_equal (NMTCQdisc *qdisc, NMTCQdisc *other) * * Returns: (transfer full): a copy of @qdisc * - * Since: 1.10.2 + * Since: 1.12 **/ NMTCQdisc * nm_tc_qdisc_dup (NMTCQdisc *qdisc) @@ -184,7 +184,7 @@ nm_tc_qdisc_dup (NMTCQdisc *qdisc) * * Returns: * - * Since: 1.10.2 + * Since: 1.12 **/ const char * nm_tc_qdisc_get_kind (NMTCQdisc *qdisc) @@ -201,7 +201,7 @@ nm_tc_qdisc_get_kind (NMTCQdisc *qdisc) * * Returns: the queueing discipline handle * - * Since: 1.10.2 + * Since: 1.12 **/ guint32 nm_tc_qdisc_get_handle (NMTCQdisc *qdisc) @@ -219,7 +219,7 @@ nm_tc_qdisc_get_handle (NMTCQdisc *qdisc) * * Sets the queueing discipline handle. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_tc_qdisc_set_handle (NMTCQdisc *qdisc, guint32 handle) @@ -236,7 +236,7 @@ nm_tc_qdisc_set_handle (NMTCQdisc *qdisc, guint32 handle) * * Returns: the parent class * - * Since: 1.10.2 + * Since: 1.12 **/ guint32 nm_tc_qdisc_get_parent (NMTCQdisc *qdisc) @@ -268,7 +268,7 @@ struct NMTCAction { * * Returns: (transfer full): the new #NMTCAction object, or %NULL on error * - * Since: 1.10.2 + * Since: 1.12 **/ NMTCAction * nm_tc_action_new (const char *kind, @@ -298,7 +298,7 @@ nm_tc_action_new (const char *kind, * * Increases the reference count of the object. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_tc_action_ref (NMTCAction *action) @@ -316,7 +316,7 @@ nm_tc_action_ref (NMTCAction *action) * Decreases the reference count of the object. If the reference count * reaches zero, the object will be destroyed. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_tc_action_unref (NMTCAction *action) @@ -343,7 +343,7 @@ nm_tc_action_unref (NMTCAction *action) * * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_tc_action_equal (NMTCAction *action, NMTCAction *other) @@ -389,7 +389,7 @@ nm_tc_action_equal (NMTCAction *action, NMTCAction *other) * * Returns: (transfer full): a copy of @action * - * Since: 1.10.2 + * Since: 1.12 **/ NMTCAction * nm_tc_action_dup (NMTCAction *action) @@ -420,7 +420,7 @@ nm_tc_action_dup (NMTCAction *action) * * Returns: * - * Since: 1.10.2 + * Since: 1.12 **/ const char * nm_tc_action_get_kind (NMTCAction *action) @@ -442,22 +442,12 @@ nm_tc_action_get_kind (NMTCAction *action) char ** nm_tc_action_get_attribute_names (NMTCAction *action) { - GHashTableIter iter; - const char *key; - GPtrArray *names; - - g_return_val_if_fail (action != NULL, NULL); + const char **names; - names = g_ptr_array_new (); + g_return_val_if_fail (action, NULL); - if (action->attributes) { - g_hash_table_iter_init (&iter, action->attributes); - while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL)) - g_ptr_array_add (names, g_strdup (key)); - } - g_ptr_array_add (names, NULL); - - return (char **) g_ptr_array_free (names, FALSE); + names = nm_utils_strdict_get_keys (action->attributes, TRUE, NULL); + return nm_utils_strv_make_deep_copied_nonnull (names); } /** @@ -498,8 +488,8 @@ nm_tc_action_set_attribute (NMTCAction *action, const char *name, GVariant *valu g_return_if_fail (strcmp (name, "kind") != 0); if (!action->attributes) { - action->attributes = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, (GDestroyNotify) g_variant_unref); + action->attributes = g_hash_table_new_full (nm_str_hash, g_str_equal, + g_free, (GDestroyNotify) g_variant_unref); } if (value) @@ -531,7 +521,7 @@ struct NMTCTfilter { * * Returns: (transfer full): the new #NMTCTfilter object, or %NULL on error * - * Since: 1.10.2 + * Since: 1.12 **/ NMTCTfilter * nm_tc_tfilter_new (const char *kind, @@ -571,7 +561,7 @@ nm_tc_tfilter_new (const char *kind, * * Increases the reference count of the object. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_tc_tfilter_ref (NMTCTfilter *tfilter) @@ -589,7 +579,7 @@ nm_tc_tfilter_ref (NMTCTfilter *tfilter) * Decreases the reference count of the object. If the reference count * reaches zero, the object will be destroyed. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_tc_tfilter_unref (NMTCTfilter *tfilter) @@ -616,7 +606,7 @@ nm_tc_tfilter_unref (NMTCTfilter *tfilter) * * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_tc_tfilter_equal (NMTCTfilter *tfilter, NMTCTfilter *other) @@ -644,7 +634,7 @@ nm_tc_tfilter_equal (NMTCTfilter *tfilter, NMTCTfilter *other) * * Returns: (transfer full): a copy of @tfilter * - * Since: 1.10.2 + * Since: 1.12 **/ NMTCTfilter * nm_tc_tfilter_dup (NMTCTfilter *tfilter) @@ -667,7 +657,7 @@ nm_tc_tfilter_dup (NMTCTfilter *tfilter) * * Returns: * - * Since: 1.10.2 + * Since: 1.12 **/ const char * nm_tc_tfilter_get_kind (NMTCTfilter *tfilter) @@ -684,7 +674,7 @@ nm_tc_tfilter_get_kind (NMTCTfilter *tfilter) * * Returns: the queueing discipline handle * - * Since: 1.10.2 + * Since: 1.12 **/ guint32 nm_tc_tfilter_get_handle (NMTCTfilter *tfilter) @@ -702,7 +692,7 @@ nm_tc_tfilter_get_handle (NMTCTfilter *tfilter) * * Sets the queueing discipline handle. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_tc_tfilter_set_handle (NMTCTfilter *tfilter, guint32 handle) @@ -719,7 +709,7 @@ nm_tc_tfilter_set_handle (NMTCTfilter *tfilter, guint32 handle) * * Returns: the parent class * - * Since: 1.10.2 + * Since: 1.12 **/ guint32 nm_tc_tfilter_get_parent (NMTCTfilter *tfilter) @@ -736,7 +726,7 @@ nm_tc_tfilter_get_parent (NMTCTfilter *tfilter) * * Returns: the action associated with a traffic filter. * - * Since: 1.10.2 + * Since: 1.12 **/ NMTCAction * nm_tc_tfilter_get_action (NMTCTfilter *tfilter) @@ -757,7 +747,7 @@ nm_tc_tfilter_get_action (NMTCTfilter *tfilter) * * Sets the action associated with a traffic filter. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_tc_tfilter_set_action (NMTCTfilter *tfilter, NMTCAction *action) @@ -787,7 +777,7 @@ enum { * * Linux Traffic Contril Settings. * - * Since: 1.10.2 + * Since: 1.12 */ struct _NMSettingTCConfig { NMSetting parent; @@ -810,7 +800,7 @@ NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TC_CONFIG) * * Returns: (transfer full): the new empty #NMSettingTCConfig object * - * Since: 1.10.2 + * Since: 1.12 **/ NMSetting * nm_setting_tc_config_new (void) @@ -824,7 +814,7 @@ nm_setting_tc_config_new (void) * * Returns: the number of configured queueing disciplines * - * Since: 1.10.2 + * Since: 1.12 **/ guint nm_setting_tc_config_get_num_qdiscs (NMSettingTCConfig *self) @@ -841,7 +831,7 @@ nm_setting_tc_config_get_num_qdiscs (NMSettingTCConfig *self) * * Returns: (transfer none): the qdisc at index @idx * - * Since: 1.10.2 + * Since: 1.12 **/ NMTCQdisc * nm_setting_tc_config_get_qdisc (NMSettingTCConfig *self, guint idx) @@ -864,7 +854,7 @@ nm_setting_tc_config_get_qdisc (NMSettingTCConfig *self, guint idx) * * Returns: %TRUE if the qdisc was added; %FALSE if the qdisc was already known. * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_setting_tc_config_add_qdisc (NMSettingTCConfig *self, @@ -892,7 +882,7 @@ nm_setting_tc_config_add_qdisc (NMSettingTCConfig *self, * * Removes the qdisc at index @idx. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_setting_tc_config_remove_qdisc (NMSettingTCConfig *self, guint idx) @@ -914,7 +904,7 @@ nm_setting_tc_config_remove_qdisc (NMSettingTCConfig *self, guint idx) * * Returns: %TRUE if the qdisc was found and removed; %FALSE if it was not. * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_setting_tc_config_remove_qdisc_by_value (NMSettingTCConfig *self, @@ -941,7 +931,7 @@ nm_setting_tc_config_remove_qdisc_by_value (NMSettingTCConfig *self, * * Removes all configured queueing disciplines. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_setting_tc_config_clear_qdiscs (NMSettingTCConfig *self) @@ -959,7 +949,7 @@ nm_setting_tc_config_clear_qdiscs (NMSettingTCConfig *self) * * Returns: the number of configured queueing disciplines * - * Since: 1.10.2 + * Since: 1.12 **/ guint nm_setting_tc_config_get_num_tfilters (NMSettingTCConfig *self) @@ -976,7 +966,7 @@ nm_setting_tc_config_get_num_tfilters (NMSettingTCConfig *self) * * Returns: (transfer none): the tfilter at index @idx * - * Since: 1.10.2 + * Since: 1.12 **/ NMTCTfilter * nm_setting_tc_config_get_tfilter (NMSettingTCConfig *self, guint idx) @@ -999,7 +989,7 @@ nm_setting_tc_config_get_tfilter (NMSettingTCConfig *self, guint idx) * * Returns: %TRUE if the tfilter was added; %FALSE if the tfilter was already known. * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_setting_tc_config_add_tfilter (NMSettingTCConfig *self, @@ -1027,7 +1017,7 @@ nm_setting_tc_config_add_tfilter (NMSettingTCConfig *self, * * Removes the tfilter at index @idx. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_setting_tc_config_remove_tfilter (NMSettingTCConfig *self, guint idx) @@ -1048,7 +1038,7 @@ nm_setting_tc_config_remove_tfilter (NMSettingTCConfig *self, guint idx) * * Returns: %TRUE if the tfilter was found and removed; %FALSE if it was not. * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_setting_tc_config_remove_tfilter_by_value (NMSettingTCConfig *self, @@ -1075,7 +1065,7 @@ nm_setting_tc_config_remove_tfilter_by_value (NMSettingTCConfig *self, * * Removes all configured queueing disciplines. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_setting_tc_config_clear_tfilters (NMSettingTCConfig *self) @@ -1329,7 +1319,7 @@ _action_to_variant (NMTCAction *action) for (i = 0; attrs[i]; i++) { g_variant_builder_add (&builder, "{sv}", attrs[i], - nm_tc_action_get_attribute (action, attrs[i])); + nm_tc_action_get_attribute (action, attrs[i])); } return g_variant_builder_end (&builder); @@ -1433,7 +1423,6 @@ _tfilters_from_variant (GVariant *value) action_var = g_variant_lookup_value (tfilter_var, "action", G_VARIANT_TYPE_VARDICT); - if (action_var) { if (!g_variant_lookup (action_var, "kind", "&s", &action_kind)) { //g_warning ("Ignoring tfilter with invalid action"); @@ -1517,11 +1506,9 @@ nm_setting_tc_config_class_init (NMSettingTCConfigClass *setting_class) /* Properties */ /** - * NMSettingTCConfig:qdiscs: + * NMSettingTCConfig:qdiscs: (type GPtrArray(NMTCQdisc)) * * Array of TC queuening disciplines. - * - * Element-Type: NMTCQdisc **/ /* ---ifcfg-rh--- * property: qdiscs @@ -1546,11 +1533,9 @@ nm_setting_tc_config_class_init (NMSettingTCConfigClass *setting_class) NULL); /** - * NMSettingTCConfig:tfilters: + * NMSettingTCConfig:tfilters: (type GPtrArray(NMTCTfilter)) * * Array of TC traffic filters. - * - * Element-Type: NMTCTfilter **/ /* ---ifcfg-rh--- * property: qdiscs diff --git a/libnm-core/nm-setting-tc-config.h b/libnm-core/nm-setting-tc-config.h index 8117d5ea..6296b1ab 100644 --- a/libnm-core/nm-setting-tc-config.h +++ b/libnm-core/nm-setting-tc-config.h @@ -30,106 +30,103 @@ G_BEGIN_DECLS typedef struct NMTCQdisc NMTCQdisc; -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 GType nm_tc_qdisc_get_type (void); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTCQdisc *nm_tc_qdisc_new (const char *kind, guint32 parent, GError **error); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_tc_qdisc_ref (NMTCQdisc *qdisc); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_tc_qdisc_unref (NMTCQdisc *qdisc); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_tc_qdisc_equal (NMTCQdisc *qdisc, NMTCQdisc *other); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTCQdisc *nm_tc_qdisc_dup (NMTCQdisc *qdisc); - -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 const char *nm_tc_qdisc_get_kind (NMTCQdisc *qdisc); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 guint32 nm_tc_qdisc_get_handle (NMTCQdisc *qdisc); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_tc_qdisc_set_handle (NMTCQdisc *qdisc, guint32 handle); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 guint32 nm_tc_qdisc_get_parent (NMTCQdisc *qdisc); typedef struct NMTCAction NMTCAction; -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 GType nm_tc_action_get_type (void); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTCAction *nm_tc_action_new (const char *kind, GError **error); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_tc_action_ref (NMTCAction *action); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_tc_action_unref (NMTCAction *action); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_tc_action_equal (NMTCAction *action, NMTCAction *other); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTCAction *nm_tc_action_dup (NMTCAction *action); - -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 const char *nm_tc_action_get_kind (NMTCAction *action); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 char **nm_tc_action_get_attribute_names (NMTCAction *action); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 GVariant *nm_tc_action_get_attribute (NMTCAction *action, const char *name); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_tc_action_set_attribute (NMTCAction *action, const char *name, GVariant *value); typedef struct NMTCTfilter NMTCTfilter; -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 GType nm_tc_tfilter_get_type (void); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTCTfilter *nm_tc_tfilter_new (const char *kind, guint32 parent, GError **error); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_tc_tfilter_ref (NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_tc_tfilter_unref (NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_tc_tfilter_equal (NMTCTfilter *tfilter, NMTCTfilter *other); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTCTfilter *nm_tc_tfilter_dup (NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 const char *nm_tc_tfilter_get_kind (NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 guint32 nm_tc_tfilter_get_handle (NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_tc_tfilter_set_handle (NMTCTfilter *tfilter, guint32 handle); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 guint32 nm_tc_tfilter_get_parent (NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTCAction *nm_tc_tfilter_get_action (NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_tc_tfilter_set_action (NMTCTfilter *tfilter, NMTCAction *action); - #define NM_TYPE_SETTING_TC_CONFIG (nm_setting_tc_config_get_type ()) #define NM_SETTING_TC_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_TC_CONFIG, NMSettingTCConfig)) #define NM_SETTING_TC_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_TC_CONFIG, NMSettingTCConfigClass)) @@ -146,41 +143,41 @@ typedef struct _NMSettingTCConfigClass NMSettingTCConfigClass; GType nm_setting_tc_config_get_type (void); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMSetting *nm_setting_tc_config_new (void); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 guint nm_setting_tc_config_get_num_qdiscs (NMSettingTCConfig *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTCQdisc *nm_setting_tc_config_get_qdisc (NMSettingTCConfig *setting, guint idx); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_setting_tc_config_add_qdisc (NMSettingTCConfig *setting, NMTCQdisc *qdisc); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_setting_tc_config_remove_qdisc (NMSettingTCConfig *setting, guint idx); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_setting_tc_config_remove_qdisc_by_value (NMSettingTCConfig *setting, NMTCQdisc *qdisc); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_setting_tc_config_clear_qdiscs (NMSettingTCConfig *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 guint nm_setting_tc_config_get_num_tfilters (NMSettingTCConfig *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTCTfilter *nm_setting_tc_config_get_tfilter (NMSettingTCConfig *setting, guint idx); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_setting_tc_config_add_tfilter (NMSettingTCConfig *setting, NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_setting_tc_config_remove_tfilter (NMSettingTCConfig *setting, guint idx); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_setting_tc_config_remove_tfilter_by_value (NMSettingTCConfig *setting, NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_setting_tc_config_clear_tfilters (NMSettingTCConfig *setting); G_END_DECLS diff --git a/libnm-core/nm-setting-team-port.c b/libnm-core/nm-setting-team-port.c index 5ab8f691..b902b822 100644 --- a/libnm-core/nm-setting-team-port.c +++ b/libnm-core/nm-setting-team-port.c @@ -80,7 +80,6 @@ static const _NMUtilsTeamPropertyKeys _prop_to_keys[LAST_PROP] = { [PROP_LINK_WATCHERS] = { "link_watch", NULL, NULL, 0 } }; - /** * nm_setting_team_port_new: * @@ -114,7 +113,7 @@ nm_setting_team_port_get_config (NMSettingTeamPort *setting) * * Returns: the #NMSettingTeamPort:queue_id property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ gint nm_setting_team_port_get_queue_id (NMSettingTeamPort *setting) @@ -130,7 +129,7 @@ nm_setting_team_port_get_queue_id (NMSettingTeamPort *setting) * * Returns: the #NMSettingTeamPort:prio property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ gint nm_setting_team_port_get_prio (NMSettingTeamPort *setting) @@ -146,7 +145,7 @@ nm_setting_team_port_get_prio (NMSettingTeamPort *setting) * * Returns: the #NMSettingTeamPort:sticky property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_setting_team_port_get_sticky (NMSettingTeamPort *setting) @@ -162,7 +161,7 @@ nm_setting_team_port_get_sticky (NMSettingTeamPort *setting) * * Returns: the #NMSettingTeamPort:lacp-prio property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ gint nm_setting_team_port_get_lacp_prio (NMSettingTeamPort *setting) @@ -178,7 +177,7 @@ nm_setting_team_port_get_lacp_prio (NMSettingTeamPort *setting) * * Returns: the #NMSettingTeamPort:lacp-key property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ gint nm_setting_team_port_get_lacp_key (NMSettingTeamPort *setting) @@ -194,7 +193,7 @@ nm_setting_team_port_get_lacp_key (NMSettingTeamPort *setting) * * Returns: the number of configured link watchers * - * Since: 1.10.2 + * Since: 1.12 **/ guint nm_setting_team_port_get_num_link_watchers (NMSettingTeamPort *setting) @@ -213,7 +212,7 @@ nm_setting_team_port_get_num_link_watchers (NMSettingTeamPort *setting) * * Returns: (transfer none): the link watcher at index @idx. * - * Since: 1.10.2 + * Since: 1.12 **/ NMTeamLinkWatcher * nm_setting_team_port_get_link_watcher (NMSettingTeamPort *setting, guint idx) @@ -236,7 +235,7 @@ nm_setting_team_port_get_link_watcher (NMSettingTeamPort *setting, guint idx) * Returns: %TRUE if the link watcher is added; %FALSE if an identical link * watcher was already there. * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_setting_team_port_add_link_watcher (NMSettingTeamPort *setting, @@ -265,7 +264,7 @@ nm_setting_team_port_add_link_watcher (NMSettingTeamPort *setting, * * Removes the link watcher at index #idx. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_setting_team_port_remove_link_watcher (NMSettingTeamPort *setting, guint idx) @@ -288,7 +287,7 @@ nm_setting_team_port_remove_link_watcher (NMSettingTeamPort *setting, guint idx) * * Returns: %TRUE if the link watcher was found and removed, %FALSE otherwise. * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_setting_team_port_remove_link_watcher_by_value (NMSettingTeamPort *setting, @@ -315,7 +314,7 @@ nm_setting_team_port_remove_link_watcher_by_value (NMSettingTeamPort *setting, * * Removes all configured link watchers. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_setting_team_port_clear_link_watchers (NMSettingTeamPort *setting) @@ -630,7 +629,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class) * Corresponds to the teamd ports.PORTIFNAME.queue_id. * When set to -1 means the parameter is skipped from the json config. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_QUEUE_ID, @@ -644,7 +643,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class) * * Corresponds to the teamd ports.PORTIFNAME.prio. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_PRIO, @@ -658,7 +657,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class) * * Corresponds to the teamd ports.PORTIFNAME.sticky. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_STICKY, @@ -672,7 +671,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class) * * Corresponds to the teamd ports.PORTIFNAME.lacp_prio. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_LACP_PRIO, @@ -686,7 +685,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class) * * Corresponds to the teamd ports.PORTIFNAME.lacp_key. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_LACP_KEY, @@ -696,7 +695,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class) G_PARAM_STATIC_STRINGS)); /** - * NMSettingTeamPort:link-watchers: + * NMSettingTeamPort:link-watchers: (type GPtrArray(NMTeamLinkWatcher)) * * Link watchers configuration for the connection: each link watcher is * defined by a dictionary, whose keys depend upon the selected link @@ -707,8 +706,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class) * arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', * 'validate-incative', 'send-always'. See teamd.conf man for more details. * - * Element-Type: NMTeamLinkWatcher - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_LINK_WATCHERS, diff --git a/libnm-core/nm-setting-team-port.h b/libnm-core/nm-setting-team-port.h index 26b2e098..4ecb1838 100644 --- a/libnm-core/nm-setting-team-port.h +++ b/libnm-core/nm-setting-team-port.h @@ -71,33 +71,33 @@ GType nm_setting_team_port_get_type (void); NMSetting * nm_setting_team_port_new (void); const char * nm_setting_team_port_get_config (NMSettingTeamPort *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gint nm_setting_team_port_get_queue_id (NMSettingTeamPort *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gint nm_setting_team_port_get_prio (NMSettingTeamPort *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_setting_team_port_get_sticky (NMSettingTeamPort *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gint nm_setting_team_port_get_lacp_prio (NMSettingTeamPort *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gint nm_setting_team_port_get_lacp_key (NMSettingTeamPort *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 guint nm_setting_team_port_get_num_link_watchers (NMSettingTeamPort *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTeamLinkWatcher * nm_setting_team_port_get_link_watcher (NMSettingTeamPort *setting, guint idx); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_setting_team_port_add_link_watcher (NMSettingTeamPort *setting, NMTeamLinkWatcher *link_watcher); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_setting_team_port_remove_link_watcher (NMSettingTeamPort *setting, guint idx); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_setting_team_port_remove_link_watcher_by_value (NMSettingTeamPort *setting, NMTeamLinkWatcher *link_watcher); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_setting_team_port_clear_link_watchers (NMSettingTeamPort *setting); G_END_DECLS diff --git a/libnm-core/nm-setting-team.c b/libnm-core/nm-setting-team.c index 1db2428d..f49a04da 100644 --- a/libnm-core/nm-setting-team.c +++ b/libnm-core/nm-setting-team.c @@ -59,7 +59,7 @@ static const char* _link_watcher_name[] = { struct NMTeamLinkWatcher { guint refcount; - guint8 type; /* LinkWatcherTypes */ + guint8 type; /* LinkWatcherTypes */ /* * The union is constructed in order to allow mapping the options of all the @@ -115,7 +115,7 @@ struct NMTeamLinkWatcher { * * Returns: (transfer full): the new #NMTeamLinkWatcher object * - * Since: 1.10.2 + * Since: 1.12 **/ NMTeamLinkWatcher * nm_team_link_watcher_new_ethtool (gint delay_up, @@ -158,7 +158,7 @@ nm_team_link_watcher_new_ethtool (gint delay_up, * * Returns: (transfer full): the new #NMTeamLinkWatcher object, or %NULL on error * - * Since: 1.10.2 + * Since: 1.12 **/ NMTeamLinkWatcher * nm_team_link_watcher_new_nsna_ping (gint init_wait, @@ -222,7 +222,7 @@ nm_team_link_watcher_new_nsna_ping (gint init_wait, * * Returns: (transfer full): the new #NMTeamLinkWatcher object, or %NULL on error * - * Since: 1.10.2 + * Since: 1.12 **/ NMTeamLinkWatcher * nm_team_link_watcher_new_arp_ping (gint init_wait, @@ -287,7 +287,7 @@ nm_team_link_watcher_new_arp_ping (gint init_wait, * * Increases the reference count of the object. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_team_link_watcher_ref (NMTeamLinkWatcher *watcher){ @@ -303,7 +303,7 @@ nm_team_link_watcher_ref (NMTeamLinkWatcher *watcher){ * Decreases the reference count of the object. If the reference count * reaches zero, the object will be destroyed. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_team_link_watcher_unref (NMTeamLinkWatcher *watcher) @@ -328,7 +328,7 @@ nm_team_link_watcher_unref (NMTeamLinkWatcher *watcher) * * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_team_link_watcher_equal (NMTeamLinkWatcher *watcher, NMTeamLinkWatcher *other) @@ -356,7 +356,7 @@ nm_team_link_watcher_equal (NMTeamLinkWatcher *watcher, NMTeamLinkWatcher *other * * Returns: (transfer full): a copy of @watcher * - * Since: 1.10.2 + * Since: 1.12 **/ NMTeamLinkWatcher * nm_team_link_watcher_dup (NMTeamLinkWatcher *watcher) @@ -396,7 +396,7 @@ nm_team_link_watcher_dup (NMTeamLinkWatcher *watcher) * * Gets the name of the link watcher to be used. * - * Since: 1.10.2 + * Since: 1.12 **/ const char * nm_team_link_watcher_get_name (NMTeamLinkWatcher *watcher) @@ -413,7 +413,7 @@ nm_team_link_watcher_get_name (NMTeamLinkWatcher *watcher) * Gets the delay_up interval (in milliseconds) that elapses between the link * coming up and the runner beeing notified about it. * - * Since: 1.10.2 + * Since: 1.12 **/ int nm_team_link_watcher_get_delay_up (NMTeamLinkWatcher *watcher) @@ -432,7 +432,7 @@ nm_team_link_watcher_get_delay_up (NMTeamLinkWatcher *watcher) * Gets the delay_down interval (in milliseconds) that elapses between the link * going down and the runner beeing notified about it. * - * Since: 1.10.2 + * Since: 1.12 **/ int nm_team_link_watcher_get_delay_down (NMTeamLinkWatcher *watcher) @@ -451,7 +451,7 @@ nm_team_link_watcher_get_delay_down (NMTeamLinkWatcher *watcher) * Gets the init_wait interval (in milliseconds) that the team slave should * wait before sending the first packet to the target host. * - * Since: 1.10.2 + * Since: 1.12 **/ int nm_team_link_watcher_get_init_wait (NMTeamLinkWatcher *watcher) @@ -472,7 +472,7 @@ nm_team_link_watcher_get_init_wait (NMTeamLinkWatcher *watcher) * Gets the interval (in milliseconds) that the team slave should wait between * sending two check packets to the target host. * - * Since: 1.10.2 + * Since: 1.12 **/ int nm_team_link_watcher_get_interval (NMTeamLinkWatcher *watcher) @@ -492,7 +492,7 @@ nm_team_link_watcher_get_interval (NMTeamLinkWatcher *watcher) * * Gets the number of missed replies after which the link is considered down. * - * Since: 1.10.2 + * Since: 1.12 **/ int nm_team_link_watcher_get_missed_max (NMTeamLinkWatcher *watcher) @@ -513,7 +513,7 @@ nm_team_link_watcher_get_missed_max (NMTeamLinkWatcher *watcher) * Gets the host name/ip address to be used as destination for the link probing * packets. * - * Since: 1.10.2 + * Since: 1.12 **/ const char * nm_team_link_watcher_get_target_host (NMTeamLinkWatcher *watcher) @@ -529,7 +529,7 @@ nm_team_link_watcher_get_target_host (NMTeamLinkWatcher *watcher) * * Gets the ip address to be used as source for the link probing packets. * - * Since: 1.10.2 + * Since: 1.12 **/ const char * nm_team_link_watcher_get_source_host (NMTeamLinkWatcher *watcher) @@ -545,7 +545,7 @@ nm_team_link_watcher_get_source_host (NMTeamLinkWatcher *watcher) * * Gets the arp ping watcher flags. * - * Since: 1.10.2 + * Since: 1.12 **/ NMTeamLinkWatcherArpPingFlags nm_team_link_watcher_get_flags (NMTeamLinkWatcher *watcher) @@ -659,7 +659,7 @@ nm_setting_team_get_config (NMSettingTeam *setting) * * Returns: the ##NMSettingTeam:notify-peers-count property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ gint nm_setting_team_get_notify_peers_count (NMSettingTeam *setting) @@ -675,7 +675,7 @@ nm_setting_team_get_notify_peers_count (NMSettingTeam *setting) * * Returns: the ##NMSettingTeam:notify-peers-interval property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ gint nm_setting_team_get_notify_peers_interval (NMSettingTeam *setting) @@ -691,7 +691,7 @@ nm_setting_team_get_notify_peers_interval (NMSettingTeam *setting) * * Returns: the ##NMSettingTeam:mcast-rejoin-count property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ gint nm_setting_team_get_mcast_rejoin_count (NMSettingTeam *setting) @@ -707,7 +707,7 @@ nm_setting_team_get_mcast_rejoin_count (NMSettingTeam *setting) * * Returns: the ##NMSettingTeam:mcast-rejoin-interval property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ gint nm_setting_team_get_mcast_rejoin_interval (NMSettingTeam *setting) @@ -723,7 +723,7 @@ nm_setting_team_get_mcast_rejoin_interval (NMSettingTeam *setting) * * Returns: the ##NMSettingTeam:runner property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ const char * nm_setting_team_get_runner (NMSettingTeam *setting) @@ -739,7 +739,7 @@ nm_setting_team_get_runner (NMSettingTeam *setting) * * Returns: the ##NMSettingTeam:runner-hwaddr-policy property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ const char * nm_setting_team_get_runner_hwaddr_policy (NMSettingTeam *setting) @@ -755,7 +755,7 @@ nm_setting_team_get_runner_hwaddr_policy (NMSettingTeam *setting) * * Returns: the ##NMSettingTeam:runner-tx-balancer property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ const char * nm_setting_team_get_runner_tx_balancer (NMSettingTeam *setting) @@ -771,7 +771,7 @@ nm_setting_team_get_runner_tx_balancer (NMSettingTeam *setting) * * Returns: the ##NMSettingTeam:runner-tx-balancer_interval property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ gint nm_setting_team_get_runner_tx_balancer_interval (NMSettingTeam *setting) @@ -787,7 +787,7 @@ nm_setting_team_get_runner_tx_balancer_interval (NMSettingTeam *setting) * * Returns: the ##NMSettingTeam:runner_active property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_setting_team_get_runner_active (NMSettingTeam *setting) @@ -803,7 +803,7 @@ nm_setting_team_get_runner_active (NMSettingTeam *setting) * * Returns: the ##NMSettingTeam:runner-fast-rate property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_setting_team_get_runner_fast_rate (NMSettingTeam *setting) @@ -819,7 +819,7 @@ nm_setting_team_get_runner_fast_rate (NMSettingTeam *setting) * * Returns: the ##NMSettingTeam:runner-sys-prio property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ gint nm_setting_team_get_runner_sys_prio (NMSettingTeam *setting) @@ -835,7 +835,7 @@ nm_setting_team_get_runner_sys_prio (NMSettingTeam *setting) * * Returns: the ##NMSettingTeam:runner-min-ports property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ gint nm_setting_team_get_runner_min_ports (NMSettingTeam *setting) @@ -851,7 +851,7 @@ nm_setting_team_get_runner_min_ports (NMSettingTeam *setting) * * Returns: the ##NMSettingTeam:runner-agg-select-policy property of the setting * - * Since: 1.10.2 + * Since: 1.12 **/ const char * nm_setting_team_get_runner_agg_select_policy (NMSettingTeam *setting) @@ -870,7 +870,7 @@ nm_setting_team_get_runner_agg_select_policy (NMSettingTeam *setting) * * Returns: %TRUE if the txhash element was found and removed; %FALSE if it was not. * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_setting_team_remove_runner_tx_hash_by_value (NMSettingTeam *setting, @@ -899,7 +899,7 @@ nm_setting_team_remove_runner_tx_hash_by_value (NMSettingTeam *setting, * * Returns: the number of elements in txhash * - * Since: 1.10.2 + * Since: 1.12 **/ guint nm_setting_team_get_num_runner_tx_hash (NMSettingTeam *setting) @@ -918,7 +918,7 @@ nm_setting_team_get_num_runner_tx_hash (NMSettingTeam *setting) * * Returns: the txhash element at index @idx * - * Since: 1.10.2 + * Since: 1.12 **/ const char * nm_setting_team_get_runner_tx_hash (NMSettingTeam *setting, guint idx) @@ -938,7 +938,7 @@ nm_setting_team_get_runner_tx_hash (NMSettingTeam *setting, guint idx) * * Removes the txhash element at index @idx. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_setting_team_remove_runner_tx_hash (NMSettingTeam *setting, guint idx) @@ -962,7 +962,7 @@ nm_setting_team_remove_runner_tx_hash (NMSettingTeam *setting, guint idx) * Returns: %TRUE if the txhash element was added; %FALSE if the element * was already knnown. * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_setting_team_add_runner_tx_hash (NMSettingTeam *setting, const char *txhash) @@ -992,7 +992,7 @@ nm_setting_team_add_runner_tx_hash (NMSettingTeam *setting, const char *txhash) * * Returns: the number of configured link watchers * - * Since: 1.10.2 + * Since: 1.12 **/ guint nm_setting_team_get_num_link_watchers (NMSettingTeam *setting) @@ -1011,7 +1011,7 @@ nm_setting_team_get_num_link_watchers (NMSettingTeam *setting) * * Returns: (transfer none): the link watcher at index @idx. * - * Since: 1.10.2 + * Since: 1.12 **/ NMTeamLinkWatcher * nm_setting_team_get_link_watcher (NMSettingTeam *setting, guint idx) @@ -1034,7 +1034,7 @@ nm_setting_team_get_link_watcher (NMSettingTeam *setting, guint idx) * Returns: %TRUE if the link watcher is added; %FALSE if an identical link * watcher was already there. * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_setting_team_add_link_watcher (NMSettingTeam *setting, @@ -1063,7 +1063,7 @@ nm_setting_team_add_link_watcher (NMSettingTeam *setting, * * Removes the link watcher at index #idx. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_setting_team_remove_link_watcher (NMSettingTeam *setting, guint idx) @@ -1086,7 +1086,7 @@ nm_setting_team_remove_link_watcher (NMSettingTeam *setting, guint idx) * * Returns: %TRUE if the link watcher was found and removed, %FALSE otherwise. * - * Since: 1.10.2 + * Since: 1.12 **/ gboolean nm_setting_team_remove_link_watcher_by_value (NMSettingTeam *setting, @@ -1113,7 +1113,7 @@ nm_setting_team_remove_link_watcher_by_value (NMSettingTeam *setting, * * Removes all configured link watchers. * - * Since: 1.10.2 + * Since: 1.12 **/ void nm_setting_team_clear_link_watchers (NMSettingTeam *setting) { @@ -1304,7 +1304,6 @@ finalize (GObject *object) G_OBJECT_CLASS (nm_setting_team_parent_class)->finalize (object); } - #define JSON_TO_VAL(typ, id) _nm_utils_json_extract_##typ (priv->config, _prop_to_keys[id], FALSE) static void @@ -1600,7 +1599,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * * Corresponds to the teamd notify_peers.count. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_NOTIFY_PEERS_COUNT, @@ -1614,7 +1613,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * * Corresponds to the teamd notify_peers.interval. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_NOTIFY_PEERS_INTERVAL, @@ -1628,7 +1627,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * * Corresponds to the teamd mcast_rejoin.count. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_MCAST_REJOIN_COUNT, @@ -1642,7 +1641,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * * Corresponds to the teamd mcast_rejoin.interval. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_MCAST_REJOIN_INTERVAL, @@ -1662,7 +1661,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * other runners will be set to an empty value (or if not possible to * a default value). * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_RUNNER, @@ -1676,7 +1675,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * * Corresponds to the teamd runner.hwaddr_policy. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_RUNNER_HWADDR_POLICY, @@ -1690,7 +1689,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * * Corresponds to the teamd runner.tx_hash. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_RUNNER_TX_HASH, @@ -1705,7 +1704,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * * Corresponds to the teamd runner.tx_balancer.name. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_RUNNER_TX_BALANCER, @@ -1719,7 +1718,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * * Corresponds to the teamd runner.tx_balancer.interval. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_RUNNER_TX_BALANCER_INTERVAL, @@ -1733,7 +1732,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * * Corresponds to the teamd runner.active. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_RUNNER_ACTIVE, @@ -1747,7 +1746,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * * Corresponds to the teamd runner.fast_rate. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_RUNNER_FAST_RATE, @@ -1761,7 +1760,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * * Corresponds to the teamd runner.sys_prio. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_RUNNER_SYS_PRIO, @@ -1775,7 +1774,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * * Corresponds to the teamd runner.min_ports. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_RUNNER_MIN_PORTS, @@ -1789,7 +1788,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * * Corresponds to the teamd runner.agg_select_policy. * - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_RUNNER_AGG_SELECT_POLICY, @@ -1799,7 +1798,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) G_PARAM_STATIC_STRINGS)); /** - * NMSettingTeam:link-watchers: + * NMSettingTeam:link-watchers: (type GPtrArray(NMTeamLinkWatcher)) * * Link watchers configuration for the connection: each link watcher is * defined by a dictionary, whose keys depend upon the selected link @@ -1810,8 +1809,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', * 'validate-incative', 'send-always'. See teamd.conf man for more details. * - * Element-Type: NMTeamLinkWatcher - * Since: 1.10.2 + * Since: 1.12 **/ g_object_class_install_property (object_class, PROP_LINK_WATCHERS, diff --git a/libnm-core/nm-setting-team.h b/libnm-core/nm-setting-team.h index 8e5178a4..cd766d8e 100644 --- a/libnm-core/nm-setting-team.h +++ b/libnm-core/nm-setting-team.h @@ -52,22 +52,21 @@ typedef enum { /*< flags >*/ #define NM_TEAM_LINK_WATCHER_ARP_PING "arp_ping" #define NM_TEAM_LINK_WATCHER_NSNA_PING "nsna_ping" - typedef struct NMTeamLinkWatcher NMTeamLinkWatcher; GType nm_team_link_watcher_get_type (void); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTeamLinkWatcher *nm_team_link_watcher_new_ethtool (gint delay_up, gint delay_down, GError **error); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTeamLinkWatcher *nm_team_link_watcher_new_nsna_ping (gint init_wait, gint interval, gint missed_max, const char *target_host, GError **error); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTeamLinkWatcher *nm_team_link_watcher_new_arp_ping (gint init_wait, gint interval, gint missed_max, @@ -75,34 +74,33 @@ NMTeamLinkWatcher *nm_team_link_watcher_new_arp_ping (gint init_wait, const char *source_host, NMTeamLinkWatcherArpPingFlags flags, GError **error); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_team_link_watcher_ref (NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_team_link_watcher_unref (NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_team_link_watcher_equal (NMTeamLinkWatcher *watcher, NMTeamLinkWatcher *other); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTeamLinkWatcher *nm_team_link_watcher_dup (NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 const char *nm_team_link_watcher_get_name (NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 int nm_team_link_watcher_get_delay_up (NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 int nm_team_link_watcher_get_delay_down (NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 int nm_team_link_watcher_get_init_wait (NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 int nm_team_link_watcher_get_interval (NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 int nm_team_link_watcher_get_missed_max (NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 const char *nm_team_link_watcher_get_target_host (NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 const char *nm_team_link_watcher_get_source_host (NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTeamLinkWatcherArpPingFlags nm_team_link_watcher_get_flags (NMTeamLinkWatcher *watcher); - #define NM_TYPE_SETTING_TEAM (nm_setting_team_get_type ()) #define NM_SETTING_TEAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_TEAM, NMSettingTeam)) #define NM_SETTING_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_TEAM, NMSettingTeamClass)) @@ -154,7 +152,6 @@ NMTeamLinkWatcherArpPingFlags nm_team_link_watcher_get_flags (NMTeamLinkWatcher #define NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT 65535 #define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_DEFAULT NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO - /** * NMSettingTeam: * @@ -176,55 +173,55 @@ GType nm_setting_team_get_type (void); NMSetting * nm_setting_team_new (void); const char * nm_setting_team_get_config (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gint nm_setting_team_get_notify_peers_count (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gint nm_setting_team_get_notify_peers_interval (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gint nm_setting_team_get_mcast_rejoin_count (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gint nm_setting_team_get_mcast_rejoin_interval (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 const char * nm_setting_team_get_runner (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 const char * nm_setting_team_get_runner_hwaddr_policy (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 const char * nm_setting_team_get_runner_tx_balancer (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gint nm_setting_team_get_runner_tx_balancer_interval (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_setting_team_get_runner_active (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_setting_team_get_runner_fast_rate (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gint nm_setting_team_get_runner_sys_prio (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gint nm_setting_team_get_runner_min_ports (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 const char * nm_setting_team_get_runner_agg_select_policy (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_setting_team_remove_runner_tx_hash_by_value (NMSettingTeam *setting, const char *txhash); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 guint nm_setting_team_get_num_runner_tx_hash (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 const char *nm_setting_team_get_runner_tx_hash (NMSettingTeam *setting, guint idx); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_setting_team_remove_runner_tx_hash (NMSettingTeam *setting, guint idx); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_setting_team_add_runner_tx_hash (NMSettingTeam *setting, const char *txhash); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 guint nm_setting_team_get_num_link_watchers (NMSettingTeam *setting); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTeamLinkWatcher * nm_setting_team_get_link_watcher (NMSettingTeam *setting, guint idx); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_setting_team_add_link_watcher (NMSettingTeam *setting, NMTeamLinkWatcher *link_watcher); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_setting_team_remove_link_watcher (NMSettingTeam *setting, guint idx); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 gboolean nm_setting_team_remove_link_watcher_by_value (NMSettingTeam *setting, NMTeamLinkWatcher *link_watcher); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 void nm_setting_team_clear_link_watchers (NMSettingTeam *setting); G_END_DECLS diff --git a/libnm-core/nm-setting-tun.c b/libnm-core/nm-setting-tun.c index dab407bd..edcb3ffd 100644 --- a/libnm-core/nm-setting-tun.c +++ b/libnm-core/nm-setting-tun.c @@ -179,8 +179,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE (setting); - if ( priv->mode != NM_SETTING_TUN_MODE_TUN - && priv->mode != NM_SETTING_TUN_MODE_TAP) { + if (!NM_IN_SET (priv->mode, NM_SETTING_TUN_MODE_TUN, + NM_SETTING_TUN_MODE_TAP)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, diff --git a/libnm-core/nm-setting-user.c b/libnm-core/nm-setting-user.c index 049607e1..ccc030aa 100644 --- a/libnm-core/nm-setting-user.c +++ b/libnm-core/nm-setting-user.c @@ -210,7 +210,7 @@ nm_setting_user_check_val (const char *val, GError **error) static GHashTable * _create_data_hash (void) { - return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + return g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free); } /** @@ -226,7 +226,6 @@ nm_setting_user_get_keys (NMSettingUser *setting, guint *out_len) { NMSettingUser *self = setting; NMSettingUserPrivate *priv; - guint len; g_return_val_if_fail (NM_IS_SETTING_USER (self), NULL); @@ -237,19 +236,13 @@ nm_setting_user_get_keys (NMSettingUser *setting, guint *out_len) return priv->keys; } - if (!priv->data || !g_hash_table_size (priv->data)) { - NM_SET_OUT (out_len, 0); - return (const char **) &priv->keys; - } + priv->keys = nm_utils_strdict_get_keys (priv->data, + TRUE, + out_len); - priv->keys = (const char **) g_hash_table_get_keys_as_array (priv->data, &len); - g_qsort_with_data (priv->keys, - len, - sizeof (const char *), - nm_strcmp_p_with_data, - NULL); - NM_SET_OUT (out_len, len); - return priv->keys; + /* don't return %NULL, but hijack the @keys fields as a pseudo + * empty strv array. */ + return priv->keys ?: ((const char **) &priv->keys); } /*****************************************************************************/ @@ -587,14 +580,12 @@ nm_setting_user_class_init (NMSettingUserClass *klass) setting_class->verify = verify; /** - * NMSettingUser:data: + * NMSettingUser:data: (type GHashTable(utf8,utf8)) * * A dictionary of key/value pairs with user data. This data is ignored by NetworkManager * and can be used at the users discretion. The keys only support a strict ascii format, * but the values can be arbitrary UTF8 strings up to a certain length. * - * Type: GHashTable(utf8,utf8) - * * Since: 1.8 **/ /* ---ifcfg-rh--- diff --git a/libnm-core/nm-setting-user.h b/libnm-core/nm-setting-user.h index 38e97a93..5a2e2cfd 100644 --- a/libnm-core/nm-setting-user.h +++ b/libnm-core/nm-setting-user.h @@ -57,7 +57,6 @@ const char *nm_setting_user_get_data (NMSettingUser *setting, const NM_AVAILABLE_IN_1_8 gboolean nm_setting_user_set_data (NMSettingUser *setting, const char *key, const char *val, GError **error); - NM_AVAILABLE_IN_1_8 gboolean nm_setting_user_check_key (const char *key, GError **error); NM_AVAILABLE_IN_1_8 diff --git a/libnm-core/nm-setting-vlan.h b/libnm-core/nm-setting-vlan.h index ec41b595..63492ebf 100644 --- a/libnm-core/nm-setting-vlan.h +++ b/libnm-core/nm-setting-vlan.h @@ -80,12 +80,12 @@ typedef enum { * @NM_VLAN_FLAG_REORDER_HEADERS: indicates that this interface should reorder * outgoing packet headers to look more like a non-VLAN Ethernet interface * @NM_VLAN_FLAG_GVRP: indicates that this interface should use GVRP to register - * itself with it's switch + * itself with its switch * @NM_VLAN_FLAG_LOOSE_BINDING: indicates that this interface's operating * state is tied to the underlying network interface but other details * (like routing) are not. * @NM_VLAN_FLAG_MVRP: indicates that this interface should use MVRP to register - * itself with it's switch + * itself with its switch * * #NMVlanFlags values control the behavior of the VLAN interface. **/ diff --git a/libnm-core/nm-setting-vpn.c b/libnm-core/nm-setting-vpn.c index 34607252..a921f51f 100644 --- a/libnm-core/nm-setting-vpn.c +++ b/libnm-core/nm-setting-vpn.c @@ -216,6 +216,30 @@ nm_setting_vpn_get_data_item (NMSettingVpn *setting, const char *key) } /** + * nm_setting_vpn_get_data_keys: + * @setting: the #NMSettingVpn + * @out_length: (allow-none): (out): the length of the returned array + * + * Retrieves every data key inside @setting, as an array. + * + * Returns: (array length=out_length) (transfer container): a + * %NULL-terminated array containing each data key or %NULL if + * there are no data items. + * + * Since: 1.12 + */ +const char ** +nm_setting_vpn_get_data_keys (NMSettingVpn *setting, + guint *out_length) +{ + g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL); + + return nm_utils_strdict_get_keys (NM_SETTING_VPN_GET_PRIVATE (setting)->data, + TRUE, + out_length); +} + +/** * nm_setting_vpn_remove_data_item: * @setting: the #NMSettingVpn * @key: the name of the data item to remove @@ -240,32 +264,52 @@ nm_setting_vpn_remove_data_item (NMSettingVpn *setting, const char *key) } static void -foreach_item_helper (GHashTable *hash, +foreach_item_helper (NMSettingVpn *self, + gboolean is_secrets, NMVpnIterFunc func, gpointer user_data) { - GList *keys, *liter; - GSList *copied = NULL, *siter; + NMSettingVpnPrivate *priv; + guint len, i; + gs_strfreev char **keys = NULL; + GHashTable *hash; - g_return_if_fail (hash != NULL); + nm_assert (NM_IS_SETTING_VPN (self)); + nm_assert (func); - /* Grab keys and copy them so that the callback func can modify - * the hash table items if it wants to. - */ - keys = g_hash_table_get_keys (hash); - for (liter = keys; liter; liter = g_list_next (liter)) - copied = g_slist_prepend (copied, g_strdup (liter->data)); - copied = g_slist_reverse (copied); - g_list_free (keys); + priv = NM_SETTING_VPN_GET_PRIVATE (self); - for (siter = copied; siter; siter = g_slist_next (siter)) { - gpointer value; + if (is_secrets) { + keys = (char **) nm_setting_vpn_get_secret_keys (self, &len); + hash = priv->secrets; + } else { + keys = (char **) nm_setting_vpn_get_data_keys (self, &len); + hash = priv->data; + } - value = g_hash_table_lookup (hash, siter->data); - func (siter->data, value, user_data); + if (!len) { + nm_assert (!keys); + return; } - g_slist_free_full (copied, g_free); + for (i = 0; i < len; i++) { + nm_assert (keys[i]); + keys[i] = g_strdup (keys[i]); + } + nm_assert (!keys[i]); + + for (i = 0; i < len; i++) { + const char *value; + + value = g_hash_table_lookup (hash, keys[i]); + /* NOTE: note that we call the function with a clone of @key, + * not with the actual key from the dictionary. + * + * The @value on the other hand, is actually inside our dictionary, + * it's not a clone. However, it might be %NULL, in case the key was + * deleted while iterating. */ + func (keys[i], value, user_data); + } } /** @@ -284,8 +328,9 @@ nm_setting_vpn_foreach_data_item (NMSettingVpn *setting, gpointer user_data) { g_return_if_fail (NM_IS_SETTING_VPN (setting)); + g_return_if_fail (func); - foreach_item_helper (NM_SETTING_VPN_GET_PRIVATE (setting)->data, func, user_data); + foreach_item_helper (setting, FALSE, func, user_data); } /** @@ -348,6 +393,30 @@ nm_setting_vpn_get_secret (NMSettingVpn *setting, const char *key) } /** + * nm_setting_vpn_get_secret_keys: + * @setting: the #NMSettingVpn + * @out_length: (allow-none): (out): the length of the returned array + * + * Retrieves every secret key inside @setting, as an array. + * + * Returns: (array length=out_length) (transfer container): a + * %NULL-terminated array containing each secret key or %NULL if + * there are no secrets. + * + * Since: 1.12 + */ +const char ** +nm_setting_vpn_get_secret_keys (NMSettingVpn *setting, + guint *out_length) +{ + g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL); + + return nm_utils_strdict_get_keys (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, + TRUE, + out_length); +} + +/** * nm_setting_vpn_remove_secret: * @setting: the #NMSettingVpn * @key: the name of the secret to remove @@ -387,8 +456,9 @@ nm_setting_vpn_foreach_secret (NMSettingVpn *setting, gpointer user_data) { g_return_if_fail (NM_IS_SETTING_VPN (setting)); + g_return_if_fail (func); - foreach_item_helper (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, func, user_data); + foreach_item_helper (setting, TRUE, func, user_data); } /** @@ -719,22 +789,12 @@ clear_secrets_with_flags (NMSetting *setting, } static void -destroy_one_secret (gpointer data) -{ - char *secret = (char *) data; - - /* Don't leave the secret lying around in memory */ - memset (secret, 0, strlen (secret)); - g_free (secret); -} - -static void nm_setting_vpn_init (NMSettingVpn *setting) { NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting); - priv->data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - priv->secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_one_secret); + priv->data = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free); + priv->secrets = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) nm_free_secret); } static void @@ -885,12 +945,10 @@ nm_setting_vpn_class_init (NMSettingVpnClass *setting_class) G_PARAM_STATIC_STRINGS)); /** - * NMSettingVpn:data: + * NMSettingVpn:data: (type GHashTable(utf8,utf8)): * * Dictionary of key/value pairs of VPN plugin specific data. Both keys and * values must be strings. - * - * Type: GHashTable(utf8,utf8) **/ /* ---keyfile--- * property: data @@ -912,12 +970,10 @@ nm_setting_vpn_class_init (NMSettingVpnClass *setting_class) _nm_utils_strdict_from_dbus); /** - * NMSettingVpn:secrets: + * NMSettingVpn:secrets: (type GHashTable(utf8,utf8)): * * Dictionary of key/value pairs of VPN plugin specific secrets like * passwords or private keys. Both keys and values must be strings. - * - * Type: GHashTable(utf8,utf8) **/ /* ---keyfile--- * property: secrets diff --git a/libnm-core/nm-setting-vpn.h b/libnm-core/nm-setting-vpn.h index 115aa867..be14e7c0 100644 --- a/libnm-core/nm-setting-vpn.h +++ b/libnm-core/nm-setting-vpn.h @@ -90,6 +90,9 @@ gboolean nm_setting_vpn_remove_data_item (NMSettingVpn *setting, void nm_setting_vpn_foreach_data_item (NMSettingVpn *setting, NMVpnIterFunc func, gpointer user_data); +NM_AVAILABLE_IN_1_12 +const char ** nm_setting_vpn_get_data_keys (NMSettingVpn *setting, + guint *out_length); guint32 nm_setting_vpn_get_num_secrets (NMSettingVpn *setting); void nm_setting_vpn_add_secret (NMSettingVpn *setting, @@ -102,6 +105,10 @@ gboolean nm_setting_vpn_remove_secret (NMSettingVpn *setting, void nm_setting_vpn_foreach_secret (NMSettingVpn *setting, NMVpnIterFunc func, gpointer user_data); +NM_AVAILABLE_IN_1_12 +const char ** nm_setting_vpn_get_secret_keys (NMSettingVpn *setting, + guint *out_length); + NM_AVAILABLE_IN_1_2 guint32 nm_setting_vpn_get_timeout (NMSettingVpn *setting); diff --git a/libnm-core/nm-setting-wired.c b/libnm-core/nm-setting-wired.c index 9d255e1d..3ad312e5 100644 --- a/libnm-core/nm-setting-wired.c +++ b/libnm-core/nm-setting-wired.c @@ -829,7 +829,7 @@ nm_setting_wired_init (NMSettingWired *setting) { NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (setting); - priv->s390_options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + priv->s390_options = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free); /* We use GArray rather than GPtrArray so it will automatically be NULL-terminated */ priv->mac_address_blacklist = g_array_new (TRUE, FALSE, sizeof (char *)); @@ -1363,14 +1363,12 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) G_PARAM_STATIC_STRINGS)); /** - * NMSettingWired:s390-options: + * NMSettingWired:s390-options: (type GHashTable(utf8,utf8)): * * Dictionary of key/value pairs of s390-specific device options. Both keys * and values must be strings. Allowed keys include "portno", "layer2", * "portname", "protocol", among others. Key names must contain only * alphanumeric characters (ie, [a-zA-Z0-9]). - * - * Type: GHashTable(utf8,utf8) **/ /* ---ifcfg-rh--- * property: s390-options diff --git a/libnm-core/nm-setting-wireless-security.c b/libnm-core/nm-setting-wireless-security.c index de77a493..31e386f3 100644 --- a/libnm-core/nm-setting-wireless-security.c +++ b/libnm-core/nm-setting-wireless-security.c @@ -87,6 +87,9 @@ typedef struct { /* WPS */ NMSettingWirelessSecurityWpsMethod wps_method; + + /* FILS */ + NMSettingWirelessSecurityFils fils; } NMSettingWirelessSecurityPrivate; enum { @@ -110,6 +113,7 @@ enum { PROP_LEAP_PASSWORD, PROP_LEAP_PASSWORD_FLAGS, PROP_WPS_METHOD, + PROP_FILS, LAST_PROP }; @@ -814,6 +818,22 @@ nm_setting_wireless_security_get_wps_method (NMSettingWirelessSecurity *setting) return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->wps_method; } +/* + * nm_setting_wireless_security_get_fils: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingWirelessSecurity:fils property of the setting + * + * Since: 1.12 + **/ +NMSettingWirelessSecurityFils +nm_setting_wireless_security_get_fils (NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), 0); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->fils; +} + static GPtrArray * need_secrets (NMSetting *setting) { @@ -1327,6 +1347,9 @@ set_property (GObject *object, guint prop_id, case PROP_WPS_METHOD: priv->wps_method = g_value_get_uint (value); break; + case PROP_FILS: + priv->fils = g_value_get_int (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1398,6 +1421,9 @@ get_property (GObject *object, guint prop_id, case PROP_WPS_METHOD: g_value_set_uint (value, priv->wps_method); break; + case PROP_FILS: + g_value_set_int (value, nm_setting_wireless_security_get_fils (setting)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1865,4 +1891,35 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingWirelessSecurity:fils: + * + * Indicates whether Fast Initial Link Setup (802.11ai) must be enabled for + * the connection. One of %NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (use + * global default value), %NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE + * (disable FILS), %NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL (enable FILS + * if the supplicant and the access point support it) or + * %NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED (enable FILS and fail if not + * supported). When set to %NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT and + * no global default is set, FILS will be optionally enabled. + * + * Since: 1.12 + **/ + /* ---ifcfg-rh--- + * property: fils + * variable: FILS(+) + * values: default, disable, optional, required + * description: Enables or disables FILS (802.11ai) + * example: FILS=required + * ---end--- + */ + g_object_class_install_property + (object_class, PROP_FILS, + g_param_spec_int (NM_SETTING_WIRELESS_SECURITY_FILS, "", "", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_FUZZY_IGNORE | + G_PARAM_STATIC_STRINGS)); } diff --git a/libnm-core/nm-setting-wireless-security.h b/libnm-core/nm-setting-wireless-security.h index e7641b31..5a732ac0 100644 --- a/libnm-core/nm-setting-wireless-security.h +++ b/libnm-core/nm-setting-wireless-security.h @@ -109,6 +109,28 @@ typedef enum { NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN = 0x00000008, } NMSettingWirelessSecurityWpsMethod; +/** + * NMSettingWirelessSecurityFils: + * @NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT: use the default value + * @NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE: disable FILS + * @NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL: enable FILS if the supplicant and the AP support it + * @NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED: require FILS and fail if not available + * @_NM_SETTING_WIRELESS_SECURITY_FILS_NUM: placeholder value for bounds-checking + * @NM_SETTING_WIRELESS_SECURITY_FILS_LAST: placeholder value for bounds-checking + * + * These flags indicate whether FILS must be enabled. + * + * Since: 1.12 + **/ +typedef enum { + NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT = 0, + NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE = 1, + NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL = 2, + NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED = 3, + _NM_SETTING_WIRELESS_SECURITY_FILS_NUM, /*< skip >*/ + NM_SETTING_WIRELESS_SECURITY_FILS_LAST = _NM_SETTING_WIRELESS_SECURITY_FILS_NUM - 1, /*< skip >*/ +} NMSettingWirelessSecurityFils; + #define NM_SETTING_WIRELESS_SECURITY_KEY_MGMT "key-mgmt" #define NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX "wep-tx-keyidx" #define NM_SETTING_WIRELESS_SECURITY_AUTH_ALG "auth-alg" @@ -128,6 +150,7 @@ typedef enum { #define NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD "leap-password" #define NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS "leap-password-flags" #define NM_SETTING_WIRELESS_SECURITY_WPS_METHOD "wps-method" +#define NM_SETTING_WIRELESS_SECURITY_FILS "fils" /** * NMSettingWirelessSecurity: @@ -193,6 +216,9 @@ NMWepKeyType nm_setting_wireless_security_get_wep_key_type (NMSettingWirelessSec NM_AVAILABLE_IN_1_10 NMSettingWirelessSecurityWpsMethod nm_setting_wireless_security_get_wps_method (NMSettingWirelessSecurity *setting); +NM_AVAILABLE_IN_1_12 +NMSettingWirelessSecurityFils nm_setting_wireless_security_get_fils (NMSettingWirelessSecurity *setting); + G_END_DECLS #endif /* __NM_SETTING_WIRELESS_SECURITY_H__ */ diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c index 0a3915bf..38948dee 100644 --- a/libnm-core/nm-setting-wireless.c +++ b/libnm-core/nm-setting-wireless.c @@ -1548,6 +1548,9 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) * probe-scanning the SSID for more reliable network discovery. However, * these workarounds expose inherent insecurities with hidden SSID networks, * and thus hidden SSID networks should be used with caution. + * + * Note that marking the network as hidden may be a privacy issue for you, as + * the explicit probe-scans may be distinctly recognizable on the air. **/ /* ---ifcfg-rh--- * property: hidden diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index 9c8e53ae..218f0dad 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -94,8 +94,7 @@ static void _ensure_registered (void) { if (G_UNLIKELY (registered_settings == NULL)) { - nm_g_type_init (); - registered_settings = g_hash_table_new (g_str_hash, g_str_equal); + registered_settings = g_hash_table_new (nm_str_hash, g_str_equal); registered_settings_by_type = g_hash_table_new (_nm_gtype_hash, _nm_gtype_equal); } } @@ -683,7 +682,6 @@ set_property_from_dbus (const NMSettingProperty *property, return TRUE; } - /** * _nm_setting_to_dbus: * @setting: the #NMSetting @@ -807,7 +805,7 @@ _nm_setting_new_from_dbus (GType setting_type, GVariant *entry, *entry_key; char *key; - keys = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + keys = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, NULL); g_variant_iter_init (&iter, setting_dict); while ((entry = g_variant_iter_next_value (&iter))) { @@ -816,7 +814,7 @@ _nm_setting_new_from_dbus (GType setting_type, g_variant_unref (entry_key); g_variant_unref (entry); - if (!nm_g_hash_table_add (keys, key)) { + if (!g_hash_table_add (keys, key)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, _("duplicate property")); g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), key); @@ -1359,7 +1357,7 @@ nm_setting_diff (NMSetting *a, } if (*results == NULL) { - *results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + *results = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, NULL); results_created = TRUE; } @@ -1800,21 +1798,19 @@ get_secret_flags (NMSetting *setting, NMSettingSecretFlags *out_flags, GError **error) { - char *flags_prop; + gs_free char *name_to_free = NULL; NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; if (verify_secret && !is_secret_prop (setting, secret_name, error)) { - if (out_flags) - *out_flags = NM_SETTING_SECRET_FLAG_NONE; + NM_SET_OUT (out_flags, NM_SETTING_SECRET_FLAG_NONE); return FALSE; } - flags_prop = g_strdup_printf ("%s-flags", secret_name); - g_object_get (G_OBJECT (setting), flags_prop, &flags, NULL); - g_free (flags_prop); - - if (out_flags) - *out_flags = flags; + g_object_get (G_OBJECT (setting), + nm_construct_name_a ("%s-flags", secret_name, &name_to_free), + &flags, + NULL); + NM_SET_OUT (out_flags, flags); return TRUE; } @@ -1850,14 +1846,15 @@ set_secret_flags (NMSetting *setting, NMSettingSecretFlags flags, GError **error) { - char *flags_prop; + gs_free char *name_to_free = NULL; if (verify_secret) g_return_val_if_fail (is_secret_prop (setting, secret_name, error), FALSE); - flags_prop = g_strdup_printf ("%s-flags", secret_name); - g_object_set (G_OBJECT (setting), flags_prop, flags, NULL); - g_free (flags_prop); + g_object_set (G_OBJECT (setting), + nm_construct_name_a ("%s-flags", secret_name, &name_to_free), + flags, + NULL); return TRUE; } diff --git a/libnm-core/nm-setting.h b/libnm-core/nm-setting.h index bf3f8e56..47a2fdc1 100644 --- a/libnm-core/nm-setting.h +++ b/libnm-core/nm-setting.h @@ -51,7 +51,6 @@ G_BEGIN_DECLS /* Note: all non-glib GParamFlags bits are reserved by NetworkManager */ - #define NM_SETTING_NAME "name" /** @@ -130,7 +129,6 @@ typedef enum { /* Higher flags like 0x80000000 and 0x40000000 are used internally as private flags */ } NMSettingCompareFlags; - /** * NMSettingMacRandomization: * @NM_SETTING_MAC_RANDOMIZATION_DEFAULT: the default value, which unless @@ -146,7 +144,6 @@ typedef enum { NM_SETTING_MAC_RANDOMIZATION_ALWAYS, } NMSettingMacRandomization; - /** * NMSetting: * @@ -157,7 +154,6 @@ struct _NMSetting { GObject parent; }; - /** * NMSettingClearSecretsWithFlagsFn: * @setting: The setting for which secrets are being iterated @@ -233,7 +229,6 @@ typedef void (*NMSettingValueIterFn) (NMSetting *setting, GParamFlags flags, gpointer user_data); - GType nm_setting_get_type (void); GType nm_setting_lookup_type (const char *name); diff --git a/libnm-core/nm-simple-connection.c b/libnm-core/nm-simple-connection.c index 11700666..f06e1aed 100644 --- a/libnm-core/nm-simple-connection.c +++ b/libnm-core/nm-simple-connection.c @@ -113,11 +113,16 @@ NMConnection * nm_simple_connection_new_clone (NMConnection *connection) { NMConnection *clone; + const char *path; g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); clone = nm_simple_connection_new (); - nm_connection_set_path (clone, nm_connection_get_path (connection)); + + path = nm_connection_get_path (connection); + if (path) + nm_connection_set_path (clone, path); + nm_connection_replace_settings_from_connection (clone, connection); return clone; diff --git a/libnm-core/nm-utils-private.h b/libnm-core/nm-utils-private.h index c76b3200..5d0f8386 100644 --- a/libnm-core/nm-utils-private.h +++ b/libnm-core/nm-utils-private.h @@ -21,8 +21,8 @@ #ifndef __NM_UTILS_PRIVATE_H__ #define __NM_UTILS_PRIVATE_H__ -#ifdef __NETWORKMANAGER_TYPES_H__ -#error "nm-utils-private.h" must not be used outside of libnm-core/. Do you want "nm-core-internal.h"? +#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) +#error Cannot use this header. #endif #include "nm-setting-private.h" diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index ebbbfd3a..eb65f8db 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -35,13 +35,11 @@ #include <net/if.h> #include <linux/pkt_sched.h> -#if WITH_JANSSON +#if WITH_JSON_VALIDATION #include "nm-json.h" -#include <jansson.h> #endif #include "nm-utils/nm-enum-utils.h" -#include "nm-utils/nm-hash-utils.h" #include "nm-common-macros.h" #include "nm-utils-private.h" #include "nm-setting-private.h" @@ -138,7 +136,6 @@ static const struct IsoLangToEncodings isoLangEntries2[] = LANG_ENCODINGS (NULL, NULL) }; - static GHashTable * langToEncodings5 = NULL; static GHashTable * langToEncodings2 = NULL; @@ -150,7 +147,7 @@ init_lang_to_encodings_hash (void) if (G_UNLIKELY (langToEncodings5 == NULL)) { /* Five-letter codes */ enc = (struct IsoLangToEncodings *) &isoLangEntries5[0]; - langToEncodings5 = g_hash_table_new (g_str_hash, g_str_equal); + langToEncodings5 = g_hash_table_new (nm_str_hash, g_str_equal); while (enc->lang) { g_hash_table_insert (langToEncodings5, (gpointer) enc->lang, (gpointer) enc->encodings); @@ -161,7 +158,7 @@ init_lang_to_encodings_hash (void) if (G_UNLIKELY (langToEncodings2 == NULL)) { /* Two-letter codes */ enc = (struct IsoLangToEncodings *) &isoLangEntries2[0]; - langToEncodings2 = g_hash_table_new (g_str_hash, g_str_equal); + langToEncodings2 = g_hash_table_new (nm_str_hash, g_str_equal); while (enc->lang) { g_hash_table_insert (langToEncodings2, (gpointer) enc->lang, (gpointer) enc->encodings); @@ -252,11 +249,9 @@ _nm_utils_init (void) g_error ("libnm-util symbols detected; Mixing libnm with libnm-util/libnm-glib is not supported"); g_module_close (self); - bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bindtextdomain (GETTEXT_PACKAGE, NMLOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - nm_g_type_init (); - _nm_dbus_errors_init (); } @@ -468,7 +463,7 @@ _nm_utils_string_slist_validate (GSList *list, const char **valid_values) * @hash: a #GHashTable * * Utility function to iterate over a hash table and return - * it's values as a #GSList. + * its values as a #GSList. * * Returns: (element-type gpointer) (transfer container): a newly allocated #GSList * containing the values of the hash table. The caller must free the @@ -546,7 +541,7 @@ _nm_utils_strdict_from_dbus (GVariant *dbus_value, const char *key, *value; GHashTable *hash; - hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + hash = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free); g_variant_iter_init (&iter, dbus_value); while (g_variant_iter_next (&iter, "{&s&s}", &key, &value)) g_hash_table_insert (hash, g_strdup (key), g_strdup (value)); @@ -561,7 +556,7 @@ _nm_utils_copy_strdict (GHashTable *strdict) GHashTableIter iter; gpointer key, value; - copy = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + copy = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free); if (strdict) { g_hash_table_iter_init (&iter, strdict); while (g_hash_table_iter_next (&iter, &key, &value)) @@ -1883,7 +1878,7 @@ GVariant * nm_utils_ip_addresses_to_variant (GPtrArray *addresses) { GVariantBuilder builder; - int i; + guint i; g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); @@ -1891,8 +1886,8 @@ nm_utils_ip_addresses_to_variant (GPtrArray *addresses) for (i = 0; i < addresses->len; i++) { NMIPAddress *addr = addresses->pdata[i]; GVariantBuilder addr_builder; - char **names; - int n; + gs_free const char **names = NULL; + guint j, len; g_variant_builder_init (&addr_builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add (&addr_builder, "{sv}", @@ -1902,13 +1897,12 @@ nm_utils_ip_addresses_to_variant (GPtrArray *addresses) "prefix", g_variant_new_uint32 (nm_ip_address_get_prefix (addr))); - names = nm_ip_address_get_attribute_names (addr); - for (n = 0; names[n]; n++) { + names = _nm_ip_address_get_attribute_names (addr, TRUE, &len); + for (j = 0; j < len; j++) { g_variant_builder_add (&addr_builder, "{sv}", - names[n], - nm_ip_address_get_attribute (addr, names[n])); + names[j], + nm_ip_address_get_attribute (addr, names[j])); } - g_strfreev (names); g_variant_builder_add (&builder, "a{sv}", &addr_builder); } @@ -2226,7 +2220,7 @@ _nm_utils_string_append_tc_qdisc_rest (GString *string, NMTCQdisc *qdisc) * * Returns: formatted string or %NULL * - * Since: 1.10.2 + * Since: 1.12 */ char * nm_utils_tc_qdisc_to_str (NMTCQdisc *qdisc, GError **error) @@ -2242,7 +2236,6 @@ nm_utils_tc_qdisc_to_str (NMTCQdisc *qdisc, GError **error) return g_string_free (string, FALSE); } - static gboolean _tc_read_common_opts (const char *str, guint32 *handle, @@ -2327,7 +2320,7 @@ _tc_read_common_opts (const char *str, * * Returns: the %NMTCQdisc or %NULL * - * Since: 1.10.2 + * Since: 1.12 */ NMTCQdisc * nm_utils_tc_qdisc_from_str (const char *str, GError **error) @@ -2416,7 +2409,7 @@ _string_append_tc_action (GString *string, NMTCAction *action, GError **error) * * Returns: formatted string or %NULL * - * Since: 1.10.2 + * Since: 1.12 */ char * nm_utils_tc_action_to_str (NMTCAction *action, GError **error) @@ -2442,7 +2435,7 @@ nm_utils_tc_action_to_str (NMTCAction *action, GError **error) * * Returns: the %NMTCAction or %NULL * - * Since: 1.10.2 + * Since: 1.12 */ NMTCAction * nm_utils_tc_action_from_str (const char *str, GError **error) @@ -2458,10 +2451,10 @@ nm_utils_tc_action_from_str (const char *str, GError **error) nm_assert (str); nm_assert (!error || !*error); - ht = nm_utils_parse_variant_attributes (str, - ' ', ' ', FALSE, - tc_action_attribute_spec, - error); + ht = nm_utils_parse_variant_attributes (str, + ' ', ' ', FALSE, + tc_action_attribute_spec, + error); if (!ht) return FALSE; @@ -2497,10 +2490,10 @@ nm_utils_tc_action_from_str (const char *str, GError **error) return NULL; } - options = nm_utils_parse_variant_attributes (rest, - ' ', ' ', FALSE, - attrs, - error); + options = nm_utils_parse_variant_attributes (rest, + ' ', ' ', FALSE, + attrs, + error); if (!options) { nm_tc_action_unref (action); return NULL; @@ -2560,7 +2553,7 @@ _nm_utils_string_append_tc_tfilter_rest (GString *string, NMTCTfilter *tfilter, * * Returns: formatted string or %NULL * - * Since: 1.10.2 + * Since: 1.12 */ char * nm_utils_tc_tfilter_to_str (NMTCTfilter *tfilter, GError **error) @@ -2595,7 +2588,7 @@ static const NMVariantAttributeSpec * const tc_tfilter_attribute_spec[] = { * * Returns: the %NMTCTfilter or %NULL * - * Since: 1.10.2 + * Since: 1.12 */ NMTCTfilter * nm_utils_tc_tfilter_from_str (const char *str, GError **error) @@ -3043,7 +3036,6 @@ _nm_utils_check_file (const char *filename, return TRUE; } - gboolean _nm_utils_check_module_file (const char *name, int check_owner, @@ -3444,59 +3436,28 @@ nm_utils_wifi_5ghz_freqs (void) * @strength: the access point strength, from 0 to 100 * * Converts @strength into a 4-character-wide graphical representation of - * strength suitable for printing to stdout. If the current locale and terminal - * support it, this will use unicode graphics characters to represent - * "bars". Otherwise it will use 0 to 4 asterisks. + * strength suitable for printing to stdout. + * + * Previous versions used to take a guess at the terminal type and possibly + * return a wide UTF-8 encoded string. Now it always returns a 7-bit + * clean strings of one to 0 to 4 asterisks. Users that actually need + * the functionality are encouraged to make their implementations instead. * * Returns: the graphical representation of the access point strength */ const char * nm_utils_wifi_strength_bars (guint8 strength) { - static const char *strength_full, *strength_high, *strength_med, *strength_low, *strength_none; - - if (G_UNLIKELY (strength_full == NULL)) { - gboolean can_show_graphics = TRUE; - char *locale_str; - - if (!g_get_charset (NULL)) { - /* Non-UTF-8 locale */ - locale_str = g_locale_from_utf8 ("\342\226\202\342\226\204\342\226\206\342\226\210", -1, NULL, NULL, NULL); - if (locale_str) - g_free (locale_str); - else - can_show_graphics = FALSE; - } - - /* The linux console font doesn't have these characters */ - if (g_strcmp0 (g_getenv ("TERM"), "linux") == 0) - can_show_graphics = FALSE; - - if (can_show_graphics) { - strength_full = /* ▂▄▆█ */ "\342\226\202\342\226\204\342\226\206\342\226\210"; - strength_high = /* ▂▄▆_ */ "\342\226\202\342\226\204\342\226\206_"; - strength_med = /* ▂▄__ */ "\342\226\202\342\226\204__"; - strength_low = /* ▂___ */ "\342\226\202___"; - strength_none = /* ____ */ "____"; - } else { - strength_full = "****"; - strength_high = "*** "; - strength_med = "** "; - strength_low = "* "; - strength_none = " "; - } - } - if (strength > 80) - return strength_full; + return "****"; else if (strength > 55) - return strength_high; + return "*** "; else if (strength > 30) - return strength_med; + return "** "; else if (strength > 5) - return strength_low; + return "* "; else - return strength_none; + return " "; } /** @@ -3698,7 +3659,7 @@ _nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize buffer_length, gs /** * nm_utils_hwaddr_aton: * @asc: the ASCII representation of a hardware address - * @buffer: buffer to store the result into + * @buffer: (type guint8) (array length=length): buffer to store the result into * @length: the expected length in bytes of the result and * the size of the buffer in bytes. * @@ -3724,8 +3685,8 @@ nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize length) return buffer; } -static void -_bin2str (gconstpointer addr, gsize length, const char delimiter, gboolean upper_case, char *out) +void +_nm_utils_bin2str_full (gconstpointer addr, gsize length, const char delimiter, gboolean upper_case, char *out) { const guint8 *in = addr; const char *LOOKUP = upper_case ? "0123456789ABCDEF" : "0123456789abcdef"; @@ -3775,7 +3736,7 @@ nm_utils_bin2hexstr (gconstpointer src, gsize len, int final_len) g_return_val_if_fail (final_len < 0 || (gsize) final_len < buflen, NULL); result = g_malloc (buflen); - _bin2str (src, len, '\0', FALSE, result); + _nm_utils_bin2str_full (src, len, '\0', FALSE, result); /* Cut converted key off at the correct length for this cipher type */ if (final_len >= 0 && (gsize) final_len < buflen) @@ -3802,7 +3763,7 @@ nm_utils_hwaddr_ntoa (gconstpointer addr, gsize length) g_return_val_if_fail (length > 0, g_strdup ("")); result = g_malloc (length * 3); - _bin2str (addr, length, ':', TRUE, result); + _nm_utils_bin2str_full (addr, length, ':', TRUE, result); return result; } @@ -3815,7 +3776,7 @@ nm_utils_hwaddr_ntoa_buf (gconstpointer addr, gsize addr_len, gboolean upper_cas if (buf_len < addr_len * 3) g_return_val_if_reached (NULL); - _bin2str (addr, addr_len, ':', upper_case, buf); + _nm_utils_bin2str_full (addr, addr_len, ':', upper_case, buf); return buf; } @@ -3838,7 +3799,7 @@ _nm_utils_bin2str (gconstpointer addr, gsize length, gboolean upper_case) g_return_val_if_fail (length > 0, g_strdup ("")); result = g_malloc (length * 3); - _bin2str (addr, length, ':', upper_case, result); + _nm_utils_bin2str_full (addr, length, ':', upper_case, result); return result; } @@ -3866,9 +3827,11 @@ nm_utils_hwaddr_valid (const char *asc, gssize length) if (!hwaddr_aton (asc, buf, length, &l)) return FALSE; return length == l; - } else if (length == -1) { + } else if (length == -1) return !!hwaddr_aton (asc, buf, sizeof (buf), &l); - } else + else if (length == 0) + return FALSE; + else g_return_val_if_reached (FALSE); } @@ -3930,9 +3893,9 @@ _nm_utils_hwaddr_canonical_or_invalid (const char *mac, gssize length) /** * nm_utils_hwaddr_matches: - * @hwaddr1: pointer to a binary or ASCII hardware address, or %NULL + * @hwaddr1: (nullable): pointer to a binary or ASCII hardware address, or %NULL * @hwaddr1_len: size of @hwaddr1, or -1 if @hwaddr1 is ASCII - * @hwaddr2: pointer to a binary or ASCII hardware address, or %NULL + * @hwaddr2: (nullable): pointer to a binary or ASCII hardware address, or %NULL * @hwaddr2_len: size of @hwaddr2, or -1 if @hwaddr2 is ASCII * * Generalized hardware address comparison function. Tests if @hwaddr1 and @@ -4357,7 +4320,7 @@ nm_utils_inet_ntop (int addr_family, gconstpointer addr, char *dst) s = inet_ntop (addr_family, addr, - dst ? dst : _nm_utils_inet_ntop_buffer, + dst ?: _nm_utils_inet_ntop_buffer, addr_family == AF_INET6 ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN); nm_assert (s); return s; @@ -4371,7 +4334,7 @@ nm_utils_inet_ntop (int addr_family, gconstpointer addr, char *dst) * characters. If set to %NULL, it will return a pointer to an internal, static * buffer (shared with nm_utils_inet6_ntop()). Beware, that the internal * buffer will be overwritten with ever new call of nm_utils_inet4_ntop() or - * nm_utils_inet6_ntop() that does not provied it's own @dst buffer. Also, + * nm_utils_inet6_ntop() that does not provide its own @dst buffer. Also, * using the internal buffer is not thread safe. When in doubt, pass your own * @dst buffer to avoid these issues. * @@ -4383,7 +4346,7 @@ nm_utils_inet_ntop (int addr_family, gconstpointer addr, char *dst) const char * nm_utils_inet4_ntop (in_addr_t inaddr, char *dst) { - return inet_ntop (AF_INET, &inaddr, dst ? dst : _nm_utils_inet_ntop_buffer, + return inet_ntop (AF_INET, &inaddr, dst ?: _nm_utils_inet_ntop_buffer, INET_ADDRSTRLEN); } @@ -4395,7 +4358,7 @@ nm_utils_inet4_ntop (in_addr_t inaddr, char *dst) * characters. If set to %NULL, it will return a pointer to an internal, static * buffer (shared with nm_utils_inet4_ntop()). Beware, that the internal * buffer will be overwritten with ever new call of nm_utils_inet4_ntop() or - * nm_utils_inet6_ntop() that does not provied it's own @dst buffer. Also, + * nm_utils_inet6_ntop() that does not provide its own @dst buffer. Also, * using the internal buffer is not thread safe. When in doubt, pass your own * @dst buffer to avoid these issues. * @@ -4409,7 +4372,7 @@ const char * nm_utils_inet6_ntop (const struct in6_addr *in6addr, char *dst) { g_return_val_if_fail (in6addr, NULL); - return inet_ntop (AF_INET6, in6addr, dst ? dst : _nm_utils_inet_ntop_buffer, + return inet_ntop (AF_INET6, in6addr, dst ?: _nm_utils_inet_ntop_buffer, INET6_ADDRSTRLEN); } @@ -4622,9 +4585,6 @@ _nm_utils_strstrdictkey_hash (gconstpointer a) nm_hash_update_val (&h, k->type); if (k->type & STRSTRDICTKEY_ALL_SET) { - gsize n; - - n = 0; p = strchr (k->data, '\0'); if (k->type == STRSTRDICTKEY_ALL_SET) { /* the key contains two strings. Continue... */ @@ -4844,7 +4804,7 @@ gssize _nm_utils_dns_option_find_idx (GPtrArray *array, const char *option) char * nm_utils_enum_to_str (GType type, int value) { - return _nm_utils_enum_to_str_full (type, value, ", "); + return _nm_utils_enum_to_str_full (type, value, ", ", NULL); } /** @@ -4927,33 +4887,7 @@ _nm_utils_is_json_object_no_validation (const char *str, GError **error) return FALSE; } -#if WITH_JANSSON - -/* Added in Jansson v2.3 (released Jan 27 2012) */ -#ifndef json_object_foreach -#define json_object_foreach(object, key, value) \ - for(key = json_object_iter_key(json_object_iter(object)); \ - key && (value = json_object_iter_value(json_object_iter_at (object, key) )); \ - key = json_object_iter_key(json_object_iter_next(object, json_object_iter_at (object, key)))) -#endif - -/* Added in Jansson v2.4 (released Sep 23 2012), but travis.ci has v2.2. */ -#ifndef json_boolean -#define json_boolean(val) ((val) ? json_true() : json_false()) -#endif - -/* Added in Jansson v2.5 (released Sep 19 2013), but travis.ci has v2.2. */ -#ifndef json_array_foreach -#define json_array_foreach(array, index, value) \ - for (index = 0; \ - index < json_array_size(array) && (value = json_array_get(array, index)); \ - index++) -#endif - -/* Added in Jansson v2.7 */ -#ifndef json_boolean_value -#define json_boolean_value json_is_true -#endif +#if WITH_JSON_VALIDATION static void _json_add_object (json_t *json, @@ -5083,7 +5017,6 @@ _json_team_add_defaults (json_t *json, json_object_set_new (json_element, "name", json_string (runner)); } - if (nm_streq (runner, NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP)) { _json_add_object (json, "notify_peers", "count", NULL, json_integer (NM_SETTING_TEAM_NOTIFY_PEERS_COUNT_ACTIVEBACKUP_DEFAULT)); @@ -5370,7 +5303,6 @@ fail: return NULL; } - /** * nm_utils_is_json_object: * @str: the JSON string to test @@ -5427,15 +5359,6 @@ nm_utils_is_json_object (const char *str, GError **error) return TRUE; } -/* json_object_foreach_safe() is only available since Jansson 2.8, - * reimplement it */ -#define _json_object_foreach_safe(object, n, key, value) \ - for (key = json_object_iter_key (json_object_iter (object)), \ - n = json_object_iter_next (object, json_object_iter_at (object, key)); \ - key && (value = json_object_iter_value (json_object_iter_at (object, key))); \ - key = json_object_iter_key (n), \ - n = json_object_iter_next (object, json_object_iter_at (object, key))) - gboolean _nm_utils_team_config_equal (const char *conf1, const char *conf2, @@ -5475,7 +5398,7 @@ _nm_utils_team_config_equal (const char *conf1, /* Only consider a given subset of nodes, others can change depending on * current state */ for (i = 0, json = json1; i < 2; i++, json = json2) { - _json_object_foreach_safe (json, tmp, key, value) { + json_object_foreach_safe (json, tmp, key, value) { if (!NM_IN_STRSET (key, "runner", "link_watch")) json_object_del (json, key); } @@ -5495,7 +5418,6 @@ out: return ret; } - GValue * _nm_utils_team_config_get (const char *conf, const char *key, @@ -5734,7 +5656,7 @@ done: return updated; } -#else /* WITH_JANSSON */ +#else /* !WITH_JSON_VALIDATION */ gboolean nm_utils_is_json_object (const char *str, GError **error) @@ -6026,7 +5948,8 @@ attribute_unescape (const char *start, const char *end) * * Parse attributes from a string. * - * Returns: (transfer full): a #GHashTable mapping attribute names to #GVariant values. + * Returns: (transfer full) (element-type utf8 GVariant): a #GHashTable mapping + * attribute names to #GVariant values. * * Since: 1.8 */ @@ -6048,7 +5971,7 @@ nm_utils_parse_variant_attributes (const char *string, g_return_val_if_fail (key_value_separator, NULL); g_return_val_if_fail (!error || !*error, NULL); - ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); + ht = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); while (TRUE) { gs_free char *name = NULL, *value = NULL; @@ -6185,7 +6108,7 @@ next: /* * nm_utils_format_variant_attributes: - * @attributes: a #GHashTable mapping attribute names to #GVariant values + * @attributes: (element-type utf8 GVariant): a #GHashTable mapping attribute names to #GVariant values * @attr_separator: the attribute separator character * @key_value_separator: character separating key and values * @@ -6207,8 +6130,8 @@ nm_utils_format_variant_attributes (GHashTable *attributes, const char *name, *value; char *escaped; char buf[64]; - gs_free_list GList *keys = NULL; - GList *iter; + gs_free NMUtilsNamedValue *values = NULL; + guint i, len; g_return_val_if_fail (attr_separator, NULL); g_return_val_if_fail (key_value_separator, NULL); @@ -6216,12 +6139,13 @@ nm_utils_format_variant_attributes (GHashTable *attributes, if (!attributes || !g_hash_table_size (attributes)) return NULL; - keys = g_list_sort (g_hash_table_get_keys (attributes), (GCompareFunc) g_strcmp0); + values = nm_utils_named_values_from_str_dict (attributes, &len); + str = g_string_new (""); - for (iter = keys; iter; iter = g_list_next (iter)) { - name = iter->data; - variant = g_hash_table_lookup (attributes, name); + for (i = 0; i < len; i++) { + name = values[i].name; + variant = (GVariant *) values[i].value_ptr; value = NULL; if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32)) diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h index df9284b3..1f645a80 100644 --- a/libnm-core/nm-utils.h +++ b/libnm-core/nm-utils.h @@ -233,19 +233,19 @@ char * nm_utils_format_variant_attributes (GHashTable *attributes, /*****************************************************************************/ -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTCQdisc *nm_utils_tc_qdisc_from_str (const char *str, GError **error); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 char *nm_utils_tc_qdisc_to_str (NMTCQdisc *qdisc, GError **error); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTCAction *nm_utils_tc_action_from_str (const char *str, GError **error); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 char *nm_utils_tc_action_to_str (NMTCAction *action, GError **error); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 NMTCTfilter *nm_utils_tc_tfilter_from_str (const char *str, GError **error); -NM_AVAILABLE_IN_1_10_2 +NM_AVAILABLE_IN_1_12 char *nm_utils_tc_tfilter_to_str (NMTCTfilter *tfilter, GError **error); G_END_DECLS diff --git a/libnm-core/nm-version.h b/libnm-core/nm-version.h index 61bfa5b1..0412bc8e 100644 --- a/libnm-core/nm-version.h +++ b/libnm-core/nm-version.h @@ -29,17 +29,17 @@ #if !defined (NM_VERSION_MIN_REQUIRED) || (NM_VERSION_MIN_REQUIRED == 0) # undef NM_VERSION_MIN_REQUIRED -# define NM_VERSION_MIN_REQUIRED (NM_VERSION_CUR_STABLE) +# define NM_VERSION_MIN_REQUIRED (NM_API_VERSION) #endif #if !defined (NM_VERSION_MAX_ALLOWED) || (NM_VERSION_MAX_ALLOWED == 0) # undef NM_VERSION_MAX_ALLOWED -# define NM_VERSION_MAX_ALLOWED (NM_VERSION_CUR_STABLE) +# define NM_VERSION_MAX_ALLOWED (NM_API_VERSION) #endif /* sanity checks */ -#if NM_VERSION_MIN_REQUIRED > NM_VERSION_NEXT_STABLE -#error "NM_VERSION_MIN_REQUIRED must be <= NM_VERSION_NEXT_STABLE" +#if NM_VERSION_MIN_REQUIRED > NM_API_VERSION +#error "NM_VERSION_MIN_REQUIRED must be <= NM_API_VERSION" #endif #if NM_VERSION_MAX_ALLOWED < NM_VERSION_MIN_REQUIRED #error "NM_VERSION_MAX_ALLOWED must be >= NM_VERSION_MIN_REQUIRED" @@ -146,10 +146,18 @@ # define NM_AVAILABLE_IN_1_10 #endif -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_10_2 -# define NM_AVAILABLE_IN_1_10_2 G_UNAVAILABLE(1,10.2) +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_12 +# define NM_DEPRECATED_IN_1_12 G_DEPRECATED +# define NM_DEPRECATED_IN_1_12_FOR(f) G_DEPRECATED_FOR(f) #else -# define NM_AVAILABLE_IN_1_10_2 +# define NM_DEPRECATED_IN_1_12 +# define NM_DEPRECATED_IN_1_12_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_12 +# define NM_AVAILABLE_IN_1_12 G_UNAVAILABLE(1,12) +#else +# define NM_AVAILABLE_IN_1_12 #endif #endif /* NM_VERSION_H */ diff --git a/libnm-core/nm-vpn-dbus-interface.h b/libnm-core/nm-vpn-dbus-interface.h index 9c9bc297..4ef80f1d 100644 --- a/libnm-core/nm-vpn-dbus-interface.h +++ b/libnm-core/nm-vpn-dbus-interface.h @@ -60,7 +60,6 @@ #define NM_DBUS_VPN_BAD_ARGUMENTS "BadArguments" #define NM_DBUS_VPN_INTERACTIVE_NOT_SUPPORTED "InteractiveNotSupported" - /* * VPN daemon signals */ @@ -95,7 +94,6 @@ typedef enum { NM_VPN_SERVICE_STATE_STOPPED } NMVpnServiceState; - /** * NMVpnConnectionState: * @NM_VPN_CONNECTION_STATE_UNKNOWN: The state of the VPN connection is @@ -216,7 +214,6 @@ typedef enum { */ #define NM_VPN_PLUGIN_CAN_PERSIST "can-persist" - /*** Ip4Config ***/ /* uint32: IP address of the internal gateway of the subnet the VPN interface is @@ -273,7 +270,6 @@ typedef enum { #define NM_VPN_PLUGIN_IP4_CONFIG_MTU NM_VPN_PLUGIN_CONFIG_MTU #define NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV NM_VPN_PLUGIN_CONFIG_TUNDEV - /*** Ip6Config ***/ /* array of uint8: IP address of the internal gateway of the subnet the VPN interface is diff --git a/libnm-core/nm-vpn-editor-plugin.c b/libnm-core/nm-vpn-editor-plugin.c index 32e2a4ed..d690d9b0 100644 --- a/libnm-core/nm-vpn-editor-plugin.c +++ b/libnm-core/nm-vpn-editor-plugin.c @@ -262,7 +262,7 @@ _nm_vpn_editor_plugin_load (const char *plugin_name, if (do_file_checks) { if ( !strchr (plugin_name, '/') && !g_str_has_suffix (plugin_name, ".la")) { - plugin_filename_free = g_module_build_path (NMPLUGINDIR, plugin_name); + plugin_filename_free = g_module_build_path (NMVPNDIR, plugin_name); plugin_filename = plugin_filename_free; } } diff --git a/libnm-core/nm-vpn-editor-plugin.h b/libnm-core/nm-vpn-editor-plugin.h index e93d8fbd..0bdd9298 100644 --- a/libnm-core/nm-vpn-editor-plugin.h +++ b/libnm-core/nm-vpn-editor-plugin.h @@ -34,7 +34,7 @@ G_BEGIN_DECLS -struct _NMVpnPluginInfo; +typedef struct _NMVpnPluginInfo NMVpnPluginInfo; typedef struct _NMVpnEditorPlugin NMVpnEditorPlugin; typedef struct _NMVpnEditor NMVpnEditor; @@ -47,7 +47,6 @@ typedef NMVpnEditorPlugin * (*NMVpnEditorPluginFactory) (GError **error); NMVpnEditorPlugin *nm_vpn_editor_plugin_factory (GError **error); #endif - /*****************************************************************************/ /* Editor plugin interface */ /*****************************************************************************/ @@ -128,7 +127,7 @@ typedef struct { char * (*get_suggested_filename) (NMVpnEditorPlugin *plugin, NMConnection *connection); void (*notify_plugin_info_set) (NMVpnEditorPlugin *plugin, - struct _NMVpnPluginInfo *plugin_info); + NMVpnPluginInfo *plugin_info); const NMVpnEditorPluginVT *(*get_vt) (NMVpnEditorPlugin *plugin, gsize *out_vt_size); @@ -171,12 +170,12 @@ NMVpnEditorPlugin *nm_vpn_editor_plugin_load (const char *plugin_name, GError **error); NM_AVAILABLE_IN_1_4 -struct _NMVpnPluginInfo *nm_vpn_editor_plugin_get_plugin_info (NMVpnEditorPlugin *plugin); +NMVpnPluginInfo *nm_vpn_editor_plugin_get_plugin_info (NMVpnEditorPlugin *plugin); NM_AVAILABLE_IN_1_4 -void nm_vpn_editor_plugin_set_plugin_info (NMVpnEditorPlugin *plugin, struct _NMVpnPluginInfo *plugin_info); +void nm_vpn_editor_plugin_set_plugin_info (NMVpnEditorPlugin *plugin, NMVpnPluginInfo *plugin_info); #include "nm-vpn-plugin-info.h" G_END_DECLS -#endif /* __NM_VPN_EDITOR_PLUGIN_H__ */ +#endif /* __NM_VPN_EDITOR_PLUGIN_H__ */ diff --git a/libnm-core/nm-vpn-plugin-info.c b/libnm-core/nm-vpn-plugin-info.c index 115c397f..79542279 100644 --- a/libnm-core/nm-vpn-plugin-info.c +++ b/libnm-core/nm-vpn-plugin-info.c @@ -933,7 +933,6 @@ nm_vpn_plugin_info_supports_multiple (NMVpnPluginInfo *self) return _nm_utils_ascii_str_to_bool (s, FALSE); } - /** * nm_vpn_plugin_info_get_aliases: * @self: plugin info instance diff --git a/libnm-core/nm-vpn-plugin-info.h b/libnm-core/nm-vpn-plugin-info.h index 908ee482..61539cbc 100644 --- a/libnm-core/nm-vpn-plugin-info.h +++ b/libnm-core/nm-vpn-plugin-info.h @@ -49,10 +49,10 @@ struct _NMVpnPluginInfo; /** * NMVpnPluginInfo: */ -typedef struct _NMVpnPluginInfo { +struct _NMVpnPluginInfo { NM_AVAILABLE_IN_1_2 GObject parent; -} NMVpnPluginInfo; +}; typedef struct { NM_AVAILABLE_IN_1_2 diff --git a/libnm-core/tests/meson.build b/libnm-core/tests/meson.build new file mode 100644 index 00000000..2eeadd88 --- /dev/null +++ b/libnm-core/tests/meson.build @@ -0,0 +1,49 @@ +# test-cert.p12 created with: +# +# openssl pkcs12 -export \ +# -in test_key_and_cert.pem \ +# -inkey test_key_and_cert.pem \ +# -certfile test_ca_cert.pem \ +# -name "test-pkcs12" \ +# -out test-cert.p12 + +enum_types = 'nm-core-tests-enum-types' + +enum = gnome.mkenums( + enum_types, + sources: 'test-general-enums.h', + identifier_prefix: nm_id_prefix, + c_template: enum_types + '.c.template', + h_template: enum_types + '.h.template' +) + +test_units = [ + 'test-compare', + 'test-crypto', + 'test-general', + 'test-keyfile', + 'test-secrets', + 'test-setting', + 'test-settings-defaults' +] + +test_cert_dir = join_paths(meson.current_source_dir(), 'certs') + +foreach test_unit: test_units + exe = executable( + 'libnm-core-' + test_unit, + [test_unit + '.c'] + enum, + dependencies: nm_core_dep, + c_args: [ + '-DNETWORKMANAGER_COMPILATION_TEST', + '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIBNM_CORE', + ] + + nm_build_cflags, + link_with: libnm_core + ) + test( + 'libnm-core/' + test_unit, + test_script, + args: test_args + [exe.full_path()] + ) +endforeach diff --git a/libnm-core/tests/nm-core-tests-enum-types.c.template b/libnm-core/tests/nm-core-tests-enum-types.c.template new file mode 100644 index 00000000..1160be86 --- /dev/null +++ b/libnm-core/tests/nm-core-tests-enum-types.c.template @@ -0,0 +1,35 @@ +/*** BEGIN file-header ***/ +#include "config.h" + +#include "nm-core-tests-enum-types.h" + +#include "test-general-enums.h" +/*** END file-header ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} + +/*** END value-tail ***/ diff --git a/libnm-core/tests/nm-core-tests-enum-types.h.template b/libnm-core/tests/nm-core-tests-enum-types.h.template new file mode 100644 index 00000000..62e82b77 --- /dev/null +++ b/libnm-core/tests/nm-core-tests-enum-types.h.template @@ -0,0 +1,21 @@ +/*** BEGIN file-header ***/ +#ifndef __NM_CORE_TESTS_ENUM_TYPES_H__ +#define __NM_CORE_TESTS_ENUM_TYPES_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +/*** END file-header ***/ + +/*** BEGIN enumeration-production ***/ +GType @enum_name@_get_type (void) G_GNUC_CONST; +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) + +/*** END enumeration-production ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* __NM_CORE_TESTS_ENUM_TYPES_H__ */ +/*** END file-tail ***/ diff --git a/libnm-core/tests/test-crypto.c b/libnm-core/tests/test-crypto.c index 0c2ef48a..fb99ffea 100644 --- a/libnm-core/tests/test-crypto.c +++ b/libnm-core/tests/test-crypto.c @@ -35,6 +35,8 @@ #include "nm-utils/nm-test-utils.h" +#define TEST_CERT_DIR NM_BUILD_SRCDIR"/libnm-core/tests/certs" + #if 0 static const char *pem_rsa_key_begin = "-----BEGIN RSA PRIVATE KEY-----"; static const char *pem_rsa_key_end = "-----END RSA PRIVATE KEY-----"; diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index 520ed581..3b9debd9 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -26,7 +26,7 @@ #include <string.h> #include "nm-utils/c-list-util.h" -#include "nm-utils/nm-hash-utils.h" +#include "nm-utils/nm-enum-utils.h" #include "nm-utils.h" #include "nm-setting-private.h" @@ -168,6 +168,17 @@ _test_hash_str (const char *str) static void test_nm_hash (void) { + g_assert (nm_hash_static (0)); + g_assert (nm_hash_static (777)); + + g_assert (nm_hash_str (NULL)); + g_assert (nm_hash_str ("")); + g_assert (nm_hash_str ("a")); + + g_assert (nm_hash_ptr (NULL)); + g_assert (nm_hash_ptr ("")); + g_assert (nm_hash_ptr ("a")); + _test_hash_str (""); _test_hash_str ("a"); _test_hash_str ("aa"); @@ -200,6 +211,10 @@ static void test_nm_g_slice_free_fcn (void) { gpointer p; + struct { + char a1; + char a2; + } xx; p = g_slice_new (gint64); (nm_g_slice_free_fcn (gint64)) (p); @@ -212,6 +227,9 @@ test_nm_g_slice_free_fcn (void) p = g_slice_new (gint64); nm_g_slice_free_fcn_gint64 (p); + + p = g_slice_alloc (sizeof (xx)); + (nm_g_slice_free_fcn (xx)) (p); } /*****************************************************************************/ @@ -279,7 +297,6 @@ test_nm_utils_strsplit_set (void) typedef struct { int val; - int idx; CList lst; } CListSort; @@ -303,71 +320,86 @@ _c_list_sort_cmp (const CList *lst_a, const CList *lst_b, const void *user_data) } static void -test_c_list_sort (void) +_do_test_c_list_sort (CListSort *elements, guint n_list, gboolean headless) { - guint i, n_list, repeat, headless; CList head, *iter, *iter_prev, *lst; - CListSort elements[30]; + guint i; const CListSort *el_prev; + CListSort *el; c_list_init (&head); - c_list_sort (&head, _c_list_sort_cmp, NULL); - g_assert (c_list_length (&head) == 0); - g_assert (c_list_is_empty (&head)); - - for (repeat = 0; repeat < 10; repeat++) { - for (n_list = 1; n_list < G_N_ELEMENTS (elements); n_list++) { - for (headless = 0; headless < 2; headless++) { - c_list_init (&head); - for (i = 0; i < n_list; i++) { - CListSort *el; - - el = &elements[i]; - el->val = nmtst_get_rand_int () % (2*n_list); - el->idx = i; - c_list_link_tail (&head, &el->lst); - } + for (i = 0; i < n_list; i++) { + el = &elements[i]; + el->val = nmtst_get_rand_int () % (2*n_list); + c_list_link_tail (&head, &el->lst); + } - if (headless) { - lst = head.next; - c_list_unlink_stale (&head); - lst = c_list_sort_headless (lst, _c_list_sort_cmp, NULL); - g_assert (lst); - g_assert (lst->next); - g_assert (lst->prev); - g_assert (c_list_length (lst) == n_list - 1); - iter_prev = lst->prev; - for (iter = lst; iter != lst; iter = iter->next) { - g_assert (iter); - g_assert (iter->next); - g_assert (iter->prev == iter_prev); - } - c_list_link_before (lst, &head); - } else { - c_list_sort (&head, _c_list_sort_cmp, NULL); - } + if (headless) { + lst = head.next; + c_list_unlink_stale (&head); + lst = c_list_sort_headless (lst, _c_list_sort_cmp, NULL); + g_assert (lst); + g_assert (lst->next); + g_assert (lst->prev); + g_assert (c_list_length (lst) == n_list - 1); + iter_prev = lst->prev; + for (iter = lst; iter != lst; iter = iter->next) { + g_assert (iter); + g_assert (iter->next); + g_assert (iter->prev == iter_prev); + } + c_list_link_before (lst, &head); + } else + c_list_sort (&head, _c_list_sort_cmp, NULL); + + g_assert (!c_list_is_empty (&head)); + g_assert (c_list_length (&head) == n_list); + + el_prev = NULL; + c_list_for_each (iter, &head) { + el = c_list_entry (iter, CListSort, lst); + g_assert (el >= elements && el < &elements[n_list]); + if (el_prev) { + if (el_prev->val == el->val) + g_assert (el_prev < el); + else + g_assert (el_prev->val < el->val); + g_assert (iter->prev == &el_prev->lst); + g_assert (el_prev->lst.next == iter); + } + el_prev = el; + } + g_assert (head.prev == &el_prev->lst); +} - g_assert (!c_list_is_empty (&head)); - g_assert (c_list_length (&head) == n_list); - - el_prev = NULL; - c_list_for_each (iter, &head) { - CListSort *el; - - el = c_list_entry (iter, CListSort, lst); - g_assert (el->idx >= 0 && el->idx < n_list); - g_assert (el == &elements[el->idx]); - if (el_prev) { - g_assert (el_prev->val <= el->val); - if (el_prev->val == el->val) - g_assert (el_prev->idx < el->idx); - g_assert (iter->prev == &el_prev->lst); - g_assert (el_prev->lst.next == iter); - } - el_prev = el; - } - g_assert (head.prev == &el_prev->lst); - } +static void +test_c_list_sort (void) +{ + const guint N_ELEMENTS = 10000; + guint n_list, repeat; + gs_free CListSort *elements = NULL; + + { + CList head; + + c_list_init (&head); + c_list_sort (&head, _c_list_sort_cmp, NULL); + g_assert (c_list_length (&head) == 0); + g_assert (c_list_is_empty (&head)); + } + + elements = g_new0 (CListSort, N_ELEMENTS); + for (n_list = 1; n_list < N_ELEMENTS; n_list++) { + if (n_list > 150) { + n_list += nmtst_get_rand_int () % n_list; + if (n_list >= N_ELEMENTS) + break; + } + { + const guint N_REPEAT = n_list > 50 ? 1 : 5; + + for (repeat = 0; repeat < N_REPEAT; repeat++) + _do_test_c_list_sort (elements, n_list, nmtst_get_rand_int () % 2); } } } @@ -742,54 +774,54 @@ test_setting_vpn_items (void) nm_setting_vpn_remove_secret (s_vpn, "foobar4"); /* Try to add some blank values and make sure they are rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (key != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (key != NULL)); nm_setting_vpn_add_data_item (s_vpn, NULL, NULL); g_test_assert_expected_messages (); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (strlen (key) > 0)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (strlen (key) > 0)); nm_setting_vpn_add_data_item (s_vpn, "", ""); g_test_assert_expected_messages (); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (item != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (item != NULL)); nm_setting_vpn_add_data_item (s_vpn, "foobar1", NULL); g_test_assert_expected_messages (); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (strlen (item) > 0)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (strlen (item) > 0)); nm_setting_vpn_add_data_item (s_vpn, "foobar1", ""); g_test_assert_expected_messages (); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (key != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (key != NULL)); nm_setting_vpn_add_data_item (s_vpn, NULL, "blahblah1"); g_test_assert_expected_messages (); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (strlen (key) > 0)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (strlen (key) > 0)); nm_setting_vpn_add_data_item (s_vpn, "", "blahblah1"); g_test_assert_expected_messages (); nm_setting_vpn_foreach_data_item (s_vpn, vpn_check_empty_func, NULL); /* Try to add some blank secrets and make sure they are rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (key != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (key != NULL)); nm_setting_vpn_add_secret (s_vpn, NULL, NULL); g_test_assert_expected_messages (); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (strlen (key) > 0)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (strlen (key) > 0)); nm_setting_vpn_add_secret (s_vpn, "", ""); g_test_assert_expected_messages (); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (secret != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (secret != NULL)); nm_setting_vpn_add_secret (s_vpn, "foobar1", NULL); g_test_assert_expected_messages (); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (strlen (secret) > 0)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (strlen (secret) > 0)); nm_setting_vpn_add_secret (s_vpn, "foobar1", ""); g_test_assert_expected_messages (); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (key != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (key != NULL)); nm_setting_vpn_add_secret (s_vpn, NULL, "blahblah1"); g_test_assert_expected_messages (); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (strlen (key) > 0)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (strlen (key) > 0)); nm_setting_vpn_add_secret (s_vpn, "", "blahblah1"); g_test_assert_expected_messages (); @@ -942,7 +974,7 @@ test_setting_ip4_config_labels (void) nmtst_assert_setting_verifies (NM_SETTING (s_ip4)); addr = nm_setting_ip_config_get_address (s_ip4, 0); - label = nm_ip_address_get_attribute (addr, "label"); + label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); g_assert (label == NULL); /* The 'address-labels' property should be omitted from the serialization if @@ -967,28 +999,28 @@ test_setting_ip4_config_labels (void) /* addr 2 */ addr = nm_ip_address_new (AF_INET, "2.3.4.5", 24, &error); g_assert_no_error (error); - nm_ip_address_set_attribute (addr, "label", g_variant_new_string ("eth0:1")); + nm_ip_address_set_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string ("eth0:1")); nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); nmtst_assert_setting_verifies (NM_SETTING (s_ip4)); addr = nm_setting_ip_config_get_address (s_ip4, 1); - label = nm_ip_address_get_attribute (addr, "label"); + label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); g_assert (label != NULL); g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1"); /* addr 3 */ addr = nm_ip_address_new (AF_INET, "3.4.5.6", 24, &error); g_assert_no_error (error); - nm_ip_address_set_attribute (addr, "label", NULL); + nm_ip_address_set_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL, NULL); nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); nmtst_assert_setting_verifies (NM_SETTING (s_ip4)); addr = nm_setting_ip_config_get_address (s_ip4, 2); - label = nm_ip_address_get_attribute (addr, "label"); + label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); g_assert (label == NULL); /* Remove addr 1 and re-verify remaining addresses */ @@ -997,13 +1029,13 @@ test_setting_ip4_config_labels (void) addr = nm_setting_ip_config_get_address (s_ip4, 0); g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5"); - label = nm_ip_address_get_attribute (addr, "label"); + label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); g_assert (label != NULL); g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1"); addr = nm_setting_ip_config_get_address (s_ip4, 1); g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6"); - label = nm_ip_address_get_attribute (addr, "label"); + label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); g_assert (label == NULL); /* If we serialize as the daemon, the labels should appear in the D-Bus @@ -1034,11 +1066,11 @@ test_setting_ip4_config_labels (void) g_assert (addrs != NULL); g_assert_cmpint (addrs->len, ==, 2); addr = addrs->pdata[0]; - label = nm_ip_address_get_attribute (addr, "label"); + label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); g_assert (label != NULL); g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1"); addr = addrs->pdata[1]; - label = nm_ip_address_get_attribute (addr, "label"); + label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); g_assert (label == NULL); g_ptr_array_unref (addrs); @@ -1061,13 +1093,13 @@ test_setting_ip4_config_labels (void) addr = nm_setting_ip_config_get_address (s_ip4, 0); g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5"); - label = nm_ip_address_get_attribute (addr, "label"); + label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); g_assert (label != NULL); g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1"); addr = nm_setting_ip_config_get_address (s_ip4, 1); g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6"); - label = nm_ip_address_get_attribute (addr, "label"); + label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); g_assert (label == NULL); g_object_unref (conn); @@ -1084,12 +1116,12 @@ test_setting_ip4_config_labels (void) addr = nm_setting_ip_config_get_address (s_ip4, 0); g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5"); - label = nm_ip_address_get_attribute (addr, "label"); + label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1"); addr = nm_setting_ip_config_get_address (s_ip4, 1); g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6"); - label = nm_ip_address_get_attribute (addr, "label"); + label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); g_assert (label == NULL); /* Test explicit property assignment */ @@ -1109,13 +1141,13 @@ test_setting_ip4_config_labels (void) addr = nm_setting_ip_config_get_address (s_ip4, 0); g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5"); - label = nm_ip_address_get_attribute (addr, "label"); + label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); g_assert (label != NULL); g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1"); addr = nm_setting_ip_config_get_address (s_ip4, 1); g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6"); - label = nm_ip_address_get_attribute (addr, "label"); + label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); g_assert (label == NULL); g_object_unref (conn); @@ -2259,47 +2291,47 @@ test_setting_connection_permissions_helpers (void) s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ()); /* Ensure a bad [type] is rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (strcmp (ptype, "user") == 0)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (strcmp (ptype, "user") == 0)); success = nm_setting_connection_add_permission (s_con, "foobar", "blah", NULL); g_test_assert_expected_messages (); g_assert (!success); /* Ensure a bad [type] is rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (ptype)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (ptype)); success = nm_setting_connection_add_permission (s_con, NULL, "blah", NULL); g_test_assert_expected_messages (); g_assert (!success); /* Ensure a bad [item] is rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (uname)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (p != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (uname)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (p != NULL)); success = nm_setting_connection_add_permission (s_con, "user", NULL, NULL); g_test_assert_expected_messages (); g_assert (!success); /* Ensure a bad [item] is rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (uname[0] != '\0')); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (p != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (uname[0] != '\0')); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (p != NULL)); success = nm_setting_connection_add_permission (s_con, "user", "", NULL); g_test_assert_expected_messages (); g_assert (!success); /* Ensure an [item] with ':' is rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (strchr (uname, ':') == NULL)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (p != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (strchr (uname, ':') == NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (p != NULL)); success = nm_setting_connection_add_permission (s_con, "user", "ad:asdf", NULL); g_test_assert_expected_messages (); g_assert (!success); /* Ensure a non-UTF-8 [item] is rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (g_utf8_validate (uname, -1, NULL) == TRUE)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (p != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (g_utf8_validate (uname, -1, NULL) == TRUE)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (p != NULL)); success = nm_setting_connection_add_permission (s_con, "user", buf, NULL); g_test_assert_expected_messages (); g_assert (!success); /* Ensure a non-NULL [detail] is rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (detail == NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (detail == NULL)); success = nm_setting_connection_add_permission (s_con, "user", "dafasdf", "asdf"); g_test_assert_expected_messages (); g_assert (!success); @@ -2370,55 +2402,56 @@ test_setting_connection_permissions_property (void) s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ()); /* Ensure a bad [type] is rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (strncmp (str, PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (strncmp (str, PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0)); add_permission_property (s_con, "foobar", "blah", -1, NULL); g_test_assert_expected_messages (); g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0); /* Ensure a bad [type] is rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (strncmp (str, PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (strncmp (str, PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0)); add_permission_property (s_con, NULL, "blah", -1, NULL); g_test_assert_expected_messages (); g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0); /* Ensure a bad [item] is rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (last_colon > str)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (last_colon > str)); add_permission_property (s_con, "user", NULL, -1, NULL); g_test_assert_expected_messages (); g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0); /* Ensure a bad [item] is rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (last_colon > str)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (last_colon > str)); add_permission_property (s_con, "user", "", -1, NULL); g_test_assert_expected_messages (); g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0); /* Ensure an [item] with ':' in the middle is rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (str[i] != ':')); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (str[i] != ':')); add_permission_property (s_con, "user", "ad:asdf", -1, NULL); g_test_assert_expected_messages (); g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0); /* Ensure an [item] with ':' at the end is rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (str[i] != ':')); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (str[i] != ':')); add_permission_property (s_con, "user", "adasdfaf:", -1, NULL); g_test_assert_expected_messages (); g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0); /* Ensure a non-UTF-8 [item] is rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (g_utf8_validate (str, -1, NULL) == TRUE)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (g_utf8_validate (str, -1, NULL) == TRUE)); add_permission_property (s_con, "user", buf, (int) sizeof (buf), NULL); g_test_assert_expected_messages (); g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0); /* Ensure a non-NULL [detail] is rejected */ - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (*(last_colon + 1) == '\0')); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (*(last_colon + 1) == '\0')); add_permission_property (s_con, "user", "dafasdf", -1, "asdf"); g_test_assert_expected_messages (); g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0); /* Ensure a valid call results in success */ success = nm_setting_connection_add_permission (s_con, "user", TEST_UNAME, NULL); + g_assert (success); g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 1); check_permission (s_con, 0, TEST_UNAME); @@ -2572,6 +2605,7 @@ test_connection_diff_a_only (void) { NM_SETTING_CONNECTION_METERED, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_CONNECTION_LLDP, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_CONNECTION_AUTH_RETRIES, NM_SETTING_DIFF_RESULT_IN_A }, + { NM_SETTING_CONNECTION_MDNS, NM_SETTING_DIFF_RESULT_IN_A }, { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN } } }, { NM_SETTING_WIRED_SETTING_NAME, { @@ -3040,10 +3074,10 @@ test_setting_compare_addresses (void) a = nm_ip_address_new (AF_INET, "192.168.7.5", 24, NULL); - nm_ip_address_set_attribute (a, "label", g_variant_new_string ("xoxoxo")); + nm_ip_address_set_attribute (a, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string ("xoxoxo")); nm_setting_ip_config_add_address ((NMSettingIPConfig *) s1, a); - nm_ip_address_set_attribute (a, "label", g_variant_new_string ("hello")); + nm_ip_address_set_attribute (a, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string ("hello")); nm_setting_ip_config_add_address ((NMSettingIPConfig *) s2, a); nm_ip_address_unref (a); @@ -3072,10 +3106,10 @@ test_setting_compare_routes (void) r = nm_ip_route_new (AF_INET, "192.168.12.0", 24, "192.168.11.1", 473, NULL); - nm_ip_route_set_attribute (r, "label", g_variant_new_string ("xoxoxo")); + nm_ip_route_set_attribute (r, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string ("xoxoxo")); nm_setting_ip_config_add_route ((NMSettingIPConfig *) s1, r); - nm_ip_route_set_attribute (r, "label", g_variant_new_string ("hello")); + nm_ip_route_set_attribute (r, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string ("hello")); nm_setting_ip_config_add_route ((NMSettingIPConfig *) s2, r); nm_ip_route_unref (r); @@ -3546,7 +3580,7 @@ test_setting_connection_changed_signal (void) ASSERT_CHANGED (nm_setting_connection_add_permission (s_con, "user", "billsmith", NULL)); ASSERT_CHANGED (nm_setting_connection_remove_permission (s_con, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (iter != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (iter != NULL)); ASSERT_UNCHANGED (nm_setting_connection_remove_permission (s_con, 1)); g_test_assert_expected_messages (); @@ -3554,7 +3588,7 @@ test_setting_connection_changed_signal (void) ASSERT_CHANGED (nm_setting_connection_add_secondary (s_con, uuid)); ASSERT_CHANGED (nm_setting_connection_remove_secondary (s_con, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (elt != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (elt != NULL)); ASSERT_UNCHANGED (nm_setting_connection_remove_secondary (s_con, 1)); g_test_assert_expected_messages (); @@ -3606,7 +3640,7 @@ test_setting_ip4_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_dns (s_ip4, "11.22.0.0")); ASSERT_CHANGED (nm_setting_ip_config_remove_dns (s_ip4, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns->len)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns (s_ip4, 1)); g_test_assert_expected_messages (); @@ -3616,7 +3650,7 @@ test_setting_ip4_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip4, "foobar.com")); ASSERT_CHANGED (nm_setting_ip_config_remove_dns_search (s_ip4, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns_search->len)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns_search->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_search (s_ip4, 1)); g_test_assert_expected_messages (); @@ -3628,7 +3662,7 @@ test_setting_ip4_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_address (s_ip4, addr)); ASSERT_CHANGED (nm_setting_ip_config_remove_address (s_ip4, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->addresses->len)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->addresses->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_address (s_ip4, 1)); g_test_assert_expected_messages (); @@ -3641,7 +3675,7 @@ test_setting_ip4_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_route (s_ip4, route)); ASSERT_CHANGED (nm_setting_ip_config_remove_route (s_ip4, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->routes->len)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->routes->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_route (s_ip4, 1)); g_test_assert_expected_messages (); @@ -3651,7 +3685,7 @@ test_setting_ip4_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_dns_option (s_ip4, "debug")); ASSERT_CHANGED (nm_setting_ip_config_remove_dns_option (s_ip4, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns_options->len)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns_options->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_option (s_ip4, 1)); g_test_assert_expected_messages (); @@ -3682,7 +3716,7 @@ test_setting_ip6_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_dns (s_ip6, "1:2:3::4:5:6")); ASSERT_CHANGED (nm_setting_ip_config_remove_dns (s_ip6, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns->len)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns (s_ip6, 1)); g_test_assert_expected_messages (); @@ -3692,7 +3726,7 @@ test_setting_ip6_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip6, "foobar.com")); ASSERT_CHANGED (nm_setting_ip_config_remove_dns_search (s_ip6, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns_search->len)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns_search->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_search (s_ip6, 1)); g_test_assert_expected_messages (); @@ -3705,7 +3739,7 @@ test_setting_ip6_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_address (s_ip6, addr)); ASSERT_CHANGED (nm_setting_ip_config_remove_address (s_ip6, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->addresses->len)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->addresses->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_address (s_ip6, 1)); g_test_assert_expected_messages (); @@ -3718,7 +3752,7 @@ test_setting_ip6_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_route (s_ip6, route)); ASSERT_CHANGED (nm_setting_ip_config_remove_route (s_ip6, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->routes->len)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->routes->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_route (s_ip6, 1)); g_test_assert_expected_messages (); @@ -3748,7 +3782,7 @@ test_setting_vlan_changed_signal (void) ASSERT_CHANGED (nm_setting_vlan_add_priority (s_vlan, NM_VLAN_INGRESS_MAP, 1, 3)); ASSERT_CHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_INGRESS_MAP, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx < g_slist_length (list))); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx < g_slist_length (list))); ASSERT_UNCHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_INGRESS_MAP, 1)); g_test_assert_expected_messages (); ASSERT_CHANGED (nm_setting_vlan_add_priority_str (s_vlan, NM_VLAN_INGRESS_MAP, "1:3")); @@ -3756,7 +3790,7 @@ test_setting_vlan_changed_signal (void) ASSERT_CHANGED (nm_setting_vlan_add_priority (s_vlan, NM_VLAN_EGRESS_MAP, 1, 3)); ASSERT_CHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_EGRESS_MAP, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx < g_slist_length (list))); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx < g_slist_length (list))); ASSERT_UNCHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_EGRESS_MAP, 1)); g_test_assert_expected_messages (); ASSERT_CHANGED (nm_setting_vlan_add_priority_str (s_vlan, NM_VLAN_EGRESS_MAP, "1:3")); @@ -3855,7 +3889,7 @@ test_setting_wireless_security_changed_signal (void) /* Protos */ ASSERT_CHANGED (nm_setting_wireless_security_add_proto (s_wsec, "wpa")); ASSERT_CHANGED (nm_setting_wireless_security_remove_proto (s_wsec, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (elt != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (elt != NULL)); ASSERT_UNCHANGED (nm_setting_wireless_security_remove_proto (s_wsec, 1)); g_test_assert_expected_messages (); @@ -3865,7 +3899,7 @@ test_setting_wireless_security_changed_signal (void) /* Pairwise ciphers */ ASSERT_CHANGED (nm_setting_wireless_security_add_pairwise (s_wsec, "tkip")); ASSERT_CHANGED (nm_setting_wireless_security_remove_pairwise (s_wsec, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (elt != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (elt != NULL)); ASSERT_UNCHANGED (nm_setting_wireless_security_remove_pairwise (s_wsec, 1)); g_test_assert_expected_messages (); @@ -3875,7 +3909,7 @@ test_setting_wireless_security_changed_signal (void) /* Group ciphers */ ASSERT_CHANGED (nm_setting_wireless_security_add_group (s_wsec, "ccmp")); ASSERT_CHANGED (nm_setting_wireless_security_remove_group (s_wsec, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (elt != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (elt != NULL)); ASSERT_UNCHANGED (nm_setting_wireless_security_remove_group (s_wsec, 1)); g_test_assert_expected_messages (); @@ -3910,7 +3944,7 @@ test_setting_802_1x_changed_signal (void) /* EAP methods */ ASSERT_CHANGED (nm_setting_802_1x_add_eap_method (s_8021x, "tls")); ASSERT_CHANGED (nm_setting_802_1x_remove_eap_method (s_8021x, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (elt != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (elt != NULL)); ASSERT_UNCHANGED (nm_setting_802_1x_remove_eap_method (s_8021x, 1)); g_test_assert_expected_messages (); @@ -3920,7 +3954,7 @@ test_setting_802_1x_changed_signal (void) /* alternate subject matches */ ASSERT_CHANGED (nm_setting_802_1x_add_altsubject_match (s_8021x, "EMAIL:server@example.com")); ASSERT_CHANGED (nm_setting_802_1x_remove_altsubject_match (s_8021x, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (elt != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (elt != NULL)); ASSERT_UNCHANGED (nm_setting_802_1x_remove_altsubject_match (s_8021x, 1)); g_test_assert_expected_messages (); @@ -3930,7 +3964,7 @@ test_setting_802_1x_changed_signal (void) /* phase2 alternate subject matches */ ASSERT_CHANGED (nm_setting_802_1x_add_phase2_altsubject_match (s_8021x, "EMAIL:server@example.com")); ASSERT_CHANGED (nm_setting_802_1x_remove_phase2_altsubject_match (s_8021x, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (elt != NULL)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (elt != NULL)); ASSERT_UNCHANGED (nm_setting_802_1x_remove_phase2_altsubject_match (s_8021x, 1)); g_test_assert_expected_messages (); @@ -5848,7 +5882,7 @@ test_nm_utils_check_valid_json (void) { _json_config_check_valid (NULL, FALSE); _json_config_check_valid ("", FALSE); -#if WITH_JANSSON +#if WITH_JSON_VALIDATION _json_config_check_valid ("{ }", TRUE); _json_config_check_valid ("{ \"a\" : 1 }", TRUE); _json_config_check_valid ("{ \"a\" : }", FALSE); @@ -5873,7 +5907,7 @@ _team_config_equal_check (const char *conf1, static void test_nm_utils_team_config_equal (void) { -#if WITH_JANSSON +#if WITH_JSON_VALIDATION _team_config_equal_check ("", "", TRUE, TRUE); _team_config_equal_check ("{}", "{ }", @@ -6060,66 +6094,6 @@ again: /*****************************************************************************/ -static void -test_g_ptr_array_insert (void) -{ - /* this test only makes sense on a recent glib, where we compare our compat - * with the original implementation. */ -#if GLIB_CHECK_VERSION(2, 40, 0) - gs_unref_ptrarray GPtrArray *arr1 = g_ptr_array_new (); - gs_unref_ptrarray GPtrArray *arr2 = g_ptr_array_new (); - GRand *rand = nmtst_get_rand (); - guint i; - - for (i = 0; i < 560; i++) { - gint32 idx = g_rand_int_range (rand, -1, arr1->len + 1); - - g_ptr_array_insert (arr1, idx, GINT_TO_POINTER (i)); - _nm_g_ptr_array_insert (arr2, idx, GINT_TO_POINTER (i)); - - g_assert_cmpint (arr1->len, ==, arr2->len); - g_assert (memcmp (arr1->pdata, arr2->pdata, arr1->len * sizeof (gpointer)) == 0); - } -#endif -} - -/*****************************************************************************/ - -static void -test_g_hash_table_get_keys_as_array (void) -{ - GHashTable *table = g_hash_table_new (g_str_hash, g_str_equal); - guint length = 0; - char **keys; - - g_hash_table_insert (table, "one", "1"); - g_hash_table_insert (table, "two", "2"); - g_hash_table_insert (table, "three", "3"); - - keys = (char **) _nm_g_hash_table_get_keys_as_array (table, &length); - g_assert (keys); - g_assert_cmpuint (length, ==, 3); - - g_assert ( !strcmp (keys[0], "one") - || !strcmp (keys[1], "one") - || !strcmp (keys[2], "one")); - - g_assert ( !strcmp (keys[0], "two") - || !strcmp (keys[1], "two") - || !strcmp (keys[2], "two")); - - g_assert ( !strcmp (keys[0], "three") - || !strcmp (keys[1], "three") - || !strcmp (keys[2], "three")); - - g_assert (!keys[3]); - - g_free (keys); - g_hash_table_unref (table); -} - -/*****************************************************************************/ - static int _test_find_binary_search_cmp (gconstpointer a, gconstpointer b, gpointer dummy) { @@ -6196,7 +6170,9 @@ _test_find_binary_search_do_uint32 (const int *int_array, gsize len) const int OFFSET = 100; const int NEEDLE = 0 + OFFSET; gssize expected_result = -1; - guint32 array[len]; + guint32 array[30]; + + g_assert (len <= G_N_ELEMENTS (array)); /* the test data has negative values. Shift them... */ for (idx = 0; idx < len; idx++) { @@ -6353,105 +6329,219 @@ test_nm_utils_ptrarray_find_binary_search_with_duplicates (void) } /*****************************************************************************/ + static void -test_nm_utils_enum_from_str_do (GType type, const char *str, - gboolean exp_result, int exp_flags, - const char *exp_err_token) +_test_nm_utils_enum_to_str_do_full (GType type, + int flags, + const char *exp_str, + const NMUtilsEnumValueInfo *value_infos) { - int flags = 1; - char *err_token = NULL; + gs_free char *str = NULL; + int flags2; + gs_free char *err_token = NULL; gboolean result; - result = nm_utils_enum_from_str (type, str, &flags, &err_token); + g_assert (exp_str); - g_assert (result == exp_result); - g_assert_cmpint (flags, ==, exp_flags); - g_assert_cmpstr (err_token, ==, exp_err_token); + str = _nm_utils_enum_to_str_full (type, flags, ", ", value_infos); + g_assert_cmpstr (str, ==, exp_str); + + if (!value_infos) { + gs_free char *str2 = NULL; + + str2 = nm_utils_enum_to_str (type, flags); + g_assert_cmpstr (str2, ==, exp_str); + } - g_free (err_token); + result = _nm_utils_enum_from_str_full (type, str, &flags2, &err_token, value_infos); + g_assert (result == TRUE); + g_assert_cmpint (flags2, ==, flags); + g_assert_cmpstr (err_token, ==, NULL); } +#define _test_nm_utils_enum_to_str_do(...) _test_nm_utils_enum_to_str_do_full (__VA_ARGS__, NULL) + static void -test_nm_utils_enum_to_str_do (GType type, int flags, const char *exp_str) +_test_nm_utils_enum_from_str_do_full (GType type, + const char *str, + gboolean exp_result, + int exp_flags, + const char *exp_err_token, + const NMUtilsEnumValueInfo *value_infos) { - char *str; + int flags; + gs_free char *err_token = NULL; + gboolean result; - str = nm_utils_enum_to_str (type, flags); - g_assert_cmpstr (str, ==, exp_str); - g_free (str); + result = _nm_utils_enum_from_str_full (type, str, &flags, &err_token, value_infos); + + g_assert (result == exp_result); + g_assert_cmpint (flags, ==, exp_flags); + g_assert_cmpstr (err_token, ==, exp_err_token); + + if (!value_infos) { + int flags2; + gs_free char *err_token2 = NULL; + gboolean result2; + + result2 = nm_utils_enum_from_str (type, str, &flags2, &err_token2); + g_assert (result2 == exp_result); + g_assert_cmpint (flags2, ==, exp_flags); + g_assert_cmpstr (err_token2, ==, exp_err_token); + } + + if (result) { + int flags2; + gs_free char *str2 = NULL; + gs_free char *err_token2 = NULL; + + str2 = _nm_utils_enum_to_str_full (type, flags, ", ", value_infos); + g_assert (str2); + + result = _nm_utils_enum_from_str_full (type, str2, &flags2, &err_token2, value_infos); + g_assert (result == TRUE); + g_assert_cmpint (flags2, ==, flags); + g_assert_cmpstr (err_token, ==, NULL); + } } +#define _test_nm_utils_enum_from_str_do(...) _test_nm_utils_enum_from_str_do_full(__VA_ARGS__, NULL) + static void -test_nm_utils_enum_get_values_do (GType type, int from, int to, const char *exp_str) +_test_nm_utils_enum_get_values_do (GType type, int from, int to, const char *exp_str) { - const char **strv; - char *str; + gs_free const char **strv = NULL; + gs_free char *str = NULL; + + g_assert (exp_str); strv = nm_utils_enum_get_values (type, from, to); g_assert (strv); str = g_strjoinv (",", (char **) strv); g_assert_cmpstr (str, ==, exp_str); - g_free (str); - g_free (strv); } - -static void test_nm_utils_enum (void) +static void +test_nm_utils_enum (void) { GType bool_enum = nm_test_general_bool_enum_get_type(); GType meta_flags = nm_test_general_meta_flags_get_type(); GType color_flags = nm_test_general_color_flags_get_type(); + static const NMUtilsEnumValueInfo color_value_infos[] = { + { + .nick = "nick-4d", + .value = 0x4D, + }, + { + .nick = "nick-5", + .value = 5, + }, + { + .nick = "nick-red", + .value = NM_TEST_GENERAL_COLOR_FLAGS_RED, + }, + { 0 }, + }; - test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_YES, "yes"); - test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_UNKNOWN, "unknown"); - test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_INVALID, "4"); - test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_67, "67"); - test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_46, "64"); - - test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_NONE, "none"); - test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_BAZ, "baz"); - test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_FOO | - NM_TEST_GENERAL_META_FLAGS_BAR | - NM_TEST_GENERAL_META_FLAGS_BAZ, "foo, bar, baz"); - test_nm_utils_enum_to_str_do (meta_flags, 0xFF, "foo, bar, baz, 0xf8"); - test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_0x8, "0x8"); - test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_0x4, "0x10"); - - test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED, "red"); - test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_WHITE, "0x1"); - test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED | - NM_TEST_GENERAL_COLOR_FLAGS_GREEN, "red, green"); - - test_nm_utils_enum_from_str_do (bool_enum, "", FALSE, 0, NULL); - test_nm_utils_enum_from_str_do (bool_enum, " ", FALSE, 0, NULL); - test_nm_utils_enum_from_str_do (bool_enum, "invalid", FALSE, 0, "invalid"); - test_nm_utils_enum_from_str_do (bool_enum, "yes", TRUE, NM_TEST_GENERAL_BOOL_ENUM_YES, NULL); - test_nm_utils_enum_from_str_do (bool_enum, "no", TRUE, NM_TEST_GENERAL_BOOL_ENUM_NO, NULL); - test_nm_utils_enum_from_str_do (bool_enum, "yes,no", FALSE, 0, "yes,no"); - - test_nm_utils_enum_from_str_do (meta_flags, "", TRUE, 0, NULL); - test_nm_utils_enum_from_str_do (meta_flags, " ", TRUE, 0, NULL); - test_nm_utils_enum_from_str_do (meta_flags, "foo", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO, NULL); - test_nm_utils_enum_from_str_do (meta_flags, "foo,baz", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO | - NM_TEST_GENERAL_META_FLAGS_BAZ, NULL); - test_nm_utils_enum_from_str_do (meta_flags, "foo, baz", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO | + _test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_YES, "yes"); + _test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_UNKNOWN, "unknown"); + _test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_INVALID, "4"); + _test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_67, "67"); + _test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_46, "64"); + + _test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_NONE, "none"); + _test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_BAZ, "baz"); + _test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_FOO | + NM_TEST_GENERAL_META_FLAGS_BAR | + NM_TEST_GENERAL_META_FLAGS_BAZ, "foo, bar, baz"); + _test_nm_utils_enum_to_str_do (meta_flags, 0xFF, "foo, bar, baz, 0xf8"); + _test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_0x8, "0x8"); + _test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_0x4, "0x10"); + + _test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED, "red"); + _test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_WHITE, "0x1"); + _test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED | + NM_TEST_GENERAL_COLOR_FLAGS_GREEN, "red, green"); + + _test_nm_utils_enum_to_str_do_full (color_flags, + NM_TEST_GENERAL_COLOR_FLAGS_RED + | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, + "nick-red, green", + color_value_infos); + + _test_nm_utils_enum_to_str_do_full (color_flags, + 0x4D + | NM_TEST_GENERAL_COLOR_FLAGS_RED + | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, + "nick-4d", + color_value_infos); + + _test_nm_utils_enum_to_str_do_full (color_flags, + 5 + | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, + "nick-5, green", + color_value_infos); + + _test_nm_utils_enum_from_str_do (bool_enum, "", FALSE, 0, NULL); + _test_nm_utils_enum_from_str_do (bool_enum, " ", FALSE, 0, NULL); + _test_nm_utils_enum_from_str_do (bool_enum, "invalid", FALSE, 0, "invalid"); + _test_nm_utils_enum_from_str_do (bool_enum, "yes", TRUE, NM_TEST_GENERAL_BOOL_ENUM_YES, NULL); + _test_nm_utils_enum_from_str_do (bool_enum, "no", TRUE, NM_TEST_GENERAL_BOOL_ENUM_NO, NULL); + _test_nm_utils_enum_from_str_do (bool_enum, "yes,no", FALSE, 0, "yes,no"); + + _test_nm_utils_enum_from_str_do (meta_flags, "", TRUE, 0, NULL); + _test_nm_utils_enum_from_str_do (meta_flags, " ", TRUE, 0, NULL); + _test_nm_utils_enum_from_str_do (meta_flags, "foo", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO, NULL); + _test_nm_utils_enum_from_str_do (meta_flags, "foo,baz", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO | NM_TEST_GENERAL_META_FLAGS_BAZ, NULL); - test_nm_utils_enum_from_str_do (meta_flags, "foo,,bar", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO | - NM_TEST_GENERAL_META_FLAGS_BAR, NULL); - test_nm_utils_enum_from_str_do (meta_flags, "foo,baz,quux,bar", FALSE, 0, "quux"); - test_nm_utils_enum_from_str_do (meta_flags, "foo,0x6", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO | 0x6, NULL); - test_nm_utils_enum_from_str_do (meta_flags, "0x30,0x08,foo", TRUE, 0x39, NULL); - - test_nm_utils_enum_from_str_do (color_flags, "green", TRUE, NM_TEST_GENERAL_COLOR_FLAGS_GREEN, NULL); - test_nm_utils_enum_from_str_do (color_flags, "blue,red", TRUE, NM_TEST_GENERAL_COLOR_FLAGS_BLUE | - NM_TEST_GENERAL_COLOR_FLAGS_RED, NULL); - test_nm_utils_enum_from_str_do (color_flags, "blue,white", FALSE, 0, "white"); - - test_nm_utils_enum_get_values_do (bool_enum, 0, G_MAXINT, "no,yes,maybe,unknown,67,64"); - test_nm_utils_enum_get_values_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_YES, - NM_TEST_GENERAL_BOOL_ENUM_MAYBE, "yes,maybe"); - test_nm_utils_enum_get_values_do (meta_flags, 0, G_MAXINT, "none,foo,bar,baz,0x8,0x10"); - test_nm_utils_enum_get_values_do (color_flags, 0, G_MAXINT, "blue,red,green"); + _test_nm_utils_enum_from_str_do (meta_flags, "foo, baz", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO | + NM_TEST_GENERAL_META_FLAGS_BAZ, NULL); + _test_nm_utils_enum_from_str_do (meta_flags, "foo,,bar", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO | + NM_TEST_GENERAL_META_FLAGS_BAR, NULL); + _test_nm_utils_enum_from_str_do (meta_flags, "foo,baz,quux,bar", FALSE, 0, "quux"); + _test_nm_utils_enum_from_str_do (meta_flags, "foo,0x6", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO | 0x6, NULL); + _test_nm_utils_enum_from_str_do (meta_flags, "0x30,0x08,foo", TRUE, 0x39, NULL); + + _test_nm_utils_enum_from_str_do (color_flags, "green", TRUE, NM_TEST_GENERAL_COLOR_FLAGS_GREEN, NULL); + _test_nm_utils_enum_from_str_do (color_flags, "blue,red", TRUE, NM_TEST_GENERAL_COLOR_FLAGS_BLUE | + NM_TEST_GENERAL_COLOR_FLAGS_RED, NULL); + _test_nm_utils_enum_from_str_do (color_flags, "blue,white", FALSE, 0, "white"); + + _test_nm_utils_enum_from_str_do_full (color_flags, + "nick-red", + TRUE, + NM_TEST_GENERAL_COLOR_FLAGS_RED, + NULL, + color_value_infos); + + _test_nm_utils_enum_from_str_do_full (color_flags, + "0x4D", + TRUE, + 0x4D, + NULL, + color_value_infos); + + _test_nm_utils_enum_from_str_do_full (color_flags, + "green,nick-4d", + TRUE, + 0x4D + | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, + NULL, + color_value_infos); + + _test_nm_utils_enum_from_str_do_full (color_flags, + "nick-4d,nick-red,nick-5,green,nick-red", + TRUE, + 0x4D + | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, + NULL, + color_value_infos); + + _test_nm_utils_enum_get_values_do (bool_enum, 0, G_MAXINT, "no,yes,maybe,unknown,67,64"); + _test_nm_utils_enum_get_values_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_YES, + NM_TEST_GENERAL_BOOL_ENUM_MAYBE, "yes,maybe"); + _test_nm_utils_enum_get_values_do (meta_flags, 0, G_MAXINT, "none,foo,bar,baz,0x8,0x10"); + _test_nm_utils_enum_get_values_do (color_flags, 0, G_MAXINT, "blue,red,green"); } /*****************************************************************************/ @@ -6749,7 +6839,6 @@ test_nm_in_strset (void) _ASSERT (3, !NM_IN_STRSET_SE ("a", G(NULL), G("b"), G("b"))); _ASSERT (3, !NM_IN_STRSET_SE (NULL, G("a"), G("b"), G("b"))); - _ASSERT (3, NM_IN_STRSET ("a", G(NULL), G("b"), G("a"), N("a"))); _ASSERT (4, NM_IN_STRSET ("a", G(NULL), G("b"), G("c"), G("a"))); _ASSERT (4, !NM_IN_STRSET ("a", G(NULL), G("b"), G("c"), G("d"))); @@ -6832,7 +6921,7 @@ test_route_attributes_format (void) gs_unref_hashtable GHashTable *ht = NULL; char *str; - ht = g_hash_table_new_full (g_str_hash, g_str_equal, + ht = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, (GDestroyNotify) g_variant_unref); str = nm_utils_format_variant_attributes (NULL, ' ', '='); @@ -6900,6 +6989,22 @@ test_nm_set_out (void) /*****************************************************************************/ +static void +test_get_start_time_for_pid (void) +{ + guint64 x_start_time; + char x_state; + pid_t x_ppid; + + x_start_time = nm_utils_get_start_time_for_pid (getpid (), &x_state, &x_ppid); + + g_assert (x_start_time > 0); + g_assert (x_ppid == getppid ()); + g_assert (!NM_IN_SET (x_state, '\0', ' ')); +} + +/*****************************************************************************/ + NMTST_DEFINE (); int main (int argc, char **argv) @@ -7039,8 +7144,6 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64); g_test_add_func ("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two); - g_test_add_func ("/core/general/_glib_compat_g_ptr_array_insert", test_g_ptr_array_insert); - g_test_add_func ("/core/general/_glib_compat_g_hash_table_get_keys_as_array", test_g_hash_table_get_keys_as_array); g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search); g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search_with_duplicates", test_nm_utils_ptrarray_find_binary_search_with_duplicates); g_test_add_func ("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey); @@ -7055,6 +7158,8 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/route_attributes/parse", test_route_attributes_parse); g_test_add_func ("/core/general/route_attributes/format", test_route_attributes_format); + g_test_add_func ("/core/general/get_start_time_for_pid", test_get_start_time_for_pid); + return g_test_run (); } diff --git a/libnm-core/tests/test-keyfile.c b/libnm-core/tests/test-keyfile.c index 313932f0..672c72b6 100644 --- a/libnm-core/tests/test-keyfile.c +++ b/libnm-core/tests/test-keyfile.c @@ -33,7 +33,7 @@ #include "nm-utils/nm-test-utils.h" - +#define TEST_CERT_DIR NM_BUILD_SRCDIR"/libnm-core/tests/certs" #define TEST_WIRED_TLS_CA_CERT TEST_CERT_DIR"/test-ca-cert.pem" #define TEST_WIRED_TLS_PRIVKEY TEST_CERT_DIR"/test-key-and-cert.pem" @@ -203,7 +203,6 @@ _nm_keyfile_read (GKeyFile *keyfile, return con; } - static void _keyfile_convert (NMConnection **con, GKeyFile **keyfile, @@ -412,14 +411,12 @@ test_8021x_cert (void) g_assert_no_error (error); g_assert (success); - /* test reseting ca-cert to different values and see whether we can write/read. */ nm_connection_add_setting (con, NM_SETTING (s_8021x)); nmtst_assert_connection_verifies_and_normalizable (con); nmtst_connection_normalize (con); - _test_8021x_cert_check (con, scheme, full_TEST_WIRED_TLS_CA_CERT, -1); scheme = NM_SETTING_802_1X_CK_SCHEME_BLOB; @@ -457,7 +454,6 @@ test_8021x_cert_read (void) "/test_8021x_cert_read/test0", NULL); CLEAR (&con, &keyfile); - keyfile = _keyfile_load_from_data ( "[connection]\n" "type=ethernet" @@ -480,7 +476,6 @@ test_8021x_cert_read (void) _keyfile_convert (&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE); CLEAR (&con, &keyfile); - keyfile = _keyfile_load_from_data ( "[connection]\n" "type=802-3-ethernet\n" @@ -523,7 +518,6 @@ test_8021x_cert_read (void) g_assert_cmpint (strlen (nm_setting_802_1x_get_private_key_path (s_8021x)), ==, 505); CLEAR (&con, &keyfile); - keyfile = _keyfile_load_from_data ( "[connection]\n" "type=802-3-ethernet\n" @@ -549,7 +543,6 @@ test_8021x_cert_read (void) _assert_gbytes (nm_setting_802_1x_get_private_key_blob (s_8021x), "hallo", -1); CLEAR (&con, &keyfile); - keyfile = _keyfile_load_from_data ( "[connection]\n" "type=802-3-ethernet\n" @@ -575,7 +568,6 @@ test_8021x_cert_read (void) _assert_gbytes (nm_setting_802_1x_get_private_key_blob (s_8021x), "abc.deR\0", 8); CLEAR (&con, &keyfile); - keyfile = _keyfile_load_from_data ( "[connection]\n" "type=802-3-ethernet\n" @@ -628,7 +620,7 @@ test_team_conf_read_valid (void) static void test_team_conf_read_invalid (void) { -#if WITH_JANSSON +#if WITH_JSON_VALIDATION GKeyFile *keyfile = NULL; gs_unref_object NMConnection *con = NULL; NMSettingTeam *s_team; @@ -719,6 +711,33 @@ test_user_1 (void) /*****************************************************************************/ +static void +test_vpn_1 (void) +{ + gs_unref_keyfile GKeyFile *keyfile = NULL; + gs_unref_object NMConnection *con = NULL; + NMSettingVpn *s_vpn; + + con = nmtst_create_connection_from_keyfile ( + "[connection]\n" + "id=t\n" + "type=vpn\n" + "\n" + "[vpn]\n" + "service-type=a.b.c\n" + "vpn-key-1=value1\n" + "", + "/test_vpn_1/invalid", NULL); + g_assert (con); + s_vpn = NM_SETTING_VPN (nm_connection_get_setting (con, NM_TYPE_SETTING_VPN)); + g_assert (s_vpn); + g_assert_cmpstr (nm_setting_vpn_get_data_item (s_vpn, "vpn-key-1"), ==, "value1"); + + CLEAR (&con, &keyfile); +} + +/*****************************************************************************/ + NMTST_DEFINE (); int main (int argc, char **argv) @@ -731,6 +750,7 @@ int main (int argc, char **argv) g_test_add_func ("/core/keyfile/test_team_conf_read/valid", test_team_conf_read_valid); g_test_add_func ("/core/keyfile/test_team_conf_read/invalid", test_team_conf_read_invalid); g_test_add_func ("/core/keyfile/test_user/1", test_user_1); + g_test_add_func ("/core/keyfile/test_vpn/1", test_vpn_1); return g_test_run (); } diff --git a/libnm-core/tests/test-secrets.c b/libnm-core/tests/test-secrets.c index 3328e356..d31c43d2 100644 --- a/libnm-core/tests/test-secrets.c +++ b/libnm-core/tests/test-secrets.c @@ -40,7 +40,8 @@ #include "nm-utils/nm-test-utils.h" -#define TEST_NEED_SECRETS_EAP_TLS_CA_CERT TEST_CERT_DIR "/test_ca_cert.pem" +#define TEST_CERT_DIR NM_BUILD_SRCDIR"/libnm-core/tests/certs" +#define TEST_NEED_SECRETS_EAP_TLS_CA_CERT TEST_CERT_DIR "/test_ca_cert.pem" #define TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT TEST_CERT_DIR "/test_key_and_cert.pem" #define TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY TEST_CERT_DIR "/test_key_and_cert.pem" @@ -259,7 +260,6 @@ make_tls_phase2_connection (const char *detail, NMSetting8021xCKScheme scheme) &error); nmtst_assert_success (success, error); - /* IP4 setting */ s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); nm_connection_add_setting (connection, NM_SETTING (s_ip4)); @@ -651,8 +651,7 @@ test_update_secrets_null_setting_name_with_setting_hash (void) secrets = build_wep_secrets (wepkey); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, - NMTST_G_RETURN_MSG (setting_name != NULL || full_connection)); + NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (setting_name != NULL || full_connection)); success = nm_connection_update_secrets (connection, NULL, secrets, &error); g_test_assert_expected_messages (); g_assert_no_error (error); diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c index a7282f91..6c5c6ad9 100644 --- a/libnm-core/tests/test-setting.c +++ b/libnm-core/tests/test-setting.c @@ -37,6 +37,8 @@ #include "nm-utils/nm-test-utils.h" +#define TEST_CERT_DIR NM_BUILD_SRCDIR"/libnm-core/tests/certs" + /*****************************************************************************/ static void @@ -599,7 +601,6 @@ test_bond_normalize (void) NM_SETTING_DCB_FLAG_ADVERTISE | \ NM_SETTING_DCB_FLAG_WILLING) - static void test_dcb_flags_valid (void) { @@ -663,23 +664,23 @@ test_dcb_flags_invalid (void) s_dcb = (NMSettingDcb *) nm_setting_dcb_new (); g_assert (s_dcb); - g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); + NMTST_EXPECT ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); TEST_FLAG (NM_SETTING_DCB_APP_FCOE_FLAGS, nm_setting_dcb_get_app_fcoe_flags, 0x332523); g_test_assert_expected_messages (); - g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); + NMTST_EXPECT ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); TEST_FLAG (NM_SETTING_DCB_APP_ISCSI_FLAGS, nm_setting_dcb_get_app_iscsi_flags, 0xFF); g_test_assert_expected_messages (); - g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); + NMTST_EXPECT ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); TEST_FLAG (NM_SETTING_DCB_APP_FIP_FLAGS, nm_setting_dcb_get_app_fip_flags, 0x1111); g_test_assert_expected_messages (); - g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); + NMTST_EXPECT ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); TEST_FLAG (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, nm_setting_dcb_get_priority_flow_control_flags, G_MAXUINT32); g_test_assert_expected_messages (); - g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); + NMTST_EXPECT ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); TEST_FLAG (NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, nm_setting_dcb_get_priority_group_flags, (NM_SETTING_DCB_FLAG_ENABLE | NM_SETTING_DCB_FLAG_ADVERTISE | NM_SETTING_DCB_FLAG_WILLING) + 1); g_test_assert_expected_messages (); @@ -869,6 +870,7 @@ test_dcb_bandwidth_sums (void) /*****************************************************************************/ +#if WITH_JSON_VALIDATION static void _test_team_config_sync (const char *team_config, int notify_peer_count, @@ -942,7 +944,6 @@ _test_team_config_sync (const char *team_config, g_assert (nm_setting_verify ((NMSetting *) s_team, NULL, NULL)); } - static void test_runner_roundrobin_sync_from_config (void) { @@ -1182,7 +1183,6 @@ _test_team_port_config_sync (const char *team_port_config, g_assert (nm_setting_verify ((NMSetting *) s_team_port, NULL, NULL)); } - static void test_team_port_default (void) { @@ -1258,6 +1258,7 @@ test_team_port_full_config (void) "\"send_always\": true}]}", 10, 20, true, 30, 40, NULL); } +#endif /*****************************************************************************/ @@ -1610,7 +1611,7 @@ main (int argc, char **argv) g_test_add_func ("/libnm/settings/tc_config/setting", test_tc_config_setting); g_test_add_func ("/libnm/settings/tc_config/dbus", test_tc_config_dbus); -#if WITH_JANSSON +#if WITH_JSON_VALIDATION g_test_add_func ("/libnm/settings/team/sync_runner_from_config_roundrobin", test_runner_roundrobin_sync_from_config); g_test_add_func ("/libnm/settings/team/sync_runner_from_config_broadcast", @@ -1639,7 +1640,6 @@ main (int argc, char **argv) g_test_add_func ("/libnm/settings/team-port/sync_from_config_lacp_prio", test_team_port_lacp_prio); g_test_add_func ("/libnm/settings/team-port/sync_from_config_lacp_key", test_team_port_lacp_key); g_test_add_func ("/libnm/settings/team-port/sycn_from_config_full", test_team_port_full_config); - #endif return g_test_run (); |