diff options
Diffstat (limited to 'libnm-core')
70 files changed, 3012 insertions, 6543 deletions
diff --git a/libnm-core/meson.build b/libnm-core/meson.build index 469d4161..955e1776 100644 --- a/libnm-core/meson.build +++ b/libnm-core/meson.build @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1+ + libnm_core_inc = include_directories('.') libnm_core_nm_default_dep = declare_dependency( @@ -56,6 +58,7 @@ libnm_core_headers = files( 'nm-setting-user.h', 'nm-setting-vlan.h', 'nm-setting-vpn.h', + 'nm-setting-vrf.h', 'nm-setting-vxlan.h', 'nm-setting-wifi-p2p.h', 'nm-setting-wimax.h', @@ -85,7 +88,7 @@ libnm_core_enum_sources = gnome.mkenums_simple( libnm_libnm_core_intern = static_library( 'nm-libnm-core-intern', - sources: nm_ethtool_utils_source + nm_libnm_core_utils_source + [libnm_core_enum_sources[1]], + sources: nm_ethtool_utils_source + nm_libnm_core_utils_source + nm_auth_subject_source + [libnm_core_enum_sources[1]], dependencies: libnm_core_nm_default_dep, c_args: common_c_flags, ) @@ -150,6 +153,7 @@ libnm_core_settings_sources = files( 'nm-setting-user.c', 'nm-setting-vlan.c', 'nm-setting-vpn.c', + 'nm-setting-vrf.c', 'nm-setting-vxlan.c', 'nm-setting-wifi-p2p.c', 'nm-setting-wimax.c', @@ -165,8 +169,6 @@ libnm_core_sources = libnm_core_settings_sources + files( 'nm-crypto.c', 'nm-dbus-utils.c', 'nm-errors.c', - 'nm-keyfile-utils.c', - 'nm-keyfile.c', 'nm-property-compare.c', 'nm-setting.c', 'nm-simple-connection.c', @@ -232,6 +234,24 @@ libnm_libnm_core_aux_dep = declare_dependency( link_with: libnm_libnm_core_aux, ) +libnm_keyfile = static_library( + 'nm-keyfile', + sources: nm_keyfile_source + [libnm_core_enum_sources[1]], + dependencies: libnm_utils_base_dep, + c_args: [ + '-DG_LOG_DOMAIN="@0@"'.format(libnm_name), + '-DNETWORKMANAGER_COMPILATION=(NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL|NM_NETWORKMANAGER_COMPILATION_WITH_GLIB|NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_LIB)', + ], + link_with: libnm_libnm_core_intern, +) + +libnm_keyfile_dep = declare_dependency( + sources: [libnm_core_enum_sources[1], nm_version_macro_header], + include_directories: [libnm_core_inc, shared_inc], + dependencies: glib_dep, + link_with: libnm_keyfile, +) + enums_to_docbook = join_paths(source_root, 'tools', 'enums-to-docbook.pl') docbooks = [ diff --git a/libnm-core/nm-connection-private.h b/libnm-core/nm-connection-private.h index 034c350f..3c505834 100644 --- a/libnm-core/nm-connection-private.h +++ b/libnm-core/nm-connection-private.h @@ -24,10 +24,11 @@ gboolean _nm_connection_verify_required_interface_name (NMConnection *connect GError **error); int _nm_setting_ovs_interface_verify_interface_type (NMSettingOvsInterface *self, + const char *type, NMConnection *connection, gboolean normalize, gboolean *out_modified, - const char **normalized_type, + const char **out_normalized_type, GError **error); #endif /* __NM_CONNECTION_PRIVATE_H__ */ diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index 4146fd55..5f18b651 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -887,6 +887,7 @@ static gboolean _supports_addr_family (NMConnection *self, int family) { const char *connection_type = nm_connection_get_connection_type (self); + NMSettingConnection *s_con; g_return_val_if_fail (connection_type, TRUE); if (strcmp (connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) == 0) @@ -895,6 +896,9 @@ _supports_addr_family (NMConnection *self, int family) return FALSE; if (strcmp (connection_type, NM_SETTING_6LOWPAN_SETTING_NAME) == 0) return family == AF_INET6 || family == AF_UNSPEC; + if ( (s_con = nm_connection_get_setting_connection (self)) + && (nm_streq0 (nm_setting_connection_get_slave_type (s_con), NM_SETTING_VRF_SETTING_NAME))) + return TRUE; return !nm_setting_connection_get_master (nm_connection_get_setting_connection (self)); } @@ -995,7 +999,7 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters) if ( inet_pton (AF_INET6, token, &i6_token) == 1 && _nm_utils_inet6_is_token (&i6_token)) { - nm_utils_inet6_ntop (&i6_token, normalized); + _nm_utils_inet6_ntop (&i6_token, normalized); if (g_strcmp0 (token, normalized)) { g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_TOKEN, normalized, NULL); changed = TRUE; @@ -1232,6 +1236,7 @@ _normalize_ovs_interface_type (NMConnection *self) return FALSE; v = _nm_setting_ovs_interface_verify_interface_type (s_ovs_interface, + nm_setting_ovs_interface_get_interface_type (s_ovs_interface), self, TRUE, &modified, @@ -1400,24 +1405,19 @@ nm_connection_verify (NMConnection *connection, GError **error) NMSettingVerifyResult _nm_connection_verify (NMConnection *connection, GError **error) { - NMConnectionPrivate *priv; - NMSettingConnection *s_con; NMSettingIPConfig *s_ip4, *s_ip6; NMSettingProxy *s_proxy; - GHashTableIter iter; - gpointer value; - GSList *all_settings = NULL, *setting_i; + gs_free NMSetting **settings = NULL; gs_free_error GError *normalizable_error = NULL; NMSettingVerifyResult normalizable_error_type = NM_SETTING_VERIFY_SUCCESS; + guint i; g_return_val_if_fail (NM_IS_CONNECTION (connection), NM_SETTING_VERIFY_ERROR); g_return_val_if_fail (!error || !*error, NM_SETTING_VERIFY_ERROR); - priv = NM_CONNECTION_GET_PRIVATE (connection); - - /* First, make sure there's at least 'connection' setting */ - s_con = nm_connection_get_setting_connection (connection); - if (!s_con) { + settings = nm_connection_get_settings (connection, NULL); + if ( !settings + || !NM_IS_SETTING_CONNECTION (settings[0])) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING, @@ -1426,25 +1426,13 @@ _nm_connection_verify (NMConnection *connection, GError **error) return NM_SETTING_VERIFY_ERROR; } - /* Build up the list of settings */ - g_hash_table_iter_init (&iter, priv->settings); - while (g_hash_table_iter_next (&iter, NULL, &value)) { - /* Order NMSettingConnection so that it will be verified first. - * The reason is, that errors in this setting might be more fundamental - * and should be checked and reported with higher priority. - */ - if (value == s_con) - all_settings = g_slist_append (all_settings, value); - else - all_settings = g_slist_prepend (all_settings, value); - } - all_settings = g_slist_reverse (all_settings); - - /* Now, run the verify function of each setting */ - for (setting_i = all_settings; setting_i; setting_i = setting_i->next) { + for (i = 0; settings[i]; i++) { GError *verify_error = NULL; NMSettingVerifyResult verify_result; + nm_assert (NM_IS_SETTING (settings[i])); + nm_assert (NM_IS_SETTING_CONNECTION (settings[i]) == (i == 0)); + /* verify all settings. We stop if we find the first non-normalizable * @NM_SETTING_VERIFY_ERROR. If we find normalizable errors we continue * but remember the error to return it to the user. @@ -1452,7 +1440,7 @@ _nm_connection_verify (NMConnection *connection, GError **error) * @NM_SETTING_VERIFY_NORMALIZABLE, so, if we encounter such an error type, * we remember it instead (to return it as output). **/ - verify_result = _nm_setting_verify (NM_SETTING (setting_i->data), connection, &verify_error); + verify_result = _nm_setting_verify (settings[i], connection, &verify_error); if (verify_result == NM_SETTING_VERIFY_NORMALIZABLE || verify_result == NM_SETTING_VERIFY_NORMALIZABLE_ERROR) { if ( verify_result == NM_SETTING_VERIFY_NORMALIZABLE_ERROR @@ -1467,13 +1455,11 @@ _nm_connection_verify (NMConnection *connection, GError **error) } } else if (verify_result != NM_SETTING_VERIFY_SUCCESS) { g_propagate_error (error, verify_error); - g_slist_free (all_settings); g_return_val_if_fail (verify_result == NM_SETTING_VERIFY_ERROR, NM_SETTING_VERIFY_ERROR); return NM_SETTING_VERIFY_ERROR; } g_clear_error (&verify_error); } - g_slist_free (all_settings); s_ip4 = nm_connection_get_setting_ip4_config (connection); s_ip6 = nm_connection_get_setting_ip6_config (connection); @@ -1928,7 +1914,7 @@ nm_connection_update_secrets (NMConnection *connection, error); g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection); - g_clear_pointer (&setting_dict, g_variant_unref); + nm_clear_pointer (&setting_dict, g_variant_unref); if (success_detail == NM_SETTING_UPDATE_SECRET_ERROR) { nm_assert (!error || *error); @@ -2262,39 +2248,33 @@ nm_connection_to_dbus_full (NMConnection *connection, NMConnectionSerializationFlags flags, const NMConnectionSerializationOptions *options) { - NMConnectionPrivate *priv; GVariantBuilder builder; - GHashTableIter iter; - gpointer data; - GVariant *setting_dict, *ret; + gboolean any = FALSE; + gs_free NMSetting **settings = NULL; + guint settings_len; + guint i; g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - priv = NM_CONNECTION_GET_PRIVATE (connection); - g_variant_builder_init (&builder, NM_VARIANT_TYPE_CONNECTION); - - /* Add each setting's hash to the main hash */ - - /* FIXME: the order of serialized settings must be stable. */ - - g_hash_table_iter_init (&iter, priv->settings); - while (g_hash_table_iter_next (&iter, NULL, &data)) { - NMSetting *setting = NM_SETTING (data); + settings = nm_connection_get_settings (connection, &settings_len); + for (i = 0; i < settings_len; i++) { + NMSetting *setting = settings[i]; + GVariant *setting_dict; setting_dict = _nm_setting_to_dbus (setting, connection, flags, options); - if (setting_dict) - g_variant_builder_add (&builder, "{s@a{sv}}", nm_setting_get_name (setting), setting_dict); + if (!setting_dict) + continue; + if (!any) { + any = TRUE; + g_variant_builder_init (&builder, NM_VARIANT_TYPE_CONNECTION); + } + g_variant_builder_add (&builder, "{s@a{sv}}", nm_setting_get_name (setting), setting_dict); } - ret = g_variant_builder_end (&builder); - - /* Don't send empty hashes */ - if (g_variant_n_children (ret) == 0) { - g_variant_unref (ret); - ret = NULL; - } + if (!any) + return NULL; - return ret; + return g_variant_builder_end (&builder); } /** @@ -2318,16 +2298,21 @@ nm_connection_is_type (NMConnection *connection, const char *type) } static int -_for_each_sort (NMSetting **p_a, NMSetting **p_b, void *unused) +_get_settings_sort (gconstpointer p_a, gconstpointer p_b, gpointer unused) { - NMSetting *a = *p_a; - NMSetting *b = *p_b; - int c; + NMSetting *a = *((NMSetting **) p_a); + NMSetting *b = *((NMSetting **) p_b); + + nm_assert (NM_IS_SETTING (a)); + nm_assert (NM_IS_SETTING (b)); + nm_assert (a != b); + nm_assert (G_OBJECT_TYPE (a) != G_OBJECT_TYPE (b)); + + NM_CMP_RETURN (_nm_setting_compare_priority (a, b)); + NM_CMP_DIRECT_STRCMP (nm_setting_get_name (a), nm_setting_get_name (b)); - c = _nm_setting_compare_priority (a, b); - if (c != 0) - return c; - return strcmp (nm_setting_get_name (a), nm_setting_get_name (b)); + nm_assert_not_reached (); + return 0; } /** @@ -2350,38 +2335,12 @@ NMSetting ** nm_connection_get_settings (NMConnection *connection, guint *out_length) { - NMConnectionPrivate *priv; - NMSetting **arr; - GHashTableIter iter; - NMSetting *setting; - guint i, size; - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - priv = NM_CONNECTION_GET_PRIVATE (connection); - - size = g_hash_table_size (priv->settings); - - if (!size) { - NM_SET_OUT (out_length, 0); - return NULL; - } - - arr = g_new (NMSetting *, size + 1); - - g_hash_table_iter_init (&iter, priv->settings); - for (i = 0; g_hash_table_iter_next (&iter, NULL, (gpointer *) &setting); i++) - arr[i] = setting; - nm_assert (i == size); - arr[size] = NULL; - - /* sort the settings. This has an effect on the order in which keyfile - * prints them. */ - if (size > 1) - g_qsort_with_data (arr, size, sizeof (NMSetting *), (GCompareDataFunc) _for_each_sort, NULL); - - NM_SET_OUT (out_length, size); - return arr; + return (NMSetting **) nm_utils_hash_values_to_array (NM_CONNECTION_GET_PRIVATE (connection)->settings, + _get_settings_sort, + NULL, + out_length); } /** @@ -2694,6 +2653,7 @@ nm_connection_is_virtual (NMConnection *connection) NM_SETTING_TEAM_SETTING_NAME, NM_SETTING_TUN_SETTING_NAME, NM_SETTING_VLAN_SETTING_NAME, + NM_SETTING_VRF_SETTING_NAME, NM_SETTING_VXLAN_SETTING_NAME, NM_SETTING_WIREGUARD_SETTING_NAME)) return TRUE; diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index b7222df2..ef9e982b 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -61,6 +61,7 @@ #include "nm-setting-tun.h" #include "nm-setting-vlan.h" #include "nm-setting-vpn.h" +#include "nm-setting-vrf.h" #include "nm-setting-vxlan.h" #include "nm-setting-wifi-p2p.h" #include "nm-setting-wimax.h" @@ -94,6 +95,7 @@ #define NM_BR_PORT_DEF_PRIORITY 32 #define NM_BR_PORT_MAX_PATH_COST 65535 +#define NM_BR_PORT_DEF_PATH_COST 100 /* NM_SETTING_COMPARE_FLAG_INFERRABLE: check whether a device-generated * connection can be replaced by a already-defined connection. This flag only @@ -389,15 +391,6 @@ GVariant *_nm_dbus_proxy_call_finish (GDBusProxy *proxy, const GVariantType *reply_type, GError **error); -GVariant *_nm_dbus_proxy_call_sync (GDBusProxy *proxy, - const char *method_name, - GVariant *parameters, - const GVariantType *reply_type, - GDBusCallFlags flags, - int timeout_msec, - GCancellable *cancellable, - GError **error); - GVariant * _nm_dbus_connection_call_finish (GDBusConnection *dbus_connection, GAsyncResult *result, const GVariantType *reply_type, @@ -495,15 +488,15 @@ NMSettingIPConfig *nm_connection_get_setting_ip_config (NMConnection *connection typedef enum { NM_BOND_OPTION_TYPE_INT, - NM_BOND_OPTION_TYPE_STRING, NM_BOND_OPTION_TYPE_BOTH, NM_BOND_OPTION_TYPE_IP, NM_BOND_OPTION_TYPE_MAC, NM_BOND_OPTION_TYPE_IFNAME, } NMBondOptionType; -NMBondOptionType -_nm_setting_bond_get_option_type (NMSettingBond *setting, const char *name); +NMBondOptionType _nm_setting_bond_get_option_type (NMSettingBond *setting, const char *name); + +const char* nm_setting_bond_get_option_or_default (NMSettingBond *self, const char *option); /*****************************************************************************/ @@ -528,14 +521,17 @@ NMConnectionMultiConnect _nm_connection_get_multi_connect (NMConnection *connect /*****************************************************************************/ typedef enum { - NM_BOND_MODE_UNKNOWN = 0, - NM_BOND_MODE_ROUNDROBIN, - NM_BOND_MODE_ACTIVEBACKUP, - NM_BOND_MODE_XOR, - NM_BOND_MODE_BROADCAST, - NM_BOND_MODE_8023AD, - NM_BOND_MODE_TLB, - NM_BOND_MODE_ALB, + NM_BOND_MODE_UNKNOWN = -1, + + /* The numeric values correspond to kernel's numbering of the modes. */ + NM_BOND_MODE_ROUNDROBIN = 0, + NM_BOND_MODE_ACTIVEBACKUP = 1, + NM_BOND_MODE_XOR = 2, + NM_BOND_MODE_BROADCAST = 3, + NM_BOND_MODE_8023AD = 4, + NM_BOND_MODE_TLB = 5, + NM_BOND_MODE_ALB = 6, + _NM_BOND_MODE_NUM, } NMBondMode; NMBondMode _nm_setting_bond_mode_from_string (const char *str); @@ -545,34 +541,6 @@ gboolean _nm_setting_bond_option_supported (const char *option, NMBondMode mode) NMSettingBluetooth *_nm_connection_get_setting_bluetooth_for_nap (NMConnection *connection); -/*****************************************************************************/ - -const char *nm_utils_inet_ntop (int addr_family, gconstpointer addr, char *dst); - -static inline char * -nm_utils_inet4_ntop_dup (in_addr_t addr) -{ - char buf[NM_UTILS_INET_ADDRSTRLEN]; - - return g_strdup (nm_utils_inet4_ntop (addr, buf)); -} - -static inline char * -nm_utils_inet6_ntop_dup (const struct in6_addr *addr) -{ - char buf[NM_UTILS_INET_ADDRSTRLEN]; - - return g_strdup (nm_utils_inet6_ntop (addr, buf)); -} - -static inline char * -nm_utils_inet_ntop_dup (int addr_family, gconstpointer addr) -{ - char buf[NM_UTILS_INET_ADDRSTRLEN]; - - return g_strdup (nm_utils_inet_ntop (addr_family, addr, buf)); -} - gboolean _nm_utils_inet6_is_token (const struct in6_addr *in6addr); /*****************************************************************************/ diff --git a/libnm-core/nm-core-types.h b/libnm-core/nm-core-types.h index d7c1b5b5..d1ce6310 100644 --- a/libnm-core/nm-core-types.h +++ b/libnm-core/nm-core-types.h @@ -54,6 +54,7 @@ typedef struct _NMSettingTun NMSettingTun; typedef struct _NMSettingUser NMSettingUser; typedef struct _NMSettingVlan NMSettingVlan; typedef struct _NMSettingVpn NMSettingVpn; +typedef struct _NMSettingVrf NMSettingVrf; typedef struct _NMSettingVxlan NMSettingVxlan; typedef struct _NMSettingWifiP2P NMSettingWifiP2P; typedef struct _NMSettingWimax NMSettingWimax; diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index 1cf1c888..28ee89bf 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -52,6 +52,7 @@ #define NM_DBUS_INTERFACE_DEVICE_TUN NM_DBUS_INTERFACE_DEVICE ".Tun" #define NM_DBUS_INTERFACE_DEVICE_VETH NM_DBUS_INTERFACE_DEVICE ".Veth" #define NM_DBUS_INTERFACE_DEVICE_VLAN NM_DBUS_INTERFACE_DEVICE ".Vlan" +#define NM_DBUS_INTERFACE_DEVICE_VRF NM_DBUS_INTERFACE_DEVICE ".Vrf" #define NM_DBUS_INTERFACE_DEVICE_VXLAN NM_DBUS_INTERFACE_DEVICE ".Vxlan" #define NM_DBUS_INTERFACE_DEVICE_WIFI_P2P NM_DBUS_INTERFACE_DEVICE ".WifiP2P" #define NM_DBUS_INTERFACE_DEVICE_WIMAX NM_DBUS_INTERFACE_DEVICE ".WiMax" @@ -92,7 +93,7 @@ * @NM_CAPABILITY_TEAM: Teams can be managed. This means the team device plugin * is loaded. * @NM_CAPABILITY_OVS: OpenVSwitch can be managed. This means the OVS device plugin - * is loaded. Since: 1.24, 1.22.2 + * is loaded. Since: 1.24 * * #NMCapability names the numbers in the Capabilities property. * Capabilities are positive numbers. They are part of stable API @@ -213,6 +214,7 @@ typedef enum { * @NM_DEVICE_TYPE_6LOWPAN: 6LoWPAN interface * @NM_DEVICE_TYPE_WIREGUARD: a WireGuard interface * @NM_DEVICE_TYPE_WIFI_P2P: an 802.11 Wi-Fi P2P device (Since: 1.16) + * @NM_DEVICE_TYPE_VRF: A VRF (Virtual Routing and Forwarding) interface (Since: 1.24) * * #NMDeviceType values indicate the type of hardware represented by a * device object. @@ -249,6 +251,7 @@ typedef enum { NM_DEVICE_TYPE_6LOWPAN = 28, NM_DEVICE_TYPE_WIREGUARD = 29, NM_DEVICE_TYPE_WIFI_P2P = 30, + NM_DEVICE_TYPE_VRF = 31, } NMDeviceType; /** @@ -346,6 +349,8 @@ typedef enum { /*< underscore_name=nm_802_11_ap_flags, flags >*/ * is supported * @NM_802_11_AP_SEC_KEY_MGMT_SAE: WPA/RSN Simultaneous Authentication of Equals is * supported + * @NM_802_11_AP_SEC_KEY_MGMT_OWE: WPA/RSN Opportunistic Wireless Encryption is + * supported * * 802.11 access point security and authentication flags. These flags describe * the current security requirements of an access point as determined from the @@ -364,6 +369,7 @@ typedef enum { /*< underscore_name=nm_802_11_ap_security_flags, flags >*/ NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100, NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200, NM_802_11_AP_SEC_KEY_MGMT_SAE = 0x00000400, + NM_802_11_AP_SEC_KEY_MGMT_OWE = 0x00000800, } NM80211ApSecurityFlags; /** @@ -1178,4 +1184,85 @@ typedef enum { /*< flags >*/ NM_DEVICE_INTERFACE_FLAG_CARRIER = 0x10000, } NMDeviceInterfaceFlags; +/** + * NMClientPermission: + * @NM_CLIENT_PERMISSION_NONE: unknown or no permission + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK: controls whether networking + * can be globally enabled or disabled + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI: controls whether Wi-Fi can be + * globally enabled or disabled + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN: controls whether WWAN (3G) can be + * globally enabled or disabled + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX: controls whether WiMAX can be + * globally enabled or disabled + * @NM_CLIENT_PERMISSION_SLEEP_WAKE: controls whether the client can ask + * NetworkManager to sleep and wake + * @NM_CLIENT_PERMISSION_NETWORK_CONTROL: controls whether networking connections + * can be started, stopped, and changed + * @NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED: controls whether a password + * protected Wi-Fi hotspot can be created + * @NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN: controls whether an open Wi-Fi hotspot + * can be created + * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM: controls whether connections + * that are available to all users can be modified + * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN: controls whether connections + * owned by the current user can be modified + * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME: controls whether the + * persistent hostname can be changed + * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS: modify persistent global + * DNS configuration + * @NM_CLIENT_PERMISSION_RELOAD: controls access to Reload. + * @NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK: permission to create checkpoints. + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS: controls whether device + * statistics can be globally enabled or disabled + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK: controls whether + * connectivity check can be enabled or disabled + * @NM_CLIENT_PERMISSION_WIFI_SCAN: controls whether wifi scans can be performed + * @NM_CLIENT_PERMISSION_LAST: a reserved boundary value + * + * #NMClientPermission values indicate various permissions that NetworkManager + * clients can obtain to perform certain tasks on behalf of the current user. + **/ +typedef enum { + NM_CLIENT_PERMISSION_NONE = 0, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK = 1, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI = 2, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN = 3, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX = 4, + NM_CLIENT_PERMISSION_SLEEP_WAKE = 5, + NM_CLIENT_PERMISSION_NETWORK_CONTROL = 6, + NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED = 7, + NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN = 8, + NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM = 9, + NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN = 10, + NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME = 11, + NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS = 12, + NM_CLIENT_PERMISSION_RELOAD = 13, + NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK = 14, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS = 15, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK = 16, + NM_CLIENT_PERMISSION_WIFI_SCAN = 17, + + NM_CLIENT_PERMISSION_LAST = 17, +} NMClientPermission; + +/** + * NMClientPermissionResult: + * @NM_CLIENT_PERMISSION_RESULT_UNKNOWN: unknown or no authorization + * @NM_CLIENT_PERMISSION_RESULT_YES: the permission is available + * @NM_CLIENT_PERMISSION_RESULT_AUTH: authorization is necessary before the + * permission is available + * @NM_CLIENT_PERMISSION_RESULT_NO: permission to perform the operation is + * denied by system policy + * + * #NMClientPermissionResult values indicate what authorizations and permissions + * the user requires to obtain a given #NMClientPermission + **/ +typedef enum { + NM_CLIENT_PERMISSION_RESULT_UNKNOWN = 0, + NM_CLIENT_PERMISSION_RESULT_YES, + NM_CLIENT_PERMISSION_RESULT_AUTH, + NM_CLIENT_PERMISSION_RESULT_NO +} NMClientPermissionResult; + #endif /* __NM_DBUS_INTERFACE_H__ */ diff --git a/libnm-core/nm-dbus-types.xml b/libnm-core/nm-dbus-types.xml index ad547361..0a5501ae 100644 --- a/libnm-core/nm-dbus-types.xml +++ b/libnm-core/nm-dbus-types.xml @@ -35,7 +35,7 @@ <row role="constant"> <entry role="enum_member_name"><para>NM_CAPABILITY_OVS</para><para></para></entry> <entry role="enum_member_value"><para>= <literal>2</literal></para><para></para></entry> - <entry role="enum_member_description"><para>OpenVSwitch can be managed. This means the OVS device plugin is loaded. Since: 1.24, 1.22.2</para><para></para></entry> + <entry role="enum_member_description"><para>OpenVSwitch can be managed. This means the OVS device plugin is loaded. Since: 1.24</para><para></para></entry> </row> </tbody> </tgroup> @@ -317,6 +317,11 @@ <entry role="enum_member_value"><para>= <literal>30</literal></para><para></para></entry> <entry role="enum_member_description"><para>an 802.11 Wi-Fi P2P device (Since: 1.16)</para><para></para></entry> </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_DEVICE_TYPE_VRF</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>31</literal></para><para></para></entry> + <entry role="enum_member_description"><para>A VRF (Virtual Routing and Forwarding) interface (Since: 1.24)</para><para></para></entry> + </row> </tbody> </tgroup> </informaltable> @@ -577,6 +582,11 @@ <entry role="enum_member_value"><para>= <literal>0x00000400</literal></para><para></para></entry> <entry role="enum_member_description"><para>WPA/RSN Simultaneous Authentication of Equals is supported</para><para></para></entry> </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_802_11_AP_SEC_KEY_MGMT_OWE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>0x00000800</literal></para><para></para></entry> + <entry role="enum_member_description"><para>WPA/RSN Opportunistic Wireless Encryption is supported</para><para></para></entry> + </row> </tbody> </tgroup> </informaltable> @@ -1988,4 +1998,154 @@ </refsect3> </refsect2> + <refsect2 id="NMClientPermission" role="enum"> + <title>enum NMClientPermission</title> + <indexterm zone="NMClientPermission"> + <primary>NMClientPermission</primary> + </indexterm> + <para><para><link linkend="NMClientPermission">NMClientPermission</link> values indicate various permissions that NetworkManager clients can obtain to perform certain tasks on behalf of the current user.</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_CLIENT_PERMISSION_NONE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>0</literal></para><para></para></entry> + <entry role="enum_member_description"><para>unknown or no permission</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>1</literal></para><para></para></entry> + <entry role="enum_member_description"><para>controls whether networking can be globally enabled or disabled</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>2</literal></para><para></para></entry> + <entry role="enum_member_description"><para>controls whether Wi-Fi can be globally enabled or disabled</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>3</literal></para><para></para></entry> + <entry role="enum_member_description"><para>controls whether WWAN (3G) can be globally enabled or disabled</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>4</literal></para><para></para></entry> + <entry role="enum_member_description"><para>controls whether WiMAX can be globally enabled or disabled</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_SLEEP_WAKE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>5</literal></para><para></para></entry> + <entry role="enum_member_description"><para>controls whether the client can ask NetworkManager to sleep and wake</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_NETWORK_CONTROL</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>6</literal></para><para></para></entry> + <entry role="enum_member_description"><para>controls whether networking connections can be started, stopped, and changed</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>7</literal></para><para></para></entry> + <entry role="enum_member_description"><para>controls whether a password protected Wi-Fi hotspot can be created</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>8</literal></para><para></para></entry> + <entry role="enum_member_description"><para>controls whether an open Wi-Fi hotspot can be created</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>9</literal></para><para></para></entry> + <entry role="enum_member_description"><para>controls whether connections that are available to all users can be modified</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>10</literal></para><para></para></entry> + <entry role="enum_member_description"><para>controls whether connections owned by the current user can be modified</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>11</literal></para><para></para></entry> + <entry role="enum_member_description"><para>controls whether the persistent hostname can be changed</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>12</literal></para><para></para></entry> + <entry role="enum_member_description"><para>modify persistent global DNS configuration</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_RELOAD</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>13</literal></para><para></para></entry> + <entry role="enum_member_description"><para>controls access to Reload.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>14</literal></para><para></para></entry> + <entry role="enum_member_description"><para>permission to create checkpoints.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>15</literal></para><para></para></entry> + <entry role="enum_member_description"><para>controls whether device statistics can be globally enabled or disabled</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>16</literal></para><para></para></entry> + <entry role="enum_member_description"><para>controls whether connectivity check can be enabled or disabled</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_WIFI_SCAN</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>17</literal></para><para></para></entry> + <entry role="enum_member_description"><para>controls whether wifi scans can be performed</para><para></para></entry> + </row> + </tbody> + </tgroup> + </informaltable> + </refsect3> + </refsect2> + + <refsect2 id="NMClientPermissionResult" role="enum"> + <title>enum NMClientPermissionResult</title> + <indexterm zone="NMClientPermissionResult"> + <primary>NMClientPermissionResult</primary> + </indexterm> + <para><para><link linkend="NMClientPermissionResult">NMClientPermissionResult</link> values indicate what authorizations and permissions the user requires to obtain a given <link linkend="NMClientPermission">NMClientPermission</link></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_CLIENT_PERMISSION_RESULT_UNKNOWN</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>0</literal></para><para></para></entry> + <entry role="enum_member_description"><para>unknown or no authorization</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_RESULT_YES</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>1</literal></para><para></para></entry> + <entry role="enum_member_description"><para>the permission is available</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_RESULT_AUTH</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>2</literal></para><para></para></entry> + <entry role="enum_member_description"><para>authorization is necessary before the permission is available</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CLIENT_PERMISSION_RESULT_NO</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>3</literal></para><para></para></entry> + <entry role="enum_member_description"><para>permission to perform the operation is denied by system policy</para><para></para></entry> + </row> + </tbody> + </tgroup> + </informaltable> + </refsect3> + </refsect2> + </refentry> diff --git a/libnm-core/nm-dbus-utils.c b/libnm-core/nm-dbus-utils.c index 83092948..72b9fe1f 100644 --- a/libnm-core/nm-dbus-utils.c +++ b/libnm-core/nm-dbus-utils.c @@ -221,52 +221,6 @@ _nm_dbus_proxy_call_finish (GDBusProxy *proxy, return variant; } -/** - * _nm_dbus_proxy_call_sync: - * @proxy: A #GDBusProxy. - * @method_name: Name of method to invoke. - * @parameters: (allow-none): A #GVariant tuple with parameters for the signal - * or %NULL if not passing parameters. - * @reply_type: (allow-none): the expected type of the reply, or %NULL - * @flags: Flags from the #GDBusCallFlags enumeration. - * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning - * "infinite") or -1 to use the proxy default timeout. - * @cancellable: (allow-none): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the @method_name method on @proxy, as with - * g_dbus_proxy_call_sync(), except that if @reply_type is non-%NULL, then the - * reply to the call will be checked against it, and an error returned if it - * does not match. - * - * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with - * return values. Free with g_variant_unref(). - */ -GVariant * -_nm_dbus_proxy_call_sync (GDBusProxy *proxy, - const char *method_name, - GVariant *parameters, - const GVariantType *reply_type, - GDBusCallFlags flags, - int timeout_msec, - GCancellable *cancellable, - GError **error) -{ - GVariant *variant; - - variant = g_dbus_proxy_call_sync (proxy, - method_name, - parameters, - flags, - timeout_msec, - cancellable, - error); - if ( variant - && !_nm_dbus_typecheck_response (variant, reply_type, error)) - nm_clear_pointer (&variant, g_variant_unref); - return variant; -} - GVariant * _nm_dbus_connection_call_finish (GDBusConnection *dbus_connection, GAsyncResult *result, diff --git a/libnm-core/nm-errors.h b/libnm-core/nm-errors.h index 0b54133d..031cc670 100644 --- a/libnm-core/nm-errors.h +++ b/libnm-core/nm-errors.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: LGPL-2.1+ /* * Copyright (C) 2004 - 2014 Red Hat, Inc. */ diff --git a/libnm-core/nm-keyfile-internal.h b/libnm-core/nm-keyfile-internal.h deleted file mode 100644 index 42003a5f..00000000 --- a/libnm-core/nm-keyfile-internal.h +++ /dev/null @@ -1,180 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2008 Novell, Inc. - * Copyright (C) 2015 Red Hat, Inc. - */ - -#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" -#include "nm-setting-8021x.h" - -#include "nm-core-internal.h" -#include "nm-meta-setting.h" - -/*****************************************************************************/ - -#define NM_KEYFILE_CERT_SCHEME_PREFIX_PATH "file://" -#define NM_KEYFILE_CERT_SCHEME_PREFIX_PKCS11 "pkcs11:" -#define NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB "data:;base64," - -char *nm_keyfile_detect_unqualified_path_scheme (const char *base_dir, - gconstpointer pdata, - gsize data_len, - gboolean consider_exists, - gboolean *out_exists); - -typedef enum { - NM_KEYFILE_READ_TYPE_WARN = 1, -} NMKeyfileReadType; - -/** - * NMKeyfileReadHandler: - * - * Hook to nm_keyfile_read(). The user might fail the reading by setting - * @error. - * - * Returns: should return TRUE, if the reading was handled. Otherwise, - * a default action will be performed that depends on the @type. - * For %NM_KEYFILE_READ_TYPE_WARN type, the default action is doing nothing. - */ -typedef gboolean (*NMKeyfileReadHandler) (GKeyFile *keyfile, - NMConnection *connection, - NMKeyfileReadType type, - void *type_data, - void *user_data, - GError **error); - -typedef enum { - NM_KEYFILE_WARN_SEVERITY_DEBUG = 1000, - NM_KEYFILE_WARN_SEVERITY_INFO = 2000, - NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE = 2901, - NM_KEYFILE_WARN_SEVERITY_WARN = 3000, -} NMKeyfileWarnSeverity; - -/** - * NMKeyfileReadTypeDataWarn: - * - * this struct is passed as @type_data for the @NMKeyfileReadHandler of - * type %NM_KEYFILE_READ_TYPE_WARN. - */ -typedef struct { - /* might be %NULL, if the warning is not about a group. */ - const char *group; - - /* might be %NULL, if the warning is not about a setting. */ - NMSetting *setting; - - /* might be %NULL, if the warning is not about a property. */ - const char *property_name; - - NMKeyfileWarnSeverity severity; - const char *message; -} NMKeyfileReadTypeDataWarn; - -NMConnection *nm_keyfile_read (GKeyFile *keyfile, - const char *base_dir, - NMKeyfileReadHandler handler, - void *user_data, - GError **error); - -gboolean nm_keyfile_read_ensure_id (NMConnection *connection, - const char *fallback_id); - -gboolean nm_keyfile_read_ensure_uuid (NMConnection *connection, - const char *fallback_uuid_seed); - -/*****************************************************************************/ - -typedef enum { - NM_KEYFILE_WRITE_TYPE_CERT = 1, -} NMKeyfileWriteType; - -/** - * NMKeyfileWriteHandler: - * - * This is a hook to tweak the serialization. - * - * Handler for certain properties or events that are not entirely contained - * within the keyfile or that might be serialized differently. The @type and - * @type_data arguments tell which kind of argument we have at hand. - * - * Currently only the type %NM_KEYFILE_WRITE_TYPE_CERT is supported, which provides - * @type_data as %NMKeyfileWriteTypeDataCert. However, this handler should be generic enough - * to support other types as well. - * - * This don't have to be only "properties". For example, nm_keyfile_read() uses - * a similar handler to push warnings to the caller. - * - * If the handler raises an error, it should set the @error value. This causes - * the an overall failure. - * - * Returns: whether the issue was handled. If the type was unhandled, - * a default action will be performed. This might be raise an error, - * do some fallback parsing, or do nothing. - */ -typedef gboolean (*NMKeyfileWriteHandler) (NMConnection *connection, - GKeyFile *keyfile, - NMKeyfileWriteType type, - void *type_data, - void *user_data, - GError **error); - -/** - * NMKeyfileWriteTypeDataCert: - * - * this struct is passed as @type_data for the @NMKeyfileWriteHandler of - * type %NM_KEYFILE_WRITE_TYPE_CERT. - */ -typedef struct { - const NMSetting8021xSchemeVtable *vtable; - NMSetting8021x *setting; -} NMKeyfileWriteTypeDataCert; - -GKeyFile *nm_keyfile_write (NMConnection *connection, - NMKeyfileWriteHandler handler, - void *user_data, - GError **error); - -/*****************************************************************************/ - -char *nm_keyfile_plugin_kf_get_string (GKeyFile *kf, const char *group, const char *key, GError **error); -void nm_keyfile_plugin_kf_set_string (GKeyFile *kf, const char *group, const char *key, const char *value); - -int nm_key_file_get_boolean (GKeyFile *kf, const char *group, const char *key, int default_value); - -void _nm_keyfile_copy (GKeyFile *dst, GKeyFile *src); -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); - -/*****************************************************************************/ - -#define NM_KEYFILE_GROUP_NMMETA ".nmmeta" -#define NM_KEYFILE_KEY_NMMETA_NM_GENERATED "nm-generated" -#define NM_KEYFILE_KEY_NMMETA_VOLATILE "volatile" -#define NM_KEYFILE_KEY_NMMETA_SHADOWED_STORAGE "shadowed-storage" -#define NM_KEYFILE_KEY_NMMETA_SHADOWED_OWNED "shadowed-owned" - -#define NM_KEYFILE_PATH_NAME_LIB NMLIBDIR "/system-connections" -#define NM_KEYFILE_PATH_NAME_ETC_DEFAULT NMCONFDIR "/system-connections" -#define NM_KEYFILE_PATH_NAME_RUN NMRUNDIR "/system-connections" - -#define NM_KEYFILE_PATH_SUFFIX_NMCONNECTION ".nmconnection" - -#define NM_KEYFILE_PATH_SUFFIX_NMMETA ".nmmeta" - -#define NM_KEYFILE_PATH_NMMETA_SYMLINK_NULL "/dev/null" - -gboolean nm_keyfile_utils_ignore_filename (const char *filename, gboolean require_extension); - -char *nm_keyfile_utils_create_filename (const char *filename, gboolean with_extension); - -#endif /* __NM_KEYFILE_INTERNAL_H__ */ diff --git a/libnm-core/nm-keyfile-utils.c b/libnm-core/nm-keyfile-utils.c deleted file mode 100644 index e18db20d..00000000 --- a/libnm-core/nm-keyfile-utils.c +++ /dev/null @@ -1,636 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2010 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-keyfile-utils.h" - -#include <stdlib.h> - -#include "nm-keyfile-internal.h" -#include "nm-setting-wired.h" -#include "nm-setting-wireless.h" -#include "nm-setting-wireless-security.h" - -/*****************************************************************************/ - -/** - * nm_key_file_get_boolean: - * @kf: the #GKeyFile - * @group: the group - * @key: the key - * @default_value: the default value if the value is set or not parsable as a boolean. - * - * Replacement for g_key_file_get_boolean() (which uses g_key_file_parse_value_as_boolean()). - * g_key_file_get_boolean() seems odd to me, because it accepts trailing ASCII whitespace, - * but not leading. - * This uses _nm_utils_ascii_str_to_bool(), which accepts trailing and leading whitespace, - * case-insensitive words, and also strings like "on" and "off". - * _nm_utils_ascii_str_to_bool() is our way to parse booleans from string, and we should - * use that one consistently. - * - * Also, it doesn't have g_key_file_get_boolean()'s odd API to require an error argument - * to detect parsing failures. - * - * Returns: either %TRUE or %FALSE if the key exists and is parsable as a boolean. - * Otherwise, @default_value. Sets errno to ENODATA, EINVAL or 0, depending on whether - * the key exists, whether the value is invalid, or success. - */ -int -nm_key_file_get_boolean (GKeyFile *kf, const char *group, const char *key, int default_value) -{ - int v; - gs_free char *value = NULL; - - value = g_key_file_get_value (kf, group, key, NULL); - - if (!value) { - errno = ENODATA; - return default_value; - } - v = _nm_utils_ascii_str_to_bool (value, -1); - if (v != -1) { - errno = 0; - return v; - } - errno = EINVAL; - return default_value; -} - -/*****************************************************************************/ - -typedef struct { - const char *setting; - const char *alias; -} SettingAlias; - -static const SettingAlias alias_list[] = { - { NM_SETTING_WIRED_SETTING_NAME, "ethernet" }, - { NM_SETTING_WIRELESS_SETTING_NAME, "wifi" }, - { NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, "wifi-security" }, -}; - -const char * -nm_keyfile_plugin_get_alias_for_setting_name (const char *setting_name) -{ - guint i; - - g_return_val_if_fail (setting_name != NULL, NULL); - - for (i = 0; i < G_N_ELEMENTS (alias_list); i++) { - if (nm_streq (setting_name, alias_list[i].setting)) - return alias_list[i].alias; - } - return NULL; -} - -const char * -nm_keyfile_plugin_get_setting_name_for_alias (const char *alias) -{ - guint i; - - g_return_val_if_fail (alias != NULL, NULL); - - for (i = 0; i < G_N_ELEMENTS (alias_list); i++) { - if (nm_streq (alias, alias_list[i].alias)) - return alias_list[i].setting; - } - return NULL; -} - -/*****************************************************************************/ - -/* List helpers */ -#define DEFINE_KF_LIST_WRAPPER(stype, get_ctype, set_ctype) \ -get_ctype \ -nm_keyfile_plugin_kf_get_##stype##_list (GKeyFile *kf, \ - const char *group, \ - const char *key, \ - gsize *out_length, \ - GError **error) \ -{ \ - get_ctype list; \ - const char *alias; \ - GError *local = NULL; \ - gsize l; \ - \ - list = g_key_file_get_##stype##_list (kf, group, key, &l, &local); \ - if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { \ - alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \ - if (alias) { \ - g_clear_error (&local); \ - list = g_key_file_get_##stype##_list (kf, alias, key, &l, &local); \ - } \ - } \ - nm_assert ((!local) != (!list)); \ - if (local) \ - g_propagate_error (error, local); \ - if (!list) \ - l = 0; \ - NM_SET_OUT (out_length, l); \ - return list; \ -} \ - \ -void \ -nm_keyfile_plugin_kf_set_##stype##_list (GKeyFile *kf, \ - const char *group, \ - const char *key, \ - set_ctype list[], \ - gsize length) \ -{ \ - const char *alias; \ - \ - alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \ - g_key_file_set_##stype##_list (kf, alias ?: group, key, list, length); \ -} - -DEFINE_KF_LIST_WRAPPER(integer, int*, int); -DEFINE_KF_LIST_WRAPPER(string, char **, const char* const); - -void -nm_keyfile_plugin_kf_set_integer_list_uint8 (GKeyFile *kf, - const char *group, - const char *key, - const guint8 *data, - gsize length) -{ - gsize i; - gsize l = length * 4 + 2; - gs_free char *value = g_malloc (l); - char *s = value; - - g_return_if_fail (kf); - g_return_if_fail (!length || data); - g_return_if_fail (group && group[0]); - g_return_if_fail (key && key[0]); - - value[0] = '\0'; - for (i = 0; i < length; i++) - nm_utils_strbuf_append (&s, &l, "%d;", (int) data[i]); - nm_assert (l > 0); - nm_keyfile_plugin_kf_set_value (kf, group, key, value); -} - -/* Single value helpers */ -#define DEFINE_KF_WRAPPER(stype, get_ctype, set_ctype) \ -get_ctype \ -nm_keyfile_plugin_kf_get_##stype (GKeyFile *kf, \ - const char *group, \ - const char *key, \ - GError **error) \ -{ \ - get_ctype val; \ - const char *alias; \ - GError *local = NULL; \ - \ - val = g_key_file_get_##stype (kf, group, key, &local); \ - if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { \ - alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \ - if (alias) { \ - g_clear_error (&local); \ - val = g_key_file_get_##stype (kf, alias, key, &local); \ - } \ - } \ - if (local) \ - g_propagate_error (error, local); \ - return val; \ -} \ - \ -void \ -nm_keyfile_plugin_kf_set_##stype (GKeyFile *kf, \ - const char *group, \ - const char *key, \ - set_ctype value) \ -{ \ - const char *alias; \ - \ - alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \ - g_key_file_set_##stype (kf, alias ?: group, key, value); \ -} - -DEFINE_KF_WRAPPER(string, char*, const char*); -DEFINE_KF_WRAPPER(boolean, gboolean, gboolean); -DEFINE_KF_WRAPPER(value, char*, const char*); - -gint64 -nm_keyfile_plugin_kf_get_int64 (GKeyFile *kf, - const char *group, - const char *key, - guint base, - gint64 min, - gint64 max, - gint64 fallback, - GError **error) -{ - gs_free char *s = NULL; - int errsv; - gint64 v; - - s = nm_keyfile_plugin_kf_get_value (kf, group, key, error); - if (!s) { - errno = ENODATA; - return fallback; - } - - v = _nm_utils_ascii_str_to_int64 (s, base, min, max, fallback); - errsv = errno; - if ( errsv != 0 - && error) { - g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE, - _("value is not an integer in range [%lld, %lld]"), - (long long) min, (long long) max); - errno = errsv; - } - return v; -} - -char ** -nm_keyfile_plugin_kf_get_keys (GKeyFile *kf, - const char *group, - gsize *out_length, - GError **error) -{ - char **keys; - const char *alias; - GError *local = NULL; - gsize l; - - keys = g_key_file_get_keys (kf, group, &l, &local); - if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { - alias = nm_keyfile_plugin_get_alias_for_setting_name (group); - if (alias) { - g_clear_error (&local); - keys = g_key_file_get_keys (kf, alias, &l, error ? &local : NULL); - } - } - nm_assert ((!local) != (!keys)); - if (!keys) - l = 0; - nm_assert (l == NM_PTRARRAY_LEN (keys)); - NM_SET_OUT (out_length, l); - if (local) - g_propagate_error (error, local); - return keys; -} - -gboolean -nm_keyfile_plugin_kf_has_key (GKeyFile *kf, - const char *group, - const char *key, - GError **error) -{ - gboolean has; - const char *alias; - GError *local = NULL; - - has = g_key_file_has_key (kf, group, key, &local); - if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { - alias = nm_keyfile_plugin_get_alias_for_setting_name (group); - if (alias) { - g_clear_error (&local); - has = g_key_file_has_key (kf, alias, key, &local); - } - } - if (local) - g_propagate_error (error, local); - return has; -} - -/*****************************************************************************/ - -void -_nm_keyfile_copy (GKeyFile *dst, GKeyFile *src) -{ - gs_strfreev char **groups = NULL; - guint g, k; - - groups = g_key_file_get_groups (src, NULL); - for (g = 0; groups && groups[g]; g++) { - const char *group = groups[g]; - gs_strfreev char **keys = NULL; - - keys = g_key_file_get_keys (src, group, NULL, NULL); - if (!keys) - continue; - - for (k = 0; keys[k]; k++) { - const char *key = keys[k]; - gs_free char *value = NULL; - - value = g_key_file_get_value (src, group, key, NULL); - if (value) - g_key_file_set_value (dst, group, key, value); - else - g_key_file_remove_key (dst, group, key, NULL); - } - } -} - -/*****************************************************************************/ - -gboolean -_nm_keyfile_a_contains_all_in_b (GKeyFile *kf_a, GKeyFile *kf_b) -{ - gs_strfreev char **groups = NULL; - guint i, j; - - if (kf_a == kf_b) - return TRUE; - if (!kf_a || !kf_b) - return FALSE; - - groups = g_key_file_get_groups (kf_a, NULL); - for (i = 0; groups && groups[i]; i++) { - gs_strfreev char **keys = NULL; - - keys = g_key_file_get_keys (kf_a, groups[i], NULL, NULL); - if (!keys) - continue; - - for (j = 0; keys[j]; j++) { - gs_free char *key_a = g_key_file_get_value (kf_a, groups[i], keys[j], NULL); - gs_free char *key_b = g_key_file_get_value (kf_b, groups[i], keys[j], NULL); - - if (g_strcmp0 (key_a, key_b) != 0) - return FALSE; - } - } - return TRUE; -} - -static gboolean -_nm_keyfile_equals_ordered (GKeyFile *kf_a, GKeyFile *kf_b) -{ - gs_strfreev char **groups = NULL; - gs_strfreev char **groups_b = NULL; - guint i, j; - - if (kf_a == kf_b) - return TRUE; - if (!kf_a || !kf_b) - return FALSE; - - groups = g_key_file_get_groups (kf_a, NULL); - groups_b = g_key_file_get_groups (kf_b, NULL); - if (!groups && !groups_b) - return TRUE; - if (!groups || !groups_b) - return FALSE; - for (i = 0; groups[i] && groups_b[i] && !strcmp (groups[i], groups_b[i]); i++) - ; - if (groups[i] || groups_b[i]) - return FALSE; - - for (i = 0; groups[i]; i++) { - gs_strfreev char **keys = NULL; - gs_strfreev char **keys_b = NULL; - - keys = g_key_file_get_keys (kf_a, groups[i], NULL, NULL); - keys_b = g_key_file_get_keys (kf_b, groups[i], NULL, NULL); - - if ((!keys) != (!keys_b)) - return FALSE; - if (!keys) - continue; - - for (j = 0; keys[j] && keys_b[j] && !strcmp (keys[j], keys_b[j]); j++) - ; - if (keys[j] || keys_b[j]) - return FALSE; - - for (j = 0; keys[j]; j++) { - gs_free char *key_a = g_key_file_get_value (kf_a, groups[i], keys[j], NULL); - gs_free char *key_b = g_key_file_get_value (kf_b, groups[i], keys[j], NULL); - - if (g_strcmp0 (key_a, key_b) != 0) - return FALSE; - } - } - return TRUE; -} - -gboolean -_nm_keyfile_equals (GKeyFile *kf_a, GKeyFile *kf_b, gboolean consider_order) -{ - if (!consider_order) { - return _nm_keyfile_a_contains_all_in_b (kf_a, kf_b) - && _nm_keyfile_a_contains_all_in_b (kf_b, kf_a); - } else { - return _nm_keyfile_equals_ordered (kf_a, kf_b); - } -} - -gboolean -_nm_keyfile_has_values (GKeyFile *keyfile) -{ - gs_strfreev char **groups = NULL; - - g_return_val_if_fail (keyfile, FALSE); - - groups = g_key_file_get_groups (keyfile, NULL); - return groups && groups[0]; -} - -/*****************************************************************************/ - -static const char * -_keyfile_key_encode (const char *name, - char **out_to_free) -{ - gsize len, i; - GString *str; - - nm_assert (name); - nm_assert (out_to_free && !*out_to_free); - - /* See g_key_file_is_key_name(). - * - * GKeyFile allows all UTF-8 characters (even non-well formed sequences), - * except: - * - no empty keys - * - no leading/trailing ' ' - * - no '=', '[', ']' - * - * We do something more strict here. All non-ASCII characters, all non-printable - * characters, and all invalid characters are escaped with "\\XX". - * - * We don't escape \\, unless it is followed by two hex digits. - */ - - if (!name[0]) { - /* empty keys are are backslash encoded. Note that usually - * \\00 is not a valid encode, the only exception is the empty - * word. */ - return "\\00"; - } - - /* find the first character that needs escaping. */ - i = 0; - if (name[0] != ' ') { - for (;; i++) { - const guchar ch = (guchar) name[i]; - - if (ch == '\0') - return name; - - if ( ch < 0x20 - || ch >= 127 - || NM_IN_SET (ch, '=', '[', ']') - || ( ch == '\\' - && g_ascii_isxdigit (name[i + 1]) - && g_ascii_isxdigit (name[i + 2])) - || ( ch == ' ' - && name[i + 1] == '\0')) - break; - } - } else if (name[1] == '\0') - return "\\20"; - - len = i + strlen (&name[i]); - nm_assert (len == strlen (name)); - str = g_string_sized_new (len + 15); - - if (name[0] == ' ') { - nm_assert (i == 0); - g_string_append (str, "\\20"); - i = 1; - } else - g_string_append_len (str, name, i); - - for (;; i++) { - const guchar ch = (guchar) name[i]; - - if (ch == '\0') - break; - - if ( ch < 0x20 - || ch >= 127 - || NM_IN_SET (ch, '=', '[', ']') - || ( ch == '\\' - && g_ascii_isxdigit (name[i + 1]) - && g_ascii_isxdigit (name[i + 2])) - || ( ch == ' ' - && name[i + 1] == '\0')) - g_string_append_printf (str, "\\%02X", ch); - else - g_string_append_c (str, (char) ch); - } - - return (*out_to_free = g_string_free (str, FALSE)); -} - -static const char * -_keyfile_key_decode (const char *key, - char **out_to_free) -{ - gsize i, len; - GString *str; - - nm_assert (key); - nm_assert (out_to_free && !*out_to_free); - - if (!key[0]) - return ""; - - for (i = 0; TRUE; i++) { - const char ch = key[i]; - - if (ch == '\0') - return key; - if ( ch == '\\' - && g_ascii_isxdigit (key[i + 1]) - && g_ascii_isxdigit (key[i + 2])) - break; - } - - len = i + strlen (&key[i]); - - if ( len == 3 - && nm_streq (key, "\\00")) - return ""; - - nm_assert (len == strlen (key)); - str = g_string_sized_new (len + 3); - - g_string_append_len (str, key, i); - for (;;) { - const char ch = key[i]; - char ch1, ch2; - unsigned v; - - if (ch == '\0') - break; - - if ( ch == '\\' - && g_ascii_isxdigit ((ch1 = key[i + 1])) - && g_ascii_isxdigit ((ch2 = key[i + 2]))) { - v = (g_ascii_xdigit_value (ch1) << 4) + g_ascii_xdigit_value (ch2); - if (v != 0) { - g_string_append_c (str, (char) v); - i += 3; - continue; - } - } - g_string_append_c (str, ch); - i++; - } - - return (*out_to_free = g_string_free (str, FALSE)); -} - -/*****************************************************************************/ - -const char * -nm_keyfile_key_encode (const char *name, - char **out_to_free) -{ - const char *key; - - key = _keyfile_key_encode (name, out_to_free); -#if NM_MORE_ASSERTS > 5 - nm_assert (key); - nm_assert (!*out_to_free || key == *out_to_free); - nm_assert (!*out_to_free || !nm_streq0 (name, key)); - { - gs_free char *to_free2 = NULL; - const char *name2; - - name2 = _keyfile_key_decode (key, &to_free2); - /* name2, the result of encode()+decode() is identical to name. - * That is because - * - encode() is a injective function. - * - decode() is a surjective function, however for output - * values of encode() is behaves injective too. */ - nm_assert (nm_streq0 (name2, name)); - } -#endif - return key; -} - -const char * -nm_keyfile_key_decode (const char *key, - char **out_to_free) -{ - const char *name; - - name = _keyfile_key_decode (key, out_to_free); -#if NM_MORE_ASSERTS > 5 - nm_assert (name); - nm_assert (!*out_to_free || name == *out_to_free); - { - gs_free char *to_free2 = NULL; - const char *key2; - - key2 = _keyfile_key_encode (name, &to_free2); - /* key2, the result of decode+encode may not be idential - * to the original key. That is, decode() is a surjective - * function mapping different keys to the same name. - * However, decode() behaves injective for input that - * are valid output of encode(). */ - nm_assert (key2); - } -#endif - return name; -} diff --git a/libnm-core/nm-keyfile-utils.h b/libnm-core/nm-keyfile-utils.h deleted file mode 100644 index 7fb80717..00000000 --- a/libnm-core/nm-keyfile-utils.h +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2010 - 2015 Red Hat, Inc. - */ - -#ifndef __NM_KEYFILE_UTILS_H__ -#define __NM_KEYFILE_UTILS_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" -#define NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER "wireguard-peer." - -const char *nm_keyfile_plugin_get_alias_for_setting_name (const char *setting_name); - -const char *nm_keyfile_plugin_get_setting_name_for_alias (const char *alias); - -/*****************************************************************************/ - -/* List helpers */ -#define DEFINE_KF_LIST_WRAPPER_PROTO(stype, get_ctype, set_ctype) \ -get_ctype nm_keyfile_plugin_kf_get_##stype##_list (GKeyFile *kf, \ - const char *group, \ - const char *key, \ - gsize *out_length, \ - GError **error); \ -\ -void nm_keyfile_plugin_kf_set_##stype##_list (GKeyFile *kf, \ - const char *group, \ - const char *key, \ - set_ctype list[], \ - gsize length); -DEFINE_KF_LIST_WRAPPER_PROTO(integer, int*, int) -DEFINE_KF_LIST_WRAPPER_PROTO(string, char**, const char* const) - -void nm_keyfile_plugin_kf_set_integer_list_uint8 (GKeyFile *kf, - const char *group, - const char *key, - const guint8 *list, - gsize length); - -/* Single-value helpers */ -#define DEFINE_KF_WRAPPER_PROTO(stype, get_ctype, set_ctype) \ -get_ctype nm_keyfile_plugin_kf_get_##stype (GKeyFile *kf, \ - const char *group, \ - const char *key, \ - GError **error); \ -\ -void nm_keyfile_plugin_kf_set_##stype (GKeyFile *kf, \ - const char *group, \ - const char *key, \ - set_ctype value); -DEFINE_KF_WRAPPER_PROTO(string, char*, const char*) -DEFINE_KF_WRAPPER_PROTO(boolean, gboolean, gboolean) -DEFINE_KF_WRAPPER_PROTO(value, char*, const char*) - -/* Misc */ -gint64 nm_keyfile_plugin_kf_get_int64 (GKeyFile *kf, - const char *group, - const char *key, - guint base, - gint64 min, - gint64 max, - gint64 fallback, - GError **error); - -char ** nm_keyfile_plugin_kf_get_keys (GKeyFile *kf, - const char *group, - gsize *out_length, - GError **error); - -gboolean nm_keyfile_plugin_kf_has_key (GKeyFile *kf, - const char *group, - const char *key, - GError **error); - -const char *nm_keyfile_key_encode (const char *name, - char **out_to_free); - -const char *nm_keyfile_key_decode (const char *key, - char **out_to_free); - -#endif /* __NM_KEYFILE_UTILS_H__ */ diff --git a/libnm-core/nm-keyfile.c b/libnm-core/nm-keyfile.c deleted file mode 100644 index 535acccf..00000000 --- a/libnm-core/nm-keyfile.c +++ /dev/null @@ -1,4089 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2008 - 2009 Novell, Inc. - * Copyright (C) 2008 - 2017 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-keyfile-internal.h" - -#include <stdlib.h> -#include <stdio.h> -#include <sys/stat.h> -#include <unistd.h> -#include <sys/types.h> -#include <arpa/inet.h> -#include <linux/pkt_sched.h> - -#include "nm-glib-aux/nm-secret-utils.h" -#include "systemd/nm-sd-utils-shared.h" -#include "nm-libnm-core-intern/nm-common-macros.h" -#include "nm-core-internal.h" -#include "nm-keyfile-utils.h" - -#include "nm-setting-user.h" - -/*****************************************************************************/ - -typedef struct _ParseInfoProperty ParseInfoProperty; - -typedef struct { - NMConnection *connection; - GKeyFile *keyfile; - const char *base_dir; - NMKeyfileReadHandler handler; - void *user_data; - GError *error; - const char *group; - NMSetting *setting; -} KeyfileReaderInfo; - -typedef struct { - NMConnection *connection; - GKeyFile *keyfile; - GError *error; - NMKeyfileWriteHandler handler; - void *user_data; -} KeyfileWriterInfo; - -/*****************************************************************************/ - -static void -_handle_warn (KeyfileReaderInfo *info, - const char *property_name, - NMKeyfileWarnSeverity severity, - char *message) -{ - NMKeyfileReadTypeDataWarn type_data = { - .group = info->group, - .setting = info->setting, - .property_name = property_name, - .severity = severity, - .message = message, - }; - - info->handler (info->keyfile, - info->connection, - NM_KEYFILE_READ_TYPE_WARN, - &type_data, - info->user_data, - &info->error); - g_free (message); -} -#define handle_warn(arg_info, arg_property_name, arg_severity, ...) \ - ({ \ - KeyfileReaderInfo *_info = (arg_info); \ - \ - if (_info->handler) { \ - _handle_warn (_info, (arg_property_name), (arg_severity), \ - g_strdup_printf (__VA_ARGS__)); \ - } \ - _info->error == NULL; \ - }) - -/*****************************************************************************/ - -static gboolean -_secret_flags_persist_secret (NMSettingSecretFlags flags) -{ - return flags == NM_SETTING_SECRET_FLAG_NONE; -} - -/*****************************************************************************/ -/* Some setting properties also contain setting names, such as - * NMSettingConnection's 'type' property (which specifies the base type of the - * connection, e.g. ethernet or wifi) or 'slave-type' (specifies type of slave - * connection, e.g. bond or bridge). This function handles translating those - * properties' values to the real setting name if they are an alias. - */ -static void -setting_alias_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char *setting_name = nm_setting_get_name (setting); - const char *key_setting_name; - gs_free char *s = NULL; - - s = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key, NULL); - if (!s) - return; - - key_setting_name = nm_keyfile_plugin_get_setting_name_for_alias (s); - g_object_set (G_OBJECT (setting), - key, - key_setting_name ?: s, - NULL); -} - -static void -sriov_vfs_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char *setting_name = nm_setting_get_name (setting); - gs_unref_ptrarray GPtrArray *vfs = NULL; - gs_strfreev char **keys = NULL; - gsize n_keys = 0; - int i; - - keys = nm_keyfile_plugin_kf_get_keys (info->keyfile, setting_name, &n_keys, NULL); - if (n_keys == 0) - return; - - vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref); - - for (i = 0; i < n_keys; i++) { - gs_free char *value = NULL; - NMSriovVF *vf; - const char *rest; - - if (!g_str_has_prefix (keys[i], "vf.")) - continue; - - rest = &keys[i][3]; - - if (!NM_STRCHAR_ALL (rest, ch, g_ascii_isdigit (ch))) - continue; - - value = nm_keyfile_plugin_kf_get_string (info->keyfile, - setting_name, - keys[i], - NULL); - - vf = _nm_utils_sriov_vf_from_strparts (rest, value, TRUE, NULL); - if (vf) - g_ptr_array_add (vfs, vf); - } - - g_object_set (G_OBJECT (setting), - key, vfs, - NULL); -} - -static void -read_array_of_uint (GKeyFile *file, - NMSetting *setting, - const char *key) -{ - gs_unref_array GArray *array = NULL; - gsize length; - gsize i; - gs_free int *tmp = NULL; - - tmp = nm_keyfile_plugin_kf_get_integer_list (file, nm_setting_get_name (setting), key, &length, NULL); - if (length > G_MAXUINT) - return; - - array = g_array_sized_new (FALSE, FALSE, sizeof (guint), length); - - for (i = 0; i < length; i++) { - if (tmp[i] < 0) - return; - g_array_append_val (array, tmp[i]); - } - - g_object_set (setting, key, array, NULL); -} - -static gboolean -get_one_int (KeyfileReaderInfo *info, const char *property_name, const char *str, guint32 max_val, guint32 *out) -{ - gint64 tmp; - - g_return_val_if_fail (!info == !property_name, FALSE); - - if (!str || !str[0]) { - if (property_name) - handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring missing number")); - return FALSE; - } - - tmp = _nm_utils_ascii_str_to_int64 (str, 10, 0, max_val, -1); - if (tmp == -1) { - if (property_name) { - handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid number '%s'"), - str); - } - return FALSE; - } - - *out = (guint32) tmp; - return TRUE; -} - -static gpointer -build_address (KeyfileReaderInfo *info, int family, const char *address_str, guint32 plen, const char *property_name) -{ - NMIPAddress *addr; - GError *error = NULL; - - g_return_val_if_fail (address_str, NULL); - - addr = nm_ip_address_new (family, address_str, plen, &error); - if (!addr) { - handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid %s address: %s"), - family == AF_INET ? "IPv4" : "IPv6", error->message); - g_error_free (error); - } - - return addr; -} - -static gpointer -build_route (KeyfileReaderInfo *info, - const char *property_name, - int family, - const char *dest_str, - guint32 plen, - const char *gateway_str, - const char *metric_str) -{ - NMIPRoute *route; - guint32 u32; - gint64 metric = -1; - GError *error = NULL; - - g_return_val_if_fail (dest_str, NULL); - - /* Next hop */ - if (gateway_str && gateway_str[0]) { - if (!nm_utils_ipaddr_valid (family, gateway_str)) { - /* Try workaround for routes written by broken keyfile writer. - * Due to bug bgo#719851, an older version of writer would have - * written "a:b:c:d::/plen,metric" if the gateway was ::, instead - * of "a:b:c:d::/plen,,metric" or "a:b:c:d::/plen,::,metric" - * Try workaround by interpreting gateway_str as metric to accept such - * invalid routes. This broken syntax should not be not officially - * supported. - **/ - if ( family == AF_INET6 - && !metric_str - && get_one_int (NULL, NULL, gateway_str, G_MAXUINT32, &u32)) { - metric = u32; - gateway_str = NULL; - } else { - if (!info->error) { - handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid gateway '%s' for %s route"), - gateway_str, family == AF_INET ? "IPv4" : "IPv6"); - } - return NULL; - } - } - } else - gateway_str = NULL; - - /* parse metric, default to -1 */ - if (metric_str) { - if (!get_one_int (info, property_name, metric_str, G_MAXUINT32, &u32)) - return NULL; - metric = u32; - } - - route = nm_ip_route_new (family, - dest_str, - plen, - gateway_str, - metric, - &error); - if (!route) { - handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid %s route: %s"), - family == AF_INET ? "IPv4" : "IPv6", - error->message); - g_error_free (error); - } - - return route; -} - -/* On success, returns pointer to the zero-terminated field (original @current). - * The @current * pointer target is set to point to the rest of the input - * or %NULL if there is no more input. Sets error to %NULL for convenience. - * - * On failure, returns %NULL (unspecified). The @current pointer target is - * resets to its original value to allow skipping fields. The @error target - * is set to the character that breaks the parsing or %NULL if @current was %NULL. - * - * When @current target is %NULL, gracefully fail returning %NULL while - * leaving the @current target %NULL end setting @error to %NULL; - */ -static const char * -read_field (char **current, const char **out_err_str, const char *characters, const char *delimiters) -{ - const char *start; - - nm_assert (current); - nm_assert (out_err_str); - nm_assert (characters); - nm_assert (delimiters); - - *out_err_str = NULL; - - if (!*current) { - /* graceful failure, leave '*current' NULL */ - return NULL; - } - - /* fail on empty input */ - if (!**current) - return NULL; - - /* remember beginning of input */ - start = *current; - - while (**current && strchr (characters, **current)) - (*current)++; - if (**current) - if (strchr (delimiters, **current)) { - /* success, more data available */ - *(*current)++ = '\0'; - return start; - } else { - /* error, bad character */ - *out_err_str = *current; - *current = (char *) start; - return NULL; - } - else { - /* success, end of input */ - *current = NULL; - return start; - } -} - -/*****************************************************************************/ - -#define NM_DBUS_SERVICE_OPENCONNECT "org.freedesktop.NetworkManager.openconnect" -#define NM_OPENCONNECT_KEY_GATEWAY "gateway" -#define NM_OPENCONNECT_KEY_COOKIE "cookie" -#define NM_OPENCONNECT_KEY_GWCERT "gwcert" -#define NM_OPENCONNECT_KEY_XMLCONFIG "xmlconfig" -#define NM_OPENCONNECT_KEY_LASTHOST "lasthost" -#define NM_OPENCONNECT_KEY_AUTOCONNECT "autoconnect" -#define NM_OPENCONNECT_KEY_CERTSIGS "certsigs" - -static void -openconnect_fix_secret_flags (NMSetting *setting) -{ - NMSettingVpn *s_vpn; - NMSettingSecretFlags flags; - - /* Huge hack. There were some openconnect changes that needed to happen - * pretty late, too late to get into distros. Migration has already - * happened for many people, and their secret flags are wrong. But we - * don't want to requrie re-migration, so we have to fix it up here. Ugh. - */ - - if (!NM_IS_SETTING_VPN (setting)) - return; - - s_vpn = NM_SETTING_VPN (setting); - - if (!nm_streq0 (nm_setting_vpn_get_service_type (s_vpn), NM_DBUS_SERVICE_OPENCONNECT)) - return; - - /* These are different for every login session, and should not be stored */ - flags = NM_SETTING_SECRET_FLAG_NOT_SAVED; - nm_setting_set_secret_flags (NM_SETTING (s_vpn), NM_OPENCONNECT_KEY_GATEWAY, flags, NULL); - nm_setting_set_secret_flags (NM_SETTING (s_vpn), NM_OPENCONNECT_KEY_COOKIE, flags, NULL); - nm_setting_set_secret_flags (NM_SETTING (s_vpn), NM_OPENCONNECT_KEY_GWCERT, flags, NULL); - - /* These are purely internal data for the auth-dialog, and should be stored */ - flags = 0; - nm_setting_set_secret_flags (NM_SETTING (s_vpn), NM_OPENCONNECT_KEY_XMLCONFIG, flags, NULL); - nm_setting_set_secret_flags (NM_SETTING (s_vpn), NM_OPENCONNECT_KEY_LASTHOST, flags, NULL); - nm_setting_set_secret_flags (NM_SETTING (s_vpn), NM_OPENCONNECT_KEY_AUTOCONNECT, flags, NULL); - nm_setting_set_secret_flags (NM_SETTING (s_vpn), NM_OPENCONNECT_KEY_CERTSIGS, flags, NULL); -} - -/*****************************************************************************/ - -#define IP_ADDRESS_CHARS "0123456789abcdefABCDEF:.%" -#define DIGITS "0123456789" -#define DELIMITERS "/;," - -/* The following IPv4 and IPv6 address formats are supported: - * - * address (DEPRECATED) - * address/plen - * address/gateway (DEPRECATED) - * address/plen,gateway - * - * The following IPv4 and IPv6 route formats are supported: - * - * address/plen (NETWORK dev DEVICE) - * address/plen,gateway (NETWORK via GATEWAY dev DEVICE) - * address/plen,,metric (NETWORK dev DEVICE metric METRIC) - * address/plen,gateway,metric (NETWORK via GATEWAY dev DEVICE metric METRIC) - * - * For backward, forward and sideward compatibility, slash (/), - * semicolon (;) and comma (,) are interchangeable. The choice of - * separator in the above examples is therefore not significant. - * - * Leaving out the prefix length is discouraged and DEPRECATED. The - * default value of IPv6 prefix length was 64 and has not been - * changed. The default for IPv4 is now 24, which is the closest - * IPv4 equivalent. These defaults may just as well be changed to - * match the iproute2 defaults (32 for IPv4 and 128 for IPv6). - */ -static gpointer -read_one_ip_address_or_route (KeyfileReaderInfo *info, - const char *property_name, - const char *setting_name, - const char *key_name, - gboolean ipv6, - gboolean route, - char **out_gateway, - NMSetting *setting) -{ - guint plen; - gpointer result; - const char *address_str; - const char *plen_str; - const char *gateway_str; - const char *metric_str; - const char *err_str = NULL; - char *current; - gs_free char *value = NULL; - gs_free char *value_orig = 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) - return NULL; - - current = value; - - /* get address field */ - address_str = read_field (¤t, &err_str, IP_ADDRESS_CHARS, DELIMITERS); - if (err_str) { - handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, - _("unexpected character '%c' for address %s: '%s' (position %td)"), - *err_str, key_name, VALUE_ORIG (), err_str - current); - return NULL; - } - /* get prefix length field (skippable) */ - plen_str = read_field (¤t, &err_str, DIGITS, DELIMITERS); - /* get gateway field */ - gateway_str = read_field (¤t, &err_str, IP_ADDRESS_CHARS, DELIMITERS); - if (err_str) { - handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, - _("unexpected character '%c' for %s: '%s' (position %td)"), - *err_str, key_name, VALUE_ORIG (), err_str - current); - return NULL; - } - /* for routes, get metric */ - if (route) { - metric_str = read_field (¤t, &err_str, DIGITS, DELIMITERS); - if (err_str) { - handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, - _("unexpected character '%c' in prefix length for %s: '%s' (position %td)"), - *err_str, key_name, VALUE_ORIG (), err_str - current); - return NULL; - } - } else - metric_str = NULL; - if (current) { - /* there is still some data */ - if (*current) { - /* another field follows */ - handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, - _("garbage at the end of value %s: '%s'"), - key_name, VALUE_ORIG ()); - return NULL; - } else { - /* semicolon at the end of input */ - if (!handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_INFO, - _("deprecated semicolon at the end of value %s: '%s'"), - key_name, VALUE_ORIG ())) - return NULL; - } - } - -#define DEFAULT_PREFIX(for_route, for_ipv6) ( (for_route) ? ( (for_ipv6) ? 128 : 24 ) : ( (for_ipv6) ? 64 : 24 ) ) - - /* parse plen, fallback to defaults */ - if (plen_str) { - if (!get_one_int (info, property_name, plen_str, ipv6 ? 128 : 32, &plen)) { - plen = DEFAULT_PREFIX (route, ipv6); - if ( info->error - || !handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid prefix length for %s '%s', defaulting to %d"), - key_name, VALUE_ORIG (), plen)) - return NULL; - } - } else { - plen = DEFAULT_PREFIX (route, ipv6); - if (!handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, - _("missing prefix length for %s '%s', defaulting to %d"), - key_name, VALUE_ORIG (), plen)) - return NULL; - } - - /* build the appropriate data structure for NetworkManager settings */ - if (route) { - result = build_route (info, - property_name, - ipv6 ? AF_INET6 : AF_INET, - address_str, - plen, - gateway_str, - metric_str); - } else { - result = build_address (info, - ipv6 ? AF_INET6 : AF_INET, - address_str, - plen, - property_name); - if (!result) - return NULL; - if (gateway_str) - NM_SET_OUT (out_gateway, g_strdup (gateway_str)); - } - -#undef VALUE_ORIG - - return result; -} - -static void -fill_route_attributes (GKeyFile *kf, NMIPRoute *route, const char *setting, const char *key, int family) -{ - gs_free char *value = NULL; - gs_unref_hashtable GHashTable *hash = NULL; - GHashTableIter iter; - char *name; - GVariant *variant; - - value = nm_keyfile_plugin_kf_get_string (kf, setting, key, NULL); - if (!value || !value[0]) - return; - - hash = nm_utils_parse_variant_attributes (value, ',', '=', TRUE, - nm_ip_route_get_variant_attribute_spec (), - NULL); - if (hash) { - g_hash_table_iter_init (&iter, hash); - while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant)) { - if (nm_ip_route_attribute_validate (name, variant, family, NULL, NULL)) - nm_ip_route_set_attribute (route, name, g_variant_ref (variant)); - } - } -} - -typedef struct { - const char *s_key; - gint32 key_idx; - gint8 key_type; -} BuildListData; - -typedef enum { - BUILD_LIST_TYPE_ADDRESSES, - BUILD_LIST_TYPE_ROUTES, - BUILD_LIST_TYPE_ROUTING_RULES, -} BuildListType; - -static int -_build_list_data_cmp (gconstpointer p_a, gconstpointer p_b, gpointer user_data) -{ - const BuildListData *a = p_a; - const BuildListData *b = p_b; - - NM_CMP_FIELD (a, b, key_idx); - NM_CMP_FIELD (a, b, key_type); - NM_CMP_FIELD_STR (a, b, s_key); - return 0; -} - -static gboolean -_build_list_data_is_shadowed (const BuildListData *build_list, - gsize build_list_len, - gsize idx) -{ - /* the keyfile contains duplicate keys, which are both returned - * by g_key_file_get_keys() (WHY??). - * - * Skip the earlier one. */ - return idx + 1 < build_list_len - && build_list[idx].key_idx == build_list[idx + 1].key_idx - && build_list[idx].key_type == build_list[idx + 1].key_type - && nm_streq (build_list[idx].s_key, build_list[idx + 1].s_key); -} - -static gboolean -_build_list_match_key_w_name_impl (const char *key, - const char *base_name, - gsize base_name_l, - gint32 *out_key_idx) -{ - gint64 v; - - /* some very strict parsing. */ - - /* the key must start with base_name. */ - if (strncmp (key, base_name, base_name_l) != 0) - return FALSE; - - 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; - } - - /* 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; - - /* 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; -} - -#define _build_list_match_key_w_name(key, base_name, out_key_idx) \ - _build_list_match_key_w_name_impl (key, base_name, NM_STRLEN (base_name), out_key_idx) - -static BuildListData * -_build_list_create (GKeyFile *keyfile, - const char *group_name, - BuildListType build_list_type, - gsize *out_build_list_len, - char ***out_keys_strv) -{ - gs_strfreev char **keys = NULL; - gsize i_keys, n_keys; - gs_free BuildListData *build_list = NULL; - gsize build_list_len = 0; - - nm_assert (out_build_list_len && *out_build_list_len == 0); - nm_assert (out_keys_strv && !*out_keys_strv); - - keys = nm_keyfile_plugin_kf_get_keys (keyfile, group_name, &n_keys, NULL); - if (n_keys == 0) - return NULL; - - for (i_keys = 0; i_keys < n_keys; i_keys++) { - const char *s_key = keys[i_keys]; - gint32 key_idx; - gint8 key_type = 0; - - switch (build_list_type) { - case BUILD_LIST_TYPE_ROUTES: - if (_build_list_match_key_w_name (s_key, "route", &key_idx)) - key_type = 0; - else if (_build_list_match_key_w_name (s_key, "routes", &key_idx)) - key_type = 1; - else - continue; - break; - case BUILD_LIST_TYPE_ADDRESSES: - if (_build_list_match_key_w_name (s_key, "address", &key_idx)) - key_type = 0; - else if (_build_list_match_key_w_name (s_key, "addresses", &key_idx)) - key_type = 1; - else - continue; - break; - case BUILD_LIST_TYPE_ROUTING_RULES: - if (_build_list_match_key_w_name (s_key, "routing-rule", &key_idx)) - key_type = 0; - else - continue; - break; - default: - nm_assert_not_reached (); - break; - } - - if (G_UNLIKELY (!build_list)) - build_list = g_new (BuildListData, n_keys - i_keys); - - build_list[build_list_len++] = (BuildListData) { - .s_key = s_key, - .key_idx = key_idx, - .key_type = key_type, - }; - } - - if (build_list_len == 0) - return NULL; - - if (build_list_len > 1) { - g_qsort_with_data (build_list, - build_list_len, - sizeof (BuildListData), - _build_list_data_cmp, - NULL); - } - - *out_build_list_len = build_list_len; - *out_keys_strv = g_steal_pointer (&keys); - return g_steal_pointer (&build_list); -} - -static void -ip_address_or_route_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *setting_key) -{ - const char *setting_name = nm_setting_get_name (setting); - 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; - gs_free BuildListData *build_list = NULL; - gsize i_build_list, build_list_len = 0; - - build_list = _build_list_create (info->keyfile, - setting_name, - is_routes - ? BUILD_LIST_TYPE_ROUTES - : BUILD_LIST_TYPE_ADDRESSES, - &build_list_len, - &keys); - if (!build_list) - return; - - 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 char *s_key; - gpointer item; - - if (_build_list_data_is_shadowed (build_list, build_list_len, i_build_list)) - continue; - - s_key = build_list[i_build_list].s_key; - item = read_one_ip_address_or_route (info, - setting_key, - setting_name, - 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", 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); - } - - if (list->len >= 1) - g_object_set (setting, setting_key, list, NULL); - - if (gateway) - g_object_set (setting, "gateway", gateway, NULL); -} - -static void -ip_routing_rule_parser_full (KeyfileReaderInfo *info, - const NMMetaSettingInfo *setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty *pip, - NMSetting *setting) -{ - const char *setting_name = nm_setting_get_name (setting); - gboolean is_ipv6 = nm_streq (setting_name, "ipv6"); - gs_strfreev char **keys = NULL; - gs_free BuildListData *build_list = NULL; - gsize i_build_list, build_list_len = 0; - - build_list = _build_list_create (info->keyfile, - setting_name, - BUILD_LIST_TYPE_ROUTING_RULES, - &build_list_len, - &keys); - if (!build_list) - return; - - for (i_build_list = 0; i_build_list < build_list_len; i_build_list++) { - nm_auto_unref_ip_routing_rule NMIPRoutingRule *rule = NULL; - gs_free char *value = NULL; - gs_free_error GError *local = NULL; - - if (_build_list_data_is_shadowed (build_list, build_list_len, i_build_list)) - continue; - - value = nm_keyfile_plugin_kf_get_string (info->keyfile, - setting_name, - build_list[i_build_list].s_key, - NULL); - if (!value) - continue; - - rule = nm_ip_routing_rule_from_string (value, - ( NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE - | ( is_ipv6 - ? NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6 - : NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET)), - NULL, - &local); - if (!rule) { - handle_warn (info, property_info->name, NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid value for \"%s\": %s"), - build_list[i_build_list].s_key, - local->message); - if (info->error) - return; - continue; - } - - nm_setting_ip_config_add_routing_rule (NM_SETTING_IP_CONFIG (setting), rule); - } -} - -static void -ip_dns_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - 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; - - addr_family = NM_IS_SETTING_IP4_CONFIG (setting) ? AF_INET : AF_INET6; - - n = 0; - for (i = 0; i < length; i++) { - NMIPAddr addr; - - if (inet_pton (addr_family, list[i], &addr) <= 0) { - if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("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; - } - - if (n != i) - list[n] = g_steal_pointer (&list[i]); - n++; - } - - g_object_set (setting, key, list, NULL); -} - -static void -ip6_addr_gen_mode_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - NMSettingIP6ConfigAddrGenMode addr_gen_mode; - const char *setting_name = nm_setting_get_name (setting); - gs_free char *s = NULL; - - s = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key, NULL); - if (s) { - if (!nm_utils_enum_from_str (nm_setting_ip6_config_addr_gen_mode_get_type (), s, - (int *) &addr_gen_mode, NULL)) { - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid option '%s', use one of [%s]"), - s, "eui64,stable-privacy"); - return; - } - } else - addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64; - - g_object_set (G_OBJECT (setting), key, (int) addr_gen_mode, NULL); -} - -static void -mac_address_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key, gsize enforce_length, gboolean cloned_mac_addr) -{ - const char *setting_name = nm_setting_get_name (setting); - gs_free char *tmp_string = NULL; - const char *p, *mac_str; - gs_free guint8 *buf_arr = NULL; - guint buf_len = 0; - - tmp_string = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key, NULL); - - if ( cloned_mac_addr - && NM_CLONED_MAC_IS_SPECIAL (tmp_string)) { - mac_str = tmp_string; - goto out; - } - - if (tmp_string && tmp_string[0]) { - /* Look for enough ':' characters to signify a MAC address */ - guint i = 0; - - p = tmp_string; - while (*p) { - if (*p == ':') - i++; - p++; - } - - if (enforce_length == 0 || enforce_length == i+1) { - /* If we found enough it's probably a string-format MAC address */ - buf_len = i + 1; - buf_arr = g_new (guint8, buf_len); - if (!nm_utils_hwaddr_aton (tmp_string, buf_arr, buf_len)) - g_clear_pointer (&buf_arr, g_free); - } - } - g_clear_pointer (&tmp_string, g_free); - - if (!buf_arr) { - gs_free int *tmp_list = NULL; - gsize length; - - /* Old format; list of ints */ - tmp_list = nm_keyfile_plugin_kf_get_integer_list (info->keyfile, setting_name, key, &length, NULL); - if (length > 0 && (enforce_length == 0 || enforce_length == length)) { - gsize i; - - buf_len = length; - buf_arr = g_new (guint8, buf_len); - for (i = 0; i < length; i++) { - int val = tmp_list[i]; - - if (val < 0 || val > 255) { - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid byte element '%d' (not between 0 and 255 inclusive)"), - val); - return; - } - buf_arr[i] = (guint8) val; - } - } - } - - if (!buf_arr) { - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid MAC address")); - return; - } - - tmp_string = nm_utils_hwaddr_ntoa (buf_arr, buf_len); - mac_str = tmp_string; - -out: - g_object_set (setting, key, mac_str, NULL); -} - -static void -mac_address_parser_ETHER (KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - mac_address_parser (info, setting, key, ETH_ALEN, FALSE); -} - -static void -mac_address_parser_ETHER_cloned (KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - mac_address_parser (info, setting, key, ETH_ALEN, TRUE); -} - -static void -mac_address_parser_INFINIBAND (KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - mac_address_parser (info, setting, key, INFINIBAND_ALEN, FALSE); -} - -static void -read_hash_of_string (GKeyFile *file, NMSetting *setting, const char *key) -{ - gs_strfreev char **keys = NULL; - const char *const*iter; - const char *setting_name = nm_setting_get_name (setting); - gboolean is_vpn; - gsize n_keys; - - nm_assert ( (NM_IS_SETTING_VPN (setting) && nm_streq (key, NM_SETTING_VPN_DATA)) - || (NM_IS_SETTING_VPN (setting) && nm_streq (key, NM_SETTING_VPN_SECRETS)) - || (NM_IS_SETTING_BOND (setting) && nm_streq (key, NM_SETTING_BOND_OPTIONS)) - || (NM_IS_SETTING_USER (setting) && nm_streq (key, NM_SETTING_USER_DATA))); - - keys = nm_keyfile_plugin_kf_get_keys (file, setting_name, &n_keys, NULL); - if (n_keys == 0) - return; - - if ( (is_vpn = NM_IS_SETTING_VPN (setting)) - || NM_IS_SETTING_BOND (setting)) { - for (iter = (const char *const*) keys; *iter; iter++) { - gs_free char *to_free = NULL; - gs_free char *value = NULL; - const char *name; - - value = nm_keyfile_plugin_kf_get_string (file, setting_name, *iter, NULL); - if (!value) - continue; - - name = nm_keyfile_key_decode (*iter, &to_free); - - if (is_vpn) { - /* Add any item that's not a class property to the data hash */ - if (!g_object_class_find_property (G_OBJECT_GET_CLASS (setting), name)) - nm_setting_vpn_add_data_item (NM_SETTING_VPN (setting), name, value); - } else { - if (!nm_streq (name, "interface-name")) - nm_setting_bond_add_option (NM_SETTING_BOND (setting), name, value); - } - } - openconnect_fix_secret_flags (setting); - return; - } - - if (NM_IS_SETTING_USER (setting)) { - gs_unref_hashtable GHashTable *data = NULL; - - 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; - const char *name; - - value = nm_keyfile_plugin_kf_get_string (file, setting_name, *iter, NULL); - if (!value) - continue; - name = nm_keyfile_key_decode (*iter, &to_free); - g_hash_table_insert (data, - g_steal_pointer (&to_free) ?: g_strdup (name), - value); - } - g_object_set (setting, NM_SETTING_USER_DATA, data, NULL); - return; - } - - nm_assert_not_reached (); -} - -static gsize -unescape_semicolons (char *str) -{ - gsize i, j; - - for (i = 0, j = 0; str[i]; ) { - if (str[i] == '\\' && str[i+1] == ';') - i++; - str[j++] = str[i++];; - } - nm_explicit_bzero (&str[j], i - j); - return j; -} - -static GBytes * -get_bytes (KeyfileReaderInfo *info, - const char *setting_name, - const char *key, - gboolean zero_terminate, - gboolean unescape_semicolon) -{ - nm_auto_free_secret char *tmp_string = NULL; - gboolean may_be_int_list = TRUE; - gsize length; - GBytes *result; - - /* New format: just a string - * Old format: integer list; e.g. 11;25;38; - */ - tmp_string = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key, NULL); - if (!tmp_string) - return NULL; - - /* if the string is empty, we return an empty GBytes array. - * Note that for NM_SETTING_802_1X_PASSWORD_RAW both %NULL and - * an empty GBytes are valid, and shall be destinguished. */ - if (!tmp_string[0]) { - /* note that even if @zero_terminate is TRUE, we return an empty - * byte-array. The reason is that zero_terminate is there to terminate - * *valid* strings. It's not there to terminated invalid (empty) strings. - */ - return g_bytes_new_static ("", 0); - } - - for (length = 0; tmp_string[length]; length++) { - const char ch = tmp_string[length]; - - if ( !g_ascii_isspace (ch) - && !g_ascii_isdigit (ch) - && ch != ';') { - may_be_int_list = FALSE; - length += strlen (&tmp_string[length]); - break; - } - } - - /* Try to parse the string as a integer list. */ - if (may_be_int_list && length > 0) { - nm_auto_free_secret_buf NMSecretBuf *bin = NULL; - const char *const s = tmp_string; - gsize i, d; - - bin = nm_secret_buf_new (length / 2 + 3); - -#define DIGIT(c) ((c) - '0') - i = 0; - d = 0; - while (TRUE) { - int n; - - /* leading whitespace */ - while (g_ascii_isspace (s[i])) - i++; - if (s[i] == '\0') - break; - /* then expect 1 to 3 digits */ - if (!g_ascii_isdigit (s[i])) { - d = 0; - break; - } - n = DIGIT (s[i]); - i++; - if (g_ascii_isdigit (s[i])) { - n = 10 * n + DIGIT (s[i]); - i++; - if (g_ascii_isdigit (s[i])) { - n = 10 * n + DIGIT (s[i]); - i++; - } - } - if (n > 255) { - d = 0; - break; - } - - nm_assert (d < bin->len); - bin->bin[d++] = n; - - /* allow whitespace after the digit. */ - while (g_ascii_isspace (s[i])) - i++; - /* need a semicolon as separator. */ - if (s[i] != ';') { - d = 0; - break; - } - i++; - } -#undef DIGIT - - /* Old format; list of ints. We already did a strict validation of the - * string format before. We expect that this conversion cannot fail. */ - if (d > 0) { - /* note that @zero_terminate does not add a terminating '\0' to - * binary data as an integer list. If the bytes are expressed as - * an integer list, all potential NUL characters are supposed to - * be included there explicitly. - * - * However, in the spirit of defensive programming, we do append a - * NUL character to the buffer, although this character is hidden - * and only a mitigation for bugs. */ - - if (d + 10 < bin->len) { - /* hm, too much unused memory. Copy the memory to a suitable - * sized buffer. */ - return nm_secret_copy_to_gbytes (bin->bin, d); - } - - nm_assert (d < bin->len); - bin->bin[d] = '\0'; - return nm_secret_buf_to_gbytes_take (g_steal_pointer (&bin), d); - } - } - - /* Handle as a simple string (ie, new format) */ - if (unescape_semicolon) - length = unescape_semicolons (tmp_string); - if (zero_terminate) - length++; - if (length == 0) - return NULL; - - result = g_bytes_new_with_free_func (tmp_string, - length, - (GDestroyNotify) nm_free_secret, - tmp_string); - tmp_string = NULL; - return result; -} - -static void -ssid_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char *setting_name = nm_setting_get_name (setting); - GBytes *bytes; - - bytes = get_bytes (info, setting_name, key, FALSE, TRUE); - if (bytes) { - g_object_set (setting, key, bytes, NULL); - g_bytes_unref (bytes); - } else if (!info->error) { - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid SSID")); - } -} - -static void -password_raw_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char *setting_name = nm_setting_get_name (setting); - GBytes *bytes; - - bytes = get_bytes (info, setting_name, key, FALSE, TRUE); - if (bytes) { - g_object_set (setting, key, bytes, NULL); - g_bytes_unref (bytes); - } else if (!info->error) { - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid raw password")); - } -} - -static char * -get_cert_path (const char *base_dir, const guint8 *cert_path, gsize cert_path_len) -{ - const char *base; - char *p = NULL, *path, *tmp; - - g_return_val_if_fail (base_dir != NULL, NULL); - g_return_val_if_fail (cert_path != NULL, NULL); - - path = g_strndup ((char *) cert_path, cert_path_len); - - if (path[0] == '/') - return path; - - base = path; - p = strrchr (path, '/'); - if (p) - base = p + 1; - - tmp = g_build_path ("/", base_dir, base, NULL); - g_free (path); - return tmp; -} - -static const char *certext[] = { ".pem", ".cert", ".crt", ".cer", ".p12", ".der", ".key" }; - -static gboolean -has_cert_ext (const char *path) -{ - int i; - - for (i = 0; i < G_N_ELEMENTS (certext); i++) { - if (g_str_has_suffix (path, certext[i])) - return TRUE; - } - return FALSE; -} - -char * -nm_keyfile_detect_unqualified_path_scheme (const char *base_dir, - gconstpointer pdata, - gsize data_len, - gboolean consider_exists, - gboolean *out_exists) -{ - const char *data = pdata; - gboolean exists = FALSE; - gsize validate_len; - gsize path_len, pathuri_len; - gs_free char *path = NULL; - gs_free char *pathuri = NULL; - - g_return_val_if_fail (base_dir && base_dir[0] == '/', NULL); - - if (!pdata) - return NULL; - if (data_len == -1) - data_len = strlen (data); - if (data_len > 500 || data_len < 1) - return NULL; - - /* If there's a trailing zero tell g_utf8_validate() to validate until the zero */ - if (data[data_len - 1] == '\0') { - /* setting it to -1, would mean we accept data to contain NUL characters before the - * end. Don't accept any NUL in [0 .. data_len-1[ . */ - validate_len = data_len - 1; - } else - validate_len = data_len; - if ( validate_len == 0 - || g_utf8_validate ((const char *) data, validate_len, NULL) == FALSE) - return NULL; - - /* Might be a bare path without the file:// prefix; in that case - * if it's an absolute path, use that, otherwise treat it as a - * relative path to the current directory. - */ - - path = get_cert_path (base_dir, (const guint8 *) data, data_len); - - /* FIXME(keyfile-parse-in-memory): it is wrong that keyfile reader makes decisions based on - * the file systems content. The serialization/parsing should be entirely in-memory. */ - if ( !memchr (data, '/', data_len) - && !has_cert_ext (path)) { - if (!consider_exists) - return NULL; - exists = g_file_test (path, G_FILE_TEST_EXISTS); - if (!exists) - 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. - * - * 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. */ - path_len = strlen (path); - pathuri_len = (NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) + 1) + path_len; - pathuri = g_new (char, pathuri_len); - memcpy (pathuri, NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)); - memcpy (&pathuri[NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)], path, path_len + 1); - if (nm_setting_802_1x_check_cert_scheme (pathuri, pathuri_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_PATH) - return NULL; - - NM_SET_OUT (out_exists, exists); - return g_steal_pointer (&pathuri); -} - -#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; - const char *bin = NULL; - gsize bin_len = 0; - char *path; - gboolean path_exists; - - bytes = get_bytes (info, setting_name, key, TRUE, FALSE); - 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 (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; - } - - /* FIXME(keyfile-parse-in-memory): keyfile reader must not access the file system and - * (in a first step) only operate in memory-only. If the presence of files should be checked, - * then by invoking a callback (and possibly keyfile settings plugin would - * collect the file names to be checked and check them later). */ - 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; - } - - 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; - } - - 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 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 is not a valid blob")); - return; - } - - g_object_set (setting, key, bytes, NULL); -} - -static int -_parity_from_char (int ch) -{ -#if NM_MORE_ASSERTS > 5 - { - static char check = 0; - - if (check == 0) { - nm_auto_unref_gtypeclass GEnumClass *klass = g_type_class_ref (NM_TYPE_SETTING_SERIAL_PARITY); - guint i; - - check = 1; - - /* In older versions, parity was G_TYPE_CHAR/gint8, and the character - * value was stored as integer. - * For example parity=69 equals parity=E, meaning NM_SETTING_SERIAL_PARITY_EVEN. - * - * That means, certain values are reserved. Assert that these numbers - * are not reused when we extend NMSettingSerialParity enum. - * Actually, since NM_SETTING_SERIAL_PARITY is g_param_spec_enum(), - * we anyway cannot extend the enum without breaking API... - * - * [1] commit "a91e60902e libnm-core: make NMSettingSerial:parity an enum" - * [2] https://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=a91e60902eabae1de93d61323dae6ac894b5d40f - */ - g_assert (G_IS_ENUM_CLASS (klass)); - for (i = 0; i < klass->n_values; i++) { - const GEnumValue *v = &klass->values[i]; - int num = v->value; - - g_assert (_parity_from_char (num) == -1); - g_assert (!NM_IN_SET (num, 'e', 'E', 'o', 'O', 'n', 'N')); - } - } - } -#endif - - switch (ch) { - case 'E': - case 'e': - return NM_SETTING_SERIAL_PARITY_EVEN; - case 'O': - case 'o': - return NM_SETTING_SERIAL_PARITY_ODD; - case 'N': - case 'n': - return NM_SETTING_SERIAL_PARITY_NONE; - } - - return -1; -} - -static void -parity_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char *setting_name = nm_setting_get_name (setting); - gs_free_error GError *err = NULL; - int parity; - gs_free char *tmp_str = NULL; - gint64 i64; - - /* Keyfile traditionally stored this as the ASCII value for 'E', 'o', or 'n'. - * We now accept either that or the (case-insensitive) character itself (but - * still always write it the old way, for backward compatibility). - */ - tmp_str = nm_keyfile_plugin_kf_get_value (info->keyfile, setting_name, key, &err); - if (err) - goto out_err; - - if ( tmp_str - && tmp_str[0] != '\0' - && tmp_str[1] == '\0') { - /* the ASCII characters like 'E' are taken directly... */ - parity = _parity_from_char (tmp_str[0]); - if (parity >= 0) - goto parity_good; - } - - i64 = _nm_utils_ascii_str_to_int64 (tmp_str, 0, G_MININT, G_MAXINT, G_MININT64); - if ( i64 != G_MININT64 - && errno == 0) { - - if ((parity = _parity_from_char (i64)) >= 0) { - /* another oddity: the string is a valid number. However, if the numeric values - * is one of the supported ASCII codes, accept it (like 69 for 'E'). - */ - goto parity_good; - } - - /* Finally, take the numeric value as is. */ - parity = i64; - goto parity_good; - } - - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid parity value '%s'"), - tmp_str ?: ""); - return; - -parity_good: - nm_g_object_set_property_enum (G_OBJECT (setting), key, NM_TYPE_SETTING_SERIAL_PARITY, parity, &err); - -out_err: - if (!err) - return; - if ( err->domain == G_KEY_FILE_ERROR - && NM_IN_SET (err->code, G_KEY_FILE_ERROR_GROUP_NOT_FOUND, - G_KEY_FILE_ERROR_KEY_NOT_FOUND)) { - /* ignore such errors. The key is not present. */ - return; - } - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid setting: %s"), err->message); -} - -static void -team_config_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char *setting_name = nm_setting_get_name (setting); - gs_free char *conf = NULL; - gs_free_error GError *error = NULL; - - conf = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key, NULL); - - g_object_set (G_OBJECT (setting), key, conf, NULL); - - if ( conf - && !nm_setting_verify (setting, NULL, &error)) { - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid team configuration: %s"), - error->message); - g_object_set (G_OBJECT (setting), key, NULL, NULL); - } -} - -static void -bridge_vlan_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - gs_unref_ptrarray GPtrArray *vlans = NULL; - gs_free char *value = NULL; - gs_free const char **strv = NULL; - const char *const *iter; - GError *local = NULL; - NMBridgeVlan *vlan; - - value = nm_keyfile_plugin_kf_get_string (info->keyfile, - nm_setting_get_name (setting), - key, - NULL); - if (!value || !value[0]) - return; - - vlans = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_bridge_vlan_unref); - - strv = nm_utils_escaped_tokens_split (value, ","); - if (strv) { - for (iter = strv; *iter; iter++) { - vlan = nm_bridge_vlan_from_str (*iter, &local); - if (!vlan) { - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - "invalid bridge VLAN: %s", local->message); - g_clear_error (&local); - continue; - } - g_ptr_array_add (vlans, vlan); - } - } - - if (vlans->len > 0) - g_object_set (setting, key, vlans, NULL); -} - -static void -qdisc_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char *setting_name = nm_setting_get_name (setting); - gs_unref_ptrarray GPtrArray *qdiscs = NULL; - gs_strfreev char **keys = NULL; - gsize n_keys = 0; - int i; - - keys = nm_keyfile_plugin_kf_get_keys (info->keyfile, setting_name, &n_keys, NULL); - if (n_keys == 0) - return; - - qdiscs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_tc_qdisc_unref); - - for (i = 0; i < n_keys; i++) { - NMTCQdisc *qdisc; - const char *qdisc_parent; - gs_free char *qdisc_rest = NULL; - gs_free char *qdisc_str = NULL; - gs_free_error GError *err = NULL; - - if (!g_str_has_prefix (keys[i], "qdisc.")) - continue; - - qdisc_parent = keys[i] + sizeof ("qdisc.") - 1; - qdisc_rest = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, keys[i], NULL); - qdisc_str = g_strdup_printf ("%s%s %s", - _nm_utils_parse_tc_handle (qdisc_parent, NULL) != TC_H_UNSPEC ? "parent " : "", - qdisc_parent, - qdisc_rest); - - qdisc = nm_utils_tc_qdisc_from_str (qdisc_str, &err); - if (!qdisc) { - handle_warn (info, keys[i], NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid qdisc: %s"), - err->message); - } else { - g_ptr_array_add (qdiscs, qdisc); - } - } - - if (qdiscs->len >= 1) - g_object_set (setting, key, qdiscs, NULL); -} - -static void -tfilter_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char *setting_name = nm_setting_get_name (setting); - gs_unref_ptrarray GPtrArray *tfilters = NULL; - gs_strfreev char **keys = NULL; - gsize n_keys = 0; - int i; - - keys = nm_keyfile_plugin_kf_get_keys (info->keyfile, setting_name, &n_keys, NULL); - if (n_keys == 0) - return; - - tfilters = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_tc_tfilter_unref); - - for (i = 0; i < n_keys; i++) { - NMTCTfilter *tfilter; - const char *tfilter_parent; - gs_free char *tfilter_rest = NULL; - gs_free char *tfilter_str = NULL; - gs_free_error GError *err = NULL; - - if (!g_str_has_prefix (keys[i], "tfilter.")) - continue; - - tfilter_parent = keys[i] + sizeof ("tfilter.") - 1; - tfilter_rest = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, keys[i], NULL); - tfilter_str = g_strdup_printf ("%s%s %s", - _nm_utils_parse_tc_handle (tfilter_parent, NULL) != TC_H_UNSPEC ? "parent " : "", - tfilter_parent, - tfilter_rest); - - tfilter = nm_utils_tc_tfilter_from_str (tfilter_str, &err); - if (!tfilter) { - handle_warn (info, keys[i], NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid tfilter: %s"), - err->message); - } else { - g_ptr_array_add (tfilters, tfilter); - } - } - - if (tfilters->len >= 1) - g_object_set (setting, key, tfilters, NULL); -} - -/*****************************************************************************/ - -/* 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 -sriov_vfs_writer (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value) -{ - GPtrArray *vfs; - guint i; - - vfs = g_value_get_boxed (value); - if (!vfs) - return; - - for (i = 0; i < vfs->len; i++) { - const NMSriovVF *vf = vfs->pdata[i]; - gs_free char *kf_value = NULL; - char kf_key[32]; - - kf_value = nm_utils_sriov_vf_to_str (vf, TRUE, NULL); - if (!kf_value) - continue; - - nm_sprintf_buf (kf_key, "vf.%u", nm_sriov_vf_get_index (vf)); - - nm_keyfile_plugin_kf_set_string (info->keyfile, - nm_setting_get_name (setting), - kf_key, - kf_value); - } -} - -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 (int, 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) -{ - nm_auto_free_gstring GString *output = NULL; - int addr_family; - guint i; - const char *addr; - const char *gw; - guint32 plen; - char key_name[64]; - char *key_name_idx; - - if (!array->len) - return; - - addr_family = nm_streq (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 (addr_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, "%u", i + 1); - nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, output->str); - - if (is_route) { - gs_free char *attributes = NULL; - - attributes = nm_utils_format_variant_attributes (_nm_ip_route_get_attributes (array->pdata[i]), - ',', '='); - if (attributes) { - g_strlcat (key_name, "_options", sizeof (key_name)); - nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, attributes); - } - } - } -} - -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 -bridge_vlan_writer (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value) -{ - NMBridgeVlan *vlan; - GPtrArray *vlans; - GString *string; - guint i; - - vlans = (GPtrArray *) g_value_get_boxed (value); - if (!vlans || !vlans->len) - return; - - string = g_string_new (""); - for (i = 0; i < vlans->len; i++) { - gs_free char *vlan_str = NULL; - - vlan = vlans->pdata[i]; - vlan_str = nm_bridge_vlan_to_str (vlan, NULL); - if (!vlan_str) - continue; - if (string->len > 0) - g_string_append (string, ","); - nm_utils_escaped_tokens_escape_gstr_assert (vlan_str, ",", string); - } - - nm_keyfile_plugin_kf_set_string (info->keyfile, - nm_setting_get_name (setting), - "vlans", - string->str); - - g_string_free (string, TRUE); -} - - -#define ETHERNET_S390_OPTIONS_GROUP_NAME "ethernet-s390-options" - -static void -wired_s390_options_parser_full (KeyfileReaderInfo *info, - const NMMetaSettingInfo *setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty *pip, - NMSetting *setting) -{ - NMSettingWired *s_wired = NM_SETTING_WIRED (setting); - gs_strfreev char **keys = NULL; - gsize n_keys; - gsize i; - - keys = nm_keyfile_plugin_kf_get_keys (info->keyfile, ETHERNET_S390_OPTIONS_GROUP_NAME, &n_keys, NULL); - for (i = 0; i < n_keys; i++) { - gs_free char *value = NULL; - gs_free char *key_to_free = NULL; - - value = nm_keyfile_plugin_kf_get_string (info->keyfile, - ETHERNET_S390_OPTIONS_GROUP_NAME, - keys[i], - NULL); - if (!value) - continue; - - nm_setting_wired_add_s390_option (s_wired, - nm_keyfile_key_decode (keys[i], - &key_to_free), - value); - } -} - -static void -wired_s390_options_writer_full (KeyfileWriterInfo *info, - const NMMetaSettingInfo *setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty *pip, - NMSetting *setting) -{ - NMSettingWired *s_wired = NM_SETTING_WIRED (setting); - guint i, n; - - n = nm_setting_wired_get_num_s390_options (s_wired); - for (i = 0; i < n; i++) { - const char *opt_key; - const char *opt_val; - gs_free char *key_to_free = NULL; - - nm_setting_wired_get_s390_option (s_wired, i, &opt_key, &opt_val); - nm_keyfile_plugin_kf_set_string (info->keyfile, - ETHERNET_S390_OPTIONS_GROUP_NAME, - nm_keyfile_key_encode (opt_key, &key_to_free), - opt_val); - } -} - -static void -ip_routing_rule_writer_full (KeyfileWriterInfo *info, - const NMMetaSettingInfo *setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty *pip, - NMSetting *setting) -{ - const char *setting_name = nm_setting_get_name (setting); - NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting); - guint i, j, n; - char key_name_full[100] = "routing-rule"; - char *key_name_num = &key_name_full[NM_STRLEN ("routing-rule")]; - - n = nm_setting_ip_config_get_num_routing_rules (s_ip); - j = 0; - for (i = 0; i < n; i++) { - NMIPRoutingRule *rule = nm_setting_ip_config_get_routing_rule (s_ip, i); - gs_free char *str = NULL; - - str = nm_ip_routing_rule_to_string (rule, - NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE, - NULL, - NULL); - if (!str) - continue; - - sprintf (key_name_num, "%u", ++j); - nm_keyfile_plugin_kf_set_string (info->keyfile, - setting_name, - key_name_full, - str); - } -} - -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; - - nm_assert ( (NM_IS_SETTING_VPN (setting) && nm_streq (key, NM_SETTING_VPN_DATA)) - || (NM_IS_SETTING_VPN (setting) && nm_streq (key, NM_SETTING_VPN_SECRETS)) - || (NM_IS_SETTING_BOND (setting) && nm_streq (key, NM_SETTING_BOND_OPTIONS)) - || (NM_IS_SETTING_USER (setting) && nm_streq (key, NM_SETTING_USER_DATA))); - - /* Write VPN secrets out to a different group to keep them separate */ - if ( NM_IS_SETTING_VPN (setting) - && nm_streq (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++) { - gs_free char *to_free = NULL; - const char *property, *data; - - 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; - - if (!nm_setting_get_secret_flags (setting, property, &secret_flags, NULL)) - nm_assert_not_reached (); - if (!_secret_flags_persist_secret (secret_flags)) - continue; - } - - 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) { - gs_free char *path_free = NULL; - gs_free char *base_dir = NULL; - gs_free char *tmp = NULL; - const char *path; - - 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_free = g_strconcat (base_dir, "/", path, NULL); - path = path_free; - } 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 { - tmp = g_strconcat (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, path, NULL); - path = tmp; - } - - /* 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); - } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { - GBytes *blob; - const guint8 *blob_data; - gsize blob_len; - gs_free char *blob_base64 = NULL; - gs_free char *val = NULL; - - 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); - } 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 (nm_streq0 (nm_setting_8021x_scheme_vtable[i].setting_key, key)) { - 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); -} - -/*****************************************************************************/ - -struct _ParseInfoProperty { - const char *property_name; - union { - void (*parser) (KeyfileReaderInfo *info, - NMSetting *setting, - const char *key); - void (*parser_full) (KeyfileReaderInfo *info, - const NMMetaSettingInfo *setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty *pip, - NMSetting *setting); - }; - union { - void (*writer) (KeyfileWriterInfo *info, - NMSetting *setting, - const char *key, - const GValue *value); - void (*writer_full) (KeyfileWriterInfo *info, - const NMMetaSettingInfo *setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty *pip, - NMSetting *setting); - }; - bool parser_skip; - bool parser_no_check_key:1; - bool writer_skip:1; - bool has_writer_full:1; - bool has_parser_full: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; -}; - -#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 ParseInfoProperty*const*properties; -} ParseInfoSetting; - -#define PARSE_INFO_SETTING(setting_type, ...) \ - [setting_type] = (&((const ParseInfoSetting) { \ - __VA_ARGS__ \ - })) - -static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = { - PARSE_INFO_SETTING (NM_META_SETTING_TYPE_WIRELESS, - 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_META_SETTING_TYPE_802_1X, - 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_META_SETTING_TYPE_WIRED, - 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_PROPERTY (NM_SETTING_WIRED_S390_OPTIONS, - .parser_no_check_key = TRUE, - .parser_full = wired_s390_options_parser_full, - .writer_full = wired_s390_options_writer_full, - .has_parser_full = TRUE, - .has_writer_full = TRUE, - ), - ), - ), - PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BLUETOOTH, - PARSE_INFO_PROPERTIES ( - PARSE_INFO_PROPERTY (NM_SETTING_BLUETOOTH_BDADDR, - .parser = mac_address_parser_ETHER, - ), - ), - ), - PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BOND, - PARSE_INFO_PROPERTIES ( - PARSE_INFO_PROPERTY (NM_SETTING_BOND_OPTIONS, - .parser_no_check_key = TRUE, - ), - ), - ), - PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BRIDGE, - PARSE_INFO_PROPERTIES ( - PARSE_INFO_PROPERTY (NM_SETTING_BRIDGE_MAC_ADDRESS, - .parser = mac_address_parser_ETHER, - ), - PARSE_INFO_PROPERTY (NM_SETTING_BRIDGE_VLANS, - .parser_no_check_key = TRUE, - .parser = bridge_vlan_parser, - .writer = bridge_vlan_writer, - ), - ), - ), - PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BRIDGE_PORT, - PARSE_INFO_PROPERTIES ( - PARSE_INFO_PROPERTY (NM_SETTING_BRIDGE_PORT_VLANS, - .parser_no_check_key = TRUE, - .parser = bridge_vlan_parser, - .writer = bridge_vlan_writer, - ), - ), - ), - PARSE_INFO_SETTING (NM_META_SETTING_TYPE_CONNECTION, - 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_META_SETTING_TYPE_INFINIBAND, - PARSE_INFO_PROPERTIES ( - PARSE_INFO_PROPERTY (NM_SETTING_INFINIBAND_MAC_ADDRESS, - .parser = mac_address_parser_INFINIBAND, - ), - ), - ), - PARSE_INFO_SETTING (NM_META_SETTING_TYPE_IP4_CONFIG, - 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_PROPERTY (NM_SETTING_IP_CONFIG_ROUTING_RULES, - .parser_no_check_key = TRUE, - .parser_full = ip_routing_rule_parser_full, - .writer_full = ip_routing_rule_writer_full, - .has_parser_full = TRUE, - .has_writer_full = TRUE, - ), - ), - ), - PARSE_INFO_SETTING (NM_META_SETTING_TYPE_IP6_CONFIG, - 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_PROPERTY (NM_SETTING_IP_CONFIG_ROUTING_RULES, - .parser_no_check_key = TRUE, - .parser_full = ip_routing_rule_parser_full, - .writer_full = ip_routing_rule_writer_full, - .has_parser_full = TRUE, - .has_writer_full = TRUE, - ), - ), - ), - PARSE_INFO_SETTING (NM_META_SETTING_TYPE_SERIAL, - PARSE_INFO_PROPERTIES ( - PARSE_INFO_PROPERTY (NM_SETTING_SERIAL_PARITY, - .parser = parity_parser, - ), - ), - ), - PARSE_INFO_SETTING (NM_META_SETTING_TYPE_SRIOV, - PARSE_INFO_PROPERTIES ( - PARSE_INFO_PROPERTY (NM_SETTING_SRIOV_VFS, - .parser_no_check_key = TRUE, - .parser = sriov_vfs_parser, - .writer = sriov_vfs_writer, - ), - ), - ), - PARSE_INFO_SETTING (NM_META_SETTING_TYPE_TC_CONFIG, - 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_META_SETTING_TYPE_TEAM, - 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_META_SETTING_TYPE_TEAM_PORT, - 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_META_SETTING_TYPE_USER, - PARSE_INFO_PROPERTIES ( - PARSE_INFO_PROPERTY (NM_SETTING_USER_DATA, - .parser_no_check_key = TRUE, - ), - ), - ), - PARSE_INFO_SETTING (NM_META_SETTING_TYPE_VLAN, - PARSE_INFO_PROPERTIES ( - PARSE_INFO_PROPERTY (NM_SETTING_VLAN_FLAGS, - .writer_persist_default = TRUE, - ), - ), - ), - PARSE_INFO_SETTING (NM_META_SETTING_TYPE_VPN, - 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_META_SETTING_TYPE_WIMAX, - PARSE_INFO_PROPERTIES ( - PARSE_INFO_PROPERTY (NM_SETTING_WIMAX_MAC_ADDRESS, - .parser = mac_address_parser_ETHER, - ), - ), - ), -}; - -static void -_parse_info_find (NMSetting *setting, - const char *property_name, - const NMMetaSettingInfo **out_setting_info, - const ParseInfoSetting **out_parse_info_setting, - const ParseInfoProperty **out_parse_info_property) -{ - const NMMetaSettingInfo *setting_info; - const ParseInfoSetting *pis; - const ParseInfoProperty *pip; - -#if NM_MORE_ASSERTS > 10 - { - guint i, j; - static int asserted = FALSE; - - if (!asserted) { - for (i = 0; i < G_N_ELEMENTS (parse_infos); i++) { - pis = parse_infos[i]; - - if (!pis) - continue; - if (!pis->properties) - continue; - - g_assert (pis->properties[0]); - for (j = 0; pis->properties[j]; j++) { - const ParseInfoProperty *pip0; - const ParseInfoProperty *pipj = pis->properties[j]; - - g_assert (pipj->property_name); - if ( j > 0 - && (pip0 = pis->properties[j - 1]) - && strcmp (pip0->property_name, pipj->property_name) >= 0) { - g_error ("Wrong order at index #%d.%d: \"%s.%s\" before \"%s.%s\"", - i, j - 1, - nm_meta_setting_infos[i].setting_name, pip0->property_name, - nm_meta_setting_infos[i].setting_name, pipj->property_name); - } - } - } - asserted = TRUE; - } - } -#endif - - if ( !NM_IS_SETTING (setting) - || !(setting_info = NM_SETTING_GET_CLASS (setting)->setting_info)) { - /* handle invalid setting objects gracefully. */ - NM_SET_OUT (out_setting_info, NULL); - NM_SET_OUT (out_parse_info_setting, NULL); - NM_SET_OUT (out_parse_info_property, NULL); - return; - } - - nm_assert (setting_info->setting_name); - nm_assert (_NM_INT_NOT_NEGATIVE (setting_info->meta_type)); - nm_assert (setting_info->meta_type < G_N_ELEMENTS (parse_infos)); - - pis = parse_infos[setting_info->meta_type]; - - pip = NULL; - if ( pis - && property_name) { - gssize idx; - - G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (ParseInfoProperty, property_name) == 0); - - 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) - pip = pis->properties[idx]; - } - - NM_SET_OUT (out_setting_info, setting_info); - NM_SET_OUT (out_parse_info_setting, pis); - NM_SET_OUT (out_parse_info_property, pip); -} - -/*****************************************************************************/ - -static void -read_one_setting_value (KeyfileReaderInfo *info, - NMSetting *setting, - const NMSettInfoProperty *property_info) -{ - GKeyFile *keyfile = info->keyfile; - gs_free_error GError *err = NULL; - const NMMetaSettingInfo *setting_info; - const ParseInfoProperty *pip; - gs_free char *tmp_str = NULL; - const char *key; - GType type; - guint64 u64; - gint64 i64; - - nm_assert (!info->error); - nm_assert ( !property_info->param_spec - || nm_streq (property_info->param_spec->name, property_info->name)); - - key = property_info->name; - - _parse_info_find (setting, key, &setting_info, NULL, &pip); - - nm_assert (setting_info); - - if (!pip) { - if (nm_streq (key, NM_SETTING_NAME)) - return; - if (!property_info->param_spec) - return; - if ((property_info->param_spec->flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) != G_PARAM_WRITABLE) - return; - } else { - if (pip->parser_skip) - return; - if (pip->has_parser_full) { - pip->parser_full (info, setting_info, property_info, pip, setting); - return; - } - } - - nm_assert (property_info->param_spec); - nm_assert ((property_info->param_spec->flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) == G_PARAM_WRITABLE); - - /* 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 ( (!pip || !pip->parser_no_check_key) - && !nm_keyfile_plugin_kf_has_key (keyfile, setting_info->setting_name, key, &err)) { - /* Key doesn't exist or an error occurred, thus nothing to do. */ - if (err) { - if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("error loading setting value: %s"), - err->message)) - return; - } - return; - } - - if ( pip - && pip->parser) { - pip->parser (info, setting, key); - return; - } - - type = G_PARAM_SPEC_VALUE_TYPE (property_info->param_spec); - - if (type == G_TYPE_STRING) { - gs_free char *str_val = NULL; - - str_val = nm_keyfile_plugin_kf_get_string (keyfile, setting_info->setting_name, key, &err); - if (!err) - nm_g_object_set_property_string_take (G_OBJECT (setting), key, g_steal_pointer (&str_val), &err); - } else if (type == G_TYPE_UINT) { - tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_info->setting_name, key, &err); - if (!err) { - u64 = _nm_utils_ascii_str_to_uint64 (tmp_str, 0, 0, G_MAXUINT, G_MAXUINT64); - if ( u64 == G_MAXUINT64 - && errno != 0) { - g_set_error_literal (&err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE, - _("value cannot be interpreted as integer")); - } else - nm_g_object_set_property_uint (G_OBJECT (setting), key, u64, &err); - } - } else if (type == G_TYPE_INT) { - tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_info->setting_name, key, &err); - if (!err) { - i64 = _nm_utils_ascii_str_to_int64 (tmp_str, 0, G_MININT, G_MAXINT, G_MININT64); - if ( i64 == G_MININT64 - && errno != 0) { - g_set_error_literal (&err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE, - _("value cannot be interpreted as integer")); - } else - nm_g_object_set_property_int (G_OBJECT (setting), key, i64, &err); - } - } else if (type == G_TYPE_BOOLEAN) { - gboolean bool_val; - - bool_val = nm_keyfile_plugin_kf_get_boolean (keyfile, setting_info->setting_name, key, &err); - if (!err) - nm_g_object_set_property_boolean (G_OBJECT (setting), key, bool_val, &err); - } else if (type == G_TYPE_CHAR) { - tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_info->setting_name, key, &err); - if (!err) { - /* As documented by glib, G_TYPE_CHAR is really a (signed!) gint8. */ - i64 = _nm_utils_ascii_str_to_int64 (tmp_str, 0, G_MININT8, G_MAXINT8, G_MININT64); - if ( i64 == G_MININT64 - && errno != 0) { - g_set_error_literal (&err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE, - _("value cannot be interpreted as integer")); - } else - nm_g_object_set_property_char (G_OBJECT (setting), key, i64, &err); - } - } else if (type == G_TYPE_UINT64) { - tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_info->setting_name, key, &err); - if (!err) { - u64 = _nm_utils_ascii_str_to_uint64 (tmp_str, 0, 0, G_MAXUINT64, G_MAXUINT64); - if ( u64 == G_MAXUINT64 - && errno != 0) { - g_set_error_literal (&err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE, - _("value cannot be interpreted as integer")); - } else - nm_g_object_set_property_uint64 (G_OBJECT (setting), key, u64, &err); - } - } else if (type == G_TYPE_INT64) { - tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_info->setting_name, key, &err); - if (!err) { - i64 = _nm_utils_ascii_str_to_int64 (tmp_str, 0, G_MININT64, G_MAXINT64, G_MAXINT64); - if ( i64 == G_MAXINT64 - && errno != 0) { - g_set_error_literal (&err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE, - _("value cannot be interpreted as integer")); - } else - nm_g_object_set_property_int64 (G_OBJECT (setting), key, i64, &err); - } - } else if (type == G_TYPE_BYTES) { - gs_free int *tmp = NULL; - GByteArray *array; - GBytes *bytes; - gsize length; - int i; - gboolean already_warned = FALSE; - - tmp = nm_keyfile_plugin_kf_get_integer_list (keyfile, setting_info->setting_name, key, &length, NULL); - - array = g_byte_array_sized_new (length); - for (i = 0; i < length; i++) { - const int val = tmp[i]; - unsigned char v = (unsigned char) (val & 0xFF); - - if (val < 0 || val > 255) { - if ( !already_warned - && !handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid byte element '%d' (not between 0 and 255 inclusive)"), - val)) { - g_byte_array_unref (array); - return; - } - already_warned = TRUE; - } else - g_byte_array_append (array, (const unsigned char *) &v, sizeof (v)); - } - - bytes = g_byte_array_free_to_bytes (array); - g_object_set (setting, key, bytes, NULL); - g_bytes_unref (bytes); - } else if (type == G_TYPE_STRV) { - gs_strfreev char **sa = NULL; - gsize length; - - sa = nm_keyfile_plugin_kf_get_string_list (keyfile, setting_info->setting_name, key, &length, NULL); - g_object_set (setting, key, sa, NULL); - } else if (type == G_TYPE_HASH_TABLE) { - read_hash_of_string (keyfile, setting, key); - } else if (type == G_TYPE_ARRAY) { - read_array_of_uint (keyfile, setting, key); - } else if (G_TYPE_IS_FLAGS (type)) { - tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_info->setting_name, key, &err); - if (!err) { - u64 = _nm_utils_ascii_str_to_uint64 (tmp_str, 0, 0, G_MAXUINT, G_MAXUINT64); - if ( u64 == G_MAXUINT64 - && errno != 0) { - g_set_error_literal (&err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE, - _("value cannot be interpreted as integer")); - } else - nm_g_object_set_property_flags (G_OBJECT (setting), key, type, u64, &err); - } - } else if (G_TYPE_IS_ENUM (type)) { - tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_info->setting_name, key, &err); - if (!err) { - i64 = _nm_utils_ascii_str_to_int64 (tmp_str, 0, G_MININT, G_MAXINT, G_MAXINT64); - if ( i64 == G_MAXINT64 - && errno != 0) { - g_set_error_literal (&err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE, - _("value cannot be interpreted as integer")); - } else - nm_g_object_set_property_enum (G_OBJECT (setting), key, type, i64, &err); - } - } else - g_return_if_reached (); - - if (err) { - if ( err->domain == G_KEY_FILE_ERROR - && NM_IN_SET (err->code, G_KEY_FILE_ERROR_GROUP_NOT_FOUND, - G_KEY_FILE_ERROR_KEY_NOT_FOUND)) { - /* ignore such errors. The key is not present. */ - } else { - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid setting: %s"), err->message); - } - } -} - -static void -_read_setting (KeyfileReaderInfo *info) -{ - const NMSettInfoSetting *sett_info; - gs_unref_object NMSetting *setting = NULL; - const char *alias; - GType type; - guint i; - - alias = nm_keyfile_plugin_get_setting_name_for_alias (info->group); - if (!alias) - alias = info->group; - - type = nm_setting_lookup_type (alias); - if (!type) { - handle_warn (info, NULL, NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid setting name '%s'"), info->group); - return; - } - - setting = g_object_new (type, NULL); - - info->setting = setting; - - sett_info = _nm_setting_class_get_sett_info (NM_SETTING_GET_CLASS (setting)); - - if (sett_info->detail.gendata_info) { - gs_free char **keys = NULL; - gsize k, n_keys; - - keys = g_key_file_get_keys (info->keyfile, info->group, &n_keys, NULL); - if (!keys) - n_keys = 0; - if (n_keys > 0) { - GHashTable *h = _nm_setting_gendata_hash (setting, TRUE); - - nm_utils_strv_sort (keys, n_keys); - for (k = 0; k < n_keys; k++) { - gs_free char *key = keys[k]; - gs_free_error GError *local = NULL; - const GVariantType *variant_type; - GVariant *variant; - - /* a GKeyFile can return duplicate keys, there is just no API to make sense - * of them. Skip them. */ - if ( k + 1 < n_keys - && nm_streq (key, keys[k + 1])) - continue; - - /* currently, the API is very simple. The setting class just returns - * the desired variant type, and keyfile reader will try to parse - * it accordingly. Note, that this does currently not allow, that - * a particular key can contain different variant types, nor is it - * very flexible in general. - * - * We add flexibility when we need it. Keep it simple for now. */ - variant_type = sett_info->detail.gendata_info->get_variant_type (sett_info, - key, - &local); - if (!variant_type) { - if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid key '%s.%s'"), - info->group, key)) - break; - continue; - } - - if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_BOOLEAN)) { - gboolean v; - - v = g_key_file_get_boolean (info->keyfile, - info->group, - key, - &local); - if (local) { - if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("key '%s.%s' is not boolean"), - info->group, key)) - break; - continue; - } - variant = g_variant_new_boolean (v); - } else { - nm_assert_not_reached (); - continue; - } - - g_hash_table_insert (h, - g_steal_pointer (&key), - g_variant_take_ref (variant)); - } - for (; k < n_keys; k++) - g_free (keys[k]); - } - } - - for (i = 0; i < sett_info->property_infos_len; i++) { - read_one_setting_value (info, - setting, - &sett_info->property_infos[i]); - if (info->error) - goto out; - } - -out: - info->setting = NULL; - if (!info->error) - nm_connection_add_setting (info->connection, g_steal_pointer (&setting)); -} - -static void -_read_setting_wireguard_peer (KeyfileReaderInfo *info) -{ - gs_unref_object NMSettingWireGuard *s_wg_new = NULL; - nm_auto_unref_wgpeer NMWireGuardPeer *peer = NULL; - gs_free_error GError *error = NULL; - NMSettingWireGuard *s_wg; - gs_free char *str = NULL; - const char *cstr = NULL; - const char *key; - gint64 i64; - gs_strfreev char **sa = NULL; - gsize n_sa; - - peer = nm_wireguard_peer_new (); - - nm_assert (g_str_has_prefix (info->group, NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER)); - cstr = &info->group[NM_STRLEN (NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER)]; - if ( !nm_utils_base64secret_normalize (cstr, NM_WIREGUARD_PUBLIC_KEY_LEN, &str) - || !nm_streq0 (str, cstr)) { - /* the group name must be identical to the normalized(!) key, so that it - * is uniquely identified. */ - handle_warn (info, NULL, NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid peer public key in section '%s'"), - info->group); - return; - } - nm_wireguard_peer_set_public_key (peer, cstr, TRUE); - nm_clear_g_free (&str); - - key = NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY; - str = nm_keyfile_plugin_kf_get_string (info->keyfile, info->group, key, NULL); - if (str) { - if (!nm_wireguard_peer_set_preshared_key (peer, str, FALSE)) { - if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("key '%s.%s' is not a valid 256 bit key in base64 encoding"), - info->group, key)) - return; - } - nm_clear_g_free (&str); - } - - key = NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS; - i64 = nm_keyfile_plugin_kf_get_int64 (info->keyfile, info->group, key, 0, 0, NM_SETTING_SECRET_FLAG_ALL, -1, NULL); - if (errno != ENODATA) { - if ( i64 == -1 - || !_nm_setting_secret_flags_valid (i64)) { - if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("key '%s.%s' is not a valid secret flag"), - info->group, key)) - return; - } else - nm_wireguard_peer_set_preshared_key_flags (peer, i64); - } - - key = NM_WIREGUARD_PEER_ATTR_PERSISTENT_KEEPALIVE; - i64 = nm_keyfile_plugin_kf_get_int64 (info->keyfile, info->group, key, 0, 0, G_MAXUINT32, -1, NULL); - if (errno != ENODATA) { - if (i64 == -1) { - if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("key '%s.%s' is not a integer in range 0 to 2^32"), - info->group, key)) - return; - } else - nm_wireguard_peer_set_persistent_keepalive (peer, i64); - } - - key = NM_WIREGUARD_PEER_ATTR_ENDPOINT; - str = nm_keyfile_plugin_kf_get_string (info->keyfile, info->group, key, NULL); - if (str && str[0]) { - if (!nm_wireguard_peer_set_endpoint (peer, str, FALSE)) { - if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("key '%s.%s' is not a valid endpoint"), - info->group, key)) - return; - } - } - nm_clear_g_free (&str); - - key = NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS; - sa = nm_keyfile_plugin_kf_get_string_list (info->keyfile, info->group, key, &n_sa, NULL); - if (n_sa > 0) { - gboolean has_error = FALSE; - gsize i; - - for (i = 0; i < n_sa; i++) { - if (!nm_utils_parse_inaddr_prefix_bin (AF_UNSPEC, sa[i], NULL, NULL, NULL)) { - has_error = TRUE; - continue; - } - nm_wireguard_peer_append_allowed_ip (peer, sa[i], TRUE); - } - if (has_error) { - if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("key '%s.%s' has invalid allowed-ips"), - info->group, key)) - return; - } - } - nm_clear_pointer (&sa, g_strfreev); - - if (info->error) - return; - - if (!nm_wireguard_peer_is_valid (peer, TRUE, TRUE, &error)) { - handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("peer '%s' is invalid: %s"), - info->group, error->message); - return; - } - - s_wg = NM_SETTING_WIREGUARD (nm_connection_get_setting (info->connection, NM_TYPE_SETTING_WIREGUARD)); - if (!s_wg) { - s_wg_new = NM_SETTING_WIREGUARD (nm_setting_wireguard_new ()); - s_wg = s_wg_new; - } - - nm_setting_wireguard_append_peer (s_wg, peer); - - if (s_wg_new) { - nm_connection_add_setting (info->connection, - NM_SETTING (g_steal_pointer (&s_wg_new))); - } -} - -static void -_read_setting_vpn_secrets (KeyfileReaderInfo *info) -{ - gs_strfreev char **keys = NULL; - gsize i, n_keys; - NMSettingVpn *s_vpn; - - s_vpn = nm_connection_get_setting_vpn (info->connection); - if (!s_vpn) { - /* if we don't also have a [vpn] section (which must be parsed earlier), - * we don't do anything. */ - nm_assert (!g_key_file_has_group (info->keyfile, "vpn")); - return; - } - - keys = nm_keyfile_plugin_kf_get_keys (info->keyfile, NM_KEYFILE_GROUP_VPN_SECRETS, &n_keys, NULL); - for (i = 0; i < n_keys; i++) { - gs_free char *secret = NULL; - - secret = nm_keyfile_plugin_kf_get_string (info->keyfile, NM_KEYFILE_GROUP_VPN_SECRETS, keys[i], NULL); - if (secret) - nm_setting_vpn_add_secret (s_vpn, keys[i], secret); - } -} - -gboolean -nm_keyfile_read_ensure_id (NMConnection *connection, - const char *fallback_id) -{ - NMSettingConnection *s_con; - - g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); - g_return_val_if_fail (fallback_id, FALSE); - - s_con = nm_connection_get_setting_connection (connection); - g_return_val_if_fail (NM_IS_SETTING_CONNECTION (s_con), FALSE); - - if (nm_setting_connection_get_id (s_con)) - return FALSE; - - g_object_set (s_con, NM_SETTING_CONNECTION_ID, fallback_id, NULL); - return TRUE; -} - -gboolean -nm_keyfile_read_ensure_uuid (NMConnection *connection, - const char *fallback_uuid_seed) -{ - NMSettingConnection *s_con; - gs_free char *hashed_uuid = NULL; - - g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); - g_return_val_if_fail (fallback_uuid_seed, FALSE); - - s_con = nm_connection_get_setting_connection (connection); - g_return_val_if_fail (NM_IS_SETTING_CONNECTION (s_con), FALSE); - - if (nm_setting_connection_get_uuid (s_con)) - return FALSE; - - hashed_uuid = _nm_utils_uuid_generate_from_strings ("keyfile", fallback_uuid_seed, NULL); - g_object_set (s_con, NM_SETTING_CONNECTION_UUID, hashed_uuid, NULL); - return TRUE; -} - -/** - * nm_keyfile_read: - * @keyfile: the keyfile from which to create the connection - * @base_dir: when reading certificates from files with relative name, - * the relative path is made absolute using @base_dir. This must - * be an absolute path. - * @handler: read handler - * @user_data: user data for read handler - * @error: error - * - * Tries to create a NMConnection from a keyfile. The resulting keyfile is - * not normalized and might not even verify. - * - * Returns: (transfer full): on success, returns the created connection. - */ -NMConnection * -nm_keyfile_read (GKeyFile *keyfile, - const char *base_dir, - NMKeyfileReadHandler handler, - void *user_data, - GError **error) -{ - gs_unref_object NMConnection *connection = NULL; - NMSettingConnection *s_con; - gs_strfreev char **groups = NULL; - gsize n_groups; - gsize i; - gboolean vpn_secrets = FALSE; - KeyfileReaderInfo info; - - g_return_val_if_fail (keyfile, NULL); - g_return_val_if_fail (!error || !*error, NULL); - g_return_val_if_fail (base_dir && base_dir[0] == '/', NULL); - - connection = nm_simple_connection_new (); - - info = (KeyfileReaderInfo) { - .connection = connection, - .keyfile = keyfile, - .base_dir = base_dir, - .handler = handler, - .user_data = user_data, - }; - - groups = g_key_file_get_groups (keyfile, &n_groups); - if (!groups) - n_groups = 0; - - for (i = 0; i < n_groups; i++) { - - info.group = groups[i]; - - if (nm_streq (groups[i], NM_KEYFILE_GROUP_VPN_SECRETS)) { - /* Only read out secrets when needed */ - vpn_secrets = TRUE; - } else if (NM_STR_HAS_PREFIX (groups[i], NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER)) - _read_setting_wireguard_peer (&info); - else if (nm_streq (groups[i], NM_KEYFILE_GROUP_NMMETA)) { - /* pass */ - } else - _read_setting (&info); - - info.group = NULL; - - if (info.error) - goto out_with_info_error; - } - - s_con = nm_connection_get_setting_connection (connection); - if (!s_con) { - s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ()); - nm_connection_add_setting (connection, NM_SETTING (s_con)); - } - - /* Make sure that we have 'interface-name' even if it was specified in the - * "wrong" (ie, deprecated) group. - */ - if ( !nm_setting_connection_get_interface_name (s_con) - && nm_setting_connection_get_connection_type (s_con)) { - gs_free char *interface_name = NULL; - - interface_name = g_key_file_get_string (keyfile, - nm_setting_connection_get_connection_type (s_con), - "interface-name", - NULL); - if (interface_name) - g_object_set (s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, interface_name, NULL); - } - - if (vpn_secrets) { - info.group = NM_KEYFILE_GROUP_VPN_SECRETS; - _read_setting_vpn_secrets (&info); - info.group = NULL;; - if (info.error) - goto out_with_info_error; - } - - return g_steal_pointer (&connection); - -out_with_info_error: - g_propagate_error (error, info.error); - return NULL; -} - -/*****************************************************************************/ - -static void -write_setting_value (KeyfileWriterInfo *info, - NMSetting *setting, - const NMSettInfoProperty *property_info) -{ - const NMMetaSettingInfo *setting_info; - const ParseInfoProperty *pip; - const char *key; - char numstr[64]; - GValue value; - GType type; - - nm_assert (!info->error); - nm_assert ( !property_info->param_spec - || nm_streq (property_info->param_spec->name, property_info->name)); - - key = property_info->name; - - _parse_info_find (setting, key, &setting_info, NULL, &pip); - - if (!pip) { - if (!setting_info) { - /* the setting type is unknown. That is highly unexpected - * (and as this is currently only called from NetworkManager - * daemon, not possible). - * - * Still, handle it gracefully, because later keyfile writer will become - * public API of libnm, where @setting is (untrusted) user input. - * - * Gracefully here just means: ignore the setting. */ - return; - } - if (!property_info->param_spec) - return; - if (nm_streq (key, NM_SETTING_NAME)) - return; - } else { - if (pip->has_writer_full) { - pip->writer_full (info, setting_info, property_info, pip, setting); - return; - } - if (pip->writer_skip) - return; - } - - nm_assert (property_info->param_spec); - - /* 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 ( (property_info->param_spec->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_return_if_reached (); - if (!_secret_flags_persist_secret (secret_flags)) - return; - } - - value = (GValue) { 0 }; - - g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (property_info->param_spec)); - g_object_get_property (G_OBJECT (setting), property_info->param_spec->name, &value); - - if ( (!pip || !pip->writer_persist_default) - && g_param_value_defaults (property_info->param_spec, &value)) { - nm_assert (!g_key_file_has_key (info->keyfile, setting_info->setting_name, key, NULL)); - goto out_unset_value; - } - - if ( pip - && pip->writer) { - pip->writer (info, setting, key, &value); - goto out_unset_value; - } - - 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_info->setting_name, key, str); - } else if (type == G_TYPE_UINT) { - nm_sprintf_buf (numstr, "%u", g_value_get_uint (&value)); - nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key, numstr); - } else if (type == G_TYPE_INT) { - nm_sprintf_buf (numstr, "%d", g_value_get_int (&value)); - nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key, numstr); - } else if (type == G_TYPE_UINT64) { - nm_sprintf_buf (numstr, "%" G_GUINT64_FORMAT, g_value_get_uint64 (&value)); - nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key, numstr); - } else if (type == G_TYPE_INT64) { - nm_sprintf_buf (numstr, "%" G_GINT64_FORMAT, g_value_get_int64 (&value)); - nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key, numstr); - } else if (type == G_TYPE_BOOLEAN) { - nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key, - g_value_get_boolean (&value) - ? "true" - : "false"); - } else if (type == G_TYPE_CHAR) { - nm_sprintf_buf (numstr, "%d", (int) g_value_get_schar (&value)); - nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key, numstr); - } 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_info->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_info->setting_name, key, (const char **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)) { - nm_sprintf_buf (numstr, "%u", g_value_get_flags (&value)); - nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key, numstr); - } else if (G_VALUE_HOLDS_ENUM (&value)) { - nm_sprintf_buf (numstr, "%d", g_value_get_enum (&value)); - nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key, numstr); - } else - g_return_if_reached (); - -out_unset_value: - g_value_unset (&value); -} - -static void -_write_setting_wireguard (NMSetting *setting, KeyfileWriterInfo *info) -{ - NMSettingWireGuard *s_wg; - guint i_peer, n_peers; - - s_wg = NM_SETTING_WIREGUARD (setting); - - n_peers = nm_setting_wireguard_get_peers_len (s_wg); - for (i_peer = 0; i_peer < n_peers; i_peer++) { - NMWireGuardPeer *peer = nm_setting_wireguard_get_peer (s_wg, i_peer); - const char *public_key; - char group[NM_STRLEN (NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER) + 200]; - NMSettingSecretFlags secret_flags; - gboolean any_key = FALSE; - guint i_aip, n_aip; - const char *cstr; - guint32 u32; - - public_key = nm_wireguard_peer_get_public_key (peer); - if ( !public_key - || !public_key[0] - || !NM_STRCHAR_ALL (public_key, ch, nm_sd_utils_unbase64char (ch, TRUE) >= 0)) { - /* invalid peer. Skip it */ - continue; - } - - if (g_snprintf (group, - sizeof (group), - "%s%s", - NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER, - nm_wireguard_peer_get_public_key (peer)) >= sizeof (group)) { - /* Too long. Not a valid public key. Skip the peer. */ - continue; - } - - cstr = nm_wireguard_peer_get_endpoint (peer); - if (cstr) { - g_key_file_set_string (info->keyfile, group, NM_WIREGUARD_PEER_ATTR_ENDPOINT, cstr); - any_key = TRUE; - } - - secret_flags = nm_wireguard_peer_get_preshared_key_flags (peer); - if (_secret_flags_persist_secret (secret_flags)) { - cstr = nm_wireguard_peer_get_preshared_key (peer); - if (cstr) { - g_key_file_set_string (info->keyfile, group, NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, cstr); - any_key = TRUE; - } - } - - /* usually, we don't persist the secret-flags 0 (because they are the default). - * For WireGuard peers, the default secret-flags for preshared-key are 4 (not-required). - * So, in this case behave differently: a missing preshared-key-flag setting means - * "not-required". */ - if (secret_flags != NM_SETTING_SECRET_FLAG_NOT_REQUIRED) { - g_key_file_set_int64 (info->keyfile, group, NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS, secret_flags); - any_key = TRUE; - } - - u32 = nm_wireguard_peer_get_persistent_keepalive (peer); - if (u32) { - g_key_file_set_uint64 (info->keyfile, group, NM_WIREGUARD_PEER_ATTR_PERSISTENT_KEEPALIVE, u32); - any_key = TRUE; - } - - n_aip = nm_wireguard_peer_get_allowed_ips_len (peer); - if (n_aip > 0) { - gs_free const char **strv = NULL; - - strv = g_new (const char *, ((gsize) n_aip) + 1); - for (i_aip = 0; i_aip < n_aip; i_aip++) - strv[i_aip] = nm_wireguard_peer_get_allowed_ip (peer, i_aip, NULL); - strv[n_aip] = NULL; - g_key_file_set_string_list (info->keyfile, group, NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS, - strv, n_aip); - any_key = TRUE; - } - - if (!any_key) { - /* we cannot omit all keys. At an empty endpoint. */ - g_key_file_set_string (info->keyfile, group, NM_WIREGUARD_PEER_ATTR_ENDPOINT, ""); - } - } -} - -GKeyFile * -nm_keyfile_write (NMConnection *connection, - NMKeyfileWriteHandler handler, - void *user_data, - GError **error) -{ - gs_unref_keyfile GKeyFile *keyfile = NULL; - KeyfileWriterInfo info; - gs_free NMSetting **settings = NULL; - guint i, j, n_settings = 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; - - keyfile = g_key_file_new (); - - info = (KeyfileWriterInfo) { - .connection = connection, - .keyfile = keyfile, - .error = NULL, - .handler = handler, - .user_data = user_data, - }; - - settings = nm_connection_get_settings (connection, &n_settings); - for (i = 0; i < n_settings; i++) { - const NMSettInfoSetting *sett_info; - NMSetting *setting = settings[i]; - const char *setting_name; - const char *setting_alias; - - sett_info = _nm_setting_class_get_sett_info (NM_SETTING_GET_CLASS (setting)); - - setting_name = sett_info->setting_class->setting_info->setting_name; - - if (sett_info->detail.gendata_info) { - guint k, n_keys; - const char *const*keys; - - nm_assert (!nm_keyfile_plugin_get_alias_for_setting_name (sett_info->setting_class->setting_info->setting_name)); - - n_keys = _nm_setting_gendata_get_all (setting, &keys, NULL); - - if (n_keys > 0) { - GHashTable *h = _nm_setting_gendata_hash (setting, FALSE); - - for (k = 0; k < n_keys; k++) { - const char *key = keys[k]; - GVariant *v; - - v = g_hash_table_lookup (h, key); - - if (g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)) { - g_key_file_set_boolean (info.keyfile, - setting_name, - key, - g_variant_get_boolean (v)); - } else { - /* BUG: The variant type is not implemented. Since the connection - * verifies, this can only mean we either wrongly didn't reject - * the connection as invalid, or we didn't properly implement the - * variant type. */ - nm_assert_not_reached (); - continue; - } - } - } - } - - for (j = 0; j < sett_info->property_infos_len; j++) { - const NMSettInfoProperty *property_info = _nm_sett_info_property_info_get_sorted (sett_info, j); - - write_setting_value (&info, setting, property_info); - if (info.error) - goto out_with_info_error; - } - - setting_alias = nm_keyfile_plugin_get_alias_for_setting_name (setting_name); - if ( ( setting_alias - && g_key_file_has_group (info.keyfile, setting_alias)) - || g_key_file_has_group (info.keyfile, setting_name)) { - /* we have a section for the setting. Nothing to do. */ - } else { - /* ensure the group is present. There is no API for that, so add and remove - * a dummy key. */ - g_key_file_set_value (info.keyfile, setting_alias ?: setting_name, ".X", "1"); - g_key_file_remove_key (info.keyfile, setting_alias ?: setting_name, ".X", NULL); - } - - if (NM_IS_SETTING_WIREGUARD (setting)) { - _write_setting_wireguard (setting, &info); - if (info.error) - goto out_with_info_error; - } - - nm_assert (!info.error); - } - - nm_assert (!info.error); - - return g_steal_pointer (&keyfile); - -out_with_info_error: - g_propagate_error (error, info.error); - return NULL; -} - -/*****************************************************************************/ - -static const char temp_letters[] = -"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - -/* - * Check '.[a-zA-Z0-9]{6}' file suffix used for temporary files by g_file_set_contents() (mkstemp()). - */ -static gboolean -check_mkstemp_suffix (const char *path) -{ - const char *ptr; - - nm_assert (path); - - /* Matches *.[a-zA-Z0-9]{6} suffix of mkstemp()'s temporary files */ - ptr = strrchr (path, '.'); - if ( ptr - && strspn (&ptr[1], temp_letters) == 6 - && ptr[7] == '\0') - return TRUE; - return FALSE; -} - -static gboolean -_check_suffix_impl (const char *base, const char *tag, gsize tag_len) -{ - gsize len; - - nm_assert (base); - nm_assert (tag); - nm_assert (strlen (tag) == tag_len); - - len = strlen (base); - if ( len > tag_len - && !g_ascii_strcasecmp (base + len - tag_len, tag)) - return TRUE; - return FALSE; -} -#define check_suffix(base, tag) _check_suffix_impl ((base), ""tag"", NM_STRLEN (tag)) - -#define SWP_TAG ".swp" -#define SWPX_TAG ".swpx" -#define PEM_TAG ".pem" -#define DER_TAG ".der" - -gboolean -nm_keyfile_utils_ignore_filename (const char *filename, gboolean require_extension) -{ - const char *base; - gsize l; - - /* ignore_filename() must mirror nm_keyfile_utils_create_filename() */ - - g_return_val_if_fail (filename, TRUE); - - base = strrchr (filename, '/'); - if (base) - base++; - else - base = filename; - - if (!base[0]) { - /* this check above with strrchr() also rejects "/some/path/with/trailing/slash/", - * but that is fine, because such a path would name a directory, and we are not - * interested in directories. */ - return TRUE; - } - - if (base[0] == '.') { - /* don't allow hidden files */ - return TRUE; - } - - l = strlen (base); - - if (require_extension) { - if ( l <= NM_STRLEN (NM_KEYFILE_PATH_SUFFIX_NMCONNECTION) - || !NM_STR_HAS_SUFFIX (base, NM_KEYFILE_PATH_SUFFIX_NMCONNECTION)) - return TRUE; - return FALSE; - } - - /* Ignore backup files */ - if (base[l - 1] == '~') - return TRUE; - - /* Ignore temporary files - * - * This check is also important to ignore .nmload files (see - * %NM_KEYFILE_PATH_SUFFIX_NMMETA). */ - if (check_mkstemp_suffix (base)) - return TRUE; - - /* Ignore 802.1x certificates and keys */ - if ( check_suffix (base, PEM_TAG) - || check_suffix (base, DER_TAG)) - return TRUE; - - return FALSE; -} - -char * -nm_keyfile_utils_create_filename (const char *name, - gboolean with_extension) -{ - GString *str; - const char *f = name; - /* keyfile used to escape with '*', do not change that behavior. - * - * But for newly added escapings, use '_' instead. - * Also, @with_extension is new-style. */ - const char ESCAPE_CHAR = with_extension ? '_' : '*'; - const char ESCAPE_CHAR2 = '_'; - - g_return_val_if_fail (name && name[0], NULL); - - str = g_string_sized_new (60); - - /* Convert '/' to ESCAPE_CHAR */ - for (f = name; f[0]; f++) { - if (f[0] == '/') - g_string_append_c (str, ESCAPE_CHAR); - else - g_string_append_c (str, f[0]); - } - - /* nm_keyfile_utils_create_filename() must avoid anything that ignore_filename() would reject. - * We can escape here more aggressivly then what we would read back. */ - if (str->str[0] == '.') - str->str[0] = ESCAPE_CHAR2; - if (str->str[str->len - 1] == '~') - str->str[str->len - 1] = ESCAPE_CHAR2; - if ( check_mkstemp_suffix (str->str) - || check_suffix (str->str, PEM_TAG) - || check_suffix (str->str, DER_TAG)) - g_string_append_c (str, ESCAPE_CHAR2); - - if (with_extension) - g_string_append (str, NM_KEYFILE_PATH_SUFFIX_NMCONNECTION); - - /* nm_keyfile_utils_create_filename() must mirror ignore_filename() */ - nm_assert (!strchr (str->str, '/')); - nm_assert (!nm_keyfile_utils_ignore_filename (str->str, with_extension)); - - return g_string_free (str, FALSE);; -} diff --git a/libnm-core/nm-setting-6lowpan.c b/libnm-core/nm-setting-6lowpan.c index d6aa5978..a25910ea 100644 --- a/libnm-core/nm-setting-6lowpan.c +++ b/libnm-core/nm-setting-6lowpan.c @@ -214,7 +214,6 @@ nm_setting_6lowpan_class_init (NMSetting6LowpanClass *klass) g_param_spec_string (NM_SETTING_6LOWPAN_PARENT, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-8021x.c b/libnm-core/nm-setting-8021x.c index 8464100d..ade34ff5 100644 --- a/libnm-core/nm-setting-8021x.c +++ b/libnm-core/nm-setting-8021x.c @@ -92,6 +92,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSetting8021x, PROP_SUBJECT_MATCH, PROP_ALTSUBJECT_MATCHES, PROP_DOMAIN_SUFFIX_MATCH, + PROP_DOMAIN_MATCH, PROP_CLIENT_CERT, PROP_CLIENT_CERT_PASSWORD, PROP_CLIENT_CERT_PASSWORD_FLAGS, @@ -108,6 +109,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSetting8021x, PROP_PHASE2_SUBJECT_MATCH, PROP_PHASE2_ALTSUBJECT_MATCHES, PROP_PHASE2_DOMAIN_SUFFIX_MATCH, + PROP_PHASE2_DOMAIN_MATCH, PROP_PHASE2_CLIENT_CERT, PROP_PHASE2_CLIENT_CERT_PASSWORD, PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS, @@ -135,45 +137,47 @@ typedef struct { char *pac_file; GBytes *ca_cert; char *ca_cert_password; - NMSettingSecretFlags ca_cert_password_flags; char *ca_path; char *subject_match; GSList *altsubject_matches; char *domain_suffix_match; + char *domain_match; GBytes *client_cert; char *client_cert_password; - NMSettingSecretFlags client_cert_password_flags; char *phase1_peapver; char *phase1_peaplabel; char *phase1_fast_provisioning; - NMSetting8021xAuthFlags phase1_auth_flags; char *phase2_auth; char *phase2_autheap; GBytes *phase2_ca_cert; char *phase2_ca_cert_password; - NMSettingSecretFlags phase2_ca_cert_password_flags; char *phase2_ca_path; char *phase2_subject_match; GSList *phase2_altsubject_matches; char *phase2_domain_suffix_match; + char *phase2_domain_match; GBytes *phase2_client_cert; char *phase2_client_cert_password; - NMSettingSecretFlags phase2_client_cert_password_flags; char *password; - NMSettingSecretFlags password_flags; GBytes *password_raw; - NMSettingSecretFlags password_raw_flags; char *pin; - NMSettingSecretFlags pin_flags; GBytes *private_key; char *private_key_password; - NMSettingSecretFlags private_key_password_flags; GBytes *phase2_private_key; char *phase2_private_key_password; - NMSettingSecretFlags phase2_private_key_password_flags; - gboolean system_ca_certs; int auth_timeout; - gboolean optional; + NMSetting8021xAuthFlags phase1_auth_flags; + NMSettingSecretFlags ca_cert_password_flags; + NMSettingSecretFlags client_cert_password_flags; + NMSettingSecretFlags phase2_ca_cert_password_flags; + NMSettingSecretFlags phase2_client_cert_password_flags; + NMSettingSecretFlags password_flags; + NMSettingSecretFlags password_raw_flags; + NMSettingSecretFlags pin_flags; + NMSettingSecretFlags private_key_password_flags; + NMSettingSecretFlags phase2_private_key_password_flags; + bool optional:1; + bool system_ca_certs:1; } NMSetting8021xPrivate; G_DEFINE_TYPE (NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING) @@ -1245,6 +1249,22 @@ nm_setting_802_1x_get_domain_suffix_match (NMSetting8021x *setting) } /** + * nm_setting_802_1x_get_domain_match: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSetting8021x:domain-match property. + * + * Since: 1.24 + **/ +const char * +nm_setting_802_1x_get_domain_match (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->domain_match; +} + +/** * nm_setting_802_1x_get_client_cert_scheme: * @setting: the #NMSetting8021x * @@ -1692,6 +1712,22 @@ nm_setting_802_1x_get_phase2_domain_suffix_match (NMSetting8021x *setting) } /** + * nm_setting_802_1x_get_phase2_domain_match: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSetting8021x:phase2-domain-match property. + * + * Since: 1.24 + **/ +const char * +nm_setting_802_1x_get_phase2_domain_match (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_domain_match; +} + +/** * nm_setting_802_1x_get_phase2_altsubject_match: * @setting: the #NMSettingConnection * @i: the zero-based index of the array of "phase 2" altSubjectName matches @@ -3074,6 +3110,9 @@ get_property (GObject *object, guint prop_id, case PROP_DOMAIN_SUFFIX_MATCH: g_value_set_string (value, priv->domain_suffix_match); break; + case PROP_DOMAIN_MATCH: + g_value_set_string (value, priv->domain_match); + break; case PROP_CLIENT_CERT: g_value_set_boxed (value, priv->client_cert); break; @@ -3122,6 +3161,9 @@ get_property (GObject *object, guint prop_id, case PROP_PHASE2_DOMAIN_SUFFIX_MATCH: g_value_set_string (value, priv->phase2_domain_suffix_match); break; + case PROP_PHASE2_DOMAIN_MATCH: + g_value_set_string (value, priv->phase2_domain_match); + break; case PROP_PHASE2_CLIENT_CERT: g_value_set_boxed (value, priv->phase2_client_cert); break; @@ -3233,6 +3275,10 @@ set_property (GObject *object, guint prop_id, g_free (priv->domain_suffix_match); priv->domain_suffix_match = nm_strdup_not_empty (g_value_get_string (value)); break; + case PROP_DOMAIN_MATCH: + g_free (priv->domain_match); + priv->domain_match = nm_strdup_not_empty (g_value_get_string (value)); + break; case PROP_CLIENT_CERT: g_bytes_unref (priv->client_cert); priv->client_cert = g_value_dup_boxed (value); @@ -3294,6 +3340,10 @@ set_property (GObject *object, guint prop_id, g_free (priv->phase2_domain_suffix_match); priv->phase2_domain_suffix_match = nm_strdup_not_empty (g_value_get_string (value)); break; + case PROP_PHASE2_DOMAIN_MATCH: + g_free (priv->phase2_domain_match); + priv->phase2_domain_match = nm_strdup_not_empty (g_value_get_string (value)); + break; case PROP_PHASE2_CLIENT_CERT: g_bytes_unref (priv->phase2_client_cert); priv->phase2_client_cert = g_value_dup_boxed (value); @@ -3656,6 +3706,8 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass) * the authentication server. If a matching dNSName is found, this * constraint is met. If no dNSName values are present, this constraint is * matched against SubjectName CN using same suffix match comparison. + * Since version 1.24, multiple valid FQDNs can be passed as a ";" delimited + * list. * * Since: 1.2 **/ @@ -3672,6 +3724,30 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass) G_PARAM_STATIC_STRINGS); /** + * NMSetting8021x:domain-match: + * + * Constraint for server domain name. If set, this list of FQDNs is used as + * a match requirement for dNSName element(s) of the certificate presented + * by the authentication server. If a matching dNSName is found, this + * constraint is met. If no dNSName values are present, this constraint is + * matched against SubjectName CN using the same comparison. + * Multiple valid FQDNs can be passed as a ";" delimited list. + * + * Since: 1.24 + **/ + /* ---ifcfg-rh--- + * property: domain-match + * description: Value to match domain of server certificate against. + * variable: IEEE_8021X_DOMAIN_MATCH(+) + * ---end--- + */ + obj_properties[PROP_DOMAIN_MATCH] = + g_param_spec_string (NM_SETTING_802_1X_DOMAIN_MATCH, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + /** * NMSetting8021x:client-cert: * * Contains the client certificate if used by the EAP method specified in @@ -3828,7 +3904,6 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass) obj_properties[PROP_PHASE1_AUTH_FLAGS] = g_param_spec_uint (NM_SETTING_802_1X_PHASE1_AUTH_FLAGS, "", "", 0, G_MAXUINT32, NM_SETTING_802_1X_AUTH_FLAGS_NONE, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); @@ -4007,6 +4082,8 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass) * a matching dNSName is found, this constraint is met. If no dNSName * values are present, this constraint is matched against SubjectName CN * using same suffix match comparison. + * Since version 1.24, multiple valid FQDNs can be passed as a ";" delimited + * list. * * Since: 1.2 **/ @@ -4023,6 +4100,31 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass) G_PARAM_STATIC_STRINGS); /** + * NMSetting8021x:phase2-domain-match: + * + * Constraint for server domain name. If set, this list of FQDNs is used as + * a match requirement for dNSName element(s) of the certificate presented + * by the authentication server during the inner "phase 2" authentication. + * If a matching dNSName is found, this constraint is met. If no dNSName + * values are present, this constraint is matched against SubjectName CN + * using the same comparison. + * Multiple valid FQDNs can be passed as a ";" delimited list. + * + * Since: 1.24 + **/ + /* ---ifcfg-rh--- + * property: phase2-domain-match + * description: Value to match domain of server certificate for phase 2 against. + * variable: IEEE_8021X_PHASE2_DOMAIN_MATCH(+) + * ---end--- + */ + obj_properties[PROP_PHASE2_DOMAIN_MATCH] = + g_param_spec_string (NM_SETTING_802_1X_PHASE2_DOMAIN_MATCH, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + /** * NMSetting8021x:phase2-client-cert: * * Contains the "phase 2" client certificate if used by the EAP method @@ -4401,7 +4503,6 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass) g_param_spec_boolean (NM_SETTING_802_1X_SYSTEM_CA_CERTS, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** diff --git a/libnm-core/nm-setting-8021x.h b/libnm-core/nm-setting-8021x.h index 1bcca30c..6b433aa0 100644 --- a/libnm-core/nm-setting-8021x.h +++ b/libnm-core/nm-setting-8021x.h @@ -104,6 +104,7 @@ typedef enum { /*< flags, underscore_name=nm_setting_802_1x_auth_flags >*/ #define NM_SETTING_802_1X_SUBJECT_MATCH "subject-match" #define NM_SETTING_802_1X_ALTSUBJECT_MATCHES "altsubject-matches" #define NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH "domain-suffix-match" +#define NM_SETTING_802_1X_DOMAIN_MATCH "domain-match" #define NM_SETTING_802_1X_CLIENT_CERT "client-cert" #define NM_SETTING_802_1X_CLIENT_CERT_PASSWORD "client-cert-password" #define NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS "client-cert-password-flags" @@ -120,6 +121,7 @@ typedef enum { /*< flags, underscore_name=nm_setting_802_1x_auth_flags >*/ #define NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH "phase2-subject-match" #define NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES "phase2-altsubject-matches" #define NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH "phase2-domain-suffix-match" +#define NM_SETTING_802_1X_PHASE2_DOMAIN_MATCH "phase2-domain-match" #define NM_SETTING_802_1X_PHASE2_CLIENT_CERT "phase2-client-cert" #define NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD "phase2-client-cert-password" #define NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS "phase2-client-cert-password-flags" @@ -230,6 +232,9 @@ void nm_setting_802_1x_clear_altsubject_matches (NMSetting8 NM_AVAILABLE_IN_1_2 const char * nm_setting_802_1x_get_domain_suffix_match (NMSetting8021x *setting); +NM_AVAILABLE_IN_1_24 +const char * nm_setting_802_1x_get_domain_match (NMSetting8021x *setting); + NMSetting8021xCKScheme nm_setting_802_1x_get_client_cert_scheme (NMSetting8021x *setting); GBytes * nm_setting_802_1x_get_client_cert_blob (NMSetting8021x *setting); const char * nm_setting_802_1x_get_client_cert_path (NMSetting8021x *setting); @@ -287,6 +292,9 @@ void nm_setting_802_1x_clear_phase2_altsubject_matches (NMS NM_AVAILABLE_IN_1_2 const char * nm_setting_802_1x_get_phase2_domain_suffix_match (NMSetting8021x *setting); +NM_AVAILABLE_IN_1_24 +const char * nm_setting_802_1x_get_phase2_domain_match (NMSetting8021x *setting); + NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_client_cert_scheme (NMSetting8021x *setting); GBytes * nm_setting_802_1x_get_phase2_client_cert_blob (NMSetting8021x *setting); const char * nm_setting_802_1x_get_phase2_client_cert_path (NMSetting8021x *setting); diff --git a/libnm-core/nm-setting-adsl.c b/libnm-core/nm-setting-adsl.c index e9b86669..c952353d 100644 --- a/libnm-core/nm-setting-adsl.c +++ b/libnm-core/nm-setting-adsl.c @@ -158,7 +158,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) _("property is missing")); g_prefix_error (error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_USERNAME); return FALSE; - } else if (!strlen (priv->username)) { + } + if (!priv->username[0]) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -167,10 +168,9 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if ( !priv->protocol - || ( strcmp (priv->protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA) - && strcmp (priv->protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE) - && strcmp (priv->protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM))){ + if (!NM_IN_STRSET (priv->protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA, + NM_SETTING_ADSL_PROTOCOL_PPPOE, + NM_SETTING_ADSL_PROTOCOL_IPOATM)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -180,9 +180,9 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if ( priv->encapsulation - && ( strcmp (priv->encapsulation, NM_SETTING_ADSL_ENCAPSULATION_VCMUX) - && strcmp (priv->encapsulation, NM_SETTING_ADSL_ENCAPSULATION_LLC) )) { + if (!NM_IN_STRSET (priv->encapsulation, NULL, + NM_SETTING_ADSL_ENCAPSULATION_VCMUX, + NM_SETTING_ADSL_ENCAPSULATION_LLC)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, diff --git a/libnm-core/nm-setting-bluetooth.c b/libnm-core/nm-setting-bluetooth.c index f175e5c0..14a1317b 100644 --- a/libnm-core/nm-setting-bluetooth.c +++ b/libnm-core/nm-setting-bluetooth.c @@ -295,7 +295,7 @@ nm_setting_bluetooth_class_init (NMSettingBluetoothClass *klass) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj (properties_override, obj_properties[PROP_BDADDR], &nm_sett_info_propert_type_mac_addrees); + _nm_properties_override_gobj (properties_override, obj_properties[PROP_BDADDR], &nm_sett_info_propert_type_mac_address); /** * NMSettingBluetooth:type: diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c index f3ae9ef5..8986e434 100644 --- a/libnm-core/nm-setting-bond.c +++ b/libnm-core/nm-setting-bond.c @@ -44,54 +44,285 @@ G_DEFINE_TYPE (NMSettingBond, nm_setting_bond, NM_TYPE_SETTING) /*****************************************************************************/ +static const char *const valid_options_lst[] = { + /* mode must be the first element. nm-device-bond.c relies on that. */ + NM_SETTING_BOND_OPTION_MODE, + NM_SETTING_BOND_OPTION_MIIMON, + NM_SETTING_BOND_OPTION_DOWNDELAY, + NM_SETTING_BOND_OPTION_UPDELAY, + NM_SETTING_BOND_OPTION_ARP_INTERVAL, + NM_SETTING_BOND_OPTION_ARP_IP_TARGET, + NM_SETTING_BOND_OPTION_ARP_VALIDATE, + NM_SETTING_BOND_OPTION_PRIMARY, + NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, + NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, + NM_SETTING_BOND_OPTION_USE_CARRIER, + NM_SETTING_BOND_OPTION_AD_SELECT, + NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, + NM_SETTING_BOND_OPTION_RESEND_IGMP, + NM_SETTING_BOND_OPTION_LACP_RATE, + NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, + NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, + NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, + NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, + NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE, + NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS, + NM_SETTING_BOND_OPTION_MIN_LINKS, + NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, + NM_SETTING_BOND_OPTION_NUM_UNSOL_NA, + NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, + NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, + NM_SETTING_BOND_OPTION_LP_INTERVAL, + NULL, +}; + typedef struct { - const char *opt; const char *val; - guint opt_type; + NMBondOptionType opt_type; guint min; guint max; - char *list[10]; -} BondDefault; - -static const BondDefault defaults[] = { - { NM_SETTING_BOND_OPTION_MODE, "balance-rr", NM_BOND_OPTION_TYPE_BOTH, 0, 6, - { "balance-rr", "active-backup", "balance-xor", "broadcast", "802.3ad", "balance-tlb", "balance-alb", NULL } }, - { NM_SETTING_BOND_OPTION_MIIMON, "100", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT }, - { NM_SETTING_BOND_OPTION_DOWNDELAY, "0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT }, - { NM_SETTING_BOND_OPTION_UPDELAY, "0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT }, - { NM_SETTING_BOND_OPTION_ARP_INTERVAL, "0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT }, - { NM_SETTING_BOND_OPTION_ARP_IP_TARGET, "", NM_BOND_OPTION_TYPE_IP }, - { NM_SETTING_BOND_OPTION_ARP_VALIDATE, "none", NM_BOND_OPTION_TYPE_BOTH, 0, 6, - { "none", "active", "backup", "all", "filter", "filter_active", "filter_backup", NULL } }, - { NM_SETTING_BOND_OPTION_PRIMARY, "", NM_BOND_OPTION_TYPE_IFNAME }, - { NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, "always", NM_BOND_OPTION_TYPE_BOTH, 0, 2, - { "always", "better", "failure", NULL } }, - { NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, "none", NM_BOND_OPTION_TYPE_BOTH, 0, 2, - { "none", "active", "follow", NULL } }, - { NM_SETTING_BOND_OPTION_USE_CARRIER, "1", NM_BOND_OPTION_TYPE_INT, 0, 1 }, - { NM_SETTING_BOND_OPTION_AD_SELECT, "stable", NM_BOND_OPTION_TYPE_BOTH, 0, 2, - { "stable", "bandwidth", "count", NULL } }, - { NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, "layer2", NM_BOND_OPTION_TYPE_BOTH, 0, 4, - { "layer2", "layer3+4", "layer2+3", "encap2+3", "encap3+4", NULL } }, - { NM_SETTING_BOND_OPTION_RESEND_IGMP, "1", NM_BOND_OPTION_TYPE_INT, 0, 255 }, - { NM_SETTING_BOND_OPTION_LACP_RATE, "slow", NM_BOND_OPTION_TYPE_BOTH, 0, 1, - { "slow", "fast", NULL } }, - { NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, "", NM_BOND_OPTION_TYPE_IFNAME }, - { NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO,"65535", NM_BOND_OPTION_TYPE_INT, 1, 65535 }, - { NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, NULL, NM_BOND_OPTION_TYPE_MAC }, - { NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, "0", NM_BOND_OPTION_TYPE_INT, 0, 1023}, - { NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE,"0", NM_BOND_OPTION_TYPE_INT, 0, 1}, - { NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS, "any", NM_BOND_OPTION_TYPE_BOTH, 0, 1, {"any", "all"}}, - { NM_SETTING_BOND_OPTION_MIN_LINKS, "0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT }, - { NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, "1", NM_BOND_OPTION_TYPE_INT, 0, 255 }, - { NM_SETTING_BOND_OPTION_NUM_UNSOL_NA, "1", NM_BOND_OPTION_TYPE_INT, 0, 255 }, - { NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE,"1", NM_BOND_OPTION_TYPE_INT, 0, 65535 }, - { NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, "1", NM_BOND_OPTION_TYPE_INT, 0, 1 }, - { NM_SETTING_BOND_OPTION_LP_INTERVAL, "1", NM_BOND_OPTION_TYPE_INT, 1, G_MAXINT }, -}; + const char *const*list; +} OptionMeta; + +static gboolean +_nm_assert_bond_meta (const OptionMeta *option_meta) +{ + nm_assert (option_meta); + + switch (option_meta->opt_type) { + case NM_BOND_OPTION_TYPE_BOTH: + nm_assert (option_meta->val); + nm_assert (option_meta->list); + nm_assert (option_meta->list[0]); + nm_assert (option_meta->min == 0); + nm_assert (option_meta->max == NM_PTRARRAY_LEN (option_meta->list) - 1); + nm_assert (g_strv_contains (option_meta->list, option_meta->val)); + return TRUE; + case NM_BOND_OPTION_TYPE_INT: + nm_assert (option_meta->val); + nm_assert (!option_meta->list); + nm_assert (option_meta->min < option_meta->max); + nm_assert (NM_STRCHAR_ALL (option_meta->val, ch, g_ascii_isdigit (ch))); + nm_assert (NM_STRCHAR_ALL (option_meta->val, ch, g_ascii_isdigit (ch))); + nm_assert (({ + _nm_utils_ascii_str_to_uint64 (option_meta->val, 10, option_meta->min, option_meta->max, 0); + errno == 0; + })); + return TRUE; + case NM_BOND_OPTION_TYPE_IP: + case NM_BOND_OPTION_TYPE_IFNAME: + nm_assert (option_meta->val); + /* fall-through */ + case NM_BOND_OPTION_TYPE_MAC: + nm_assert (!option_meta->list); + nm_assert (option_meta->min == 0); + nm_assert (option_meta->max == 0); + return TRUE; + } + + nm_assert_not_reached (); + return FALSE; +} + +static char const *const _option_default_strv_ad_select[] = NM_MAKE_STRV ("stable", "bandwidth", "count"); +static char const *const _option_default_strv_arp_all_targets[] = NM_MAKE_STRV ("any", "all"); +static char const *const _option_default_strv_arp_validate[] = NM_MAKE_STRV ("none", "active", "backup", "all", "filter", "filter_active", "filter_backup"); +static char const *const _option_default_strv_fail_over_mac[] = NM_MAKE_STRV ("none", "active", "follow"); +static char const *const _option_default_strv_lacp_rate[] = NM_MAKE_STRV ("slow", "fast"); +static char const *const _option_default_strv_mode[] = NM_MAKE_STRV ("balance-rr", "active-backup", "balance-xor", "broadcast", "802.3ad", "balance-tlb", "balance-alb"); +static char const *const _option_default_strv_primary_reselect[] = NM_MAKE_STRV ("always", "better", "failure"); +static char const *const _option_default_strv_xmit_hash_policy[] = NM_MAKE_STRV ("layer2", "layer3+4", "layer2+3", "encap2+3", "encap3+4"); + +static +NM_UTILS_STRING_TABLE_LOOKUP_STRUCT_DEFINE ( + _get_option_meta, + OptionMeta, + { + G_STATIC_ASSERT_EXPR (G_N_ELEMENTS (LIST) == G_N_ELEMENTS (valid_options_lst) - 1); + + if (NM_MORE_ASSERT_ONCE (5)) { + int i; + + nm_assert (G_N_ELEMENTS (LIST) == NM_PTRARRAY_LEN (valid_options_lst)); + for (i = 0; i < G_N_ELEMENTS (LIST); i++) + _nm_assert_bond_meta (&LIST[i].value); + nm_assert (nm_streq (valid_options_lst[0], NM_SETTING_BOND_OPTION_MODE)); + } + }, + { return NULL; }, + { NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, { "", NM_BOND_OPTION_TYPE_IFNAME } }, + { NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, { "65535", NM_BOND_OPTION_TYPE_INT, 1, 65535 } }, + { NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, { NULL, NM_BOND_OPTION_TYPE_MAC } }, + { NM_SETTING_BOND_OPTION_AD_SELECT, { "stable", NM_BOND_OPTION_TYPE_BOTH, 0, 2, _option_default_strv_ad_select } }, + { NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, { "0", NM_BOND_OPTION_TYPE_INT, 0, 1023 } }, + { NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE, { "0", NM_BOND_OPTION_TYPE_INT, 0, 1 } }, + { NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS, { "any", NM_BOND_OPTION_TYPE_BOTH, 0, 1, _option_default_strv_arp_all_targets } }, + { NM_SETTING_BOND_OPTION_ARP_INTERVAL, { "0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT } }, + { NM_SETTING_BOND_OPTION_ARP_IP_TARGET, { "", NM_BOND_OPTION_TYPE_IP } }, + { NM_SETTING_BOND_OPTION_ARP_VALIDATE, { "none", NM_BOND_OPTION_TYPE_BOTH, 0, 6, _option_default_strv_arp_validate } }, + { NM_SETTING_BOND_OPTION_DOWNDELAY, { "0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT } }, + { NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, { "none", NM_BOND_OPTION_TYPE_BOTH, 0, 2, _option_default_strv_fail_over_mac } }, + { NM_SETTING_BOND_OPTION_LACP_RATE, { "slow", NM_BOND_OPTION_TYPE_BOTH, 0, 1, _option_default_strv_lacp_rate } }, + { NM_SETTING_BOND_OPTION_LP_INTERVAL, { "1", NM_BOND_OPTION_TYPE_INT, 1, G_MAXINT } }, + { NM_SETTING_BOND_OPTION_MIIMON, { "100", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT } }, + { NM_SETTING_BOND_OPTION_MIN_LINKS, { "0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT } }, + { NM_SETTING_BOND_OPTION_MODE, { "balance-rr", NM_BOND_OPTION_TYPE_BOTH, 0, 6, _option_default_strv_mode } }, + { NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, { "1", NM_BOND_OPTION_TYPE_INT, 0, 255 } }, + { NM_SETTING_BOND_OPTION_NUM_UNSOL_NA, { "1", NM_BOND_OPTION_TYPE_INT, 0, 255 } }, + { NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, { "1", NM_BOND_OPTION_TYPE_INT, 0, 65535 } }, + { NM_SETTING_BOND_OPTION_PRIMARY, { "", NM_BOND_OPTION_TYPE_IFNAME } }, + { NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, { "always", NM_BOND_OPTION_TYPE_BOTH, 0, 2, _option_default_strv_primary_reselect } }, + { NM_SETTING_BOND_OPTION_RESEND_IGMP, { "1", NM_BOND_OPTION_TYPE_INT, 0, 255 } }, + { NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, { "1", NM_BOND_OPTION_TYPE_INT, 0, 1 } }, + { NM_SETTING_BOND_OPTION_UPDELAY, { "0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT } }, + { NM_SETTING_BOND_OPTION_USE_CARRIER, { "1", NM_BOND_OPTION_TYPE_INT, 0, 1 } }, + { NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, { "layer2", NM_BOND_OPTION_TYPE_BOTH, 0, 4, _option_default_strv_xmit_hash_policy } }, +); /*****************************************************************************/ +#define BIT(x) (((guint32) 1) << (x)) + +static +NM_UTILS_STRING_TABLE_LOOKUP_DEFINE ( + _bond_option_unsupp_mode, + guint32, + { ; }, + { return 0; }, + { NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, ~(BIT (NM_BOND_MODE_ACTIVEBACKUP) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB)) }, + { NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, ~(BIT (NM_BOND_MODE_8023AD)) }, + { NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, ~(BIT (NM_BOND_MODE_8023AD)) }, + { NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, ~(BIT (NM_BOND_MODE_8023AD)) }, + { NM_SETTING_BOND_OPTION_ARP_INTERVAL, (BIT (NM_BOND_MODE_8023AD) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB)) }, + { NM_SETTING_BOND_OPTION_ARP_IP_TARGET, (BIT (NM_BOND_MODE_8023AD) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB)) }, + { NM_SETTING_BOND_OPTION_ARP_VALIDATE, (BIT (NM_BOND_MODE_8023AD) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB)) }, + { NM_SETTING_BOND_OPTION_LACP_RATE, ~(BIT (NM_BOND_MODE_8023AD)) }, + { NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, ~(BIT (NM_BOND_MODE_ROUNDROBIN)) }, + { NM_SETTING_BOND_OPTION_PRIMARY, ~(BIT (NM_BOND_MODE_ACTIVEBACKUP) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB)) }, + { NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, ~(BIT (NM_BOND_MODE_TLB)) }, +) + +gboolean +_nm_setting_bond_option_supported (const char *option, NMBondMode mode) +{ + nm_assert (option); + nm_assert (mode != NM_BOND_MODE_UNKNOWN); + nm_assert (_NM_INT_NOT_NEGATIVE (mode) && mode < 32); + + return !NM_FLAGS_ANY (_bond_option_unsupp_mode (option), BIT (mode)); +} + +static const char* +_bond_get_option (NMSettingBond *self, + const char *option) +{ + g_return_val_if_fail (NM_IS_SETTING_BOND (self), NULL); + g_return_val_if_fail (option, NULL); + + return g_hash_table_lookup (NM_SETTING_BOND_GET_PRIVATE (self)->options, option); +} + +static const char* +_bond_get_option_default (NMSettingBond *self, + const char *option) +{ + const OptionMeta *option_meta; + + g_return_val_if_fail (NM_IS_SETTING_BOND (self), NULL); + + option_meta = _get_option_meta (option); + + g_return_val_if_fail (option_meta, NULL); + + return option_meta->val; +} + +static const char* +_bond_get_option_or_default (NMSettingBond *self, + const char *option) +{ + return _bond_get_option (self, option) + ?: _bond_get_option_default (self, option); +} + +static const char* +_bond_get_option_normalized (NMSettingBond* self, + const char* option, + gboolean get_default_only) +{ + const char *arp_interval_str; + const char *mode_str; + gint64 arp_interval; + NMBondMode mode; + const char *value = NULL; + + g_return_val_if_fail (NM_IS_SETTING_BOND (self), NULL); + g_return_val_if_fail (option, NULL); + + mode_str = _bond_get_option_or_default (self, NM_SETTING_BOND_OPTION_MODE); + mode = _nm_setting_bond_mode_from_string (mode_str); + g_return_val_if_fail (mode != NM_BOND_MODE_UNKNOWN, NULL); + + if (!_nm_setting_bond_option_supported (option, mode)) + return NULL; + + /* Apply custom NetworkManager policies here */ + if (!get_default_only) { + if (NM_IN_STRSET (option, + NM_SETTING_BOND_OPTION_UPDELAY, + NM_SETTING_BOND_OPTION_DOWNDELAY, + NM_SETTING_BOND_OPTION_MIIMON)) { + /* if arp_interval is explicitly set and miimon is not, then disable miimon + * (and related updelay and downdelay) as recommended by the kernel docs */ + arp_interval_str = _bond_get_option (self, NM_SETTING_BOND_OPTION_ARP_INTERVAL); + arp_interval = _nm_utils_ascii_str_to_int64 (arp_interval_str, 10, 0, G_MAXINT, 0); + + if (!arp_interval || _bond_get_option (self, NM_SETTING_BOND_OPTION_MIIMON)) { + value = _bond_get_option (self, option); + } else { + return NULL; + } + } else if (NM_IN_STRSET (option, + NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, + NM_SETTING_BOND_OPTION_NUM_UNSOL_NA)) { + /* just get one of the 2, at kernel level they're the same bond option */ + value = _bond_get_option (self, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP); + if (!value) { + value = _bond_get_option (self, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA); + } + } else { + value = _bond_get_option (self, option); + } + } + + if (!value) { + /* Apply rules that change the default value of an option */ + if (nm_streq (option, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM)) { + /* The default value depends on the current mode */ + if (NM_IN_STRSET (mode_str, "4", "802.3ad")) + return "00:00:00:00:00:00"; + else + return ""; + } else { + return _bond_get_option_or_default (self, option); + } + } + + return value; +} + +const char* +nm_setting_bond_get_option_or_default (NMSettingBond *self, + const char *option) +{ + g_return_val_if_fail (NM_IS_SETTING_BOND (self), NULL); + g_return_val_if_fail (option, NULL); + + return _bond_get_option_normalized (self, + option, + FALSE); +} + static int _atoi (const char *value) { @@ -120,6 +351,26 @@ nm_setting_bond_get_num_options (NMSettingBond *setting) return g_hash_table_size (NM_SETTING_BOND_GET_PRIVATE (setting)->options); } +static int +_get_option_sort (gconstpointer p_a, gconstpointer p_b, gpointer _unused) +{ + const char *a = *((const char *const*) p_a); + const char *b = *((const char *const*) p_b); + + NM_CMP_DIRECT (nm_streq (b, NM_SETTING_BOND_OPTION_MODE), + nm_streq (a, NM_SETTING_BOND_OPTION_MODE)); + NM_CMP_DIRECT_STRCMP (a, b); + nm_assert_not_reached (); + return 0; +} + +static void +_ensure_options_idx_cache (NMSettingBondPrivate *priv) +{ + if (!G_UNLIKELY (priv->options_idx_cache)) + priv->options_idx_cache = nm_utils_named_values_from_str_dict_with_sort (priv->options, NULL, _get_option_sort, NULL); +} + /** * nm_setting_bond_get_option: * @setting: the #NMSettingBond @@ -158,8 +409,7 @@ nm_setting_bond_get_option (NMSettingBond *setting, if (idx >= len) return FALSE; - if (!G_UNLIKELY (priv->options_idx_cache)) - priv->options_idx_cache = nm_utils_named_values_from_str_dict (priv->options, NULL); + _ensure_options_idx_cache (priv); NM_SET_OUT (out_name, priv->options_idx_cache[idx].name); NM_SET_OUT (out_value, priv->options_idx_cache[idx].value_str); @@ -167,14 +417,14 @@ nm_setting_bond_get_option (NMSettingBond *setting, } static gboolean -validate_int (const char *name, const char *value, const BondDefault *def) +validate_int (const char *name, const char *value, const OptionMeta *option_meta) { guint64 num; if (!NM_STRCHAR_ALL (value, ch, g_ascii_isdigit (ch))) return FALSE; - num = _nm_utils_ascii_str_to_uint64 (value, 10, def->min, def->max, G_MAXUINT64); + num = _nm_utils_ascii_str_to_uint64 (value, 10, option_meta->min, option_meta->max, G_MAXUINT64); if ( num == G_MAXUINT64 && errno != 0) return FALSE; @@ -183,17 +433,17 @@ validate_int (const char *name, const char *value, const BondDefault *def) } static gboolean -validate_list (const char *name, const char *value, const BondDefault *def) +validate_list (const char *name, const char *value, const OptionMeta *option_meta) { - guint i; + int i; + + nm_assert (option_meta->list); - for (i = 0; i < G_N_ELEMENTS (def->list) && def->list[i]; i++) { - if (g_strcmp0 (def->list[i], value) == 0) + for (i = 0; option_meta->list[i]; i++) { + if (nm_streq (option_meta->list[i], value)) return TRUE; } - - /* empty validation list means all values pass */ - return def->list[0] == NULL ? TRUE : FALSE; + return FALSE; } static gboolean @@ -232,9 +482,6 @@ validate_ip (const char *name, const char *value) static gboolean validate_ifname (const char *name, const char *value) { - if (!value || !value[0]) - return FALSE; - return nm_utils_ifname_valid_kernel (value, NULL); } @@ -253,33 +500,30 @@ gboolean nm_setting_bond_validate_option (const char *name, const char *value) { - guint i; + const OptionMeta *option_meta; - if (!name || !name[0]) + option_meta = _get_option_meta (name); + if (!option_meta) return FALSE; - for (i = 0; i < G_N_ELEMENTS (defaults); i++) { - if (g_strcmp0 (defaults[i].opt, name) == 0) { - if (value == NULL) - return TRUE; - switch (defaults[i].opt_type) { - case NM_BOND_OPTION_TYPE_INT: - return validate_int (name, value, &defaults[i]); - case NM_BOND_OPTION_TYPE_STRING: - return validate_list (name, value, &defaults[i]); - case NM_BOND_OPTION_TYPE_BOTH: - return ( validate_int (name, value, &defaults[i]) - || validate_list (name, value, &defaults[i])); - case NM_BOND_OPTION_TYPE_IP: - return validate_ip (name, value); - case NM_BOND_OPTION_TYPE_MAC: - return nm_utils_hwaddr_valid (value, ETH_ALEN); - case NM_BOND_OPTION_TYPE_IFNAME: - return validate_ifname (name, value); - } - return FALSE; - } + if (!value) + return TRUE; + + switch (option_meta->opt_type) { + case NM_BOND_OPTION_TYPE_INT: + return validate_int (name, value, option_meta); + case NM_BOND_OPTION_TYPE_BOTH: + return ( validate_int (name, value, option_meta) + || validate_list (name, value, option_meta)); + case NM_BOND_OPTION_TYPE_IP: + return validate_ip (name, value); + case NM_BOND_OPTION_TYPE_MAC: + return nm_utils_hwaddr_valid (value, ETH_ALEN); + case NM_BOND_OPTION_TYPE_IFNAME: + return validate_ifname (name, value); } + + nm_assert_not_reached (); return FALSE; } @@ -303,7 +547,7 @@ nm_setting_bond_get_option_by_name (NMSettingBond *setting, if (!nm_setting_bond_validate_option (name, NULL)) return NULL; - return g_hash_table_lookup (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name); + return _bond_get_option (setting, name); } /** @@ -340,17 +584,6 @@ nm_setting_bond_add_option (NMSettingBond *setting, nm_clear_g_free (&priv->options_idx_cache); g_hash_table_insert (priv->options, g_strdup (name), g_strdup (value)); - if ( !strcmp (name, NM_SETTING_BOND_OPTION_MIIMON) - && strcmp (value, "0") != 0) { - g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_ARP_INTERVAL); - g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); - } else if ( !strcmp (name, NM_SETTING_BOND_OPTION_ARP_INTERVAL) - && strcmp (value, "0") != 0) { - g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_MIIMON); - g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_DOWNDELAY); - g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_UPDELAY); - } - _notify (setting, PROP_OPTIONS); return TRUE; @@ -401,16 +634,7 @@ nm_setting_bond_remove_option (NMSettingBond *setting, const char ** nm_setting_bond_get_valid_options (NMSettingBond *setting) { - static const char *array[G_N_ELEMENTS (defaults) + 1] = { NULL }; - int i; - - /* initialize the array once */ - if (G_UNLIKELY (array[0] == NULL)) { - for (i = 0; i < G_N_ELEMENTS (defaults); i++) - array[i] = defaults[i].opt; - array[i] = NULL; - } - return array; + return (const char **) valid_options_lst; } /** @@ -424,28 +648,38 @@ nm_setting_bond_get_valid_options (NMSettingBond *setting) const char * nm_setting_bond_get_option_default (NMSettingBond *setting, const char *name) { - const char *mode; - guint i; - g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL); - g_return_val_if_fail (nm_setting_bond_validate_option (name, NULL), NULL); - - if (nm_streq (name, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM)) { - /* The default value depends on the current mode */ - mode = nm_setting_bond_get_option_by_name (setting, NM_SETTING_BOND_OPTION_MODE); - if ( nm_streq0 (mode, "4") - || nm_streq0 (mode, "802.3ad")) - return "00:00:00:00:00:00"; - else - return ""; - } - for (i = 0; i < G_N_ELEMENTS (defaults); i++) { - if (g_strcmp0 (defaults[i].opt, name) == 0) - return defaults[i].val; + if (!name) { + return NULL; } - /* Any option that passes nm_setting_bond_validate_option() should also be found in defaults */ - g_assert_not_reached (); + + return _bond_get_option_normalized (setting, + name, + TRUE); +} + +/** + * nm_setting_bond_get_option_normalized: + * @setting: the #NMSettingBond + * @name: the name of the option + * + * Since: 1.24 + * + * Returns: the value of the bond option after normalization, which is what NetworkManager + * will actually apply when activating the connection. %NULL if the option won't be applied + * to the connection. + **/ +const char * +nm_setting_bond_get_option_normalized (NMSettingBond *setting, + const char *name) +{ + g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL); + g_return_val_if_fail (name, NULL); + + return _bond_get_option_normalized (setting, + name, + FALSE); } /** @@ -458,131 +692,97 @@ nm_setting_bond_get_option_default (NMSettingBond *setting, const char *name) NMBondOptionType _nm_setting_bond_get_option_type (NMSettingBond *setting, const char *name) { - guint i; + const OptionMeta *option_meta; g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NM_BOND_OPTION_TYPE_INT); - g_return_val_if_fail (nm_setting_bond_validate_option (name, NULL), NM_BOND_OPTION_TYPE_INT); - for (i = 0; i < G_N_ELEMENTS (defaults); i++) { - if (nm_streq0 (defaults[i].opt, name)) - return defaults[i].opt_type; - } - /* Any option that passes nm_setting_bond_validate_option() should also be found in defaults */ - g_assert_not_reached (); -} + option_meta = _get_option_meta (name); -NMBondMode -_nm_setting_bond_mode_from_string (const char *str) -{ - g_return_val_if_fail (str, NM_BOND_MODE_UNKNOWN); + g_return_val_if_fail (option_meta, NM_BOND_OPTION_TYPE_INT); - if (nm_streq (str, "balance-rr")) - return NM_BOND_MODE_ROUNDROBIN; - if (nm_streq (str, "active-backup")) - return NM_BOND_MODE_ACTIVEBACKUP; - if (nm_streq (str, "balance-xor")) - return NM_BOND_MODE_XOR; - if (nm_streq (str, "broadcast")) - return NM_BOND_MODE_BROADCAST; - if (nm_streq (str, "802.3ad")) - return NM_BOND_MODE_8023AD; - if (nm_streq (str, "balance-tlb")) - return NM_BOND_MODE_TLB; - if (nm_streq (str, "balance-alb")) - return NM_BOND_MODE_ALB; - - return NM_BOND_MODE_UNKNOWN; + return option_meta->opt_type; } -/*****************************************************************************/ - -#define BIT(x) (1 << (x)) - -static const struct { - const char *option; - NMBondMode unsupp_modes; -} bond_unsupp_modes[] = { - { NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, ~(BIT (NM_BOND_MODE_ROUNDROBIN)) }, - { NM_SETTING_BOND_OPTION_ARP_VALIDATE, BIT (NM_BOND_MODE_8023AD) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB) }, - { NM_SETTING_BOND_OPTION_ARP_INTERVAL, BIT (NM_BOND_MODE_8023AD) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB) }, - { NM_SETTING_BOND_OPTION_ARP_IP_TARGET, BIT (NM_BOND_MODE_8023AD) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB) }, - { NM_SETTING_BOND_OPTION_LACP_RATE, ~(BIT (NM_BOND_MODE_8023AD)) }, - { NM_SETTING_BOND_OPTION_PRIMARY, ~(BIT (NM_BOND_MODE_ACTIVEBACKUP) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB)) }, - { NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, ~(BIT (NM_BOND_MODE_ACTIVEBACKUP) | BIT (NM_BOND_MODE_TLB) | BIT (NM_BOND_MODE_ALB)) }, - { NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, ~(BIT (NM_BOND_MODE_TLB)) }, - { NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, ~(BIT (NM_BOND_MODE_8023AD)) }, - { NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, ~(BIT (NM_BOND_MODE_8023AD)) }, - { NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, ~(BIT (NM_BOND_MODE_8023AD)) }, -}; - -gboolean -_nm_setting_bond_option_supported (const char *option, NMBondMode mode) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (bond_unsupp_modes); i++) { - if (nm_streq (option, bond_unsupp_modes[i].option)) - return !NM_FLAGS_ANY (bond_unsupp_modes[i].unsupp_modes, BIT (mode)); - } +NM_UTILS_STRING_TABLE_LOOKUP_DEFINE ( + _nm_setting_bond_mode_from_string, + NMBondMode, + { g_return_val_if_fail (name, NM_BOND_MODE_UNKNOWN); }, + { return NM_BOND_MODE_UNKNOWN; }, + { "0", NM_BOND_MODE_ROUNDROBIN }, + { "1", NM_BOND_MODE_ACTIVEBACKUP }, + { "2", NM_BOND_MODE_XOR }, + { "3", NM_BOND_MODE_BROADCAST }, + { "4", NM_BOND_MODE_8023AD }, + { "5", NM_BOND_MODE_TLB }, + { "6", NM_BOND_MODE_ALB }, + { "802.3ad", NM_BOND_MODE_8023AD }, + { "active-backup", NM_BOND_MODE_ACTIVEBACKUP }, + { "balance-alb", NM_BOND_MODE_ALB }, + { "balance-rr", NM_BOND_MODE_ROUNDROBIN }, + { "balance-tlb", NM_BOND_MODE_TLB }, + { "balance-xor", NM_BOND_MODE_XOR }, + { "broadcast", NM_BOND_MODE_BROADCAST }, +); - return TRUE; -} +/*****************************************************************************/ static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { + NMSettingBond *self = NM_SETTING_BOND (setting); NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting); - GHashTableIter iter; - const char *key, *value; - int mode, miimon = 0, arp_interval = 0; - int num_grat_arp = -1, num_unsol_na = -1; - const char *mode_orig, *mode_new; + int miimon; + int arp_interval; + int num_grat_arp; + int num_unsol_na; + const char *mode_str; const char *arp_ip_target = NULL; const char *lacp_rate; const char *primary; NMBondMode bond_mode; + guint i; + const NMUtilsNamedValue *n; - g_hash_table_iter_init (&iter, priv->options); - while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) { - if (!value[0] || !nm_setting_bond_validate_option (key, value)) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid option '%s' or its value '%s'"), - key, value); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; + _ensure_options_idx_cache (priv); + + if (priv->options_idx_cache) { + for (i = 0; priv->options_idx_cache[i].name; i++) { + n = &priv->options_idx_cache[i]; + + if ( !n->value_str + || !nm_setting_bond_validate_option (n->name, n->value_str)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid option '%s' or its value '%s'"), + n->name, n->value_str); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); + return FALSE; + } } } - value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_MIIMON); - if (value) - miimon = atoi (value); - value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_ARP_INTERVAL); - if (value) - arp_interval = atoi (value); - value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP); - if (value) - num_grat_arp = atoi (value); - value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA); - if (value) - num_unsol_na = atoi (value); - - /* Can only set one of miimon and arp_interval */ - if (miimon > 0 && arp_interval > 0) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("only one of '%s' and '%s' can be set"), - NM_SETTING_BOND_OPTION_MIIMON, - NM_SETTING_BOND_OPTION_ARP_INTERVAL); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; - } + miimon = _atoi (_bond_get_option_or_default (self, NM_SETTING_BOND_OPTION_MIIMON)); + arp_interval = _atoi (_bond_get_option_or_default (self, NM_SETTING_BOND_OPTION_ARP_INTERVAL)); + num_grat_arp = _atoi (_bond_get_option_or_default (self, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP)); + num_unsol_na = _atoi (_bond_get_option_or_default (self, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA)); + + /* Option restrictions: + * + * arp_interval conflicts [ alb, tlb ] + * arp_interval needs arp_ip_target + * arp_validate does not work with [ BOND_MODE_8023AD, BOND_MODE_TLB, BOND_MODE_ALB ] + * downdelay needs miimon + * updelay needs miimon + * primary needs [ active-backup, tlb, alb ] + */ /* Verify bond mode */ - mode_orig = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_MODE); - if (!mode_orig) { + mode_str = _bond_get_option (self, NM_SETTING_BOND_OPTION_MODE); + if (!mode_str) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -591,34 +791,42 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } - mode = nm_utils_bond_mode_string_to_int (mode_orig); - if (mode == -1) { + bond_mode = _nm_setting_bond_mode_from_string (mode_str); + if (bond_mode == NM_BOND_MODE_UNKNOWN) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' is not a valid value for '%s'"), - value, NM_SETTING_BOND_OPTION_MODE); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + mode_str, + NM_SETTING_BOND_OPTION_MODE); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); return FALSE; } - mode_new = nm_utils_bond_mode_int_to_string (mode); /* Make sure mode is compatible with other settings */ - if ( strcmp (mode_new, "balance-alb") == 0 - || strcmp (mode_new, "balance-tlb") == 0) { + if (NM_IN_SET (bond_mode, NM_BOND_MODE_TLB, + NM_BOND_MODE_ALB)) { if (arp_interval > 0) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s=%s' is incompatible with '%s > 0'"), - NM_SETTING_BOND_OPTION_MODE, mode_new, NM_SETTING_BOND_OPTION_ARP_INTERVAL); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + NM_SETTING_BOND_OPTION_MODE, + mode_str, + NM_SETTING_BOND_OPTION_ARP_INTERVAL); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); return FALSE; } } - primary = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_PRIMARY); - if (strcmp (mode_new, "active-backup") == 0) { + primary = _bond_get_option (self, NM_SETTING_BOND_OPTION_PRIMARY); + if (bond_mode == NM_BOND_MODE_ACTIVEBACKUP) { GError *tmp_error = NULL; if (primary && !nm_utils_ifname_valid_kernel (primary, &tmp_error)) { @@ -627,58 +835,64 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' is not valid for the '%s' option: %s"), primary, NM_SETTING_BOND_OPTION_PRIMARY, tmp_error->message); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); g_error_free (tmp_error); return FALSE; } - } else { - if (primary) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' option is only valid for '%s=%s'"), - NM_SETTING_BOND_OPTION_PRIMARY, - NM_SETTING_BOND_OPTION_MODE, "active-backup"); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; - } + } else if (primary) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option is only valid for '%s=%s'"), + NM_SETTING_BOND_OPTION_PRIMARY, + NM_SETTING_BOND_OPTION_MODE, "active-backup"); + g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; } - if (connection && nm_connection_get_setting_infiniband (connection)) { - if (strcmp (mode_new, "active-backup") != 0) { + if ( connection + && nm_connection_get_setting_infiniband (connection)) { + if (bond_mode != NM_BOND_MODE_ACTIVEBACKUP) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s=%s' is not a valid configuration for '%s'"), - NM_SETTING_BOND_OPTION_MODE, mode_new, NM_SETTING_INFINIBAND_SETTING_NAME); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + NM_SETTING_BOND_OPTION_MODE, mode_str, NM_SETTING_INFINIBAND_SETTING_NAME); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } if (miimon == 0) { - gpointer delayopt; - /* updelay and downdelay need miimon to be enabled to be valid */ - delayopt = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_UPDELAY); - if (delayopt && _atoi (delayopt) > 0) { + if (_atoi (_bond_get_option_or_default (self, NM_SETTING_BOND_OPTION_UPDELAY))) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option requires '%s' option to be enabled"), NM_SETTING_BOND_OPTION_UPDELAY, NM_SETTING_BOND_OPTION_MIIMON); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); return FALSE; } - delayopt = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_DOWNDELAY); - if (delayopt && _atoi (delayopt) > 0) { + if (_atoi (_bond_get_option_or_default (self, NM_SETTING_BOND_OPTION_DOWNDELAY))) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option requires '%s' option to be enabled"), NM_SETTING_BOND_OPTION_DOWNDELAY, NM_SETTING_BOND_OPTION_MIIMON); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); return FALSE; } } @@ -686,19 +900,22 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) /* arp_ip_target can only be used with arp_interval, and must * contain a comma-separated list of IPv4 addresses. */ - arp_ip_target = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); + arp_ip_target = _bond_get_option (self, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); if (arp_interval > 0) { char **addrs; guint32 addr; - int i; if (!arp_ip_target) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option requires '%s' option to be set"), - NM_SETTING_BOND_OPTION_ARP_INTERVAL, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + NM_SETTING_BOND_OPTION_ARP_INTERVAL, + NM_SETTING_BOND_OPTION_ARP_IP_TARGET); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); return FALSE; } @@ -709,7 +926,9 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option is empty"), NM_SETTING_BOND_OPTION_ARP_IP_TARGET); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + g_prefix_error (error, "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); g_strfreev (addrs); return FALSE; } @@ -720,8 +939,12 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' is not a valid IPv4 address for '%s' option"), - NM_SETTING_BOND_OPTION_ARP_IP_TARGET, addrs[i]); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + NM_SETTING_BOND_OPTION_ARP_IP_TARGET, + addrs[i]); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); g_strfreev (addrs); return FALSE; } @@ -733,17 +956,19 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option requires '%s' option to be set"), - NM_SETTING_BOND_OPTION_ARP_IP_TARGET, NM_SETTING_BOND_OPTION_ARP_INTERVAL); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + NM_SETTING_BOND_OPTION_ARP_IP_TARGET, + NM_SETTING_BOND_OPTION_ARP_INTERVAL); + g_prefix_error (error, "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); return FALSE; } } - lacp_rate = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_LACP_RATE); + lacp_rate = _bond_get_option (self, NM_SETTING_BOND_OPTION_LACP_RATE); if ( lacp_rate - && g_strcmp0 (mode_new, "802.3ad") - && strcmp (lacp_rate, "slow") != 0 - && strcmp (lacp_rate, "0") != 0) { + && bond_mode != NM_BOND_MODE_8023AD + && !NM_IN_STRSET (lacp_rate, "0", "slow")) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -753,8 +978,9 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if ( (num_grat_arp != -1 && num_unsol_na != -1) - && (num_grat_arp != num_unsol_na)) { + if ( _bond_get_option (self, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP) + && _bond_get_option (self, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA) + && num_grat_arp != num_unsol_na) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -770,7 +996,14 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) /* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */ - if (g_strcmp0 (mode_orig, mode_new) != 0) { + if (!NM_IN_STRSET (mode_str, + "802.3ad", + "active-backup", + "balance-rr", + "balance-alb", + "balance-tlb", + "balance-xor", + "broadcast")) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -781,18 +1014,18 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } /* normalize unsupported options for the current mode */ - bond_mode = _nm_setting_bond_mode_from_string (mode_new); - g_hash_table_iter_init (&iter, priv->options); - while (g_hash_table_iter_next (&iter, (gpointer) &key, NULL)) { - if (nm_streq (key, "mode")) - continue; - if (!_nm_setting_bond_option_supported (key, bond_mode)) { + for (i = 0; priv->options_idx_cache[i].name; i++) { + n = &priv->options_idx_cache[i]; + if (!_nm_setting_bond_option_supported (n->name, bond_mode)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option is not valid with mode '%s'"), - key, mode_new); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + n->name, mode_str); + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); return NM_SETTING_VERIFY_NORMALIZABLE; } } @@ -807,9 +1040,8 @@ options_equal_asym (NMSettingBond *s_bond, NMSettingBond *s_bond2, NMSettingCompareFlags flags) { - GHashTable *options2 = NM_SETTING_BOND_GET_PRIVATE (s_bond2)->options; GHashTableIter iter; - const char *key, *value, *value2; + const char *key, *value; g_hash_table_iter_init (&iter, NM_SETTING_BOND_GET_PRIVATE (s_bond)->options); while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) { @@ -824,18 +1056,7 @@ options_equal_asym (NMSettingBond *s_bond, continue; } - value2 = g_hash_table_lookup (options2, key); - - if (!value2) { - if (nm_streq (key, "num_grat_arp")) - value2 = g_hash_table_lookup (options2, "num_unsol_na"); - else if (nm_streq (key, "num_unsol_na")) - value2 = g_hash_table_lookup (options2, "num_grat_arp"); - } - - if (!value2) - value2 = nm_setting_bond_get_option_default (s_bond2, key); - if (!nm_streq (value, value2)) + if (!nm_streq0 (value, _bond_get_option (s_bond2, key))) return FALSE; } diff --git a/libnm-core/nm-setting-bond.h b/libnm-core/nm-setting-bond.h index c17babdc..fc2a3735 100644 --- a/libnm-core/nm-setting-bond.h +++ b/libnm-core/nm-setting-bond.h @@ -94,6 +94,10 @@ const char **nm_setting_bond_get_valid_options (NMSettingBond *setting); const char * nm_setting_bond_get_option_default (NMSettingBond *setting, const char *name); +NM_AVAILABLE_IN_1_24 +const char * nm_setting_bond_get_option_normalized (NMSettingBond *setting, + const char *name); + G_END_DECLS #endif /* __NM_SETTING_BOND_H__ */ diff --git a/libnm-core/nm-setting-bridge-port.c b/libnm-core/nm-setting-bridge-port.c index 152ba944..5fcf1e60 100644 --- a/libnm-core/nm-setting-bridge-port.c +++ b/libnm-core/nm-setting-bridge-port.c @@ -34,10 +34,10 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingBridgePort, ); typedef struct { + GPtrArray *vlans; guint16 priority; guint16 path_cost; - gboolean hairpin_mode; - GPtrArray *vlans; + bool hairpin_mode:1; } NMSettingBridgePortPrivate; G_DEFINE_TYPE (NMSettingBridgePort, nm_setting_bridge_port, NM_TYPE_SETTING) @@ -439,6 +439,9 @@ nm_setting_bridge_port_init (NMSettingBridgePort *setting) NMSettingBridgePortPrivate *priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE (setting); priv->vlans = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_bridge_vlan_unref); + + priv->priority = NM_BR_PORT_DEF_PRIORITY; + priv->path_cost = NM_BR_PORT_DEF_PATH_COST; } /** @@ -497,7 +500,6 @@ nm_setting_bridge_port_class_init (NMSettingBridgePortClass *klass) g_param_spec_uint (NM_SETTING_BRIDGE_PORT_PRIORITY, "", "", 0, NM_BR_PORT_MAX_PRIORITY, NM_BR_PORT_DEF_PRIORITY, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -517,9 +519,8 @@ nm_setting_bridge_port_class_init (NMSettingBridgePortClass *klass) */ obj_properties[PROP_PATH_COST] = g_param_spec_uint (NM_SETTING_BRIDGE_PORT_PATH_COST, "", "", - 0, NM_BR_PORT_MAX_PATH_COST, 100, + 0, NM_BR_PORT_MAX_PATH_COST, NM_BR_PORT_DEF_PATH_COST, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c index 585f9ced..d8000221 100644 --- a/libnm-core/nm-setting-bridge.c +++ b/libnm-core/nm-setting-bridge.c @@ -22,6 +22,18 @@ * necessary for bridging connections. **/ +#define BRIDGE_AGEING_TIME_DEFAULT 300 +#define BRIDGE_FORWARD_DELAY_DEFAULT 15 +#define BRIDGE_HELLO_TIME_DEFAULT 2 +#define BRIDGE_MAX_AGE_DEFAULT 20 +#define BRIDGE_MULTICAST_QUERIER_DEFAULT FALSE +#define BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEFAULT FALSE +#define BRIDGE_MULTICAST_SNOOPING_DEFAULT TRUE +#define BRIDGE_PRIORITY_DEFAULT 0x8000 +#define BRIDGE_STP_DEFAULT TRUE +#define BRIDGE_VLAN_DEFAULT_PVID_DEFAULT 1 +#define BRIDGE_VLAN_STATS_ENABLED_DEFAULT FALSE + /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingBridge, @@ -32,31 +44,57 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingBridge, PROP_HELLO_TIME, PROP_MAX_AGE, PROP_AGEING_TIME, + PROP_GROUP_ADDRESS, PROP_GROUP_FORWARD_MASK, + PROP_MULTICAST_ROUTER, + PROP_MULTICAST_QUERIER, + PROP_MULTICAST_QUERY_USE_IFADDR, PROP_MULTICAST_SNOOPING, PROP_VLAN_FILTERING, PROP_VLAN_DEFAULT_PVID, + PROP_VLAN_PROTOCOL, + PROP_VLAN_STATS_ENABLED, PROP_VLANS, ); typedef struct { + GPtrArray *vlans; char * mac_address; - gboolean stp; + char * multicast_router; + char * group_address; + char * vlan_protocol; + guint32 ageing_time; guint16 priority; guint16 forward_delay; guint16 hello_time; guint16 max_age; - guint32 ageing_time; - guint16 group_forward_mask; - gboolean multicast_snooping; - gboolean vlan_filtering; guint16 vlan_default_pvid; - GPtrArray *vlans; + guint16 group_forward_mask; + bool multicast_snooping:1; + bool vlan_filtering:1; + bool stp:1; + bool vlan_stats_enabled:1; + bool multicast_query_use_ifaddr:1; + bool multicast_querier:1; } NMSettingBridgePrivate; +/** + * NMSettingBridge: + * + * Bridging Settings + */ +struct _NMSettingBridge { + NMSetting parent; + NMSettingBridgePrivate _priv; +}; + +struct _NMSettingBridgeClass { + NMSettingClass parent; +}; + G_DEFINE_TYPE (NMSettingBridge, nm_setting_bridge, NM_TYPE_SETTING) -#define NM_SETTING_BRIDGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BRIDGE, NMSettingBridgePrivate)) +#define NM_SETTING_BRIDGE_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMSettingBridge, NM_IS_SETTING_BRIDGE, NMSetting) /*****************************************************************************/ @@ -876,6 +914,102 @@ nm_setting_bridge_clear_vlans (NMSettingBridge *setting) } } +/** + * nm_setting_bridge_get_group_address: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:group-address property of the setting + * + * Since 1.24 + **/ +const char * +nm_setting_bridge_get_group_address (const NMSettingBridge *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), NULL); + + return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->group_address; +} + +/** + * nm_setting_bridge_get_vlan_protocol: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:vlan-protocol property of the setting + * + * Since 1.24 + **/ +const char * +nm_setting_bridge_get_vlan_protocol (const NMSettingBridge *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), NULL); + + return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->vlan_protocol; +} + +/** + * nm_setting_bridge_get_vlan_stats_enabled: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:vlan-stats-enabled property of the setting + * + * Since 1.24 + **/ +gboolean +nm_setting_bridge_get_vlan_stats_enabled (const NMSettingBridge *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), FALSE); + + return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->vlan_stats_enabled; +} + +/** + * nm_setting_bridge_get_multicast_router: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-router property of the setting + * + * Since 1.24 + **/ +const char * +nm_setting_bridge_get_multicast_router (const NMSettingBridge *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), NULL); + + return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->multicast_router; +} + +/** + * nm_setting_bridge_get_multicast_query_use_ifaddr: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-query-use-ifaddr property of the setting + * + * Since 1.24 + **/ +gboolean +nm_setting_bridge_get_multicast_query_use_ifaddr (const NMSettingBridge *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), FALSE); + + return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->multicast_query_use_ifaddr; +} + +/** + * nm_setting_bridge_get_multicast_querier: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-querier property of the setting + * + * Since 1.24 + **/ +gboolean +nm_setting_bridge_get_multicast_querier (const NMSettingBridge *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), FALSE); + + return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->multicast_querier; +} + /*****************************************************************************/ static gboolean @@ -966,6 +1100,55 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_SETTING_BRIDGE_VLANS)) return FALSE; + if ( priv->group_address + && !_nm_utils_hwaddr_link_local_valid (priv->group_address)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is not a valid link local MAC address")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_GROUP_ADDRESS); + return FALSE; + } + + if ( priv->vlan_protocol + && !NM_IN_STRSET (priv->vlan_protocol, + "802.1Q", + "802.1ad")) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is not a valid VLAN filtering protocol")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_VLAN_PROTOCOL); + return FALSE; + } + + if (priv->multicast_router) { + if (!NM_IN_STRSET (priv->multicast_router, + "auto", + "enabled", + "disabled")) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is not a valid option")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_MULTICAST_ROUTER); + return FALSE; + } + + if ( NM_IN_STRSET (priv->multicast_router, + "auto", + "enabled") + && !priv->multicast_snooping) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option requires '%s' option to be enabled"), + NM_SETTING_BRIDGE_MULTICAST_ROUTER, NM_SETTING_BRIDGE_MULTICAST_SNOOPING); + g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_MULTICAST_ROUTER); + return FALSE; + } + } + /* Failures from here on are NORMALIZABLE... */ if (!_nm_utils_bridge_vlan_verify_list (priv->vlans, @@ -1046,18 +1229,36 @@ get_property (GObject *object, guint prop_id, case PROP_AGEING_TIME: g_value_set_uint (value, priv->ageing_time); break; + case PROP_GROUP_ADDRESS: + g_value_set_string (value, priv->group_address); + break; case PROP_GROUP_FORWARD_MASK: g_value_set_uint (value, priv->group_forward_mask); break; case PROP_MULTICAST_SNOOPING: g_value_set_boolean (value, priv->multicast_snooping); break; + case PROP_MULTICAST_ROUTER: + g_value_set_string (value, priv->multicast_router); + break; + case PROP_MULTICAST_QUERIER: + g_value_set_boolean (value, priv->multicast_querier); + break; + case PROP_MULTICAST_QUERY_USE_IFADDR: + g_value_set_boolean (value, priv->multicast_query_use_ifaddr); + break; case PROP_VLAN_FILTERING: g_value_set_boolean (value, priv->vlan_filtering); break; case PROP_VLAN_DEFAULT_PVID: g_value_set_uint (value, priv->vlan_default_pvid); break; + case PROP_VLAN_PROTOCOL: + g_value_set_string (value, priv->vlan_protocol); + break; + case PROP_VLAN_STATS_ENABLED: + g_value_set_boolean (value, priv->vlan_stats_enabled); + break; case PROP_VLANS: g_value_take_boxed (value, _nm_utils_copy_array (priv->vlans, (NMUtilsCopyFunc) nm_bridge_vlan_ref, @@ -1099,18 +1300,40 @@ set_property (GObject *object, guint prop_id, case PROP_AGEING_TIME: priv->ageing_time = g_value_get_uint (value); break; + case PROP_GROUP_ADDRESS: + g_free (priv->group_address); + priv->group_address = _nm_utils_hwaddr_canonical_or_invalid (g_value_get_string (value), + ETH_ALEN); + break; case PROP_GROUP_FORWARD_MASK: priv->group_forward_mask = (guint16) g_value_get_uint (value); break; case PROP_MULTICAST_SNOOPING: priv->multicast_snooping = g_value_get_boolean (value); break; + case PROP_MULTICAST_ROUTER: + g_free (priv->multicast_router); + priv->multicast_router = g_value_dup_string (value); + break; + case PROP_MULTICAST_QUERIER: + priv->multicast_querier = g_value_get_boolean (value); + break; + case PROP_MULTICAST_QUERY_USE_IFADDR: + priv->multicast_query_use_ifaddr = g_value_get_boolean (value); + break; case PROP_VLAN_FILTERING: priv->vlan_filtering = g_value_get_boolean (value); break; case PROP_VLAN_DEFAULT_PVID: priv->vlan_default_pvid = g_value_get_uint (value); break; + case PROP_VLAN_PROTOCOL: + g_free (priv->vlan_protocol); + priv->vlan_protocol = g_value_dup_string (value); + break; + case PROP_VLAN_STATS_ENABLED: + priv->vlan_stats_enabled = g_value_get_boolean (value); + break; case PROP_VLANS: g_ptr_array_unref (priv->vlans); priv->vlans = _nm_utils_copy_array (g_value_get_boxed (value), @@ -1131,6 +1354,18 @@ nm_setting_bridge_init (NMSettingBridge *setting) NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE (setting); priv->vlans = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_bridge_vlan_unref); + + priv->ageing_time = BRIDGE_AGEING_TIME_DEFAULT; + priv->forward_delay = BRIDGE_FORWARD_DELAY_DEFAULT; + priv->hello_time = BRIDGE_HELLO_TIME_DEFAULT; + priv->max_age = BRIDGE_MAX_AGE_DEFAULT; + priv->multicast_snooping = BRIDGE_MULTICAST_SNOOPING_DEFAULT; + priv->priority = BRIDGE_PRIORITY_DEFAULT; + priv->stp = BRIDGE_STP_DEFAULT; + priv->vlan_default_pvid = BRIDGE_VLAN_DEFAULT_PVID_DEFAULT; + priv->vlan_stats_enabled = BRIDGE_VLAN_STATS_ENABLED_DEFAULT; + priv->multicast_query_use_ifaddr = BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEFAULT; + priv->multicast_querier = BRIDGE_MULTICAST_QUERIER_DEFAULT; } /** @@ -1152,6 +1387,9 @@ finalize (GObject *object) NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE (object); g_free (priv->mac_address); + g_free (priv->multicast_router); + g_free (priv->group_address); + g_free (priv->vlan_protocol); g_ptr_array_unref (priv->vlans); G_OBJECT_CLASS (nm_setting_bridge_parent_class)->finalize (object); @@ -1164,8 +1402,6 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) NMSettingClass *setting_class = NM_SETTING_CLASS (klass); GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (klass, sizeof (NMSettingBridgePrivate)); - object_class->get_property = get_property; object_class->set_property = set_property; object_class->finalize = finalize; @@ -1209,7 +1445,7 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj (properties_override, obj_properties[PROP_MAC_ADDRESS], &nm_sett_info_propert_type_mac_addrees); + _nm_properties_override_gobj (properties_override, obj_properties[PROP_MAC_ADDRESS], &nm_sett_info_propert_type_mac_address); /** * NMSettingBridge:stp: @@ -1225,9 +1461,8 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) */ obj_properties[PROP_STP] = g_param_spec_boolean (NM_SETTING_BRIDGE_STP, "", "", - TRUE, + BRIDGE_STP_DEFAULT, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -1248,9 +1483,8 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) */ obj_properties[PROP_PRIORITY] = g_param_spec_uint (NM_SETTING_BRIDGE_PRIORITY, "", "", - 0, G_MAXUINT16, 0x8000, + 0, G_MAXUINT16, BRIDGE_PRIORITY_DEFAULT, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -1269,9 +1503,8 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) */ obj_properties[PROP_FORWARD_DELAY] = g_param_spec_uint (NM_SETTING_BRIDGE_FORWARD_DELAY, "", "", - 0, NM_BR_MAX_FORWARD_DELAY, 15, + 0, NM_BR_MAX_FORWARD_DELAY, BRIDGE_FORWARD_DELAY_DEFAULT, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -1290,9 +1523,8 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) */ obj_properties[PROP_HELLO_TIME] = g_param_spec_uint (NM_SETTING_BRIDGE_HELLO_TIME, "", "", - 0, NM_BR_MAX_HELLO_TIME, 2, + 0, NM_BR_MAX_HELLO_TIME, BRIDGE_HELLO_TIME_DEFAULT, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -1311,9 +1543,8 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) */ obj_properties[PROP_MAX_AGE] = g_param_spec_uint (NM_SETTING_BRIDGE_MAX_AGE, "", "", - 0, NM_BR_MAX_MAX_AGE, 20, + 0, NM_BR_MAX_MAX_AGE, BRIDGE_MAX_AGE_DEFAULT, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -1332,9 +1563,8 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) */ obj_properties[PROP_AGEING_TIME] = g_param_spec_uint (NM_SETTING_BRIDGE_AGEING_TIME, "", "", - NM_BR_MIN_AGEING_TIME, NM_BR_MAX_AGEING_TIME, 300, + NM_BR_MIN_AGEING_TIME, NM_BR_MAX_AGEING_TIME, BRIDGE_AGEING_TIME_DEFAULT, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -1354,7 +1584,6 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) g_param_spec_uint (NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, "", "", 0, 0xFFFF, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -1378,9 +1607,8 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) */ obj_properties[PROP_MULTICAST_SNOOPING] = g_param_spec_boolean (NM_SETTING_BRIDGE_MULTICAST_SNOOPING, "", "", - TRUE, + BRIDGE_MULTICAST_SNOOPING_DEFAULT, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -1403,7 +1631,6 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) g_param_spec_boolean (NM_SETTING_BRIDGE_VLAN_FILTERING, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -1425,9 +1652,8 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) */ obj_properties[PROP_VLAN_DEFAULT_PVID] = g_param_spec_uint (NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, "", "", - 0, NM_BRIDGE_VLAN_VID_MAX, 1, + 0, NM_BRIDGE_VLAN_VID_MAX, BRIDGE_VLAN_DEFAULT_PVID_DEFAULT, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -1473,6 +1699,140 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) */ _nm_properties_override_dbus (properties_override, "interface-name", &nm_sett_info_propert_type_deprecated_interface_name); + /** + * NMSettingBridge:group-address: + * + * If specified, The MAC address of the multicast group this bridge uses for STP. + * + * The address must be a link-local address in standard Ethernet MAC address format, + * ie an address of the form 01:80:C2:00:00:0X, with X in [0, 4..F]. + * If not specified the default value is 01:80:C2:00:00:00. + * + * Since: 1.24 + **/ + /* ---ifcfg-rh--- + * property: group-address + * variable: BRIDGING_OPTS: group_address= + * description: STP group address. + * example: BRIDGING_OPTS="group_address=01:80:C2:00:00:0A" + * ---end--- + */ + obj_properties[PROP_GROUP_ADDRESS] = + g_param_spec_string (NM_SETTING_BRIDGE_GROUP_ADDRESS, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj (properties_override, obj_properties[PROP_GROUP_ADDRESS], &nm_sett_info_propert_type_mac_address); + + /** + * NMSettingBridge:vlan-protocol: + * + * If specified, the protocol used for VLAN filtering. + * + * Supported values are: '802.1Q', '802.1ad'. + * If not specified the default value is '802.1Q'. + * + * Since: 1.24 + **/ + /* ---ifcfg-rh--- + * property: vlan-protocol + * variable: BRIDGING_OPTS: vlan_protocol= + * description: VLAN filtering protocol. + * example: BRIDGING_OPTS="vlan_protocol=802.1Q" + * ---end--- + */ + obj_properties[PROP_VLAN_PROTOCOL] = + g_param_spec_string (NM_SETTING_BRIDGE_VLAN_PROTOCOL, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:vlan-stats-enabled: + * + * Controls whether per-VLAN stats accounting is enabled. + **/ + /* ---ifcfg-rh--- + * property: vlan-stats-enabled + * variable: BRIDGING_OPTS: vlan_stats_enabled= + * default: 0 + * example: BRIDGING_OPTS="vlan_stats_enabled=1" + * ---end--- + */ + obj_properties[PROP_VLAN_STATS_ENABLED] = + g_param_spec_boolean (NM_SETTING_BRIDGE_VLAN_STATS_ENABLED, "", "", + BRIDGE_VLAN_STATS_ENABLED_DEFAULT, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-router: + * + * Sets bridge's multicast router. + * multicast-snooping must be enabled for this option to work. + * + * Supported values are: 'auto', 'disabled', 'enabled'. + * If not specified the default value is 'auto'. + **/ + /* ---ifcfg-rh--- + * property: multicast-router + * variable: BRIDGING_OPTS: multicast_router= + * values: auto, enabled, disabled + * default: auto + * example: BRIDGING_OPTS="multicast_router=enabled" + * ---end--- + */ + obj_properties[PROP_MULTICAST_ROUTER] = + g_param_spec_string (NM_SETTING_BRIDGE_MULTICAST_ROUTER, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-query-use-ifaddr: + * + * If enabled the bridge's own IP address is used as + * the source address for IGMP queries otherwise + * the default of 0.0.0.0 is used. + **/ + /* ---ifcfg-rh--- + * property: multicast-query-use-ifaddr + * variable: BRIDGING_OPTS: multicast_query_use_ifaddr= + * default: 0 + * example: BRIDGING_OPTS="multicast_query-use_ifaddr=1" + * ---end--- + */ + obj_properties[PROP_MULTICAST_QUERY_USE_IFADDR] = + g_param_spec_boolean (NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR, "", "", + BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEFAULT, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-querier: + * + * Enable or disable sending of multicast queries by the bridge. + * If not specified the option is disabled. + **/ + /* ---ifcfg-rh--- + * property: multicast-querier + * variable: BRIDGING_OPTS: multicast_querier= + * default: 0 + * example: BRIDGING_OPTS="multicast_querier=1" + * ---end--- + */ + obj_properties[PROP_MULTICAST_QUERIER] = + g_param_spec_boolean (NM_SETTING_BRIDGE_MULTICAST_QUERIER, "", "", + BRIDGE_MULTICAST_QUERIER_DEFAULT, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BRIDGE, diff --git a/libnm-core/nm-setting-bridge.h b/libnm-core/nm-setting-bridge.h index ee8b45f6..6bd5100f 100644 --- a/libnm-core/nm-setting-bridge.h +++ b/libnm-core/nm-setting-bridge.h @@ -23,37 +23,29 @@ G_BEGIN_DECLS #define NM_SETTING_BRIDGE_SETTING_NAME "bridge" -#define NM_SETTING_BRIDGE_MAC_ADDRESS "mac-address" -#define NM_SETTING_BRIDGE_STP "stp" -#define NM_SETTING_BRIDGE_PRIORITY "priority" -#define NM_SETTING_BRIDGE_FORWARD_DELAY "forward-delay" -#define NM_SETTING_BRIDGE_HELLO_TIME "hello-time" -#define NM_SETTING_BRIDGE_MAX_AGE "max-age" -#define NM_SETTING_BRIDGE_AGEING_TIME "ageing-time" -#define NM_SETTING_BRIDGE_GROUP_FORWARD_MASK "group-forward-mask" -#define NM_SETTING_BRIDGE_MULTICAST_SNOOPING "multicast-snooping" -#define NM_SETTING_BRIDGE_VLAN_FILTERING "vlan-filtering" -#define NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID "vlan-default-pvid" -#define NM_SETTING_BRIDGE_VLANS "vlans" +#define NM_SETTING_BRIDGE_MAC_ADDRESS "mac-address" +#define NM_SETTING_BRIDGE_STP "stp" +#define NM_SETTING_BRIDGE_PRIORITY "priority" +#define NM_SETTING_BRIDGE_FORWARD_DELAY "forward-delay" +#define NM_SETTING_BRIDGE_HELLO_TIME "hello-time" +#define NM_SETTING_BRIDGE_MAX_AGE "max-age" +#define NM_SETTING_BRIDGE_AGEING_TIME "ageing-time" +#define NM_SETTING_BRIDGE_GROUP_FORWARD_MASK "group-forward-mask" +#define NM_SETTING_BRIDGE_MULTICAST_SNOOPING "multicast-snooping" +#define NM_SETTING_BRIDGE_MULTICAST_ROUTER "multicast-router" +#define NM_SETTING_BRIDGE_MULTICAST_QUERIER "multicast-querier" +#define NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR "multicast-query-use-ifaddr" +#define NM_SETTING_BRIDGE_VLAN_FILTERING "vlan-filtering" +#define NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID "vlan-default-pvid" +#define NM_SETTING_BRIDGE_VLANS "vlans" +#define NM_SETTING_BRIDGE_GROUP_ADDRESS "group-address" +#define NM_SETTING_BRIDGE_VLAN_PROTOCOL "vlan-protocol" +#define NM_SETTING_BRIDGE_VLAN_STATS_ENABLED "vlan-stats-enabled" #define NM_BRIDGE_VLAN_VID_MIN 1 #define NM_BRIDGE_VLAN_VID_MAX 4094 -/** - * NMSettingBridge: - * - * Bridging Settings - */ -struct _NMSettingBridge { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingBridgeClass; +typedef struct _NMSettingBridgeClass NMSettingBridgeClass; typedef struct _NMBridgeVlan NMBridgeVlan; @@ -130,6 +122,24 @@ char * nm_bridge_vlan_to_str (const NMBridgeVlan *vlan, GError **error); NM_AVAILABLE_IN_1_18 NMBridgeVlan * nm_bridge_vlan_from_str (const char *str, GError **error); +NM_AVAILABLE_IN_1_24 +const char * nm_setting_bridge_get_group_address (const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_24 +const char * nm_setting_bridge_get_vlan_protocol (const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_24 +gboolean nm_setting_bridge_get_vlan_stats_enabled (const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_24 +const char * nm_setting_bridge_get_multicast_router (const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_24 +gboolean nm_setting_bridge_get_multicast_query_use_ifaddr (const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_24 +gboolean nm_setting_bridge_get_multicast_querier (const NMSettingBridge *setting); + G_END_DECLS #endif /* __NM_SETTING_BRIDGE_H__ */ diff --git a/libnm-core/nm-setting-cdma.c b/libnm-core/nm-setting-cdma.c index 60be8c8f..e303ab8a 100644 --- a/libnm-core/nm-setting-cdma.c +++ b/libnm-core/nm-setting-cdma.c @@ -34,8 +34,8 @@ typedef struct { char *number; /* For dialing, duh */ char *username; char *password; - NMSettingSecretFlags password_flags; guint32 mtu; + NMSettingSecretFlags password_flags; } NMSettingCdmaPrivate; G_DEFINE_TYPE (NMSettingCdma, nm_setting_cdma, NM_TYPE_SETTING) @@ -350,7 +350,6 @@ nm_setting_cdma_class_init (NMSettingCdmaClass *klass) g_param_spec_uint (NM_SETTING_CDMA_MTU, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c index 17058ea7..2e8fa37a 100644 --- a/libnm-core/nm-setting-connection.c +++ b/libnm-core/nm-setting-connection.c @@ -66,6 +66,8 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingConnection, ); typedef struct { + GSList *permissions; /* list of Permission structs */ + GSList *secondaries; /* secondary connections to activate with the base connection */ char *id; char *uuid; char *stable_id; @@ -73,23 +75,21 @@ typedef struct { char *type; char *master; char *slave_type; - NMSettingConnectionAutoconnectSlaves autoconnect_slaves; - GSList *permissions; /* list of Permission structs */ - gboolean autoconnect; + char *zone; + guint64 timestamp; int autoconnect_priority; int autoconnect_retries; int multi_connect; - guint64 timestamp; - gboolean read_only; - char *zone; - GSList *secondaries; /* secondary connections to activate with the base connection */ - guint gateway_ping_timeout; - NMMetered metered; - NMSettingConnectionLldp lldp; int auth_retries; int mdns; int llmnr; int wait_device_timeout; + guint gateway_ping_timeout; + NMSettingConnectionAutoconnectSlaves autoconnect_slaves; + NMMetered metered; + NMSettingConnectionLldp lldp; + bool read_only:1; + bool autoconnect:1; } NMSettingConnectionPrivate; G_DEFINE_TYPE (NMSettingConnection, nm_setting_connection, NM_TYPE_SETTING) @@ -1032,22 +1032,50 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) if (priv->interface_name) { GError *tmp_error = NULL; - gboolean valid_ifname = FALSE; + NMUtilsIfaceType iface_type; - /* do not perform a interface name length check for OVS connection types - * as they don't have a corresponding kernel link that enforces the 15 bytes limit. - * Here we're whitelisting the OVS interface type as well, even if most OVS - * iface types do have the limit, to let the OVS specific nm-setting verify whether the iface name - * is good or not according to the internal type (internal, patch, ...) */ if (NM_IN_STRSET (type, NM_SETTING_OVS_BRIDGE_SETTING_NAME, - NM_SETTING_OVS_PORT_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_SETTING_NAME)) - valid_ifname = nm_utils_ifname_valid (priv->interface_name, NMU_IFACE_OVS, &tmp_error); - else - valid_ifname = nm_utils_ifname_valid (priv->interface_name, NMU_IFACE_KERNEL, &tmp_error); + NM_SETTING_OVS_PORT_SETTING_NAME)) + iface_type = NMU_IFACE_OVS; + else if (nm_streq (type, NM_SETTING_OVS_INTERFACE_SETTING_NAME)) { + NMSettingOvsInterface *s_ovs_iface = NULL; + const char *ovs_iface_type; + + if (connection) + s_ovs_iface = nm_connection_get_setting_ovs_interface (connection); + _nm_setting_ovs_interface_verify_interface_type (s_ovs_iface, + s_ovs_iface ? nm_setting_ovs_interface_get_interface_type (s_ovs_iface) : NULL, + connection, + FALSE, + NULL, + &ovs_iface_type, + NULL); + if (!ovs_iface_type) { + /* We cannot determine to OVS interface type. Consequently, we cannot + * fully validate the interface name. + * + * If we have a connection (and we do a full validation anyway), skip the + * check. The connection will fail validation when we validate the OVS setting. + * + * Otherwise, do the most basic validation. + */ + if (connection) + goto after_interface_name; + iface_type = NMU_IFACE_ANY; + } else if (NM_IN_STRSET (ovs_iface_type, "patch")) { + /* this interface type is internal to OVS. */ + iface_type = NMU_IFACE_OVS; + } else { + /* This interface type also requires a netdev. We need to validate + * for both OVS and KERNEL. */ + nm_assert (NM_IN_STRSET (ovs_iface_type, "internal", "system", "dpdk")); + iface_type = NMU_IFACE_OVS_AND_KERNEL; + } + } else + iface_type = NMU_IFACE_KERNEL; - if (!valid_ifname) { + if (!nm_utils_ifname_valid (priv->interface_name, iface_type, &tmp_error)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -1057,6 +1085,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } } +after_interface_name: is_slave = FALSE; slave_setting_type = NULL; @@ -1251,11 +1280,14 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } static const char * -find_virtual_interface_name (GVariant *connection_dict) +find_virtual_interface_name (GVariant *connection_dict, + GVariant **variant_to_free) { GVariant *setting_dict; const char *interface_name; + nm_assert (variant_to_free && !*variant_to_free); + setting_dict = g_variant_lookup_value (connection_dict, NM_SETTING_BOND_SETTING_NAME, NM_VARIANT_TYPE_SETTING); if (!setting_dict) setting_dict = g_variant_lookup_value (connection_dict, NM_SETTING_BRIDGE_SETTING_NAME, NM_VARIANT_TYPE_SETTING); @@ -1267,40 +1299,16 @@ find_virtual_interface_name (GVariant *connection_dict) if (!setting_dict) return NULL; + *variant_to_free = setting_dict; + /* All of the deprecated virtual interface name properties were named "interface-name". */ if (!g_variant_lookup (setting_dict, "interface-name", "&s", &interface_name)) interface_name = NULL; - g_variant_unref (setting_dict); return interface_name; } static gboolean -nm_setting_connection_set_interface_name (NMSetting *setting, - GVariant *connection_dict, - const char *property, - GVariant *value, - NMSettingParseFlags parse_flags, - GError **error) -{ - const char *interface_name; - - /* For compatibility reasons, if there is an invalid virtual interface name, - * we need to make verification fail, even if that virtual name would be - * overridden by a valid connection.interface-name. - */ - interface_name = find_virtual_interface_name (connection_dict); - if (!interface_name || nm_utils_ifname_valid_kernel (interface_name, NULL)) - interface_name = g_variant_get_string (value, NULL); - - g_object_set (G_OBJECT (setting), - NM_SETTING_CONNECTION_INTERFACE_NAME, interface_name, - NULL); - - return TRUE; -} - -static gboolean nm_setting_connection_no_interface_name (NMSetting *setting, GVariant *connection_dict, const char *property, @@ -1308,8 +1316,9 @@ nm_setting_connection_no_interface_name (NMSetting *setting, GError **error) { const char *virtual_interface_name; + gs_unref_variant GVariant *variant_to_free = NULL; - virtual_interface_name = find_virtual_interface_name (connection_dict); + virtual_interface_name = find_virtual_interface_name (connection_dict, &variant_to_free); g_object_set (G_OBJECT (setting), NM_SETTING_CONNECTION_INTERFACE_NAME, virtual_interface_name, NULL); @@ -1566,9 +1575,15 @@ nm_setting_connection_init (NMSettingConnection *setting) { NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting); - priv->mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; - priv->llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; - priv->wait_device_timeout = -1; + priv->auth_retries = -1; + priv->autoconnect = TRUE; + priv->autoconnect_priority = NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT; + priv->autoconnect_retries = -1; + priv->autoconnect_slaves = NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT; + priv->lldp = NM_SETTING_CONNECTION_LLDP_DEFAULT; + priv->llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; + priv->mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; + priv->wait_device_timeout = -1; } /** @@ -1753,7 +1768,6 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass) obj_properties[PROP_INTERFACE_NAME], NM_SETT_INFO_PROPERT_TYPE ( .dbus_type = G_VARIANT_TYPE_STRING, - .from_dbus_fcn = nm_setting_connection_set_interface_name, .missing_from_dbus_fcn = nm_setting_connection_no_interface_name, )); @@ -1836,7 +1850,6 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass) g_param_spec_boolean (NM_SETTING_CONNECTION_AUTOCONNECT, "", "", TRUE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -1863,7 +1876,6 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass) NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MAX, NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -1889,7 +1901,6 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass) g_param_spec_int (NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES, "", "", -1, G_MAXINT32, -1, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -1906,7 +1917,7 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass) * variable: MULTI_CONNECT(+) * description: whether the profile can be active on multiple devices at a given * moment. The values are numbers corresponding to #NMConnectionMultiConnect enum. - * example: ZONE=3 + * example: MULTI_CONNECT=3 * ---end--- */ obj_properties[PROP_MULTI_CONNECT] = @@ -1931,7 +1942,6 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass) g_param_spec_uint64 (NM_SETTING_CONNECTION_TIMESTAMP, "", "", 0, G_MAXUINT64, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); _nm_properties_override_gobj (properties_override, @@ -1952,7 +1962,6 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass) g_param_spec_boolean (NM_SETTING_CONNECTION_READ_ONLY, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -1979,7 +1988,6 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass) g_param_spec_string (NM_SETTING_CONNECTION_ZONE, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_REAPPLY_IMMEDIATELY | G_PARAM_STATIC_STRINGS); @@ -2059,7 +2067,6 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass) NM_TYPE_SETTING_CONNECTION_AUTOCONNECT_SLAVES, NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -2103,7 +2110,6 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass) g_param_spec_uint (NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, "", "", 0, 600, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -2153,7 +2159,6 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass) G_MININT32, G_MAXINT32, NM_SETTING_CONNECTION_LLDP_DEFAULT, NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -2178,7 +2183,6 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass) g_param_spec_int (NM_SETTING_CONNECTION_AUTH_RETRIES, "", "", -1, G_MAXINT32, -1, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-dcb.c b/libnm-core/nm-setting-dcb.c index 3c12abdf..415eb37b 100644 --- a/libnm-core/nm-setting-dcb.c +++ b/libnm-core/nm-setting-dcb.c @@ -49,27 +49,21 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingDcb, ); typedef struct { - NMSettingDcbFlags app_fcoe_flags; - int app_fcoe_priority; char * app_fcoe_mode; - - NMSettingDcbFlags app_iscsi_flags; - int app_iscsi_priority; - - NMSettingDcbFlags app_fip_flags; - int app_fip_priority; - - /* Priority Flow Control */ - NMSettingDcbFlags pfc_flags; guint pfc[8]; - - /* Priority Groups */ - NMSettingDcbFlags priority_group_flags; guint priority_group_id[8]; guint priority_group_bandwidth[8]; guint priority_bandwidth[8]; guint priority_strict[8]; guint priority_traffic_class[8]; + int app_fcoe_priority; + int app_iscsi_priority; + int app_fip_priority; + NMSettingDcbFlags app_fcoe_flags; + NMSettingDcbFlags app_iscsi_flags; + NMSettingDcbFlags app_fip_flags; + NMSettingDcbFlags pfc_flags; + NMSettingDcbFlags priority_group_flags; } NMSettingDcbPrivate; G_DEFINE_TYPE (NMSettingDcb, nm_setting_dcb, NM_TYPE_SETTING) @@ -872,8 +866,14 @@ set_property (GObject *object, guint prop_id, /*****************************************************************************/ static void -nm_setting_dcb_init (NMSettingDcb *setting) +nm_setting_dcb_init (NMSettingDcb *self) { + NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE (self); + + priv->app_fcoe_mode = g_strdup (NM_SETTING_DCB_FCOE_MODE_FABRIC); + priv->app_fcoe_priority = -1; + priv->app_fip_priority = -1; + priv->app_iscsi_priority = -1; } /** @@ -954,7 +954,6 @@ nm_setting_dcb_class_init (NMSettingDcbClass *klass) g_param_spec_int (NM_SETTING_DCB_APP_FCOE_PRIORITY, "", "", -1, 7, -1, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -975,7 +974,6 @@ nm_setting_dcb_class_init (NMSettingDcbClass *klass) g_param_spec_string (NM_SETTING_DCB_APP_FCOE_MODE, "", "", NM_SETTING_DCB_FCOE_MODE_FABRIC, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -1017,7 +1015,6 @@ nm_setting_dcb_class_init (NMSettingDcbClass *klass) g_param_spec_int (NM_SETTING_DCB_APP_ISCSI_PRIORITY, "", "", -1, 7, -1, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -1059,7 +1056,6 @@ nm_setting_dcb_class_init (NMSettingDcbClass *klass) g_param_spec_int (NM_SETTING_DCB_APP_FIP_PRIORITY, "", "", -1, 7, -1, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** diff --git a/libnm-core/nm-setting-gsm.c b/libnm-core/nm-setting-gsm.c index 4bc957d3..19e2554a 100644 --- a/libnm-core/nm-setting-gsm.c +++ b/libnm-core/nm-setting-gsm.c @@ -41,26 +41,20 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - gboolean auto_config; - char *number; /* For dialing, duh */ char *username; char *password; - NMSettingSecretFlags password_flags; - - /* Restrict connection to certain devices or SIMs */ char *device_id; char *sim_id; char *sim_operator_id; - char *apn; /* NULL for dynamic */ char *network_id; /* for manual registration or NULL for automatic */ - char *pin; + NMSettingSecretFlags password_flags; NMSettingSecretFlags pin_flags; - - gboolean home_only; guint32 mtu; + bool auto_config:1; + bool home_only:1; } NMSettingGsmPrivate; G_DEFINE_TYPE (NMSettingGsm, nm_setting_gsm, NM_TYPE_SETTING) @@ -91,7 +85,7 @@ nm_setting_gsm_get_auto_config (NMSettingGsm *setting) * * Returns: the #NMSettingGsm:number property of the setting * - * Deprecated: 1.16: user-provided values for this setting are no longer used. + * Deprecated: 1.16: User-provided values for this setting are no longer used. **/ const char * nm_setting_gsm_get_number (NMSettingGsm *setting) @@ -665,7 +659,7 @@ nm_setting_gsm_class_init (NMSettingGsmClass *klass) * Legacy setting that used to help establishing PPP data sessions for * GSM-based modems. * - * Deprecated: 1.16: user-provided values for this setting are no longer used. + * Deprecated: 1.16: User-provided values for this setting are no longer used. **/ obj_properties[PROP_NUMBER] = g_param_spec_string (NM_SETTING_GSM_NUMBER, "", "", @@ -842,7 +836,6 @@ nm_setting_gsm_class_init (NMSettingGsmClass *klass) g_param_spec_uint (NM_SETTING_GSM_MTU, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-infiniband.c b/libnm-core/nm-setting-infiniband.c index fcaa1f9a..bfce580e 100644 --- a/libnm-core/nm-setting-infiniband.c +++ b/libnm-core/nm-setting-infiniband.c @@ -35,9 +35,10 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( typedef struct { char *mac_address; char *transport_mode; - guint32 mtu; + char *parent; + char *virtual_iface_name; int p_key; - char *parent, *virtual_iface_name; + guint32 mtu; } NMSettingInfinibandPrivate; G_DEFINE_TYPE (NMSettingInfiniband, nm_setting_infiniband, NM_TYPE_SETTING) @@ -210,39 +211,23 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) s_con = nm_connection_get_setting_connection (connection); if (s_con) { const char *interface_name = nm_setting_connection_get_interface_name (s_con); - GError *tmp_error = NULL; - if (!interface_name) - ; - else if (!nm_utils_ifname_valid_kernel (interface_name, &tmp_error)) { - /* report the error for NMSettingConnection:interface-name, because - * it's that property that is invalid -- although we currently verify() - * NMSettingInfiniband. - **/ - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - "'%s': %s", interface_name, tmp_error->message); - g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME); - g_error_free (tmp_error); - return FALSE; - } else { - if (priv->p_key != -1) { - if (!priv->virtual_iface_name) - priv->virtual_iface_name = g_strdup_printf ("%s.%04x", priv->parent, priv->p_key); - - if (strcmp (interface_name, priv->virtual_iface_name) != 0) { - /* We don't support renaming software infiniband devices. Later we might, but - * for now just reject such connections. - **/ - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("interface name of software infiniband device must be '%s' or unset (instead it is '%s')"), - priv->virtual_iface_name, interface_name); - g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME); - return FALSE; - } + if ( interface_name + && priv->p_key != -1) { + if (!priv->virtual_iface_name) + priv->virtual_iface_name = g_strdup_printf ("%s.%04x", priv->parent, priv->p_key); + + if (strcmp (interface_name, priv->virtual_iface_name) != 0) { + /* We don't support renaming software infiniband devices. Later we might, but + * for now just reject such connections. + **/ + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("interface name of software infiniband device must be '%s' or unset (instead it is '%s')"), + priv->virtual_iface_name, interface_name); + g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME); + return FALSE; } } } @@ -322,12 +307,12 @@ set_property (GObject *object, guint prop_id, break; case PROP_P_KEY: priv->p_key = g_value_get_int (value); - g_clear_pointer (&priv->virtual_iface_name, g_free); + nm_clear_g_free (&priv->virtual_iface_name); break; case PROP_PARENT: g_free (priv->parent); priv->parent = g_value_dup_string (value); - g_clear_pointer (&priv->virtual_iface_name, g_free); + nm_clear_g_free (&priv->virtual_iface_name); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -338,8 +323,11 @@ set_property (GObject *object, guint prop_id, /*****************************************************************************/ static void -nm_setting_infiniband_init (NMSettingInfiniband *setting) +nm_setting_infiniband_init (NMSettingInfiniband *self) { + NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE (self); + + priv->p_key = -1; } /** @@ -414,7 +402,7 @@ nm_setting_infiniband_class_init (NMSettingInfinibandClass *klass) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj (properties_override, obj_properties[PROP_MAC_ADDRESS], &nm_sett_info_propert_type_mac_addrees); + _nm_properties_override_gobj (properties_override, obj_properties[PROP_MAC_ADDRESS], &nm_sett_info_propert_type_mac_address); /** * NMSettingInfiniband:mtu: @@ -432,7 +420,6 @@ nm_setting_infiniband_class_init (NMSettingInfinibandClass *klass) g_param_spec_uint (NM_SETTING_INFINIBAND_MTU, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -454,7 +441,6 @@ nm_setting_infiniband_class_init (NMSettingInfinibandClass *klass) g_param_spec_string (NM_SETTING_INFINIBAND_TRANSPORT_MODE, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -480,7 +466,6 @@ nm_setting_infiniband_class_init (NMSettingInfinibandClass *klass) g_param_spec_int (NM_SETTING_INFINIBAND_P_KEY, "", "", -1, 0xFFFF, -1, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -504,7 +489,6 @@ nm_setting_infiniband_class_init (NMSettingInfinibandClass *klass) g_param_spec_string (NM_SETTING_INFINIBAND_PARENT, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c index 7f1690ac..55cec35f 100644 --- a/libnm-core/nm-setting-ip-config.c +++ b/libnm-core/nm-setting-ip-config.c @@ -50,19 +50,6 @@ const NMUtilsDNSOptionDesc _nm_utils_dns_option_descs[] = { { NULL, FALSE, FALSE } }; -static int -_addr_size (int family) -{ - switch (family) { - case AF_INET: - return sizeof (in_addr_t); - case AF_INET6: - return sizeof (struct in6_addr); - default: - g_return_val_if_reached (0); - } -} - static char * canonicalize_ip (int family, const char *ip, gboolean null_any) { @@ -84,7 +71,7 @@ canonicalize_ip (int family, const char *ip, gboolean null_any) g_return_val_if_fail (ret == 1, NULL); if (null_any) { - if (!memcmp (addr_bytes, &in6addr_any, _addr_size (family))) + if (!memcmp (addr_bytes, &in6addr_any, nm_utils_addr_family_to_size (family))) return NULL; } @@ -106,7 +93,7 @@ canonicalize_ip_binary (int family, gconstpointer ip, gboolean null_any) g_return_val_if_reached (NULL); } if (null_any) { - if (!memcmp (ip, &in6addr_any, _addr_size (family))) + if (!memcmp (ip, &in6addr_any, nm_utils_addr_family_to_size (family))) return NULL; } return g_strdup (inet_ntop (family, ip, string, sizeof (string))); @@ -120,7 +107,7 @@ valid_ip (int family, const char *ip, GError **error) family == AF_INET ? _("Missing IPv4 address") : _("Missing IPv6 address")); return FALSE; } - if (!nm_utils_ipaddr_valid (family, ip)) { + if (!nm_utils_ipaddr_is_valid (family, ip)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, family == AF_INET ? _("Invalid IPv4 address '%s'") : _("Invalid IPv6 address '%s'"), ip); @@ -446,7 +433,7 @@ nm_ip_address_set_address (NMIPAddress *address, { g_return_if_fail (address != NULL); g_return_if_fail (addr != NULL); - g_return_if_fail (nm_utils_ipaddr_valid (address->family, addr)); + g_return_if_fail (nm_utils_ipaddr_is_valid (address->family, addr)); g_free (address->address); address->address = canonicalize_ip (address->family, addr, FALSE); @@ -900,14 +887,14 @@ nm_ip_route_get_dest (NMIPRoute *route) * Sets the destination property of this route object. * * @dest must be a valid address of @route's family. If you aren't sure you - * have a valid address, use nm_utils_ipaddr_valid() to check it. + * have a valid address, use nm_utils_ipaddr_is_valid() to check it. **/ void nm_ip_route_set_dest (NMIPRoute *route, const char *dest) { g_return_if_fail (route != NULL); - g_return_if_fail (nm_utils_ipaddr_valid (route->family, dest)); + g_return_if_fail (nm_utils_ipaddr_is_valid (route->family, dest)); g_free (route->dest); route->dest = canonicalize_ip (route->family, dest, FALSE); @@ -1022,7 +1009,7 @@ nm_ip_route_set_next_hop (NMIPRoute *route, const char *next_hop) { g_return_if_fail (route != NULL); - g_return_if_fail (!next_hop || nm_utils_ipaddr_valid (route->family, next_hop)); + g_return_if_fail (!next_hop || nm_utils_ipaddr_is_valid (route->family, next_hop)); g_free (route->next_hop); route->next_hop = canonicalize_ip (route->family, next_hop, TRUE); @@ -1051,7 +1038,7 @@ nm_ip_route_get_next_hop_binary (NMIPRoute *route, inet_pton (route->family, route->next_hop, next_hop); return TRUE; } else { - memset (next_hop, 0, _addr_size (route->family)); + memset (next_hop, 0, nm_utils_addr_family_to_size (route->family)); return FALSE; } } @@ -1310,7 +1297,7 @@ nm_ip_route_attribute_validate (const char *name, switch (spec->str_type) { case 'a': /* IP address */ - if (!nm_utils_ipaddr_valid (family, string)) { + if (!nm_utils_ipaddr_is_valid (family, string)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, @@ -1338,7 +1325,7 @@ nm_ip_route_attribute_validate (const char *name, return FALSE; } } - if (!nm_utils_ipaddr_valid (family, addr)) { + if (!nm_utils_ipaddr_is_valid (family, addr)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, @@ -3598,27 +3585,27 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingIPConfig, ); typedef struct { - char *method; - GPtrArray *dns; /* array of IP address strings */ - GPtrArray *dns_search; /* array of domain name strings */ - GPtrArray *dns_options;/* array of DNS options */ - int dns_priority; - GPtrArray *addresses; /* array of NMIPAddress */ - GPtrArray *routes; /* array of NMIPRoute */ + GPtrArray *dns; /* array of IP address strings */ + GPtrArray *dns_search; /* array of domain name strings */ + GPtrArray *dns_options; /* array of DNS options */ + GPtrArray *addresses; /* array of NMIPAddress */ + GPtrArray *routes; /* array of NMIPRoute */ GPtrArray *routing_rules; - gint64 route_metric; - guint32 route_table; + char *method; char *gateway; - gboolean ignore_auto_routes; - gboolean ignore_auto_dns; char *dhcp_hostname; - gboolean dhcp_send_hostname; - gboolean never_default; - gboolean may_fail; - int dad_timeout; - int dhcp_timeout; char *dhcp_iaid; + gint64 route_metric; guint dhcp_hostname_flags; + int dns_priority; + int dad_timeout; + int dhcp_timeout; + guint32 route_table; + bool ignore_auto_routes:1; + bool ignore_auto_dns:1; + bool dhcp_send_hostname:1; + bool never_default:1; + bool may_fail:1; } NMSettingIPConfigPrivate; G_DEFINE_ABSTRACT_TYPE (NMSettingIPConfig, nm_setting_ip_config, NM_TYPE_SETTING) @@ -3698,7 +3685,7 @@ nm_setting_ip_config_add_dns (NMSettingIPConfig *setting, const char *dns) g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE); g_return_val_if_fail (dns != NULL, FALSE); - g_return_val_if_fail (nm_utils_ipaddr_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), dns), FALSE); + g_return_val_if_fail (nm_utils_ipaddr_is_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), dns), FALSE); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); @@ -3754,7 +3741,7 @@ nm_setting_ip_config_remove_dns_by_value (NMSettingIPConfig *setting, const char g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE); g_return_val_if_fail (dns != NULL, FALSE); - g_return_val_if_fail (nm_utils_ipaddr_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), dns), FALSE); + g_return_val_if_fail (nm_utils_ipaddr_is_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), dns), FALSE); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); @@ -4959,7 +4946,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) for (i = 0; i < priv->dns->len; i++) { const char *dns = priv->dns->pdata[i]; - if (!nm_utils_ipaddr_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), dns)) { + if (!nm_utils_ipaddr_is_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), dns)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -5019,7 +5006,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (!nm_utils_ipaddr_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), priv->gateway)) { + if (!nm_utils_ipaddr_is_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), priv->gateway)) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -5441,7 +5428,7 @@ set_property (GObject *object, guint prop_id, break; case PROP_GATEWAY: gateway = g_value_get_string (value); - g_return_if_fail (!gateway || nm_utils_ipaddr_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), gateway)); + g_return_if_fail (!gateway || nm_utils_ipaddr_is_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), gateway)); g_free (priv->gateway); priv->gateway = canonicalize_ip (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), gateway, TRUE); break; @@ -5501,11 +5488,14 @@ nm_setting_ip_config_init (NMSettingIPConfig *setting) { NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); - priv->dns = g_ptr_array_new_with_free_func (g_free); - priv->dns_search = g_ptr_array_new_with_free_func (g_free); - priv->dns_options = NULL; - priv->addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref); - priv->routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref); + priv->dns = g_ptr_array_new_with_free_func (g_free); + priv->dns_search = g_ptr_array_new_with_free_func (g_free); + priv->addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref); + priv->routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref); + priv->route_metric = -1; + priv->dhcp_send_hostname = TRUE; + priv->may_fail = TRUE; + priv->dad_timeout = -1; } static void @@ -5628,7 +5618,7 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass) * The relative priority for DNS servers specified by this setting. A lower * value is better (higher priority). Zero selects a globally configured * default value. If the latter is missing or zero too, it defaults to - * 50 for VPNs and 100 for other connections. + * 50 for VPNs (including WireGuard) and 100 for other connections. * * Note that the priority is to order DNS settings for multiple active * connections. It does not disambiguate multiple DNS servers within the @@ -5660,7 +5650,6 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass) g_param_spec_int (NM_SETTING_IP_CONFIG_DNS_PRIORITY, "", "", G_MININT32, G_MAXINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -5725,7 +5714,6 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass) g_param_spec_int64 (NM_SETTING_IP_CONFIG_ROUTE_METRIC, "", "", -1, G_MAXUINT32, -1, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -5766,7 +5754,6 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass) g_param_spec_boolean (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -5782,7 +5769,6 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass) g_param_spec_boolean (NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -5812,7 +5798,6 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass) g_param_spec_boolean (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, "", "", TRUE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -5826,7 +5811,6 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass) g_param_spec_boolean (NM_SETTING_IP_CONFIG_NEVER_DEFAULT, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -5844,7 +5828,6 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass) g_param_spec_boolean (NM_SETTING_IP_CONFIG_MAY_FAIL, "", "", TRUE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -5865,7 +5848,6 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass) g_param_spec_int (NM_SETTING_IP_CONFIG_DAD_TIMEOUT, "", "", -1, NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX, -1, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-ip-tunnel.c b/libnm-core/nm-setting-ip-tunnel.c index ae1df194..f6690e8b 100644 --- a/libnm-core/nm-setting-ip-tunnel.c +++ b/libnm-core/nm-setting-ip-tunnel.c @@ -35,18 +35,18 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( typedef struct { char *parent; - NMIPTunnelMode mode; char *local; char *remote; - guint ttl; - guint tos; - gboolean path_mtu_discovery; char *input_key; char *output_key; + guint ttl; + guint tos; guint encapsulation_limit; guint flow_label; + NMIPTunnelMode mode; guint32 mtu; guint32 flags; + bool path_mtu_discovery:1; } NMSettingIPTunnelPrivate; G_DEFINE_TYPE (NMSettingIPTunnel, nm_setting_ip_tunnel, NM_TYPE_SETTING) @@ -341,7 +341,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (priv->local && !nm_utils_ipaddr_valid (family, priv->local)) { + if (priv->local && !nm_utils_ipaddr_is_valid (family, priv->local)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -361,7 +361,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (!nm_utils_ipaddr_valid (family, priv->remote)) { + if (!nm_utils_ipaddr_is_valid (family, priv->remote)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -576,8 +576,11 @@ set_property (GObject *object, guint prop_id, /*****************************************************************************/ static void -nm_setting_ip_tunnel_init (NMSettingIPTunnel *setting) +nm_setting_ip_tunnel_init (NMSettingIPTunnel *self) { + NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE (self); + + priv->path_mtu_discovery = TRUE; } /** @@ -697,7 +700,6 @@ nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *klass) g_param_spec_uint (NM_SETTING_IP_TUNNEL_TTL, "", "", 0, 255, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -713,7 +715,6 @@ nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *klass) g_param_spec_uint (NM_SETTING_IP_TUNNEL_TOS, "", "", 0, 255, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -728,7 +729,6 @@ nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *klass) g_param_spec_boolean (NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY, "", "", TRUE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -774,7 +774,6 @@ nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *klass) g_param_spec_uint (NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT, "", "", 0, 255, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -790,7 +789,6 @@ nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *klass) g_param_spec_uint (NM_SETTING_IP_TUNNEL_FLOW_LABEL, "", "", 0, (1 << 20) - 1, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -806,7 +804,6 @@ nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *klass) g_param_spec_uint (NM_SETTING_IP_TUNNEL_MTU, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c index f3306ade..c7c2c48d 100644 --- a/libnm-core/nm-setting-ip6-config.c +++ b/libnm-core/nm-setting-ip6-config.c @@ -143,7 +143,7 @@ nm_setting_ip6_config_get_dhcp_duid (NMSettingIP6Config *setting) * Returns: The configured %NM_SETTING_IP6_CONFIG_RA_TIMEOUT value with the * timeout for router advertisements in seconds. * - * Since: 1.24, 1.22.8 + * Since: 1.24 **/ gint32 nm_setting_ip6_config_get_ra_timeout (NMSettingIP6Config *setting) @@ -254,7 +254,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (g_strcmp0 (priv->token, nm_utils_inet6_ntop (&i6_token, s_token))) + if (g_strcmp0 (priv->token, _nm_utils_inet6_ntop (&i6_token, s_token))) token_needs_normalization = TRUE; } else { g_set_error_literal (error, @@ -538,6 +538,10 @@ set_property (GObject *object, guint prop_id, static void nm_setting_ip6_config_init (NMSettingIP6Config *setting) { + NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + + priv->ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; + priv->addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY; } /** @@ -787,7 +791,6 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *klass) NM_TYPE_SETTING_IP6_CONFIG_PRIVACY, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -836,7 +839,6 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *klass) G_MININT, G_MAXINT, NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -870,7 +872,7 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *klass) * * Set to 2147483647 (MAXINT32) for infinity. * - * Since: 1.24, 1.22.8 + * Since: 1.24 **/ /* ---ifcfg-rh--- * property: dhcp-timeout diff --git a/libnm-core/nm-setting-ip6-config.h b/libnm-core/nm-setting-ip6-config.h index 4173c3b0..e6eb49bb 100644 --- a/libnm-core/nm-setting-ip6-config.h +++ b/libnm-core/nm-setting-ip6-config.h @@ -161,7 +161,7 @@ NM_AVAILABLE_IN_1_4 const char *nm_setting_ip6_config_get_token (NMSettingIP6Config *setting); NM_AVAILABLE_IN_1_12 const char *nm_setting_ip6_config_get_dhcp_duid (NMSettingIP6Config *setting); -NM_AVAILABLE_IN_1_22_8 +NM_AVAILABLE_IN_1_24 gint32 nm_setting_ip6_config_get_ra_timeout (NMSettingIP6Config *setting); G_END_DECLS diff --git a/libnm-core/nm-setting-macsec.c b/libnm-core/nm-setting-macsec.c index 62351eb5..87f4492d 100644 --- a/libnm-core/nm-setting-macsec.c +++ b/libnm-core/nm-setting-macsec.c @@ -42,14 +42,14 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( typedef struct { char *parent; - NMSettingMacsecMode mode; - bool encrypt:1; - bool send_sci:1; char *mka_cak; - NMSettingSecretFlags mka_cak_flags; char *mka_ckn; int port; + NMSettingMacsecMode mode; + NMSettingSecretFlags mka_cak_flags; NMSettingMacsecValidation validation; + bool encrypt:1; + bool send_sci:1; } NMSettingMacsecPrivate; G_DEFINE_TYPE (NMSettingMacsec, nm_setting_macsec, NM_TYPE_SETTING) @@ -458,8 +458,15 @@ set_property (GObject *object, guint prop_id, /*****************************************************************************/ static void -nm_setting_macsec_init (NMSettingMacsec *setting) +nm_setting_macsec_init (NMSettingMacsec *self) { + NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE (self); + + nm_assert (priv->mode == NM_SETTING_MACSEC_MODE_PSK); + priv->encrypt = TRUE; + priv->port = 1; + priv->send_sci = TRUE; + priv->validation = NM_SETTING_MACSEC_VALIDATION_STRICT; } /** @@ -519,7 +526,6 @@ nm_setting_macsec_class_init (NMSettingMacsecClass *klass) g_param_spec_string (NM_SETTING_MACSEC_PARENT, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -535,7 +541,6 @@ nm_setting_macsec_class_init (NMSettingMacsecClass *klass) g_param_spec_int (NM_SETTING_MACSEC_MODE, "", "", G_MININT, G_MAXINT, NM_SETTING_MACSEC_MODE_PSK, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -550,7 +555,6 @@ nm_setting_macsec_class_init (NMSettingMacsecClass *klass) g_param_spec_boolean (NM_SETTING_MACSEC_ENCRYPT, "", "", TRUE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -565,7 +569,6 @@ nm_setting_macsec_class_init (NMSettingMacsecClass *klass) g_param_spec_string (NM_SETTING_MACSEC_MKA_CAK, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); @@ -596,7 +599,6 @@ nm_setting_macsec_class_init (NMSettingMacsecClass *klass) g_param_spec_string (NM_SETTING_MACSEC_MKA_CKN, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -610,7 +612,6 @@ nm_setting_macsec_class_init (NMSettingMacsecClass *klass) g_param_spec_int (NM_SETTING_MACSEC_PORT, "", "", 1, 65534, 1, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -625,7 +626,6 @@ nm_setting_macsec_class_init (NMSettingMacsecClass *klass) g_param_spec_int (NM_SETTING_MACSEC_VALIDATION, "", "", G_MININT, G_MAXINT, NM_SETTING_MACSEC_VALIDATION_STRICT, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -641,7 +641,6 @@ nm_setting_macsec_class_init (NMSettingMacsecClass *klass) g_param_spec_boolean (NM_SETTING_MACSEC_SEND_SCI, "", "", TRUE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/libnm-core/nm-setting-macvlan.c b/libnm-core/nm-setting-macvlan.c index d62184c2..cbaadd3f 100644 --- a/libnm-core/nm-setting-macvlan.c +++ b/libnm-core/nm-setting-macvlan.c @@ -35,8 +35,8 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( typedef struct { char *parent; NMSettingMacvlanMode mode; - gboolean promiscuous; - gboolean tap; + bool promiscuous:1; + bool tap:1; } NMSettingMacvlanPrivate; G_DEFINE_TYPE (NMSettingMacvlan, nm_setting_macvlan, NM_TYPE_SETTING) @@ -217,8 +217,11 @@ set_property (GObject *object, guint prop_id, /*****************************************************************************/ static void -nm_setting_macvlan_init (NMSettingMacvlan *setting) +nm_setting_macvlan_init (NMSettingMacvlan *self) { + NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE (self); + + priv->promiscuous = TRUE; } /** @@ -275,7 +278,6 @@ nm_setting_macvlan_class_init (NMSettingMacvlanClass *klass) g_param_spec_string (NM_SETTING_MACVLAN_PARENT, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -291,7 +293,6 @@ nm_setting_macvlan_class_init (NMSettingMacvlanClass *klass) g_param_spec_uint (NM_SETTING_MACVLAN_MODE, "", "", 0, G_MAXUINT, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -306,7 +307,6 @@ nm_setting_macvlan_class_init (NMSettingMacvlanClass *klass) g_param_spec_boolean (NM_SETTING_MACVLAN_PROMISCUOUS, "", "", TRUE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -321,7 +321,6 @@ nm_setting_macvlan_class_init (NMSettingMacvlanClass *klass) g_param_spec_boolean (NM_SETTING_MACVLAN_TAP, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-match.c b/libnm-core/nm-setting-match.c index 2fbd0716..2e058810 100644 --- a/libnm-core/nm-setting-match.c +++ b/libnm-core/nm-setting-match.c @@ -25,7 +25,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingMatch, /** * NMSettingMatch: * - * Match settings. + * Match settings * * Since: 1.14 */ diff --git a/libnm-core/nm-setting-olpc-mesh.c b/libnm-core/nm-setting-olpc-mesh.c index 0e1d27cf..7c7f1753 100644 --- a/libnm-core/nm-setting-olpc-mesh.c +++ b/libnm-core/nm-setting-olpc-mesh.c @@ -31,8 +31,8 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( typedef struct { GBytes *ssid; - guint32 channel; char *dhcp_anycast_addr; + guint32 channel; } NMSettingOlpcMeshPrivate; G_DEFINE_TYPE (NMSettingOlpcMesh, nm_setting_olpc_mesh, NM_TYPE_SETTING) @@ -234,7 +234,6 @@ nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *klass) g_param_spec_uint (NM_SETTING_OLPC_MESH_CHANNEL, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -250,7 +249,7 @@ nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj (properties_override, obj_properties[PROP_DHCP_ANYCAST_ADDRESS], &nm_sett_info_propert_type_mac_addrees); + _nm_properties_override_gobj (properties_override, obj_properties[PROP_DHCP_ANYCAST_ADDRESS], &nm_sett_info_propert_type_mac_address); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/libnm-core/nm-setting-ovs-bridge.c b/libnm-core/nm-setting-ovs-bridge.c index 7f9ca1dc..2f907885 100644 --- a/libnm-core/nm-setting-ovs-bridge.c +++ b/libnm-core/nm-setting-ovs-bridge.c @@ -39,9 +39,9 @@ struct _NMSettingOvsBridge { char *fail_mode; char *datapath_type; - gboolean mcast_snooping_enable; - gboolean rstp_enable; - gboolean stp_enable; + bool mcast_snooping_enable:1; + bool rstp_enable:1; + bool stp_enable:1; }; struct _NMSettingOvsBridgeClass { @@ -305,7 +305,6 @@ nm_setting_ovs_bridge_class_init (NMSettingOvsBridgeClass *klass) g_param_spec_string (NM_SETTING_OVS_BRIDGE_FAIL_MODE, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -320,7 +319,6 @@ nm_setting_ovs_bridge_class_init (NMSettingOvsBridgeClass *klass) g_param_spec_boolean (NM_SETTING_OVS_BRIDGE_MCAST_SNOOPING_ENABLE, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -334,7 +332,6 @@ nm_setting_ovs_bridge_class_init (NMSettingOvsBridgeClass *klass) g_param_spec_boolean (NM_SETTING_OVS_BRIDGE_RSTP_ENABLE, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -348,7 +345,6 @@ nm_setting_ovs_bridge_class_init (NMSettingOvsBridgeClass *klass) g_param_spec_boolean (NM_SETTING_OVS_BRIDGE_STP_ENABLE, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** diff --git a/libnm-core/nm-setting-ovs-dpdk.c b/libnm-core/nm-setting-ovs-dpdk.c index ed3c3255..03180535 100644 --- a/libnm-core/nm-setting-ovs-dpdk.c +++ b/libnm-core/nm-setting-ovs-dpdk.c @@ -148,7 +148,6 @@ nm_setting_ovs_dpdk_class_init (NMSettingOvsDpdkClass *klass) g_param_spec_string (NM_SETTING_OVS_DPDK_DEVARGS, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-ovs-interface.c b/libnm-core/nm-setting-ovs-interface.c index 849b9a4e..b9a133d0 100644 --- a/libnm-core/nm-setting-ovs-interface.c +++ b/libnm-core/nm-setting-ovs-interface.c @@ -64,30 +64,29 @@ nm_setting_ovs_interface_get_interface_type (NMSettingOvsInterface *self) int _nm_setting_ovs_interface_verify_interface_type (NMSettingOvsInterface *self, + const char *type, NMConnection *connection, gboolean normalize, gboolean *out_modified, - const char **normalized_type, + const char **out_normalized_type, GError **error) { - const char *type; const char *type_from_setting = NULL; const char *type_setting = NULL; const char *connection_type; gboolean is_ovs_connection_type; - g_return_val_if_fail (NM_IS_SETTING_OVS_INTERFACE (self), FALSE); if (normalize) { + g_return_val_if_fail (NM_IS_SETTING_OVS_INTERFACE (self), FALSE); g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); nm_assert (self == nm_connection_get_setting_ovs_interface (connection)); - } else + } else { + g_return_val_if_fail (!self || NM_IS_SETTING_OVS_INTERFACE (self), FALSE); g_return_val_if_fail (!connection || NM_IS_CONNECTION (connection), FALSE); - - g_return_val_if_fail (!normalized_type || !(*normalized_type), FALSE); + } NM_SET_OUT (out_modified, FALSE); - - type = self->type; + NM_SET_OUT (out_normalized_type, NULL); if ( type && !NM_IN_STRSET (type, "internal", "system", "patch", "dpdk")) { @@ -100,8 +99,10 @@ _nm_setting_ovs_interface_verify_interface_type (NMSettingOvsInterface *self, return FALSE; } - if (!connection) + if (!connection) { + NM_SET_OUT (out_normalized_type, type); return TRUE; + } connection_type = nm_connection_get_connection_type (connection); if (!connection_type) { @@ -192,6 +193,7 @@ _nm_setting_ovs_interface_verify_interface_type (NMSettingOvsInterface *self, g_prefix_error (error, "%s.%s: ", NM_SETTING_OVS_INTERFACE_SETTING_NAME, NM_SETTING_OVS_INTERFACE_TYPE); return FALSE; } + NM_SET_OUT (out_normalized_type, type); return TRUE; } type = type_from_setting; @@ -208,16 +210,17 @@ _nm_setting_ovs_interface_verify_interface_type (NMSettingOvsInterface *self, } } - if (type) + if (type) { + NM_SET_OUT (out_normalized_type, type); return TRUE; + } if (is_ovs_connection_type) type = "internal"; else type = "system"; - if (normalized_type) - *normalized_type = type; + NM_SET_OUT (out_normalized_type, type); normalize: if (!normalize) { @@ -254,8 +257,6 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingOvsInterface *self = NM_SETTING_OVS_INTERFACE (setting); NMSettingConnection *s_con = NULL; - const char *normalized_type = NULL; - int result = NM_SETTING_VERIFY_ERROR; if (connection) { const char *slave_type; @@ -295,39 +296,13 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } } - result = _nm_setting_ovs_interface_verify_interface_type (self, - connection, - FALSE, - NULL, - &normalized_type, - error); - - /* From 'man ovs-vswitchd.conf.db': OVS patch interfaces do not have - * a limit on interface name length, all the other types do */ - if (result != NM_SETTING_VERIFY_ERROR && s_con) { - gs_free_error GError *ifname_error = NULL; - const char *ifname = nm_setting_connection_get_interface_name (s_con); - - normalized_type = self->type ? self->type : normalized_type; - - if ( ifname - && !nm_streq0 (normalized_type, "patch") - && !nm_utils_ifname_valid (ifname, - NMU_IFACE_KERNEL, - &ifname_error)) { - g_clear_error (error); - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - "'%s': %s", ifname, ifname_error->message); - g_prefix_error (error, "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_INTERFACE_NAME); - return NM_SETTING_VERIFY_ERROR; - } - } - - return result; + return _nm_setting_ovs_interface_verify_interface_type (self, + self->type, + connection, + FALSE, + NULL, + NULL, + error); } /*****************************************************************************/ @@ -420,7 +395,6 @@ nm_setting_ovs_interface_class_init (NMSettingOvsInterfaceClass *klass) g_param_spec_string (NM_SETTING_OVS_INTERFACE_TYPE, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-ovs-patch.c b/libnm-core/nm-setting-ovs-patch.c index e74a35ca..6a9c9f56 100644 --- a/libnm-core/nm-setting-ovs-patch.c +++ b/libnm-core/nm-setting-ovs-patch.c @@ -81,8 +81,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if ( !nm_utils_ipaddr_valid (AF_INET, self->peer) - && !nm_utils_ipaddr_valid (AF_INET6, self->peer)) { + if ( !nm_utils_ipaddr_is_valid (AF_INET, self->peer) + && !nm_utils_ipaddr_is_valid (AF_INET6, self->peer)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -188,7 +188,6 @@ nm_setting_ovs_patch_class_init (NMSettingOvsPatchClass *klass) g_param_spec_string (NM_SETTING_OVS_PATCH_PEER, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-ovs-port.c b/libnm-core/nm-setting-ovs-port.c index ab4b63d8..a2073ed3 100644 --- a/libnm-core/nm-setting-ovs-port.c +++ b/libnm-core/nm-setting-ovs-port.c @@ -39,9 +39,9 @@ struct _NMSettingOvsPort { NMSetting parent; char *vlan_mode; - guint tag; char *lacp; char *bond_mode; + guint tag; guint bond_updelay; guint bond_downdelay; }; @@ -367,7 +367,6 @@ nm_setting_ovs_port_class_init (NMSettingOvsPortClass *klass) g_param_spec_string (NM_SETTING_OVS_PORT_VLAN_MODE, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -382,7 +381,6 @@ nm_setting_ovs_port_class_init (NMSettingOvsPortClass *klass) g_param_spec_uint (NM_SETTING_OVS_PORT_TAG, "", "", 0, 4095, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -397,7 +395,6 @@ nm_setting_ovs_port_class_init (NMSettingOvsPortClass *klass) g_param_spec_string (NM_SETTING_OVS_PORT_LACP, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -412,7 +409,6 @@ nm_setting_ovs_port_class_init (NMSettingOvsPortClass *klass) g_param_spec_string (NM_SETTING_OVS_PORT_BOND_MODE, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -427,7 +423,6 @@ nm_setting_ovs_port_class_init (NMSettingOvsPortClass *klass) g_param_spec_uint (NM_SETTING_OVS_PORT_BOND_UPDELAY, "", "", 0, G_MAXUINT, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -442,7 +437,6 @@ nm_setting_ovs_port_class_init (NMSettingOvsPortClass *klass) g_param_spec_uint (NM_SETTING_OVS_PORT_BOND_DOWNDELAY, "", "", 0, G_MAXUINT, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-ppp.c b/libnm-core/nm-setting-ppp.c index c42feb46..090f3c08 100644 --- a/libnm-core/nm-setting-ppp.c +++ b/libnm-core/nm-setting-ppp.c @@ -44,24 +44,24 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - gboolean noauth; - gboolean refuse_eap; - gboolean refuse_pap; - gboolean refuse_chap; - gboolean refuse_mschap; - gboolean refuse_mschapv2; - gboolean nobsdcomp; - gboolean nodeflate; - gboolean no_vj_comp; - gboolean require_mppe; - gboolean require_mppe_128; - gboolean mppe_stateful; - gboolean crtscts; guint32 baud; guint32 mru; guint32 mtu; guint32 lcp_echo_failure; guint32 lcp_echo_interval; + bool noauth:1; + bool refuse_eap:1; + bool refuse_pap:1; + bool refuse_chap:1; + bool refuse_mschap:1; + bool refuse_mschapv2:1; + bool nobsdcomp:1; + bool nodeflate:1; + bool no_vj_comp:1; + bool require_mppe:1; + bool require_mppe_128:1; + bool mppe_stateful:1; + bool crtscts:1; } NMSettingPppPrivate; G_DEFINE_TYPE (NMSettingPpp, nm_setting_ppp, NM_TYPE_SETTING) @@ -495,8 +495,11 @@ set_property (GObject *object, guint prop_id, /*****************************************************************************/ static void -nm_setting_ppp_init (NMSettingPpp *setting) +nm_setting_ppp_init (NMSettingPpp *self) { + NMSettingPppPrivate *priv = NM_SETTING_PPP_GET_PRIVATE (self); + + priv->noauth = TRUE; } /** @@ -536,7 +539,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_boolean (NM_SETTING_PPP_NOAUTH, "", "", TRUE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -548,7 +550,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_boolean (NM_SETTING_PPP_REFUSE_EAP, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -560,7 +561,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_boolean (NM_SETTING_PPP_REFUSE_PAP, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -572,7 +572,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_boolean (NM_SETTING_PPP_REFUSE_CHAP, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -584,7 +583,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_boolean (NM_SETTING_PPP_REFUSE_MSCHAP, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -596,7 +594,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_boolean (NM_SETTING_PPP_REFUSE_MSCHAPV2, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -608,7 +605,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_boolean (NM_SETTING_PPP_NOBSDCOMP, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -621,7 +617,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_boolean (NM_SETTING_PPP_NODEFLATE, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -634,7 +629,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_boolean (NM_SETTING_PPP_NO_VJ_COMP, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -650,7 +644,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_boolean (NM_SETTING_PPP_REQUIRE_MPPE, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -663,7 +656,7 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) obj_properties[PROP_REQUIRE_MPPE_128] = g_param_spec_boolean (NM_SETTING_PPP_REQUIRE_MPPE_128, "", "", FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); /** @@ -676,7 +669,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_boolean (NM_SETTING_PPP_MPPE_STATEFUL, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -690,7 +682,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_boolean (NM_SETTING_PPP_CRTSCTS, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -704,7 +695,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_uint (NM_SETTING_PPP_BAUD, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -719,7 +709,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_uint (NM_SETTING_PPP_MRU, "", "", 0, 16384, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -732,7 +721,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_uint (NM_SETTING_PPP_MTU, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -748,7 +736,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_uint (NM_SETTING_PPP_LCP_ECHO_FAILURE, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -764,7 +751,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass) g_param_spec_uint (NM_SETTING_PPP_LCP_ECHO_INTERVAL, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-pppoe.c b/libnm-core/nm-setting-pppoe.c index 0fee96a1..d61364c9 100644 --- a/libnm-core/nm-setting-pppoe.c +++ b/libnm-core/nm-setting-pppoe.c @@ -302,7 +302,6 @@ nm_setting_pppoe_class_init (NMSettingPppoeClass *klass) g_param_spec_string (NM_SETTING_PPPOE_PARENT, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-proxy.c b/libnm-core/nm-setting-proxy.c index 9e83339c..a81b2d03 100644 --- a/libnm-core/nm-setting-proxy.c +++ b/libnm-core/nm-setting-proxy.c @@ -34,10 +34,10 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - NMSettingProxyMethod method; - gboolean browser_only; char *pac_url; char *pac_script; + int method; + bool browser_only:1; } NMSettingProxyPrivate; G_DEFINE_TYPE (NMSettingProxy, nm_setting_proxy, NM_TYPE_SETTING) @@ -119,11 +119,8 @@ static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingProxyPrivate *priv = NM_SETTING_PROXY_GET_PRIVATE (setting); - NMSettingProxyMethod method; - method = priv->method; - - if (!NM_IN_SET (method, + if (!NM_IN_SET (priv->method, NM_SETTING_PROXY_METHOD_NONE, NM_SETTING_PROXY_METHOD_AUTO)) { g_set_error (error, @@ -134,7 +131,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (method != NM_SETTING_PROXY_METHOD_AUTO) { + if (priv->method != NM_SETTING_PROXY_METHOD_AUTO) { if (priv->pac_url) { g_set_error (error, NM_CONNECTION_ERROR, @@ -241,8 +238,9 @@ set_property (GObject *object, guint prop_id, /*****************************************************************************/ static void -nm_setting_proxy_init (NMSettingProxy *setting) +nm_setting_proxy_init (NMSettingProxy *self) { + nm_assert (NM_SETTING_PROXY_GET_PRIVATE (self)->method == NM_SETTING_PROXY_METHOD_NONE); } /** @@ -306,7 +304,6 @@ nm_setting_proxy_class_init (NMSettingProxyClass *klass) g_param_spec_int (NM_SETTING_PROXY_METHOD, "", "", G_MININT32, G_MAXINT32, NM_SETTING_PROXY_METHOD_NONE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** diff --git a/libnm-core/nm-setting-serial.c b/libnm-core/nm-setting-serial.c index c050e238..fe7c05ee 100644 --- a/libnm-core/nm-setting-serial.c +++ b/libnm-core/nm-setting-serial.c @@ -31,11 +31,11 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { + guint64 send_delay; guint baud; guint bits; - char parity; guint stopbits; - guint64 send_delay; + char parity; } NMSettingSerialPrivate; G_DEFINE_TYPE (NMSettingSerial, nm_setting_serial, NM_TYPE_SETTING) @@ -206,8 +206,14 @@ set_property (GObject *object, guint prop_id, /*****************************************************************************/ static void -nm_setting_serial_init (NMSettingSerial *setting) +nm_setting_serial_init (NMSettingSerial *self) { + NMSettingSerialPrivate *priv = NM_SETTING_SERIAL_GET_PRIVATE (self); + + nm_assert (priv->parity == NM_SETTING_SERIAL_PARITY_NONE); + priv->stopbits = 1; + priv->baud = 57600; + priv->bits = 8; } /** @@ -246,7 +252,6 @@ nm_setting_serial_class_init (NMSettingSerialClass *klass) g_param_spec_uint (NM_SETTING_SERIAL_BAUD, "", "", 0, G_MAXUINT, 57600, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -258,7 +263,6 @@ nm_setting_serial_class_init (NMSettingSerialClass *klass) g_param_spec_uint (NM_SETTING_SERIAL_BITS, "", "", 5, 8, 8, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -286,7 +290,6 @@ nm_setting_serial_class_init (NMSettingSerialClass *klass) NM_TYPE_SETTING_SERIAL_PARITY, NM_SETTING_SERIAL_PARITY_NONE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); _nm_properties_override_gobj (properties_override, obj_properties[PROP_PARITY], @@ -306,7 +309,6 @@ nm_setting_serial_class_init (NMSettingSerialClass *klass) g_param_spec_uint (NM_SETTING_SERIAL_STOPBITS, "", "", 1, 2, 1, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -318,7 +320,6 @@ nm_setting_serial_class_init (NMSettingSerialClass *klass) g_param_spec_uint64 (NM_SETTING_SERIAL_SEND_DELAY, "", "", 0, G_MAXUINT64, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/libnm-core/nm-setting-sriov.c b/libnm-core/nm-setting-sriov.c index 9ef68cce..a679a0be 100644 --- a/libnm-core/nm-setting-sriov.c +++ b/libnm-core/nm-setting-sriov.c @@ -27,7 +27,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingSriov, /** * NMSettingSriov: * - * SR-IOV settings. + * SR-IOV settings * * Since: 1.14 */ @@ -234,7 +234,7 @@ vf_add_vlan (NMSriovVF *vf, vf->vlans = _vf_vlan_create_hash (); g_hash_table_add (vf->vlans, vlan); - g_clear_pointer (&vf->vlan_ids, g_free); + nm_clear_g_free (&vf->vlan_ids); } /** @@ -530,7 +530,7 @@ nm_sriov_vf_remove_vlan (NMSriovVF *vf, guint vlan_id) || !g_hash_table_remove (vf->vlans, &vlan_id)) return FALSE; - g_clear_pointer (&vf->vlan_ids, g_free); + nm_clear_g_free (&vf->vlan_ids); return TRUE; } @@ -1217,6 +1217,8 @@ static void nm_setting_sriov_init (NMSettingSriov *setting) { setting->vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref); + + setting->autoprobe_drivers = NM_TERNARY_DEFAULT; } /** @@ -1265,7 +1267,8 @@ nm_setting_sriov_class_init (NMSettingSriovClass *klass) * * Note that when the sriov setting is present NetworkManager * enforces the number of virtual functions on the interface - * also when it is zero. To prevent any changes to SR-IOV + * (also when it is zero) during activation and resets it + * upon deactivation. To prevent any changes to SR-IOV * parameters don't add a sriov setting to the connection. * * Since: 1.14 @@ -1282,7 +1285,6 @@ nm_setting_sriov_class_init (NMSettingSriovClass *klass) 0, G_MAXUINT32, 0, NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -1370,7 +1372,6 @@ nm_setting_sriov_class_init (NMSettingSriovClass *klass) NM_TERNARY_DEFAULT, NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/libnm-core/nm-setting-tc-config.c b/libnm-core/nm-setting-tc-config.c index af503741..86582315 100644 --- a/libnm-core/nm-setting-tc-config.c +++ b/libnm-core/nm-setting-tc-config.c @@ -967,7 +967,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingTCConfig, /** * NMSettingTCConfig: * - * Linux Traffic Control Settings. + * Linux Traffic Control Settings * * Since: 1.12 */ diff --git a/libnm-core/nm-setting-tun.c b/libnm-core/nm-setting-tun.c index 312c5c53..ba9e64ad 100644 --- a/libnm-core/nm-setting-tun.c +++ b/libnm-core/nm-setting-tun.c @@ -34,12 +34,12 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); typedef struct { - NMSettingTunMode mode; char *owner; char *group; - gboolean pi; - gboolean vnet_hdr; - gboolean multi_queue; + NMSettingTunMode mode; + bool pi:1; + bool vnet_hdr:1; + bool multi_queue:1; } NMSettingTunPrivate; G_DEFINE_TYPE (NMSettingTun, nm_setting_tun, NM_TYPE_SETTING) @@ -248,8 +248,11 @@ set_property (GObject *object, guint prop_id, /*****************************************************************************/ static void -nm_setting_tun_init (NMSettingTun *setting) +nm_setting_tun_init (NMSettingTun *self) { + NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE (self); + + priv->mode = NM_SETTING_TUN_MODE_TUN; } /** @@ -307,7 +310,6 @@ nm_setting_tun_class_init (NMSettingTunClass *klass) g_param_spec_uint (NM_SETTING_TUN_MODE, "", "", 0, G_MAXUINT, NM_SETTING_TUN_MODE_TUN, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-user.c b/libnm-core/nm-setting-user.c index 87a0dfed..1c60d55b 100644 --- a/libnm-core/nm-setting-user.c +++ b/libnm-core/nm-setting-user.c @@ -327,7 +327,7 @@ out: /* setting a value purges all invalid values that were set * via GObject property. */ changed = TRUE; - g_clear_pointer (&priv->data_invalid, g_hash_table_unref); + nm_clear_pointer (&priv->data_invalid, g_hash_table_unref); } if (changed) _notify (self, PROP_DATA); @@ -462,8 +462,8 @@ set_property (GObject *object, guint prop_id, data = g_value_get_boxed (value); if (!data || !g_hash_table_size (data)) { - g_clear_pointer (&priv->data, g_hash_table_unref); - g_clear_pointer (&priv->data_invalid, g_hash_table_unref); + nm_clear_pointer (&priv->data, g_hash_table_unref); + nm_clear_pointer (&priv->data_invalid, g_hash_table_unref); return; } @@ -488,7 +488,7 @@ set_property (GObject *object, guint prop_id, } if ( priv->data_invalid && !g_hash_table_size (priv->data_invalid)) - g_clear_pointer (&priv->data_invalid, g_hash_table_unref); + nm_clear_pointer (&priv->data_invalid, g_hash_table_unref); break; default: diff --git a/libnm-core/nm-setting-vlan.c b/libnm-core/nm-setting-vlan.c index 30f43760..b4bbdd64 100644 --- a/libnm-core/nm-setting-vlan.c +++ b/libnm-core/nm-setting-vlan.c @@ -36,11 +36,11 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingVlan, ); typedef struct { + GSList *ingress_priority_map; + GSList *egress_priority_map; char *parent; guint32 id; guint32 flags; - GSList *ingress_priority_map; - GSList *egress_priority_map; } NMSettingVlanPrivate; G_DEFINE_TYPE (NMSettingVlan, nm_setting_vlan, NM_TYPE_SETTING) @@ -791,8 +791,11 @@ set_property (GObject *object, guint prop_id, /*****************************************************************************/ static void -nm_setting_vlan_init (NMSettingVlan *setting) +nm_setting_vlan_init (NMSettingVlan *self) { + NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE (self); + + priv->flags = NM_VLAN_FLAG_REORDER_HEADERS; } /** @@ -854,7 +857,6 @@ nm_setting_vlan_class_init (NMSettingVlanClass *klass) g_param_spec_string (NM_SETTING_VLAN_PARENT, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -874,7 +876,6 @@ nm_setting_vlan_class_init (NMSettingVlanClass *klass) g_param_spec_uint (NM_SETTING_VLAN_ID, "", "", 0, 4095, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -905,7 +906,6 @@ nm_setting_vlan_class_init (NMSettingVlanClass *klass) NM_TYPE_VLAN_FLAGS, NM_VLAN_FLAG_REORDER_HEADERS, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); _nm_properties_override_gobj (properties_override, diff --git a/libnm-core/nm-setting-vpn.c b/libnm-core/nm-setting-vpn.c index 05fca918..baca3f32 100644 --- a/libnm-core/nm-setting-vpn.c +++ b/libnm-core/nm-setting-vpn.c @@ -81,6 +81,23 @@ G_DEFINE_TYPE (NMSettingVpn, nm_setting_vpn, NM_TYPE_SETTING) /*****************************************************************************/ +static GHashTable * +_ensure_strdict (GHashTable **p_hash, gboolean for_secrets) +{ + if (!*p_hash) { + *p_hash = g_hash_table_new_full (nm_str_hash, + g_str_equal, + g_free, + for_secrets + ? (GDestroyNotify) nm_free_secret + : g_free); + } + return *p_hash; +} + + +/*****************************************************************************/ + /** * nm_setting_vpn_get_service_type: * @setting: the #NMSettingVpn @@ -139,30 +156,39 @@ nm_setting_vpn_get_num_data_items (NMSettingVpn *setting) { g_return_val_if_fail (NM_IS_SETTING_VPN (setting), 0); - return g_hash_table_size (NM_SETTING_VPN_GET_PRIVATE (setting)->data); + return nm_g_hash_table_size (NM_SETTING_VPN_GET_PRIVATE (setting)->data); } /** * nm_setting_vpn_add_data_item: * @setting: the #NMSettingVpn * @key: a name that uniquely identifies the given value @item - * @item: the value to be referenced by @key + * @item: (allow-none): the value to be referenced by @key * * Establishes a relationship between @key and @item internally in the * setting which may be retrieved later. Should not be used to store passwords * or other secrets, which is what nm_setting_vpn_add_secret() is for. + * + * Before 1.24, @item must not be %NULL and not an empty string. Since 1.24, + * @item can be set to an empty string. It can also be set to %NULL to unset + * the key. In that case, the behavior is as if calling nm_setting_vpn_remove_data_item(). **/ void nm_setting_vpn_add_data_item (NMSettingVpn *setting, const char *key, const char *item) { + if (!item) { + nm_setting_vpn_remove_data_item (setting, key); + return; + } + g_return_if_fail (NM_IS_SETTING_VPN (setting)); g_return_if_fail (key && key[0]); - g_return_if_fail (item && item[0]); - g_hash_table_insert (NM_SETTING_VPN_GET_PRIVATE (setting)->data, - g_strdup (key), g_strdup (item)); + g_hash_table_insert (_ensure_strdict (&NM_SETTING_VPN_GET_PRIVATE (setting)->data, FALSE), + g_strdup (key), + g_strdup (item)); _notify (setting, PROP_DATA); } @@ -180,8 +206,9 @@ const char * nm_setting_vpn_get_data_item (NMSettingVpn *setting, const char *key) { g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL); + g_return_val_if_fail (key && key[0], NULL); - return (const char *) g_hash_table_lookup (NM_SETTING_VPN_GET_PRIVATE (setting)->data, key); + return nm_g_hash_table_lookup (NM_SETTING_VPN_GET_PRIVATE (setting)->data, key); } /** @@ -222,63 +249,58 @@ nm_setting_vpn_get_data_keys (NMSettingVpn *setting, gboolean nm_setting_vpn_remove_data_item (NMSettingVpn *setting, const char *key) { - gboolean found; - g_return_val_if_fail (NM_IS_SETTING_VPN (setting), FALSE); - g_return_val_if_fail (key, FALSE); + g_return_val_if_fail (key && key[0], FALSE); - found = g_hash_table_remove (NM_SETTING_VPN_GET_PRIVATE (setting)->data, key); - if (found) + if (nm_g_hash_table_remove (NM_SETTING_VPN_GET_PRIVATE (setting)->data, key)) { _notify (setting, PROP_DATA); - return found; + return TRUE; + } + return FALSE; } static void foreach_item_helper (NMSettingVpn *self, - gboolean is_secrets, + GHashTable **p_hash, NMVpnIterFunc func, gpointer user_data) { - NMSettingVpnPrivate *priv; - guint len, i; + gs_unref_object NMSettingVpn *self_keep_alive = NULL; gs_strfreev char **keys = NULL; - GHashTable *hash; + guint i, len; nm_assert (NM_IS_SETTING_VPN (self)); nm_assert (func); - priv = NM_SETTING_VPN_GET_PRIVATE (self); - - 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; - } - - if (!len) { + keys = nm_utils_strv_make_deep_copied (nm_utils_strdict_get_keys (*p_hash, + TRUE, + &len)); + if (len == 0u) { nm_assert (!keys); return; } - for (i = 0; i < len; i++) { - nm_assert (keys && keys[i]); - keys[i] = g_strdup (keys[i]); - } - nm_assert (!keys[i]); + if (len > 1u) + self_keep_alive = g_object_ref (self); 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); + * The @value on the other hand, is not cloned but retrieved before + * invoking @func(). That means, if @func() modifies the setting while + * being called, the values are as they currently are, but the + * keys (and their order) were pre-determined before starting to + * invoke the callbacks. + * + * The idea is to give some sensible, stable behavior in case the user + * modifies the settings. Whether this particular behavior is optimal + * is unclear. It's probably a bad idea to modify the settings while + * iterating the values. But at least, it's a safe thing to do and we + * do something sensible. */ + func (keys[i], + nm_g_hash_table_lookup (*p_hash, keys[i]), + user_data); } } @@ -300,7 +322,7 @@ nm_setting_vpn_foreach_data_item (NMSettingVpn *setting, g_return_if_fail (NM_IS_SETTING_VPN (setting)); g_return_if_fail (func); - foreach_item_helper (setting, FALSE, func, user_data); + foreach_item_helper (setting, &NM_SETTING_VPN_GET_PRIVATE (setting)->data, func, user_data); } /** @@ -316,29 +338,38 @@ nm_setting_vpn_get_num_secrets (NMSettingVpn *setting) { g_return_val_if_fail (NM_IS_SETTING_VPN (setting), 0); - return g_hash_table_size (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets); + return nm_g_hash_table_size (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets); } /** * nm_setting_vpn_add_secret: * @setting: the #NMSettingVpn * @key: a name that uniquely identifies the given secret @secret - * @secret: the secret to be referenced by @key + * @secret: (allow-none): the secret to be referenced by @key * * Establishes a relationship between @key and @secret internally in the * setting which may be retrieved later. + * + * Before 1.24, @secret must not be %NULL and not an empty string. Since 1.24, + * @secret can be set to an empty string. It can also be set to %NULL to unset + * the key. In that case, the behavior is as if calling nm_setting_vpn_remove_secret(). **/ void nm_setting_vpn_add_secret (NMSettingVpn *setting, const char *key, const char *secret) { + if (!secret) { + nm_setting_vpn_remove_secret (setting, key); + return; + } + g_return_if_fail (NM_IS_SETTING_VPN (setting)); g_return_if_fail (key && key[0]); - g_return_if_fail (secret && secret[0]); - g_hash_table_insert (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, - g_strdup (key), g_strdup (secret)); + g_hash_table_insert (_ensure_strdict (&NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, TRUE), + g_strdup (key), + g_strdup (secret)); _notify (setting, PROP_SECRETS); } @@ -356,8 +387,9 @@ const char * nm_setting_vpn_get_secret (NMSettingVpn *setting, const char *key) { g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL); + g_return_val_if_fail (key && key[0], NULL); - return (const char *) g_hash_table_lookup (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, key); + return nm_g_hash_table_lookup (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, key); } /** @@ -398,15 +430,14 @@ nm_setting_vpn_get_secret_keys (NMSettingVpn *setting, gboolean nm_setting_vpn_remove_secret (NMSettingVpn *setting, const char *key) { - gboolean found; - g_return_val_if_fail (NM_IS_SETTING_VPN (setting), FALSE); - g_return_val_if_fail (key, FALSE); + g_return_val_if_fail (key && key[0], FALSE); - found = g_hash_table_remove (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, key); - if (found) + if (nm_g_hash_table_remove (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, key)) { _notify (setting, PROP_SECRETS); - return found; + return TRUE; + } + return FALSE; } /** @@ -427,7 +458,7 @@ nm_setting_vpn_foreach_secret (NMSettingVpn *setting, g_return_if_fail (NM_IS_SETTING_VPN (setting)); g_return_if_fail (func); - foreach_item_helper (setting, TRUE, func, user_data); + foreach_item_helper (setting, &NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, func, user_data); } static gboolean @@ -444,7 +475,7 @@ aggregate (NMSetting *setting, switch (type) { case NM_CONNECTION_AGGREGATE_ANY_SECRETS: - if (g_hash_table_size (priv->secrets) > 0) { + if (nm_g_hash_table_size (priv->secrets) > 0u) { *((gboolean *) arg) = TRUE; return TRUE; } @@ -452,32 +483,36 @@ aggregate (NMSetting *setting, case NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS: - g_hash_table_iter_init (&iter, priv->secrets); - while (g_hash_table_iter_next (&iter, (gpointer *) &key_name, NULL)) { - if (!nm_setting_get_secret_flags (NM_SETTING (setting), key_name, &secret_flags, NULL)) - nm_assert_not_reached (); - if (secret_flags == NM_SETTING_SECRET_FLAG_NONE) { - *((gboolean *) arg) = TRUE; - return TRUE; + if (priv->secrets) { + g_hash_table_iter_init (&iter, priv->secrets); + while (g_hash_table_iter_next (&iter, (gpointer *) &key_name, NULL)) { + if (!nm_setting_get_secret_flags (NM_SETTING (setting), key_name, &secret_flags, NULL)) + nm_assert_not_reached (); + if (secret_flags == NM_SETTING_SECRET_FLAG_NONE) { + *((gboolean *) arg) = TRUE; + return TRUE; + } } } - /* Ok, we have no secrets with system-secret flags. + /* OK, we have no secrets with system-secret flags. * But do we have any secret-flags (without secrets) that indicate system secrets? */ - g_hash_table_iter_init (&iter, priv->data); - while (g_hash_table_iter_next (&iter, (gpointer *) &key_name, NULL)) { - gs_free char *secret_name = NULL; + if (priv->data) { + g_hash_table_iter_init (&iter, priv->data); + while (g_hash_table_iter_next (&iter, (gpointer *) &key_name, NULL)) { + gs_free char *secret_name = NULL; - if (!g_str_has_suffix (key_name, "-flags")) - continue; - secret_name = g_strndup (key_name, strlen (key_name) - NM_STRLEN ("-flags")); - if (secret_name[0] == '\0') - continue; - if (!nm_setting_get_secret_flags (NM_SETTING (setting), secret_name, &secret_flags, NULL)) - nm_assert_not_reached (); - if (secret_flags == NM_SETTING_SECRET_FLAG_NONE) { - *((gboolean *) arg) = TRUE; - return TRUE; + if (!NM_STR_HAS_SUFFIX (key_name, "-flags")) + continue; + secret_name = g_strndup (key_name, strlen (key_name) - NM_STRLEN ("-flags")); + if (secret_name[0] == '\0') + continue; + if (!nm_setting_get_secret_flags (NM_SETTING (setting), secret_name, &secret_flags, NULL)) + nm_assert_not_reached (); + if (secret_flags == NM_SETTING_SECRET_FLAG_NONE) { + *((gboolean *) arg) = TRUE; + return TRUE; + } } } @@ -517,8 +552,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) g_prefix_error (error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, NM_SETTING_VPN_SERVICE_TYPE); return FALSE; } - - if (!strlen (priv->service_type)) { + if (!priv->service_type[0]) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -528,7 +562,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } /* default username can be NULL, but can't be zero-length */ - if (priv->user_name && !strlen (priv->user_name)) { + if ( priv->user_name + && !priv->user_name[0]) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -558,21 +593,15 @@ update_secret_string (NMSetting *setting, { NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting); - g_return_val_if_fail (key != NULL, NM_SETTING_UPDATE_SECRET_ERROR); - g_return_val_if_fail (value != NULL, NM_SETTING_UPDATE_SECRET_ERROR); - - if (!value || !strlen (value)) { - g_set_error (error, NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("secret was empty")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, key); - return NM_SETTING_UPDATE_SECRET_ERROR; - } + g_return_val_if_fail (key && key[0], NM_SETTING_UPDATE_SECRET_ERROR); + g_return_val_if_fail (value, NM_SETTING_UPDATE_SECRET_ERROR); - if (g_strcmp0 (g_hash_table_lookup (priv->secrets, key), value) == 0) + if (nm_streq0 (nm_g_hash_table_lookup (priv->secrets, key), value)) return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; - g_hash_table_insert (priv->secrets, g_strdup (key), g_strdup (value)); + g_hash_table_insert (_ensure_strdict (&priv->secrets, TRUE), + g_strdup (key), + g_strdup (value)); return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; } @@ -591,39 +620,24 @@ update_secret_dict (NMSetting *setting, /* Make sure the items are valid */ g_variant_iter_init (&iter, secrets); while (g_variant_iter_next (&iter, "{&s&s}", &name, &value)) { - if (!name || !strlen (name)) { + if (!name[0]) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, _("setting contained a secret with an empty name")); g_prefix_error (error, "%s: ", NM_SETTING_VPN_SETTING_NAME); return NM_SETTING_UPDATE_SECRET_ERROR; } - - if (!value || !strlen (value)) { - g_set_error (error, NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("secret value was empty")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, name); - return NM_SETTING_UPDATE_SECRET_ERROR; - } } /* Now add the items to the settings' secrets list */ g_variant_iter_init (&iter, secrets); while (g_variant_iter_next (&iter, "{&s&s}", &name, &value)) { - if (value == NULL) { - g_warn_if_fail (value != NULL); - continue; - } - if (strlen (value) == 0) { - g_warn_if_fail (strlen (value) > 0); + if (nm_streq0 (nm_g_hash_table_lookup (priv->secrets, name), value)) continue; - } - if (g_strcmp0 (g_hash_table_lookup (priv->secrets, name), value) == 0) - continue; - - g_hash_table_insert (priv->secrets, g_strdup (name), g_strdup (value)); + g_hash_table_insert (_ensure_strdict (&priv->secrets, TRUE), + g_strdup (name), + g_strdup (value)); result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; } @@ -646,7 +660,7 @@ update_one_secret (NMSetting *setting, const char *key, GVariant *value, GError */ success = update_secret_string (setting, key, g_variant_get_string (value, NULL), error); } else if (g_variant_is_of_type (value, G_VARIANT_TYPE ("a{ss}"))) { - if (strcmp (key, NM_SETTING_VPN_SECRETS) != 0) { + if (!nm_streq (key, NM_SETTING_VPN_SECRETS)) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, _("not a secret property")); @@ -728,14 +742,23 @@ get_secret_flags (NMSetting *setting, const char *flags_val; gint64 i64; + nm_assert (secret_name); + + if (!secret_name[0]) { + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, + _("secret name cannot be empty")); + return FALSE; + } + flags_key = nm_construct_name_a ("%s-flags", secret_name, &flags_key_free); - if (!g_hash_table_lookup_extended (priv->data, flags_key, NULL, (gpointer *) &flags_val)) { + if ( !priv->data + || !g_hash_table_lookup_extended (priv->data, flags_key, NULL, (gpointer *) &flags_val)) { NM_SET_OUT (out_flags, NM_SETTING_SECRET_FLAG_NONE); /* having no secret flag for the secret is fine, as long as there * is the secret itself... */ - if (!g_hash_table_contains (priv->secrets, secret_name)) { + if (!nm_g_hash_table_lookup (priv->secrets, secret_name)) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, @@ -768,7 +791,15 @@ set_secret_flags (NMSetting *setting, NMSettingSecretFlags flags, GError **error) { - g_hash_table_insert (NM_SETTING_VPN_GET_PRIVATE (setting)->data, + nm_assert (secret_name); + + if (!secret_name[0]) { + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, + _("secret name cannot be empty")); + return FALSE; + } + + g_hash_table_insert (_ensure_strdict (&NM_SETTING_VPN_GET_PRIVATE (setting)->data, FALSE), g_strdup_printf ("%s-flags", secret_name), g_strdup_printf ("%u", flags)); _notify (NM_SETTING_VPN (setting), PROP_SECRETS); @@ -802,8 +833,12 @@ compare_property_secrets (NMSettingVpn *a, for (run = 0; run < 2; run++) { NMSettingVpn *current_a = (run == 0) ? a : b; NMSettingVpn *current_b = (run == 0) ? b : a; + NMSettingVpnPrivate *priv_a = NM_SETTING_VPN_GET_PRIVATE (current_a); + + if (!priv_a->secrets) + continue; - g_hash_table_iter_init (&iter, NM_SETTING_VPN_GET_PRIVATE (current_a)->secrets); + g_hash_table_iter_init (&iter, priv_a->secrets); while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &val)) { if (nm_streq0 (val, nm_setting_vpn_get_secret (current_b, key))) @@ -899,11 +934,26 @@ vpn_secrets_from_dbus (NMSetting *setting, NMSettingParseFlags parse_flags, GError **error) { - nm_auto_unset_gvalue GValue object_value = G_VALUE_INIT; + NMSettingVpn *self = NM_SETTING_VPN (setting); + NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (self); + gs_unref_hashtable GHashTable *hash_free = NULL; + GVariantIter iter; + const char *key; + const char *val; + + hash_free = g_steal_pointer (&priv->secrets); + + g_variant_iter_init (&iter, value); + while (g_variant_iter_next (&iter, "{&s&s}", &key, &val)) { + if (!key[0]) + continue; + g_hash_table_insert (_ensure_strdict (&priv->secrets, TRUE), + g_strdup (key), + g_strdup (val)); + } - g_value_init (&object_value, G_TYPE_HASH_TABLE); - _nm_utils_strdict_from_dbus (value, &object_value); - return nm_g_object_set_property (G_OBJECT (setting), property, &object_value, error); + _notify (self, PROP_SECRETS); + return TRUE; } static GVariant * @@ -914,29 +964,30 @@ vpn_secrets_to_dbus (const NMSettInfoSetting *sett_info, NMConnectionSerializationFlags flags, const NMConnectionSerializationOptions *options) { - gs_unref_hashtable GHashTable *secrets = NULL; - const char *property_name = sett_info->property_infos[property_idx].name; + NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting); GVariantBuilder builder; - GHashTableIter iter; - const char *key, *value; - NMSettingSecretFlags secret_flags; + gs_free const char **keys = NULL; + guint i, len; if (NM_FLAGS_HAS (flags, NM_CONNECTION_SERIALIZE_NO_SECRETS)) return NULL; g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}")); - g_object_get (setting, property_name, &secrets, NULL); - - if (secrets) { - g_hash_table_iter_init (&iter, secrets); - while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) { - if (NM_FLAGS_HAS (flags, NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED)) { - if ( !nm_setting_get_secret_flags (setting, key, &secret_flags, NULL) - || !NM_FLAGS_HAS (secret_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) - continue; - } - g_variant_builder_add (&builder, "{ss}", key, value); + + keys = nm_utils_strdict_get_keys (priv->secrets, TRUE, &len); + for (i = 0; i < len; i++) { + const char *key = keys[i]; + NMSettingSecretFlags secret_flags; + + if (NM_FLAGS_HAS (flags, NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED)) { + if ( !nm_setting_get_secret_flags (setting, key, &secret_flags, NULL) + || !NM_FLAGS_HAS (secret_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) + continue; } + g_variant_builder_add (&builder, + "{ss}", + key, + g_hash_table_lookup (priv->secrets, key)); } return g_variant_builder_end (&builder); @@ -995,12 +1046,42 @@ set_property (GObject *object, guint prop_id, priv->persistent = g_value_get_boolean (value); break; case PROP_DATA: - g_hash_table_unref (priv->data); - priv->data = _nm_utils_copy_strdict (g_value_get_boxed (value)); - break; - case PROP_SECRETS: - g_hash_table_unref (priv->secrets); - priv->secrets = _nm_utils_copy_strdict (g_value_get_boxed (value)); + case PROP_SECRETS: { + gs_unref_hashtable GHashTable *hash_free = NULL; + GHashTable *src_hash = g_value_get_boxed (value); + GHashTable **p_hash; + const gboolean is_secrets = (prop_id == PROP_SECRETS); + + if (is_secrets) + p_hash = &priv->secrets; + else + p_hash = &priv->data; + + hash_free = g_steal_pointer (p_hash); + + if ( src_hash + && g_hash_table_size (src_hash) > 0) { + GHashTableIter iter; + const char *key; + const char *val; + + g_hash_table_iter_init (&iter, src_hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) { + if ( !key + || !key[0] + || !val) { + /* NULL keys/values and empty key are not allowed. Usually, we would reject them in verify(), but + * then our nm_setting_vpn_remove_data_item() also doesn't allow empty keys. So, if we failed + * it in verify(), it would be only fixable by setting PROP_DATA again. Instead, + * silently ignore them. */ + continue; + } + g_hash_table_insert (_ensure_strdict (p_hash, is_secrets), + g_strdup (key), + g_strdup (val)); + } + } + } break; case PROP_TIMEOUT: priv->timeout = g_value_get_uint (value); @@ -1016,10 +1097,6 @@ set_property (GObject *object, guint prop_id, static void nm_setting_vpn_init (NMSettingVpn *setting) { - NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting); - - 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); } /** @@ -1042,8 +1119,10 @@ finalize (GObject *object) g_free (priv->service_type); g_free (priv->user_name); - g_hash_table_destroy (priv->data); - g_hash_table_destroy (priv->secrets); + if (priv->data) + g_hash_table_unref (priv->data); + if (priv->secrets) + g_hash_table_unref (priv->secrets); G_OBJECT_CLASS (nm_setting_vpn_parent_class)->finalize (object); } diff --git a/libnm-core/nm-setting-vrf.c b/libnm-core/nm-setting-vrf.c new file mode 100644 index 00000000..296f4542 --- /dev/null +++ b/libnm-core/nm-setting-vrf.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: LGPL-2.1+ + +#include "nm-default.h" + +#include "nm-setting-vrf.h" + +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-vrf + * @short_description: Describes connection properties for vrf interfaces + * + * The #NMSettingVrf object is a #NMSetting subclass that describes properties + * necessary for connection to vrf devices + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE ( + PROP_TABLE, +); + +/** + * NMSettingVrf: + * + * VRF settings + * + * Since: 1.24 + */ +struct _NMSettingVrf { + NMSetting parent; + guint32 table; +}; + +struct _NMSettingVrfClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE (NMSettingVrf, nm_setting_vrf, NM_TYPE_SETTING) + +/*****************************************************************************/ + +/** + * nm_setting_vrf_get_table: + * @setting: the #NMSettingVrf + * + * Returns: the routing table for the VRF + * + * Since: 1.24 + **/ +guint32 +nm_setting_vrf_get_table (NMSettingVrf *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VRF (setting), 0); + + return setting->table; +} + +/*****************************************************************************/ + +static gboolean +verify (NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingVrf *self = NM_SETTING_VRF (setting); + + if (!_nm_connection_verify_required_interface_name (connection, error)) + return FALSE; + + if (self->table == 0) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("table cannot be zero")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_VRF_SETTING_NAME, + NM_SETTING_VRF_TABLE); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingVrf *self = NM_SETTING_VRF (object); + + switch (prop_id) { + case PROP_TABLE: + g_value_set_uint (value, self->table); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingVrf *self = NM_SETTING_VRF (object); + + switch (prop_id) { + case PROP_TABLE: + self->table = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_vrf_init (NMSettingVrf *setting) +{ +} + +/** + * nm_setting_vrf_new: + * + * Creates a new #NMSettingVrf object with default values. + * + * Returns: (transfer full): the new empty #NMSettingVrf object + * + * Since: 1.24 + **/ +NMSetting * +nm_setting_vrf_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_VRF, NULL); +} + +static void +nm_setting_vrf_class_init (NMSettingVrfClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + + object_class->get_property = get_property; + object_class->set_property = set_property; + + setting_class->verify = verify; + + /** + * NMSettingVrf:table: + * + * The routing table for this VRF. + * + * Since: 1.24 + **/ + obj_properties[PROP_TABLE] = + g_param_spec_uint (NM_SETTING_VRF_TABLE, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_VRF); +} diff --git a/libnm-core/nm-setting-vrf.h b/libnm-core/nm-setting-vrf.h new file mode 100644 index 00000000..774a4824 --- /dev/null +++ b/libnm-core/nm-setting-vrf.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: LGPL-2.1+ + +#ifndef __NM_SETTING_VRF_H__ +#define __NM_SETTING_VRF_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_VRF (nm_setting_vrf_get_type ()) +#define NM_SETTING_VRF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_VRF, NMSettingVrf)) +#define NM_SETTING_VRF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_VRFCONFIG, NMSettingVrfClass)) +#define NM_IS_SETTING_VRF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_VRF)) +#define NM_IS_SETTING_VRF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_VRF)) +#define NM_SETTING_VRF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_VRF, NMSettingVrfClass)) + +#define NM_SETTING_VRF_SETTING_NAME "vrf" + +#define NM_SETTING_VRF_TABLE "table" + +typedef struct _NMSettingVrfClass NMSettingVrfClass; + +NM_AVAILABLE_IN_1_24 +GType nm_setting_vrf_get_type (void); +NM_AVAILABLE_IN_1_24 +NMSetting *nm_setting_vrf_new (void); +NM_AVAILABLE_IN_1_24 +guint32 nm_setting_vrf_get_table (NMSettingVrf *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_VRF_H__ */ diff --git a/libnm-core/nm-setting-vxlan.c b/libnm-core/nm-setting-vxlan.c index 4e449bc8..edde1ad5 100644 --- a/libnm-core/nm-setting-vxlan.c +++ b/libnm-core/nm-setting-vxlan.c @@ -45,9 +45,9 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( typedef struct { char *parent; - guint id; char *local; char *remote; + guint id; guint source_port_min; guint source_port_max; guint destination_port; @@ -55,11 +55,11 @@ typedef struct { guint ttl; guint ageing; guint limit; - gboolean learning; - gboolean proxy; - gboolean rsc; - gboolean l2_miss; - gboolean l3_miss; + bool learning:1; + bool proxy:1; + bool rsc:1; + bool l2_miss:1; + bool l3_miss:1; } NMSettingVxlanPrivate; G_DEFINE_TYPE (NMSettingVxlan, nm_setting_vxlan, NM_TYPE_SETTING) @@ -327,9 +327,9 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (nm_utils_ipaddr_valid (AF_INET, priv->remote)) + if (nm_utils_ipaddr_is_valid (AF_INET, priv->remote)) family = AF_INET; - else if (nm_utils_ipaddr_valid (AF_INET6, priv->remote)) + else if (nm_utils_ipaddr_is_valid (AF_INET6, priv->remote)) family = AF_INET6; else { g_set_error (error, @@ -344,7 +344,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } if (priv->local) { - if (!nm_utils_ipaddr_valid (family, priv->local)) { + if (!nm_utils_ipaddr_is_valid (family, priv->local)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -519,8 +519,13 @@ set_property (GObject *object, guint prop_id, /*****************************************************************************/ static void -nm_setting_vxlan_init (NMSettingVxlan *setting) +nm_setting_vxlan_init (NMSettingVxlan *self) { + NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE (self); + + priv->destination_port = DST_PORT_DEFAULT; + priv->ageing = 300; + priv->learning = TRUE; } /** @@ -576,7 +581,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_string (NM_SETTING_VXLAN_PARENT, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** @@ -591,7 +595,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_uint (NM_SETTING_VXLAN_ID, "", "", 0, (1 << 24) - 1, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -606,7 +609,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_string (NM_SETTING_VXLAN_LOCAL, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -623,7 +625,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_string (NM_SETTING_VXLAN_REMOTE, "", "", NULL, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -639,7 +640,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_uint (NM_SETTING_VXLAN_SOURCE_PORT_MIN, "", "", 0, G_MAXUINT16, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -655,7 +655,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_uint (NM_SETTING_VXLAN_SOURCE_PORT_MAX, "", "", 0, G_MAXUINT16, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -671,7 +670,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_uint (NM_SETTING_VXLAN_DESTINATION_PORT, "", "", 0, G_MAXUINT16, DST_PORT_DEFAULT, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -686,7 +684,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_uint (NM_SETTING_VXLAN_AGEING, "", "", 0, G_MAXUINT32, 300, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -702,7 +699,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_uint (NM_SETTING_VXLAN_LIMIT, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -717,7 +713,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_uint (NM_SETTING_VXLAN_TOS, "", "", 0, 255, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -732,7 +727,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_uint (NM_SETTING_VXLAN_TTL, "", "", 0, 255, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -747,7 +741,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_boolean (NM_SETTING_VXLAN_PROXY, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -763,7 +756,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_boolean (NM_SETTING_VXLAN_LEARNING, "", "", TRUE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** @@ -777,7 +769,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_boolean (NM_SETTING_VXLAN_RSC, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** @@ -791,7 +782,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_boolean (NM_SETTING_VXLAN_L2_MISS, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); @@ -806,7 +796,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) g_param_spec_boolean (NM_SETTING_VXLAN_L3_MISS, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-wifi-p2p.c b/libnm-core/nm-setting-wifi-p2p.c index df33f1d0..065f6e32 100644 --- a/libnm-core/nm-setting-wifi-p2p.c +++ b/libnm-core/nm-setting-wifi-p2p.c @@ -183,7 +183,7 @@ set_property (GObject *object, guint prop_id, priv->wps_method = g_value_get_uint (value); break; case PROP_WFD_IES: - g_clear_pointer (&priv->wfd_ies, g_bytes_unref); + nm_clear_pointer (&priv->wfd_ies, g_bytes_unref); priv->wfd_ies = g_value_dup_boxed (value); break; default: diff --git a/libnm-core/nm-setting-wimax.c b/libnm-core/nm-setting-wimax.c index cfc1250e..0e547989 100644 --- a/libnm-core/nm-setting-wimax.c +++ b/libnm-core/nm-setting-wimax.c @@ -236,7 +236,7 @@ nm_setting_wimax_class_init (NMSettingWimaxClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj (properties_override, obj_properties[PROP_MAC_ADDRESS], &nm_sett_info_propert_type_mac_addrees); + _nm_properties_override_gobj (properties_override, obj_properties[PROP_MAC_ADDRESS], &nm_sett_info_propert_type_mac_address); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/libnm-core/nm-setting-wired.c b/libnm-core/nm-setting-wired.c index f328e7a6..ab13d88a 100644 --- a/libnm-core/nm-setting-wired.c +++ b/libnm-core/nm-setting-wired.c @@ -48,24 +48,24 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingWired, ); typedef struct { + struct { + NMUtilsNamedValue *arr; + guint len; + guint n_alloc; + } s390_options; + GArray *mac_address_blacklist; + char **s390_subchannels; char *port; - guint32 speed; char *duplex; - gboolean auto_negotiate; char *device_mac_address; char *cloned_mac_address; char *generate_mac_address_mask; - GArray *mac_address_blacklist; - guint32 mtu; - char **s390_subchannels; char *s390_nettype; - struct { - NMUtilsNamedValue *arr; - guint len; - guint n_alloc; - } s390_options; - NMSettingWiredWakeOnLan wol; char *wol_password; + NMSettingWiredWakeOnLan wol; + guint32 speed; + guint32 mtu; + bool auto_negotiate:1; } NMSettingWiredPrivate; G_DEFINE_TYPE (NMSettingWired, nm_setting_wired, NM_TYPE_SETTING) @@ -1145,6 +1145,8 @@ nm_setting_wired_init (NMSettingWired *setting) /* We use GArray rather than GPtrArray so it will automatically be NULL-terminated */ priv->mac_address_blacklist = g_array_new (TRUE, FALSE, sizeof (char *)); g_array_set_clear_func (priv->mac_address_blacklist, (GDestroyNotify) clear_blacklist_item); + + priv->wol = NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT; } /** @@ -1248,7 +1250,6 @@ nm_setting_wired_class_init (NMSettingWiredClass *klass) g_param_spec_uint (NM_SETTING_WIRED_SPEED, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -1304,7 +1305,6 @@ nm_setting_wired_class_init (NMSettingWiredClass *klass) g_param_spec_boolean (NM_SETTING_WIRED_AUTO_NEGOTIATE, "", "", FALSE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); _nm_properties_override_gobj (properties_override, obj_properties[PROP_AUTO_NEGOTIATE], @@ -1343,7 +1343,7 @@ nm_setting_wired_class_init (NMSettingWiredClass *klass) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj (properties_override, obj_properties[PROP_MAC_ADDRESS], &nm_sett_info_propert_type_mac_addrees); + _nm_properties_override_gobj (properties_override, obj_properties[PROP_MAC_ADDRESS], &nm_sett_info_propert_type_mac_address); /** * NMSettingWired:cloned-mac-address: @@ -1501,7 +1501,6 @@ nm_setting_wired_class_init (NMSettingWiredClass *klass) g_param_spec_uint (NM_SETTING_WIRED_MTU, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -1591,7 +1590,6 @@ nm_setting_wired_class_init (NMSettingWiredClass *klass) obj_properties[PROP_WAKE_ON_LAN] = g_param_spec_uint (NM_SETTING_WIRED_WAKE_ON_LAN, "", "", 0, G_MAXUINT32, NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting-wireless-security.c b/libnm-core/nm-setting-wireless-security.c index a634546d..036434cc 100644 --- a/libnm-core/nm-setting-wireless-security.c +++ b/libnm-core/nm-setting-wireless-security.c @@ -13,6 +13,7 @@ #include "nm-utils-private.h" #include "nm-setting-private.h" #include "nm-setting-wireless.h" +#include "nm-glib-aux/nm-secret-utils.h" /** * SECTION:nm-setting-wireless-security @@ -62,36 +63,26 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingWirelessSecurity, ); typedef struct { + GSList *proto; /* GSList of strings */ + GSList *pairwise; /* GSList of strings */ + GSList *group; /* GSList of strings */ char *key_mgmt; char *auth_alg; - GSList *proto; /* GSList of strings */ - GSList *pairwise; /* GSList of strings */ - GSList *group; /* GSList of strings */ - NMSettingWirelessSecurityPmf pmf; - - /* LEAP */ char *leap_username; char *leap_password; - NMSettingSecretFlags leap_password_flags; - - /* WEP */ char *wep_key0; char *wep_key1; char *wep_key2; char *wep_key3; - NMSettingSecretFlags wep_key_flags; - NMWepKeyType wep_key_type; - guint32 wep_tx_keyidx; - - /* WPA-PSK */ char *psk; + NMSettingSecretFlags leap_password_flags; + NMSettingSecretFlags wep_key_flags; NMSettingSecretFlags psk_flags; - - /* WPS */ + NMSettingWirelessSecurityPmf pmf; + NMWepKeyType wep_key_type; NMSettingWirelessSecurityWpsMethod wps_method; - - /* FILS */ NMSettingWirelessSecurityFils fils; + guint32 wep_tx_keyidx; } NMSettingWirelessSecurityPrivate; G_DEFINE_TYPE (NMSettingWirelessSecurity, nm_setting_wireless_security, NM_TYPE_SETTING) @@ -175,7 +166,7 @@ nm_setting_wireless_security_add_proto (NMSettingWirelessSecurity *setting, cons priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); for (iter = priv->proto; iter; iter = g_slist_next (iter)) { - if (strcasecmp (proto, (char *) iter->data) == 0) + if (g_ascii_strcasecmp (proto, (char *) iter->data) == 0) return FALSE; } @@ -229,7 +220,7 @@ nm_setting_wireless_security_remove_proto_by_value (NMSettingWirelessSecurity *s priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); for (iter = priv->proto; iter; iter = g_slist_next (iter)) { - if (strcasecmp (proto, (char *) iter->data) == 0) { + if (g_ascii_strcasecmp (proto, (char *) iter->data) == 0) { priv->proto = g_slist_delete_link (priv->proto, iter); _notify (setting, PROP_PROTO); return TRUE; @@ -319,7 +310,7 @@ nm_setting_wireless_security_add_pairwise (NMSettingWirelessSecurity *setting, c priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); for (iter = priv->pairwise; iter; iter = g_slist_next (iter)) { - if (strcasecmp (pairwise, (char *) iter->data) == 0) + if (g_ascii_strcasecmp (pairwise, (char *) iter->data) == 0) return FALSE; } @@ -375,7 +366,7 @@ nm_setting_wireless_security_remove_pairwise_by_value (NMSettingWirelessSecurity priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); for (iter = priv->pairwise; iter; iter = g_slist_next (iter)) { - if (strcasecmp (pairwise, (char *) iter->data) == 0) { + if (g_ascii_strcasecmp (pairwise, (char *) iter->data) == 0) { priv->pairwise = g_slist_delete_link (priv->pairwise, iter); _notify (setting, PROP_PAIRWISE); return TRUE; @@ -466,7 +457,7 @@ nm_setting_wireless_security_add_group (NMSettingWirelessSecurity *setting, cons priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); for (iter = priv->group; iter; iter = g_slist_next (iter)) { - if (strcasecmp (group, (char *) iter->data) == 0) + if (g_ascii_strcasecmp (group, (char *) iter->data) == 0) return FALSE; } @@ -523,7 +514,7 @@ nm_setting_wireless_security_remove_group_by_value (NMSettingWirelessSecurity *s priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); for (iter = priv->group; iter; iter = g_slist_next (iter)) { - if (strcasecmp (group, (char *) iter->data) == 0) { + if (g_ascii_strcasecmp (group, (char *) iter->data) == 0) { priv->group = g_slist_delete_link (priv->group, iter); _notify (setting, PROP_GROUP); return TRUE; @@ -865,7 +856,8 @@ need_secrets (NMSetting *setting) } if ( (strcmp (priv->key_mgmt, "ieee8021x") == 0) - || (strcmp (priv->key_mgmt, "wpa-eap") == 0)) { + || (strcmp (priv->key_mgmt, "wpa-eap") == 0) + || (strcmp (priv->key_mgmt, "owe") == 0)) { /* Let caller check the 802.1x setting for secrets */ goto no_secrets; } @@ -884,7 +876,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingWirelessSecurity *self = NM_SETTING_WIRELESS_SECURITY (setting); NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (self); - const char *valid_key_mgmt[] = { "none", "ieee8021x", "wpa-psk", "wpa-eap", "sae", NULL }; + const char *valid_key_mgmt[] = { "none", "ieee8021x", "wpa-psk", "wpa-eap", "sae", "owe", NULL }; const char *valid_auth_algs[] = { "open", "shared", "leap", NULL }; const char *valid_protos[] = { "wpa", "rsn", NULL }; const char *valid_pairwise[] = { "tkip", "ccmp", NULL }; @@ -1054,7 +1046,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) if ( NM_IN_SET (priv->pmf, NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL, NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) - && !NM_IN_STRSET (priv->key_mgmt, "wpa-eap", "wpa-psk", "sae")) { + && !NM_IN_STRSET (priv->key_mgmt, "wpa-eap", "wpa-psk", "sae", "owe")) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -1315,33 +1307,33 @@ set_property (GObject *object, guint prop_id, priv->leap_username = g_value_dup_string (value); break; case PROP_WEP_KEY0: - g_free (priv->wep_key0); + nm_free_secret (priv->wep_key0); priv->wep_key0 = g_value_dup_string (value); break; case PROP_WEP_KEY1: - g_free (priv->wep_key1); + nm_free_secret (priv->wep_key1); priv->wep_key1 = g_value_dup_string (value); break; case PROP_WEP_KEY2: - g_free (priv->wep_key2); + nm_free_secret (priv->wep_key2); priv->wep_key2 = g_value_dup_string (value); break; case PROP_WEP_KEY3: - g_free (priv->wep_key3); + nm_free_secret (priv->wep_key3); priv->wep_key3 = g_value_dup_string (value); break; case PROP_WEP_KEY_FLAGS: priv->wep_key_flags = g_value_get_flags (value); break; case PROP_PSK: - g_free (priv->psk); + nm_free_secret (priv->psk); priv->psk = g_value_dup_string (value); break; case PROP_PSK_FLAGS: priv->psk_flags = g_value_get_flags (value); break; case PROP_LEAP_PASSWORD: - g_free (priv->leap_password); + nm_free_secret (priv->leap_password); priv->leap_password = g_value_dup_string (value); break; case PROP_LEAP_PASSWORD_FLAGS: @@ -1365,8 +1357,10 @@ set_property (GObject *object, guint prop_id, /*****************************************************************************/ static void -nm_setting_wireless_security_init (NMSettingWirelessSecurity *setting) +nm_setting_wireless_security_init (NMSettingWirelessSecurity *self) { + nm_assert (NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (self)->wep_key_type == NM_WEP_KEY_TYPE_UNKNOWN); + nm_assert (NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (self)->wps_method == NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT); } /** @@ -1391,12 +1385,12 @@ finalize (GObject *object) g_free (priv->key_mgmt); g_free (priv->auth_alg); g_free (priv->leap_username); - g_free (priv->wep_key0); - g_free (priv->wep_key1); - g_free (priv->wep_key2); - g_free (priv->wep_key3); - g_free (priv->psk); - g_free (priv->leap_password); + nm_free_secret (priv->wep_key0); + nm_free_secret (priv->wep_key1); + nm_free_secret (priv->wep_key2); + nm_free_secret (priv->wep_key3); + nm_free_secret (priv->psk); + nm_free_secret (priv->leap_password); g_slist_free_full (priv->proto, g_free); g_slist_free_full (priv->pairwise, g_free); @@ -1429,7 +1423,8 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *klass) * * Key management used for the connection. One of "none" (WEP), * "ieee8021x" (Dynamic WEP), "wpa-psk" (infrastructure WPA-PSK), "sae" - * (SAE) or "wpa-eap" (WPA-Enterprise). This property must be set for + * (SAE), "owe" (Opportunistic Wireless Encryption) or "wpa-eap" + * (WPA-Enterprise). This property must be set for * any Wi-Fi connection that uses security. **/ /* ---ifcfg-rh--- @@ -1466,7 +1461,6 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *klass) g_param_spec_uint (NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, "", "", 0, 3, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -1582,7 +1576,6 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *klass) g_param_spec_int (NM_SETTING_WIRELESS_SECURITY_PMF, "", "", G_MININT32, G_MAXINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -1809,7 +1802,6 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *klass) NM_TYPE_WEP_KEY_TYPE, NM_WEP_KEY_TYPE_UNKNOWN, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); _nm_properties_override_gobj (properties_override, obj_properties[PROP_WEP_KEY_TYPE], @@ -1844,7 +1836,6 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *klass) g_param_spec_uint (NM_SETTING_WIRELESS_SECURITY_WPS_METHOD, "", "", 0, G_MAXUINT32, NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -1874,7 +1865,6 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *klass) 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.c b/libnm-core/nm-setting-wireless.c index 1731673f..2ef51088 100644 --- a/libnm-core/nm-setting-wireless.c +++ b/libnm-core/nm-setting-wireless.c @@ -47,22 +47,22 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingWireless, typedef struct { GBytes *ssid; + GArray *mac_address_blacklist; + GPtrArray *seen_bssids; char *mode; char *band; - guint32 channel; char *bssid; - guint32 rate; - guint32 tx_power; char *device_mac_address; char *cloned_mac_address; char *generate_mac_address_mask; - GArray *mac_address_blacklist; - GPtrArray *seen_bssids; + guint32 channel; + guint32 rate; + guint32 tx_power; guint32 mtu; - gboolean hidden; guint32 powersave; - NMSettingMacRandomization mac_address_randomization; guint32 wowl; + NMSettingMacRandomization mac_address_randomization; + bool hidden:1; } NMSettingWirelessPrivate; G_DEFINE_TYPE (NMSettingWireless, nm_setting_wireless, NM_TYPE_SETTING) @@ -206,7 +206,8 @@ nm_setting_wireless_ap_security_compatible (NMSettingWireless *s_wireless, /* WPA[2]-PSK and WPA[2] Enterprise */ if ( !strcmp (key_mgmt, "wpa-psk") || !strcmp (key_mgmt, "wpa-eap") - || !strcmp (key_mgmt, "sae")) { + || !strcmp (key_mgmt, "sae") + || !strcmp (key_mgmt, "owe")) { if (!strcmp (key_mgmt, "wpa-psk")) { if ( !(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) @@ -220,6 +221,10 @@ nm_setting_wireless_ap_security_compatible (NMSettingWireless *s_wireless, if ( !(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_SAE) && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_SAE)) return FALSE; + } else if (!strcmp (key_mgmt, "owe")) { + if ( !(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_OWE) + && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_OWE)) + return FALSE; } // FIXME: should handle WPA and RSN separately here to ensure that @@ -1214,6 +1219,8 @@ nm_setting_wireless_init (NMSettingWireless *setting) /* We use GArray rather than GPtrArray so it will automatically be NULL-terminated */ priv->mac_address_blacklist = g_array_new (TRUE, FALSE, sizeof (char *)); g_array_set_clear_func (priv->mac_address_blacklist, (GDestroyNotify) clear_blacklist_item); + + priv->wowl = NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT; } /** @@ -1354,7 +1361,6 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass) g_param_spec_uint (NM_SETTING_WIRELESS_CHANNEL, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); /** @@ -1377,7 +1383,7 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj (properties_override, obj_properties[PROP_BSSID], &nm_sett_info_propert_type_mac_addrees); + _nm_properties_override_gobj (properties_override, obj_properties[PROP_BSSID], &nm_sett_info_propert_type_mac_address); /** * NMSettingWireless:rate: @@ -1397,7 +1403,6 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass) g_param_spec_uint (NM_SETTING_WIRELESS_RATE, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -1418,7 +1423,6 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass) g_param_spec_uint (NM_SETTING_WIRELESS_TX_POWER, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -1451,7 +1455,7 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj (properties_override, obj_properties[PROP_MAC_ADDRESS], &nm_sett_info_propert_type_mac_addrees); + _nm_properties_override_gobj (properties_override, obj_properties[PROP_MAC_ADDRESS], &nm_sett_info_propert_type_mac_address); /** * NMSettingWireless:cloned-mac-address: @@ -1635,7 +1639,6 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass) g_param_spec_uint (NM_SETTING_WIRELESS_MTU, "", "", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); @@ -1705,7 +1708,7 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass) * 'cloned-mac-address'. * * Since: 1.2 - * Deprecated: 1.4: Deprecated by NMSettingWireless:cloned-mac-address property + * Deprecated: 1.4: Deprecated by NMSettingWireless:cloned-mac-address property. **/ /* ---ifcfg-rh--- * property: mac-address-randomization @@ -1763,7 +1766,6 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass) obj_properties[PROP_WAKE_ON_WLAN] = g_param_spec_uint (NM_SETTING_WIRELESS_WAKE_ON_WLAN, "", "", 0, G_MAXUINT32, NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index b7be9c65..a75302f0 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -151,15 +151,18 @@ _nm_setting_slave_type_is_valid (const char *slave_type, const char **out_port_t if (!slave_type) found = FALSE; - else if (!strcmp (slave_type, NM_SETTING_BOND_SETTING_NAME)) - ; - else if (!strcmp (slave_type, NM_SETTING_BRIDGE_SETTING_NAME)) + else if (NM_IN_STRSET (slave_type, + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_VRF_SETTING_NAME)) { + /* pass */ + } + else if (nm_streq (slave_type, NM_SETTING_BRIDGE_SETTING_NAME)) port_type = NM_SETTING_BRIDGE_PORT_SETTING_NAME; - else if (!strcmp (slave_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) + else if (nm_streq (slave_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) port_type = NM_SETTING_OVS_PORT_SETTING_NAME; - else if (!strcmp (slave_type, NM_SETTING_OVS_PORT_SETTING_NAME)) + else if (nm_streq (slave_type, NM_SETTING_OVS_PORT_SETTING_NAME)) port_type = NM_SETTING_OVS_INTERFACE_SETTING_NAME; - else if (!strcmp (slave_type, NM_SETTING_TEAM_SETTING_NAME)) + else if (nm_streq (slave_type, NM_SETTING_TEAM_SETTING_NAME)) port_type = NM_SETTING_TEAM_PORT_SETTING_NAME; else found = FALSE; diff --git a/libnm-core/nm-utils-private.h b/libnm-core/nm-utils-private.h index 4ca9dfc2..f3e9d3f1 100644 --- a/libnm-core/nm-utils-private.h +++ b/libnm-core/nm-utils-private.h @@ -49,7 +49,7 @@ gboolean _nm_utils_wps_method_validate (NMSettingWirelessSecurityWpsMethod wps_m extern const NMSettInfoPropertType nm_sett_info_propert_type_strdict; -extern const NMSettInfoPropertType nm_sett_info_propert_type_mac_addrees; +extern const NMSettInfoPropertType nm_sett_info_propert_type_mac_address; extern const NMSettInfoPropertType nm_sett_info_propert_type_cloned_mac_address; @@ -65,6 +65,8 @@ void _nm_utils_bytes_from_dbus (GVariant *dbus_value, char * _nm_utils_hwaddr_canonical_or_invalid (const char *mac, gssize length); +gboolean _nm_utils_hwaddr_link_local_valid (const char *mac); + void _nm_utils_format_variant_attributes_full (GString *str, const NMUtilsNamedValue *values, guint num_values, diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index ea4c52c0..062ff393 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -802,53 +802,7 @@ _nm_utils_hash_values_to_slist (GHashTable *hash) static GVariant * _nm_utils_strdict_to_dbus (const GValue *prop_value) { - GHashTable *hash; - GHashTableIter iter; - const char *key, *value; - GVariantBuilder builder; - guint i, len; - - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}")); - - hash = g_value_get_boxed (prop_value); - if (!hash) - goto out; - len = g_hash_table_size (hash); - if (!len) - goto out; - - g_hash_table_iter_init (&iter, hash); - if (!g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) - nm_assert_not_reached (); - - if (len == 1) - g_variant_builder_add (&builder, "{ss}", key, value); - else { - gs_free NMUtilsNamedValue *idx_free = NULL; - NMUtilsNamedValue *idx; - - if (len > 300 / sizeof (NMUtilsNamedValue)) { - idx_free = g_new (NMUtilsNamedValue, len); - idx = idx_free; - } else - idx = g_alloca (sizeof (NMUtilsNamedValue) * len); - - i = 0; - do { - idx[i].name = key; - idx[i].value_str = value; - i++; - } while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)); - nm_assert (i == len); - - nm_utils_named_value_list_sort (idx, len, NULL, NULL); - - for (i = 0; i < len; i++) - g_variant_builder_add (&builder, "{ss}", idx[i].name, idx[i].value_str); - } - -out: - return g_variant_builder_end (&builder); + return nm_utils_strdict_to_variant_ass (g_value_get_boxed (prop_value)); } void @@ -1119,8 +1073,14 @@ nm_utils_ap_mode_security_valid (NMUtilsSecurityType type, case NMU_SEC_WPA_PSK: case NMU_SEC_WPA2_PSK: case NMU_SEC_SAE: + case NMU_SEC_OWE: return TRUE; - default: + case NMU_SEC_LEAP: + case NMU_SEC_DYNAMIC_WEP: + case NMU_SEC_WPA_ENTERPRISE: + case NMU_SEC_WPA2_ENTERPRISE: + return FALSE; + case NMU_SEC_INVALID: break; } return FALSE; @@ -1159,48 +1119,46 @@ nm_utils_security_valid (NMUtilsSecurityType type, NM80211ApSecurityFlags ap_wpa, NM80211ApSecurityFlags ap_rsn) { - gboolean good = TRUE; - - if (!have_ap) { - if (type == NMU_SEC_NONE) - return TRUE; - if ( (type == NMU_SEC_STATIC_WEP) - || ((type == NMU_SEC_DYNAMIC_WEP) && !adhoc) - || ((type == NMU_SEC_LEAP) && !adhoc)) { - if (wifi_caps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104)) - return TRUE; - else - return FALSE; - } - } - switch (type) { case NMU_SEC_NONE: - g_assert (have_ap); + if (!have_ap) + return TRUE; if (ap_flags & NM_802_11_AP_FLAGS_PRIVACY) return FALSE; - if (ap_wpa || ap_rsn) + if ( ap_wpa + || ap_rsn) return FALSE; - break; + return TRUE; case NMU_SEC_LEAP: /* require PRIVACY bit for LEAP? */ if (adhoc) return FALSE; /* fall-through */ case NMU_SEC_STATIC_WEP: - g_assert (have_ap); + if (!have_ap) { + if (wifi_caps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104)) + return TRUE; + return FALSE; + } if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)) return FALSE; - if (ap_wpa || ap_rsn) { - if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, TRUE)) + if ( ap_wpa + || ap_rsn) { + if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, TRUE)) { if (!device_supports_ap_ciphers (wifi_caps, ap_rsn, TRUE)) return FALSE; + } } - break; + return TRUE; case NMU_SEC_DYNAMIC_WEP: if (adhoc) return FALSE; - g_assert (have_ap); - if (ap_rsn || !(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)) + if (!have_ap) { + if (wifi_caps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104)) + return TRUE; + return FALSE; + } + if ( ap_rsn + || !(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)) return FALSE; /* Some APs broadcast minimal WPA-enabled beacons that must be handled */ if (ap_wpa) { @@ -1209,102 +1167,99 @@ nm_utils_security_valid (NMUtilsSecurityType type, if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, FALSE)) return FALSE; } - break; + return TRUE; case NMU_SEC_WPA_PSK: if (adhoc) return FALSE; if (!(wifi_caps & NM_WIFI_DEVICE_CAP_WPA)) return FALSE; - if (have_ap) { - if (ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) { - if ( (ap_wpa & NM_802_11_AP_SEC_PAIR_TKIP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)) - return TRUE; - if ( (ap_wpa & NM_802_11_AP_SEC_PAIR_CCMP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) - return TRUE; - } - return FALSE; + if (!have_ap) + return TRUE; + if (ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) { + if ( (ap_wpa & NM_802_11_AP_SEC_PAIR_TKIP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)) + return TRUE; + if ( (ap_wpa & NM_802_11_AP_SEC_PAIR_CCMP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) + return TRUE; } - break; + return FALSE; case NMU_SEC_WPA2_PSK: if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) return FALSE; - if (have_ap) { - if (adhoc) { - if (!(wifi_caps & NM_WIFI_DEVICE_CAP_IBSS_RSN)) - return FALSE; - if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) - return TRUE; - } else { - if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK) { - if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_TKIP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)) - return TRUE; - if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) - return TRUE; - } - } + if (!have_ap) + return TRUE; + if (adhoc) { + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_IBSS_RSN)) + return FALSE; + if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) + return TRUE; return FALSE; } - break; + if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK) { + if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_TKIP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)) + return TRUE; + if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) + return TRUE; + } + return FALSE; case NMU_SEC_WPA_ENTERPRISE: if (adhoc) return FALSE; if (!(wifi_caps & NM_WIFI_DEVICE_CAP_WPA)) return FALSE; - if (have_ap) { - if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) - return FALSE; - /* Ensure at least one WPA cipher is supported */ - if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, FALSE)) - return FALSE; - } - break; + if (!have_ap) + return TRUE; + if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + return FALSE; + /* Ensure at least one WPA cipher is supported */ + if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, FALSE)) + return FALSE; + return TRUE; case NMU_SEC_WPA2_ENTERPRISE: if (adhoc) return FALSE; if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) return FALSE; - if (have_ap) { - if (!(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) - return FALSE; - /* Ensure at least one WPA cipher is supported */ - if (!device_supports_ap_ciphers (wifi_caps, ap_rsn, FALSE)) - return FALSE; - } - break; + if (!have_ap) + return TRUE; + if (!(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + return FALSE; + /* Ensure at least one WPA cipher is supported */ + if (!device_supports_ap_ciphers (wifi_caps, ap_rsn, FALSE)) + return FALSE; + return TRUE; case NMU_SEC_SAE: if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) return FALSE; - if (have_ap) { - if (adhoc) { - if (!(wifi_caps & NM_WIFI_DEVICE_CAP_IBSS_RSN)) - return FALSE; - if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) - return TRUE; - } else { - if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_SAE) { - if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_TKIP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)) - return TRUE; - if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) - return TRUE; - } - } + if (adhoc) return FALSE; + if (!have_ap) + return TRUE; + if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_SAE) { + if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) + return TRUE; } - break; - default: - good = FALSE; + return FALSE; + case NMU_SEC_OWE: + if (adhoc) + return FALSE; + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) + return FALSE; + if (!have_ap) + return TRUE; + if (!(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_OWE)) + return FALSE; + return TRUE; + case NMU_SEC_INVALID: break; } - return good; + return FALSE; } /** @@ -2298,7 +2253,7 @@ _nm_utils_parse_tc_handle (const char *str, GError **error) nm_assert (str); - maj = g_ascii_strtoll (str, (char **) &sep, 0x10); + maj = nm_g_ascii_strtoll (str, (char **) &sep, 0x10); if (sep == str) goto fail; @@ -2307,7 +2262,7 @@ _nm_utils_parse_tc_handle (const char *str, GError **error) if (sep[0] == ':') { const char *str2 = &sep[1]; - min = g_ascii_strtoll (str2, (char **) &sep, 0x10); + min = nm_g_ascii_strtoll (str2, (char **) &sep, 0x10); sep = nm_str_skip_leading_spaces (sep); if (sep[0] != '\0') goto fail; @@ -4231,6 +4186,41 @@ _nm_utils_hwaddr_canonical_or_invalid (const char *mac, gssize length) return g_strdup (mac); } +/* + * Determine if given Ethernet address is link-local + * + * Return value: %TRUE if @mac is link local + * reserved addr (01:80:c2:00:00:0X) per IEEE 802.1Q 8.6.3 Frame filtering, %FALSE if not. + */ +gboolean +_nm_utils_hwaddr_link_local_valid (const char *mac) +{ + guint8 mac_net[ETH_ALEN]; + static const guint8 eth_reserved_addr_base[] = { + 0x01, 0x80, + 0xc2, 0x00, + 0x00 + }; + + if (!mac) + return FALSE; + + if (!nm_utils_hwaddr_aton (mac, mac_net, ETH_ALEN)) + return FALSE; + + if ( memcmp (mac_net, + eth_reserved_addr_base, ETH_ALEN - 1) + || (mac_net[5] & 0xF0)) + return FALSE; + + if ( mac_net[5] == 1 /* 802.3x Pause address */ + || mac_net[5] == 2 /* 802.3ad Slow protocols */ + || mac_net[5] == 3) /* 802.1X PAE address */ + return FALSE; + + return TRUE; +} + /** * nm_utils_hwaddr_matches: * @hwaddr1: (nullable): pointer to a binary or ASCII hardware address, or %NULL @@ -4487,7 +4477,7 @@ _nm_utils_hwaddr_from_dbus (GVariant *dbus_value, g_value_take_string (prop_value, str); } -const NMSettInfoPropertType nm_sett_info_propert_type_mac_addrees = { +const NMSettInfoPropertType nm_sett_info_propert_type_mac_address = { .dbus_type = G_VARIANT_TYPE_BYTESTRING, .gprop_to_dbus_fcn = _nm_utils_hwaddr_to_dbus, .gprop_from_dbus_fcn = _nm_utils_hwaddr_from_dbus, @@ -4728,7 +4718,7 @@ nm_utils_is_valid_iface_name (const char *name, GError **error) * * Validate the network interface name. * - * Deprecated: 1.6: use nm_utils_is_valid_iface_name() instead, with better error reporting. + * Deprecated: 1.6: Use nm_utils_is_valid_iface_name() instead, with better error reporting. * * Returns: %TRUE if interface name is valid, otherwise %FALSE is returned. * @@ -4781,23 +4771,6 @@ nm_utils_is_uuid (const char *str) static char _nm_utils_inet_ntop_buffer[NM_UTILS_INET_ADDRSTRLEN]; -const char * -nm_utils_inet_ntop (int addr_family, gconstpointer addr, char *dst) -{ - const char *s; - - nm_assert_addr_family (addr_family); - nm_assert (addr); - nm_assert (dst); - - s = inet_ntop (addr_family, - addr, - dst, - addr_family == AF_INET6 ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN); - nm_assert (s); - return s; -} - /** * nm_utils_inet4_ntop: (skip) * @inaddr: the address that should be converted to string. @@ -4823,8 +4796,7 @@ nm_utils_inet4_ntop (in_addr_t inaddr, char *dst) * * However, still support it to be lenient against mistakes and because * this is public API of libnm. */ - return inet_ntop (AF_INET, &inaddr, dst ?: _nm_utils_inet_ntop_buffer, - INET_ADDRSTRLEN); + return _nm_utils_inet4_ntop (inaddr, dst ?: _nm_utils_inet_ntop_buffer); } /** @@ -4854,8 +4826,7 @@ nm_utils_inet6_ntop (const struct in6_addr *in6addr, char *dst) * However, still support it to be lenient against mistakes and because * this is public API of libnm. */ g_return_val_if_fail (in6addr, NULL); - return inet_ntop (AF_INET6, in6addr, dst ?: _nm_utils_inet_ntop_buffer, - INET6_ADDRSTRLEN); + return _nm_utils_inet6_ntop (in6addr, dst ?: _nm_utils_inet_ntop_buffer); } /** @@ -4871,17 +4842,9 @@ nm_utils_inet6_ntop (const struct in6_addr *in6addr, char *dst) gboolean nm_utils_ipaddr_valid (int family, const char *ip) { - guint8 buf[sizeof (struct in6_addr)]; - g_return_val_if_fail (family == AF_INET || family == AF_INET6 || family == AF_UNSPEC, FALSE); - if (!ip) - return FALSE; - - if (family == AF_UNSPEC) - family = strchr (ip, ':') ? AF_INET6 : AF_INET; - - return inet_pton (family, ip, buf) == 1; + return nm_utils_ipaddr_is_valid (family, ip); } /** @@ -5835,7 +5798,7 @@ nm_utils_get_timestamp_msec (void) { gint64 ts; - ts = nm_utils_clock_gettime_ms (CLOCK_BOOTTIME); + ts = nm_utils_clock_gettime_msec (CLOCK_BOOTTIME); if (ts >= 0) return ts; @@ -5844,7 +5807,7 @@ nm_utils_get_timestamp_msec (void) * criminally old kernel, prior to 2.6.39 (released on 18 May, 2011). * That happens during buildcheck on old builders, we don't expect to * be actually runs on kernels that old. */ - ts = nm_utils_clock_gettime_ms (CLOCK_MONOTONIC); + ts = nm_utils_clock_gettime_msec (CLOCK_MONOTONIC); if (ts >= 0) return ts; } diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h index 5418a1e6..4cbf24ab 100644 --- a/libnm-core/nm-utils.h +++ b/libnm-core/nm-utils.h @@ -51,6 +51,7 @@ char * nm_utils_ssid_to_utf8 (const guint8 *ssid, gsize len); * @NMU_SEC_WPA2_PSK: WPA2/RSN is used with Pre-Shared Keys (PSK) * @NMU_SEC_WPA2_ENTERPRISE: WPA2 is used with 802.1x authentication * @NMU_SEC_SAE: is used with WPA3 Enterprise + * @NMU_SEC_OWE: is used with Enhanced Open * * Describes generic security mechanisms that 802.11 access points may offer. * Used with nm_utils_security_valid() for checking whether a given access @@ -67,6 +68,7 @@ typedef enum { NMU_SEC_WPA2_PSK, NMU_SEC_WPA2_ENTERPRISE, NMU_SEC_SAE, + NMU_SEC_OWE, } NMUtilsSecurityType; gboolean nm_utils_security_valid (NMUtilsSecurityType type, diff --git a/libnm-core/nm-version.h b/libnm-core/nm-version.h index 3fd2f346..195fc196 100644 --- a/libnm-core/nm-version.h +++ b/libnm-core/nm-version.h @@ -215,24 +215,18 @@ # define NM_AVAILABLE_IN_1_22 #endif -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_22_2 -# define NM_DEPRECATED_IN_1_22_2 G_DEPRECATED -# define NM_DEPRECATED_IN_1_22_2_FOR(f) G_DEPRECATED_FOR(f) +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_24 +# define NM_DEPRECATED_IN_1_24 G_DEPRECATED +# define NM_DEPRECATED_IN_1_24_FOR(f) G_DEPRECATED_FOR(f) #else -# define NM_DEPRECATED_IN_1_22_2 -# define NM_DEPRECATED_IN_1_22_2_FOR(f) +# define NM_DEPRECATED_IN_1_24 +# define NM_DEPRECATED_IN_1_24_FOR(f) #endif -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_22_2 -# define NM_AVAILABLE_IN_1_22_2 G_UNAVAILABLE(1,22.2) +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_24 +# define NM_AVAILABLE_IN_1_24 G_UNAVAILABLE(1,24) #else -# define NM_AVAILABLE_IN_1_22_2 -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_22_8 -# define NM_AVAILABLE_IN_1_22_8 G_UNAVAILABLE(1,22.8) -#else -# define NM_AVAILABLE_IN_1_22_8 +# define NM_AVAILABLE_IN_1_24 #endif /* @@ -255,10 +249,11 @@ * around g_dbus_connection_call_sync(). You may call it directly * without feeling dirty. * - * We don't want to force users away from this API, for that reason the - * macro does not yet expand to G_DEPRECATED. + * The API is marked as deprecated since 1.22, however the macro only starts + * complaining in 1.24. That's intentional, because in 1.22 the asynchronous + * alternative was not yet available. */ -#define _NM_DEPRECATED_SYNC_METHOD /*NM_DEPRECATED_IN_1_22*/ -#define _NM_DEPRECATED_SYNC_WRITABLE_PROPERTY /*NM_DEPRECATED_IN_1_22*/ +#define _NM_DEPRECATED_SYNC_METHOD NM_DEPRECATED_IN_1_24 +#define _NM_DEPRECATED_SYNC_WRITABLE_PROPERTY /* NM_DEPRECATED_IN_1_22 */ #endif /* NM_VERSION_H */ diff --git a/libnm-core/nm-vpn-plugin-info.c b/libnm-core/nm-vpn-plugin-info.c index df3ef08d..7fbd8954 100644 --- a/libnm-core/nm-vpn-plugin-info.c +++ b/libnm-core/nm-vpn-plugin-info.c @@ -42,13 +42,31 @@ typedef struct { NMVpnEditorPlugin *editor_plugin; } NMVpnPluginInfoPrivate; +/** + * NMVpnPluginInfo: + */ +struct _NMVpnPluginInfo { + GObject parent; + NMVpnPluginInfoPrivate _priv; +}; + +struct _NMVpnPluginInfoClass { + GObjectClass parent; +}; + +#define NM_VPN_PLUGIN_INFO_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMVpnPluginInfo, NM_IS_VPN_PLUGIN_INFO) + static void nm_vpn_plugin_info_initable_iface_init (GInitableIface *iface); G_DEFINE_TYPE_WITH_CODE (NMVpnPluginInfo, nm_vpn_plugin_info, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_vpn_plugin_info_initable_iface_init); ) -#define NM_VPN_PLUGIN_INFO_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_PLUGIN_INFO, NMVpnPluginInfoPrivate)) +/*****************************************************************************/ + +static NMVpnPluginInfo *_list_find_by_service (GSList *list, + const char *name, + const char *service); /*****************************************************************************/ @@ -172,23 +190,6 @@ _sort_files (LoadDirInfo *a, LoadDirInfo *b) nm_vpn_plugin_info_get_filename (b->plugin_info)); } -#define DEFINE_DEFAULT_DIR_LIST(dir) \ - const char *dir[] = { \ - /* We load plugins from NM_VPN_PLUGIN_DIR *and* DEFAULT_DIR*, with - * preference to the former. - * - * load user directory with highest priority. */ \ - _nm_vpn_plugin_info_get_default_dir_user (), \ - \ - /* lib directory has higher priority then etc. The reason is that - * etc is deprecated and used by old plugins. We expect newer plugins - * to install their file in lib, where they have higher priority. - * - * Optimally, there are no duplicates anyway, so it doesn't really matter. */ \ - _nm_vpn_plugin_info_get_default_dir_lib (), \ - _nm_vpn_plugin_info_get_default_dir_etc (), \ - } - /** * _nm_vpn_plugin_info_get_default_dir_etc: * @@ -223,7 +224,7 @@ _nm_vpn_plugin_info_get_default_dir_lib () const char * _nm_vpn_plugin_info_get_default_dir_user () { - return g_getenv ("NM_VPN_PLUGIN_DIR"); + return nm_str_not_empty (g_getenv ("NM_VPN_PLUGIN_DIR")); } /** @@ -316,7 +317,21 @@ nm_vpn_plugin_info_list_load () gint64 uid; GSList *list = NULL; GSList *infos, *info; - DEFINE_DEFAULT_DIR_LIST (dir); + const char *const dir[] = { + /* We load plugins from NM_VPN_PLUGIN_DIR *and* DEFAULT_DIR*, with + * preference to the former. + * + * load user directory with highest priority. */ + _nm_vpn_plugin_info_get_default_dir_user (), + + /* lib directory has higher priority then etc. The reason is that + * etc is deprecated and used by old plugins. We expect newer plugins + * to install their file in lib, where they have higher priority. + * + * Optimally, there are no duplicates anyway, so it doesn't really matter. */ + _nm_vpn_plugin_info_get_default_dir_lib (), + _nm_vpn_plugin_info_get_default_dir_etc (), + }; uid = getuid (); @@ -354,45 +369,16 @@ nm_vpn_plugin_info_list_load () NMVpnPluginInfo * nm_vpn_plugin_info_new_search_file (const char *name, const char *service) { - int i; - gint64 uid; - NMVpnPluginInfo *plugin_info = NULL; - GSList *infos, *info; - DEFINE_DEFAULT_DIR_LIST (dir); + NMVpnPluginInfo *info; + GSList *infos; if (!name && !service) g_return_val_if_reached (NULL); - uid = getuid (); - - for (i = 0; !plugin_info && i < G_N_ELEMENTS (dir); i++) { - if ( !dir[i] - || nm_utils_strv_find_first ((char **) dir, i, dir[i]) >= 0) - continue; - - /* We still must load the entire directory while searching for the matching - * plugin-info. The reason is that reading the directory has no stable - * order and we can only sort them after reading the entire directory -- - * which _nm_vpn_plugin_info_list_load_dir() does. */ - infos = _nm_vpn_plugin_info_list_load_dir (dir[i], TRUE, uid, NULL, NULL); - - for (info = infos; info; info = info->next) { - NMVpnPluginInfo *p = info->data; - - if (name && !nm_streq (nm_vpn_plugin_info_get_name (p), name)) - continue; - if ( service - && !nm_streq (nm_vpn_plugin_info_get_service (p), service) - && (nm_utils_strv_find_first (NM_VPN_PLUGIN_INFO_GET_PRIVATE (p)->aliases, - -1, service) < 0)) - continue; - plugin_info = g_object_ref (p); - break; - } - - g_slist_free_full (infos, g_object_unref); - } - return plugin_info; + infos = nm_vpn_plugin_info_list_load (); + info = nm_g_object_ref (_list_find_by_service (infos, name, service)); + g_slist_free_full (infos, g_object_unref); + return info; } /*****************************************************************************/ @@ -557,14 +543,22 @@ nm_vpn_plugin_info_list_find_by_filename (GSList *list, const char *filename) } static NMVpnPluginInfo * -_list_find_by_service (GSList *list, const char *service) +_list_find_by_service (GSList *list, + const char *name, + const char *service) { for (; list; list = list->next) { NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE (list->data); - if ( nm_streq (priv->service, service) - || nm_utils_strv_find_first (priv->aliases, -1, service) >= 0) - return list->data; + if ( name + && !nm_streq (name, priv->name)) + continue; + if ( service + && !nm_streq (priv->service, service) + && (nm_utils_strv_find_first (priv->aliases, -1, service) < 0)) + continue; + + return list->data; } return NULL; } @@ -584,7 +578,7 @@ nm_vpn_plugin_info_list_find_by_service (GSList *list, const char *service) { if (!service) g_return_val_if_reached (NULL); - return _list_find_by_service (list, service); + return _list_find_by_service (list, NULL, service); } /* known_names are well known short names for the service-type. They all implicitly @@ -627,7 +621,7 @@ static const char *known_names[] = { char * nm_vpn_plugin_info_list_find_service_type (GSList *list, const char *name) { - GSList *iter; + NMVpnPluginInfo *info; char *n; if (!name) @@ -636,17 +630,15 @@ nm_vpn_plugin_info_list_find_service_type (GSList *list, const char *name) return NULL; /* First, try to interpret @name as a full service-type (or alias). */ - if (_list_find_by_service (list, name)) + info = _list_find_by_service (list, NULL, name); + if (info) return g_strdup (name); /* try to interpret @name as plugin name, in which case we return * the main service-type (not an alias). */ - for (iter = list; iter; iter = iter->next) { - NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE (iter->data); - - if (nm_streq (priv->name, name)) - return g_strdup (priv->service); - } + info = _list_find_by_service (list, name, NULL); + if (info) + return g_strdup (NM_VPN_PLUGIN_INFO_GET_PRIVATE (info)->service); /* check the hard-coded list of short-names. They all have have the same * well-known prefix org.freedesktop.NetworkManager and the name. */ @@ -656,7 +648,7 @@ nm_vpn_plugin_info_list_find_service_type (GSList *list, const char *name) /* try, if there exists a plugin with @name under org.freedesktop.NetworkManager. * Allow this to be a valid abbreviation. */ n = g_strdup_printf ("%s.%s", NM_DBUS_INTERFACE, name); - if (_list_find_by_service (list, n)) + if (_list_find_by_service (list, NULL, n)) return n; g_free (n); @@ -1163,7 +1155,7 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) priv->aliases = g_key_file_get_string_list (priv->keyfile, NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, "aliases", NULL, NULL); if (priv->aliases && !priv->aliases[0]) - g_clear_pointer (&priv->aliases, g_free); + nm_clear_g_free (&priv->aliases); priv->keys = g_hash_table_new_full (_nm_utils_strstrdictkey_hash, _nm_utils_strstrdictkey_equal, @@ -1184,7 +1176,7 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) } } - g_clear_pointer (&priv->keyfile, g_key_file_unref); + nm_clear_pointer (&priv->keyfile, g_key_file_unref); return TRUE; } @@ -1269,7 +1261,7 @@ finalize (GObject *object) g_free (priv->filename); g_hash_table_unref (priv->keys); - g_clear_pointer (&priv->keyfile, g_key_file_unref); + nm_clear_pointer (&priv->keyfile, g_key_file_unref); G_OBJECT_CLASS (nm_vpn_plugin_info_parent_class)->finalize (object); } @@ -1279,8 +1271,6 @@ nm_vpn_plugin_info_class_init (NMVpnPluginInfoClass *plugin_class) { GObjectClass *object_class = G_OBJECT_CLASS (plugin_class); - g_type_class_add_private (object_class, sizeof (NMVpnPluginInfoPrivate)); - object_class->set_property = set_property; object_class->get_property = get_property; object_class->dispose = dispose; diff --git a/libnm-core/nm-vpn-plugin-info.h b/libnm-core/nm-vpn-plugin-info.h index c6242ac6..bc356cf2 100644 --- a/libnm-core/nm-vpn-plugin-info.h +++ b/libnm-core/nm-vpn-plugin-info.h @@ -29,24 +29,7 @@ G_BEGIN_DECLS #define NM_VPN_PLUGIN_INFO_KF_GROUP_LIBNM "libnm" #define NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME "GNOME" -struct _NMVpnPluginInfo; - -/** - * NMVpnPluginInfo: - */ -struct _NMVpnPluginInfo { - NM_AVAILABLE_IN_1_2 - GObject parent; -}; - -typedef struct { - NM_AVAILABLE_IN_1_2 - GObjectClass parent; - - /*< private >*/ - NM_AVAILABLE_IN_1_2 - gpointer padding[8]; -} NMVpnPluginInfoClass NM_AVAILABLE_IN_1_2; +typedef struct _NMVpnPluginInfoClass NMVpnPluginInfoClass; NM_AVAILABLE_IN_1_2 GType nm_vpn_plugin_info_get_type (void); diff --git a/libnm-core/tests/meson.build b/libnm-core/tests/meson.build index 292eeaa0..58615e4d 100644 --- a/libnm-core/tests/meson.build +++ b/libnm-core/tests/meson.build @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1+ + # test-cert.p12 created with: # # openssl pkcs12 -export \ @@ -16,6 +18,7 @@ enum_sources = gnome.mkenums_simple( ) deps = [ + libnm_keyfile_dep, libnm_core_dep, libnm_core_nm_default_dep, ] diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index 0ccdd5d2..138702e4 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -10,7 +10,6 @@ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> -#include <glib-unix.h> #include "nm-std-aux/c-list-util.h" #include "nm-glib-aux/nm-enum-utils.h" @@ -52,7 +51,7 @@ #include "nm-setting-wireless-security.h" #include "nm-setting-wpan.h" #include "nm-simple-connection.h" -#include "nm-keyfile-internal.h" +#include "nm-keyfile/nm-keyfile-internal.h" #include "nm-glib-aux/nm-dedup-multi.h" #include "nm-libnm-core-intern/nm-ethtool-utils.h" @@ -660,6 +659,333 @@ test_nm_utils_strsplit_set (void) /*****************************************************************************/ +static char * +_escaped_tokens_create_random_word_full (const char *const*tokens, + gsize n_tokens, + gsize len) +{ + GString *gstr = g_string_new (NULL); + gsize i; + char random_token[2] = { 0 }; + + for (i = 0; i < len; i++) { + const char *token = tokens[nmtst_get_rand_uint32 () % n_tokens]; + + if (!token[0]) { + do { + random_token[0] = nmtst_get_rand_uint32 (); + } while (random_token[0] == '\0'); + token = random_token; + } + g_string_append (gstr, token); + } + + /* reallocate the string, so that we don't have any excess memory from + * the GString buffer. This is so that valgrind may better detect an out + * or range access. */ + return nm_str_realloc (g_string_free (gstr, FALSE)); +} + +/* set to 1 to exclude characters that are annoying to see in the debugger + * and printf() output. */ +#define ESCAPED_TOKENS_ONLY_NICE_CHARS 0 + +static char * +_escaped_tokens_create_random_whitespace (void) +{ + static const char *tokens[] = { + " ", +#if !ESCAPED_TOKENS_ONLY_NICE_CHARS + "\n", + "\t", + "\r", + "\f", +#endif + }; + + return _escaped_tokens_create_random_word_full (tokens, G_N_ELEMENTS (tokens), nmtst_get_rand_word_length (NULL) / 4u); +} + +static char * +_escaped_tokens_create_random_word (void) +{ + static const char *tokens[] = { + "a", + "b", + "c", + " ", + ",", + "=", + "\\", +#if !ESCAPED_TOKENS_ONLY_NICE_CHARS + "\n", + "\f", + ":", + "", +#endif + }; + + return _escaped_tokens_create_random_word_full (tokens, G_N_ELEMENTS (tokens), nmtst_get_rand_word_length (NULL)); +} + +static void +_escaped_tokens_str_append_delimiter (GString *str, + gboolean strict, + gboolean needs_delimiter) +{ + guint len = nmtst_get_rand_word_length (NULL) / 10u; + char *s; + +again: + if (!strict) { + g_string_append (str, (s = _escaped_tokens_create_random_whitespace ())); + nm_clear_g_free (&s); + } + + if (needs_delimiter) + g_string_append_c (str, ','); + + if (!strict) { + g_string_append (str, (s = _escaped_tokens_create_random_whitespace ())); + nm_clear_g_free (&s); + if (len-- > 0) { + needs_delimiter = TRUE; + goto again; + } + } +} + +static void +_escaped_tokens_split (char *str, const char **out_key, const char **out_val) +{ + const char *key; + const char *val; + gsize len = strlen (str); + + g_assert (str); + + nm_utils_escaped_tokens_options_split (str, &key, &val); + g_assert (key); + g_assert (key == str); + if (val) { + g_assert (val > str); + g_assert (val > key); + g_assert (val <= &str[len]); + } + NM_SET_OUT (out_key, key); + NM_SET_OUT (out_val, val); +} + +static void +_escaped_tokens_combine (GString *combined, + const char *key, + const char *val, + gboolean strict, + gboolean allow_append_delimiter_before, + gboolean needs_delimiter_after) +{ + gs_free char *escaped_key = NULL; + gs_free char *escaped_val = NULL; + + if (allow_append_delimiter_before) + _escaped_tokens_str_append_delimiter (combined, strict, FALSE); + g_string_append (combined, nm_utils_escaped_tokens_options_escape_key (key, &escaped_key)); + if (val) { + char *s; + + if (!strict) { + g_string_append (combined, (s = _escaped_tokens_create_random_whitespace ())); + nm_clear_g_free (&s); + } + g_string_append_c (combined, '='); + if (!strict) { + g_string_append (combined, (s = _escaped_tokens_create_random_whitespace ())); + nm_clear_g_free (&s); + } + g_string_append (combined, nm_utils_escaped_tokens_options_escape_val (val, &escaped_val)); + } + _escaped_tokens_str_append_delimiter (combined, strict, needs_delimiter_after); +} + +static void +_escaped_tokens_check_one_impl (const char *expected_key, + const char *expected_val, + const char *expected_combination, + const char *const*other, + gsize n_other) +{ + nm_auto_free_gstring GString *combined = g_string_new (NULL); + gsize i; + + g_assert (expected_key); + g_assert (expected_combination); + g_assert (other); + + _escaped_tokens_combine (combined, + expected_key, + expected_val, + TRUE, + TRUE, + FALSE); + + g_assert_cmpstr (combined->str, ==, expected_combination); + + for (i = 0; i < n_other + 2u; i++) { + nm_auto_free_gstring GString *str0 = NULL; + gs_free const char **strv_split = NULL; + gs_free char *strv_split0 = NULL; + const char *comb; + const char *key; + const char *val; + + if (i == 0) + comb = expected_combination; + else if (i == 1) { + _escaped_tokens_combine (nm_gstring_prepare (&str0), + expected_key, + expected_val, + FALSE, + TRUE, + FALSE); + comb = str0->str; + } else + comb = other[i - 2]; + + strv_split = nm_utils_escaped_tokens_options_split_list (comb); + if (!strv_split) { + g_assert_cmpstr (expected_key, ==, ""); + g_assert_cmpstr (expected_val, ==, NULL); + continue; + } + g_assert (expected_val || expected_key[0]); + + g_assert_cmpuint (NM_PTRARRAY_LEN (strv_split), ==, 1u); + + strv_split0 = g_strdup (strv_split[0]); + + _escaped_tokens_split (strv_split0, &key, &val); + g_assert_cmpstr (key, ==, expected_key); + g_assert_cmpstr (val, ==, expected_val); + } +} + +#define _escaped_tokens_check_one(expected_key, expected_val, expected_combination, ...) \ + _escaped_tokens_check_one_impl (expected_key, expected_val, expected_combination, NM_MAKE_STRV (__VA_ARGS__), NM_NARG (__VA_ARGS__)) + +static void +test_nm_utils_escaped_tokens (void) +{ + int i_run; + + for (i_run = 0; i_run < 1000; i_run++) { + const guint num_options = nmtst_get_rand_word_length (NULL); + gs_unref_ptrarray GPtrArray *options = g_ptr_array_new_with_free_func (g_free); + nm_auto_free_gstring GString *combined = g_string_new (NULL); + gs_free const char **strv_split = NULL; + guint i_option; + guint i; + + /* Generate a list of random words for option key-value pairs. */ + for (i_option = 0; i_option < 2u * num_options; i_option++) { + char *word = NULL; + + if ( i_option % 2u == 1 + && nmtst_get_rand_uint32 () % 5 == 0 + && strlen (options->pdata[options->len - 1]) > 0u) { + /* For some options, leave the value unset and only generate a key. + * + * If key is "", then we cannot do that, because the test below would try + * to append "" to the combined list, which the parser then would drop. + * Only test omitting the value, if strlen() of the key is positive. */ + } else + word = _escaped_tokens_create_random_word (); + g_ptr_array_add (options, word); + } + + /* Combine the options in one comma separated list, with proper escaping. */ + for (i_option = 0; i_option < num_options; i_option++) { + _escaped_tokens_combine (combined, + options->pdata[2u*i_option + 0u], + options->pdata[2u*i_option + 1u], + FALSE, + i_option == 0, + i_option != num_options - 1); + } + + /* ensure that we can split and parse the options without difference. */ + strv_split = nm_utils_escaped_tokens_options_split_list (combined->str); + for (i_option = 0; i_option < num_options; i_option++) { + const char *expected_key = options->pdata[2u*i_option + 0u]; + const char *expected_val = options->pdata[2u*i_option + 1u]; + gs_free char *s_split = i_option < NM_PTRARRAY_LEN (strv_split) ? g_strdup (strv_split[i_option]) : NULL; + const char *key = NULL; + const char *val = NULL; + + if (s_split) + _escaped_tokens_split (s_split, &key, &val); + + if ( !nm_streq0 (key, expected_key) + || !nm_streq0 (val, expected_val)) { + g_print (">>> ASSERTION IS ABOUT TO FAIL for item %5d of %5d\n", i_option, num_options); + g_print (">>> combined = \"%s\"\n", combined->str); + g_print (">>> %c parsed[%5d].key = \"%s\"\n", nm_streq (key, expected_key) ? ' ' : 'X', i_option, key); + g_print (">>> %c parsed[%5d].val = %s%s%s\n", nm_streq0 (val, expected_val) ? ' ' : 'X', i_option, NM_PRINT_FMT_QUOTE_STRING (val)); + for (i = 0; i < num_options; i++) { + g_print (">>> %c original[%5d].key = \"%s\"\n", i == i_option ? '*' : ' ', i, (char *) options->pdata[2u*i + 0u]); + g_print (">>> %c original[%5d].val = %s%s%s\n", i == i_option ? '*' : ' ', i, NM_PRINT_FMT_QUOTE_STRING ((char *) options->pdata[2u*i + 1u])); + } + for (i = 0; i < NM_PTRARRAY_LEN (strv_split); i++) + g_print (">>> split[%5d] = \"%s\"\n", i, strv_split[i]); + } + + g_assert_cmpstr (key, ==, expected_key); + g_assert_cmpstr (val, ==, expected_val); + } + g_assert_cmpint (NM_PTRARRAY_LEN (strv_split), ==, num_options); + + /* Above we show a full round-trip of random option key-value pairs, that they can + * without loss escape, concatenate, split-list, and split. This proofed that every + * option key-value pair can be represented as a combined string and parsed back. + * + * Now, just check that we can also parse arbitrary random words in nm_utils_escaped_tokens_options_split(). + * split() is a non-injective surjective function. As we check the round-trip above for random words, where + * options-split() is the last step, we show that every random word can be the output of the function + * (which shows, the surjective part). + * + * But multiple random input arguments, may map to the same output argument (non-injective). + * Just test whether we can handle random input words without crashing. For that, just use the + * above generate list of random words. + */ + for (i = 0; i < 1u + 2u * i_option; i++) { + gs_free char *str = NULL; + const char *cstr; + + if (i == 0) + cstr = combined->str; + else + cstr = options->pdata[i - 1u]; + if (!cstr) + continue; + + str = g_strdup (cstr); + _escaped_tokens_split (str, NULL, NULL); + } + } + + _escaped_tokens_check_one ("", NULL, ""); + _escaped_tokens_check_one ("", "", "=", " ="); + _escaped_tokens_check_one ("a", "b", "a=b", "a = b"); + _escaped_tokens_check_one ("a\\=", "b\\=", "a\\\\\\==b\\\\=", "a\\\\\\==b\\\\\\="); + _escaped_tokens_check_one ("\\=", "\\=", "\\\\\\==\\\\=", "\\\\\\==\\\\\\="); + _escaped_tokens_check_one (" ", "bb=", "\\ =bb=", "\\ =bb\\="); + _escaped_tokens_check_one (" ", "bb\\=", "\\ =bb\\\\=", "\\ =bb\\\\\\="); + _escaped_tokens_check_one ("a b", "a b", "a b=a b"); + _escaped_tokens_check_one ("a b", "a b", "a b=a b"); + _escaped_tokens_check_one ("a = b", "a = b", "a \\= b=a = b", "a \\= b=a \\= b"); +} + +/*****************************************************************************/ + typedef struct { int val; CList lst; @@ -1173,13 +1499,11 @@ test_setting_vpn_items (void) nm_setting_vpn_add_data_item (s_vpn, "", ""); g_test_assert_expected_messages (); - NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (item && item[0])); - nm_setting_vpn_add_data_item (s_vpn, "foobar1", NULL); - g_test_assert_expected_messages (); - - NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (item && item[0])); nm_setting_vpn_add_data_item (s_vpn, "foobar1", ""); - g_test_assert_expected_messages (); + g_assert_cmpstr (nm_setting_vpn_get_data_item (s_vpn, "foobar1"), ==, ""); + + nm_setting_vpn_add_data_item (s_vpn, "foobar1", NULL); + g_assert_cmpstr (nm_setting_vpn_get_data_item (s_vpn, "foobar1"), ==, NULL); NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (key && key[0])); nm_setting_vpn_add_data_item (s_vpn, NULL, "blahblah1"); @@ -1200,13 +1524,9 @@ test_setting_vpn_items (void) nm_setting_vpn_add_secret (s_vpn, "", ""); g_test_assert_expected_messages (); - NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (secret && secret[0])); - nm_setting_vpn_add_secret (s_vpn, "foobar1", NULL); - g_test_assert_expected_messages (); - - NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (secret && secret[0])); nm_setting_vpn_add_secret (s_vpn, "foobar1", ""); - g_test_assert_expected_messages (); + + nm_setting_vpn_add_secret (s_vpn, "foobar1", NULL); NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (key && key[0])); nm_setting_vpn_add_secret (s_vpn, NULL, "blahblah1"); @@ -3494,14 +3814,14 @@ test_setting_compare_addresses (void) nm_ip_address_unref (a); if (nmtst_get_rand_uint32 () % 2) - NMTST_SWAP (s1, s2); + NM_SWAP (s1, s2); success = nm_setting_compare (s1, s2, NM_SETTING_COMPARE_FLAG_EXACT); g_assert (!success); success = nm_setting_diff (s1, s2, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, &result); g_assert (!success); - g_clear_pointer (&result, g_hash_table_unref); + nm_clear_pointer (&result, g_hash_table_unref); } static void @@ -3526,14 +3846,14 @@ test_setting_compare_routes (void) nm_ip_route_unref (r); if (nmtst_get_rand_uint32 () % 2) - NMTST_SWAP (s1, s2); + NM_SWAP (s1, s2); success = nm_setting_compare (s1, s2, NM_SETTING_COMPARE_FLAG_EXACT); g_assert (!success); success = nm_setting_diff (s1, s2, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, &result); g_assert (!success); - g_clear_pointer (&result, g_hash_table_unref); + nm_clear_pointer (&result, g_hash_table_unref); } static void @@ -3551,7 +3871,7 @@ test_setting_compare_wired_cloned_mac_address (void) g_assert_cmpstr ("stable", ==, nm_setting_wired_get_cloned_mac_address ((NMSettingWired *) old)); g_object_get (old, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, &str1, NULL); g_assert_cmpstr ("stable", ==, str1); - g_clear_pointer (&str1, g_free); + nm_clear_g_free (&str1); new = nm_setting_duplicate (old); g_object_set (new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "11:22:33:44:55:66", NULL); @@ -3559,7 +3879,7 @@ test_setting_compare_wired_cloned_mac_address (void) g_assert_cmpstr ("11:22:33:44:55:66", ==, nm_setting_wired_get_cloned_mac_address ((NMSettingWired *) new)); g_object_get (new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, &str1, NULL); g_assert_cmpstr ("11:22:33:44:55:66", ==, str1); - g_clear_pointer (&str1, g_free); + nm_clear_g_free (&str1); success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT); g_assert (!success); @@ -3571,7 +3891,7 @@ test_setting_compare_wired_cloned_mac_address (void) g_assert_cmpstr ("stable-bia", ==, nm_setting_wired_get_cloned_mac_address ((NMSettingWired *) new)); g_object_get (new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, &str1, NULL); g_assert_cmpstr ("stable-bia", ==, str1); - g_clear_pointer (&str1, g_free); + nm_clear_g_free (&str1); success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT); g_assert (!success); @@ -3593,7 +3913,7 @@ test_setting_compare_wireless_cloned_mac_address (void) g_assert_cmpstr ("stable", ==, nm_setting_wireless_get_cloned_mac_address ((NMSettingWireless *) old)); g_object_get (old, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, &str1, NULL); g_assert_cmpstr ("stable", ==, str1); - g_clear_pointer (&str1, g_free); + nm_clear_g_free (&str1); new = nm_setting_duplicate (old); g_object_set (new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "11:22:33:44:55:66", NULL); @@ -3601,7 +3921,7 @@ test_setting_compare_wireless_cloned_mac_address (void) g_assert_cmpstr ("11:22:33:44:55:66", ==, nm_setting_wireless_get_cloned_mac_address ((NMSettingWireless *) new)); g_object_get (new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, &str1, NULL); g_assert_cmpstr ("11:22:33:44:55:66", ==, str1); - g_clear_pointer (&str1, g_free); + nm_clear_g_free (&str1); success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT); g_assert (!success); @@ -4648,7 +4968,7 @@ test_connection_normalize_virtual_iface_name (void) g_variant_unref (setting_dict); g_variant_unref (var); - /* If vlan.interface-name is invalid, deserialization will fail. */ + /* If vlan.interface-name will be ignored. */ NMTST_VARIANT_EDITOR (connection_dict, NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_VLAN_SETTING_NAME, "interface-name", @@ -4657,8 +4977,9 @@ test_connection_normalize_virtual_iface_name (void) ); con = _connection_new_from_dbus (connection_dict, &error); - g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); - g_clear_error (&error); + nmtst_assert_success (con, error); + g_assert_cmpstr (nm_connection_get_interface_name (con), ==, IFACE_NAME); + g_clear_object (&con); /* If vlan.interface-name is valid, but doesn't match, it will be ignored. */ NMTST_VARIANT_EDITOR (connection_dict, @@ -6820,7 +7141,7 @@ _team_config_equal_check (const char *conf1, gboolean is_same; if (nmtst_get_rand_bool ()) - NMTST_SWAP (conf1, conf2); + NM_SWAP (conf1, conf2); if (!nm_streq0 (conf1, conf2)) { _team_config_equal_check (conf1, conf1, port_config, TRUE); @@ -7545,10 +7866,11 @@ _do_test_utils_str_utf8safe (const char *str, gsize str_len, const char *expecte gs_free char *str_free_7 = NULL; gs_free char *str_free_8 = NULL; gboolean str_has_nul = FALSE; +#define RND_FLAG ((nmtst_get_rand_bool ()) ? NM_UTILS_STR_UTF8_SAFE_FLAG_NONE : NM_UTILS_STR_UTF8_SAFE_FLAG_SECRET) - buf_safe = nm_utils_buf_utf8safe_escape (str, str_len, flags, &str_free_1); + buf_safe = nm_utils_buf_utf8safe_escape (str, str_len, flags | RND_FLAG, &str_free_1); - str_safe = nm_utils_str_utf8safe_escape (str, flags, &str_free_2); + str_safe = nm_utils_str_utf8safe_escape (str, flags | RND_FLAG, &str_free_2); if (str_len == 0) { g_assert (buf_safe == NULL); @@ -7568,7 +7890,7 @@ _do_test_utils_str_utf8safe (const char *str, gsize str_len, const char *expecte } else str_has_nul = TRUE; - str_free_3 = nm_utils_str_utf8safe_escape_cp (str, flags); + str_free_3 = nm_utils_str_utf8safe_escape_cp (str, flags | RND_FLAG); g_assert_cmpstr (str_free_3, ==, str_safe); g_assert ((!str && !str_free_3) || (str != str_free_3)); @@ -8201,8 +8523,12 @@ _test_integrate_cb_idle_2 (gpointer user_data) g_assert (d->extra_sources[0]); g_assert (!d->extra_sources[1]); - extra_source = g_unix_fd_source_new (d->fd_2, G_IO_IN); - g_source_set_callback (extra_source, G_SOURCE_FUNC (_test_integrate_cb_fd_2), d, NULL); + extra_source = nm_g_unix_fd_source_new (d->fd_2, + G_IO_IN, + G_PRIORITY_DEFAULT, + _test_integrate_cb_fd_2, + d, + NULL); g_source_attach (extra_source, d->c2); d->extra_sources[1] = extra_source; @@ -8269,7 +8595,7 @@ test_integrate_maincontext (gconstpointer test_data) g_source_set_callback (idle_source_1, _test_integrate_maincontext_cb_idle1, &count, NULL); g_source_attach (idle_source_1, c2); - nmtst_main_context_iterate_until (c1, 2000, count == 5); + nmtst_main_context_iterate_until_assert (c1, 2000, count == 5); } if (TEST_IDX == 2) { @@ -8296,8 +8622,12 @@ test_integrate_maincontext (gconstpointer test_data) fd_1 = open ("/dev/null", O_RDONLY | O_CLOEXEC); g_assert (fd_1 >= 0); - fd_source_1 = g_unix_fd_source_new (fd_1, G_IO_IN); - g_source_set_callback (fd_source_1, G_SOURCE_FUNC (_test_integrate_cb_fd_1), &d, NULL); + fd_source_1 = nm_g_unix_fd_source_new (fd_1, + G_IO_IN, + G_PRIORITY_DEFAULT, + _test_integrate_cb_fd_1, + &d, + NULL); g_source_attach (fd_source_1, c2); fd_2 = open ("/dev/null", O_RDONLY | O_CLOEXEC); @@ -8321,6 +8651,33 @@ test_integrate_maincontext (gconstpointer test_data) } } +/*****************************************************************************/ + +static void +test_nm_ip_addr_zero (void) +{ + in_addr_t a4 = nmtst_inet4_from_string ("0.0.0.0"); + struct in6_addr a6 = *nmtst_inet6_from_string ("::"); + char buf[NM_UTILS_INET_ADDRSTRLEN]; + NMIPAddr a = NM_IP_ADDR_INIT; + + g_assert (memcmp (&a, &nm_ip_addr_zero, sizeof (a)) == 0); + + g_assert (IN6_IS_ADDR_UNSPECIFIED (&nm_ip_addr_zero.addr6)); + g_assert (memcmp (&nm_ip_addr_zero.addr6, &in6addr_any, sizeof (in6addr_any)) == 0); + + g_assert (memcmp (&nm_ip_addr_zero, &a4, sizeof (a4)) == 0); + g_assert (memcmp (&nm_ip_addr_zero, &a6, sizeof (a6)) == 0); + + g_assert_cmpstr (_nm_utils_inet4_ntop (nm_ip_addr_zero.addr4, buf), ==, "0.0.0.0"); + g_assert_cmpstr (_nm_utils_inet6_ntop (&nm_ip_addr_zero.addr6, buf), ==, "::"); + + g_assert_cmpstr (nm_utils_inet_ntop (AF_INET, &nm_ip_addr_zero, buf), ==, "0.0.0.0"); + g_assert_cmpstr (nm_utils_inet_ntop (AF_INET6, &nm_ip_addr_zero, buf), ==, "::"); + + G_STATIC_ASSERT_EXPR (sizeof (a) == sizeof (a.array)); +} + static void test_connection_ovs_ifname (gconstpointer test_data) { @@ -8523,6 +8880,7 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/test_dedup_multi", test_dedup_multi); g_test_add_func ("/core/general/test_utils_str_utf8safe", test_utils_str_utf8safe); g_test_add_func ("/core/general/test_nm_utils_strsplit_set", test_nm_utils_strsplit_set); + g_test_add_func ("/core/general/test_nm_utils_escaped_tokens", test_nm_utils_escaped_tokens); g_test_add_func ("/core/general/test_nm_in_set", test_nm_in_set); g_test_add_func ("/core/general/test_nm_in_strset", test_nm_in_strset); g_test_add_func ("/core/general/test_setting_vpn_items", test_setting_vpn_items); @@ -8681,5 +9039,7 @@ int main (int argc, char **argv) g_test_add_data_func ("/core/general/test_integrate_maincontext/1", GUINT_TO_POINTER (1), test_integrate_maincontext); g_test_add_data_func ("/core/general/test_integrate_maincontext/2", GUINT_TO_POINTER (2), test_integrate_maincontext); + g_test_add_func ("/core/general/test_nm_ip_addr_zero", test_nm_ip_addr_zero); + return g_test_run (); } diff --git a/libnm-core/tests/test-keyfile.c b/libnm-core/tests/test-keyfile.c index 574d671f..47a27571 100644 --- a/libnm-core/tests/test-keyfile.c +++ b/libnm-core/tests/test-keyfile.c @@ -5,8 +5,8 @@ #include "nm-default.h" -#include "nm-keyfile-utils.h" -#include "nm-keyfile-internal.h" +#include "nm-keyfile/nm-keyfile-utils.h" +#include "nm-keyfile/nm-keyfile-internal.h" #include "nm-simple-connection.h" #include "nm-setting-connection.h" #include "nm-setting-wired.h" @@ -99,7 +99,7 @@ test_encode_key (void) GKeyFile **_keyfile = (keyfile); \ \ g_clear_object (_con); \ - g_clear_pointer (_keyfile, g_key_file_unref); \ + nm_clear_pointer (_keyfile, g_key_file_unref); \ } G_STMT_END static void diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c index 5b2c7077..cb8f41fb 100644 --- a/libnm-core/tests/test-setting.c +++ b/libnm-core/tests/test-setting.c @@ -24,7 +24,7 @@ #include "nm-simple-connection.h" #include "nm-setting-connection.h" #include "nm-errors.h" -#include "nm-keyfile-internal.h" +#include "nm-keyfile/nm-keyfile-internal.h" #include "nm-utils/nm-test-utils.h" @@ -500,8 +500,6 @@ create_bond_connection (NMConnection **con, NMSettingBond **s_bond) NULL, NM_SETTING_BOND_SETTING_NAME, &s_con); - g_assert (*con); - g_assert (s_con); g_object_set (s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "bond0", NULL); @@ -512,28 +510,25 @@ create_bond_connection (NMConnection **con, NMSettingBond **s_bond) } #define test_verify_options(exp, ...) \ - _test_verify_options (NM_MAKE_STRV (__VA_ARGS__), exp) + _test_verify_options (exp, NM_MAKE_STRV (__VA_ARGS__)) static void -_test_verify_options (const char *const *options, - gboolean expected_result) +_test_verify_options (gboolean expected_result, + const char *const *options) { gs_unref_object NMConnection *con = NULL; NMSettingBond *s_bond; - GError *error = NULL; - gboolean success; const char *const *option; + g_assert (NM_PTRARRAY_LEN (options) % 2 == 0); + create_bond_connection (&con, &s_bond); - for (option = options; option[0] && option[1]; option += 2) + for (option = options; option[0]; option += 2) g_assert (nm_setting_bond_add_option (s_bond, option[0], option[1])); if (expected_result) { nmtst_assert_connection_verifies_and_normalizable (con); - nmtst_connection_normalize (con); - success = nm_setting_verify ((NMSetting *) s_bond, con, &error); - nmtst_assert_success (success, error); } else { nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, @@ -595,6 +590,16 @@ test_bond_verify (void) "mode", "0", "downdelay", "0", "updelay", "0"); + test_verify_options (TRUE, + "mode", "0", + "miimon", "100", + "arp_ip_target", "1.1.1.1", + "arp_interval", "200"); + test_verify_options (TRUE, + "mode", "0", + "downdelay", "100", + "arp_ip_target", "1.1.1.1", + "arp_interval", "200"); } static void @@ -631,21 +636,23 @@ test_bond_compare (void) ((const char *[]){ "mode", "balance-rr", "miimon", "1", NULL }), ((const char *[]){ "mode", "balance-rr", "miimon", "2", NULL })); - /* ignore default values */ - test_bond_compare_options (TRUE, + test_bond_compare_options (FALSE, ((const char *[]){ "miimon", "1", NULL }), ((const char *[]){ "miimon", "1", "updelay", "0", NULL })); - /* special handling of num_grat_arp, num_unsol_na */ test_bond_compare_options (FALSE, ((const char *[]){ "num_grat_arp", "2", NULL }), ((const char *[]){ "num_grat_arp", "1", NULL })); - test_bond_compare_options (TRUE, + test_bond_compare_options (FALSE, ((const char *[]){ "num_grat_arp", "3", NULL }), ((const char *[]){ "num_unsol_na", "3", NULL })); - test_bond_compare_options (TRUE, + test_bond_compare_options (FALSE, ((const char *[]){ "num_grat_arp", "4", NULL }), ((const char *[]){ "num_unsol_na", "4", "num_grat_arp", "4", NULL })); + + test_bond_compare_options (FALSE, + ((const char *[]){ "mode", "balance-rr", "miimon", "100", NULL }), + ((const char *[]){ "mode", "balance-rr", NULL })); } static void @@ -1840,7 +1847,7 @@ test_bridge_vlans (void) str = nm_bridge_vlan_to_str (v1, &error); nmtst_assert_success (str, error); g_assert_cmpstr (str, ==, "10 pvid"); - g_clear_pointer (&str, g_free); + nm_clear_g_free (&str); v2 = nm_bridge_vlan_from_str (" 10 pvid ", &error); nmtst_assert_success (v2, error); @@ -1862,6 +1869,137 @@ test_bridge_vlans (void) nm_bridge_vlan_unref (v2); } +static void +create_bridge_connection (NMConnection **con, NMSettingBridge **s_bridge) +{ + NMSettingConnection *s_con; + + g_assert (con); + g_assert (s_bridge); + + *con = nmtst_create_minimal_connection ("bridge", + NULL, + NM_SETTING_BOND_SETTING_NAME, + &s_con); + + g_object_set (s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "bridge0", NULL); + + *s_bridge = (NMSettingBridge *) nm_setting_bridge_new (); + g_assert (*s_bridge); + + nm_connection_add_setting (*con, NM_SETTING (*s_bridge)); +} + +#define test_verify_options_bridge(exp, ...) \ + _test_verify_options_bridge (exp, NM_MAKE_STRV (__VA_ARGS__)) + +static void +_test_verify_options_bridge (gboolean expected_result, + const char *const *options) +{ + gs_unref_object NMConnection *con = NULL; + NMSettingBridge *s_bridge; + const char *const *option; + + g_assert (NM_PTRARRAY_LEN (options) % 2 == 0); + + create_bridge_connection (&con, &s_bridge); + + for (option = options; option[0]; option += 2) { + const char *option_key = option[0]; + const char *option_val = option[1]; + GParamSpec *pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (s_bridge), option_key); + + g_assert (pspec); + g_assert (option_val); + + switch (G_PARAM_SPEC_VALUE_TYPE (pspec)) { + case G_TYPE_UINT: { + guint uvalue; + + uvalue = _nm_utils_ascii_str_to_uint64 (option_val, 10, 0, G_MAXUINT, 0); + g_object_set (s_bridge, option_key, uvalue, NULL); + } + break; + case G_TYPE_BOOLEAN: { + gboolean bvalue; + + bvalue = _nm_utils_ascii_str_to_bool (option_val, FALSE); + g_object_set (s_bridge, option_key, bvalue, NULL); + } + break; + case G_TYPE_STRING: + g_object_set (s_bridge, option_key, option_val, NULL); + break; + default: + g_assert_not_reached(); + break; + } + } + + if (expected_result) + nmtst_assert_connection_verifies_and_normalizable (con); + else { + nmtst_assert_connection_unnormalizable (con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + } +} + +static void +test_bridge_verify (void) +{ + /* group-address */ + test_verify_options_bridge (FALSE, + "group-address", "nonsense"); + test_verify_options_bridge (FALSE, + "group-address", "FF:FF:FF:FF:FF:FF"); + test_verify_options_bridge (FALSE, + "group-address", "01:02:03:04:05:06"); + test_verify_options_bridge (TRUE, + "group-address", "01:80:C2:00:00:00"); + test_verify_options_bridge (FALSE, + "group-address", "01:80:C2:00:00:02"); + test_verify_options_bridge (FALSE, + "group-address", "01:80:C2:00:00:03"); + test_verify_options_bridge (TRUE, + "group-address", "01:80:C2:00:00:00"); + test_verify_options_bridge (TRUE, + "group-address", "01:80:C2:00:00:0A"); + /* vlan-protocol */ + test_verify_options_bridge (FALSE, + "vlan-protocol", "nonsense124"); + test_verify_options_bridge (FALSE, + "vlan-protocol", "802.11"); + test_verify_options_bridge (FALSE, + "vlan-protocol", "802.1Q1"); + test_verify_options_bridge (TRUE, + "vlan-protocol", "802.1Q"); + test_verify_options_bridge (TRUE, + "vlan-protocol", "802.1ad"); + /* multicast-router */ + test_verify_options_bridge (FALSE, + "multicast-router", "nonsense"); + test_verify_options_bridge (FALSE, + "multicast-snooping", "no", + "multicast-router", "auto"); + test_verify_options_bridge (FALSE, + "multicast-snooping", "no", + "multicast-router", "enabled"); + test_verify_options_bridge (TRUE, + "multicast-snooping", "no", + "multicast-router", "disabled"); + test_verify_options_bridge (TRUE, + "multicast-snooping", "yes", + "multicast-router", "enabled"); + test_verify_options_bridge (TRUE, + "multicast-snooping", "yes", + "multicast-router", "auto"); + test_verify_options_bridge (TRUE, + "multicast-snooping", "yes", + "multicast-router", "disabled"); +} + /*****************************************************************************/ static void @@ -3641,6 +3779,7 @@ main (int argc, char **argv) g_test_add_func ("/libnm/settings/tc_config/dbus", test_tc_config_dbus); g_test_add_func ("/libnm/settings/bridge/vlans", test_bridge_vlans); + g_test_add_func ("/libnm/settings/bridge/verify", test_bridge_verify); g_test_add_func ("/libnm/settings/team/sync_runner_from_config_roundrobin", test_runner_roundrobin_sync_from_config); |