diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c index 3112e2748d..949a9e3d08 100644 --- a/libnm-core/nm-setting-ip-config.c +++ b/libnm-core/nm-setting-ip-config.c @@ -1424,9 +1424,33 @@ nm_setting_ip_config_clear_dns_searches (NMSettingIPConfig *setting) guint nm_setting_ip_config_get_num_dns_options (NMSettingIPConfig *setting) { + NMSettingIPConfigPrivate *priv; + g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0); - return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->dns_options->len; + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); + + return priv->dns_options ? priv->dns_options->len : 0; +} + +/** + * nm_setting_ip_config_has_dns_options: + * @setting: the #NMSettingIPConfig + * + * NMSettingIPConfig can have a list of dns-options. If the list + * is empty, there are two similar (but differentiated) states. + * Either the options are explicitly set to have no values, + * or the options are left undefined. The latter means to use + * a default configuration, while the former explicitly means "no-options". + * + * Returns: whether DNS options are initalized or left unset (the default). + **/ +gboolean +nm_setting_ip_config_has_dns_options (NMSettingIPConfig *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0); + + return !!NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->dns_options; } /** @@ -1446,6 +1470,7 @@ nm_setting_ip_config_get_dns_option (NMSettingIPConfig *setting, guint idx) g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); + g_return_val_if_fail (priv->dns_options, NULL); g_return_val_if_fail (idx < priv->dns_options->len, NULL); return priv->dns_options->pdata[idx]; @@ -1470,6 +1495,9 @@ nm_setting_ip_config_next_valid_dns_option (NMSettingIPConfig *setting, guint id priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); + if (!priv->dns_options) + return -1; + for (; idx < priv->dns_options->len; idx++) { if (_nm_utils_dns_option_validate (priv->dns_options->pdata[idx], NULL, NULL, NM_IS_SETTING_IP6_CONFIG (setting), @@ -1505,8 +1533,12 @@ nm_setting_ip_config_add_dns_option (NMSettingIPConfig *setting, return FALSE; priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); - if (_nm_utils_dns_option_find_idx (priv->dns_options, dns_option) >= 0) - return FALSE; + if (!priv->dns_options) + priv->dns_options = g_ptr_array_new_with_free_func (g_free); + else { + if (_nm_utils_dns_option_find_idx (priv->dns_options, dns_option) >= 0) + return FALSE; + } g_ptr_array_add (priv->dns_options, g_strdup (dns_option)); g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_OPTIONS); @@ -1530,6 +1562,7 @@ nm_setting_ip_config_remove_dns_option (NMSettingIPConfig *setting, int idx) g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting)); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); + g_return_if_fail (priv->dns_options); g_return_if_fail (idx < priv->dns_options->len); g_ptr_array_remove_index (priv->dns_options, idx); @@ -1559,6 +1592,9 @@ nm_setting_ip_config_remove_dns_option_by_value (NMSettingIPConfig *setting, g_return_val_if_fail (dns_option[0] != '\0', FALSE); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); + if (!priv->dns_options) + return FALSE; + i = _nm_utils_dns_option_find_idx (priv->dns_options, dns_option); if (i >= 0) { g_ptr_array_remove_index (priv->dns_options, i); @@ -1572,20 +1608,35 @@ nm_setting_ip_config_remove_dns_option_by_value (NMSettingIPConfig *setting, /** * nm_setting_ip_config_clear_dns_options: * @setting: the #NMSettingIPConfig + * @is_set: the dns-options can be either empty or unset (default). + * Specify how to clear the options. * * Removes all configured DNS options. * * Since: 1.2 **/ void -nm_setting_ip_config_clear_dns_options (NMSettingIPConfig *setting) +nm_setting_ip_config_clear_dns_options (NMSettingIPConfig *setting, gboolean is_set) { NMSettingIPConfigPrivate *priv; g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting)); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); - g_ptr_array_set_size (priv->dns_options, 0); + if (!priv->dns_options) { + if (!is_set) + return; + priv->dns_options = g_ptr_array_new_with_free_func (g_free); + } else { + if (!is_set) { + g_ptr_array_unref (priv->dns_options); + priv->dns_options = NULL; + } else { + if (priv->dns_options->len == 0) + return; + g_ptr_array_set_size (priv->dns_options, 0); + } + } g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_OPTIONS); } @@ -2155,7 +2206,7 @@ nm_setting_ip_config_init (NMSettingIPConfig *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 = 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); } @@ -2172,7 +2223,8 @@ finalize (GObject *object) g_ptr_array_unref (priv->dns); g_ptr_array_unref (priv->dns_search); - g_ptr_array_unref (priv->dns_options); + if (priv->dns_options) + g_ptr_array_unref (priv->dns_options); g_ptr_array_unref (priv->addresses); g_ptr_array_unref (priv->routes); @@ -2204,12 +2256,21 @@ set_property (GObject *object, guint prop_id, break; case PROP_DNS_OPTIONS: strv = g_value_get_boxed (value); - g_ptr_array_unref (priv->dns_options); - priv->dns_options = g_ptr_array_new_with_free_func (g_free); - for (i = 0; strv && strv[i]; i++) { - if ( _nm_utils_dns_option_validate (strv[i], NULL, NULL, FALSE, NULL) - && _nm_utils_dns_option_find_idx (priv->dns_options, strv[i]) < 0) - g_ptr_array_add (priv->dns_options, g_strdup (strv[i])); + if (!strv) { + if (priv->dns_options) { + g_ptr_array_unref (priv->dns_options); + priv->dns_options = NULL; + } + } else { + if (priv->dns_options) + g_ptr_array_set_size (priv->dns_options, 0); + else + priv->dns_options = g_ptr_array_new_with_free_func (g_free); + for (i = 0; strv[i]; i++) { + if ( _nm_utils_dns_option_validate (strv[i], NULL, NULL, FALSE, NULL) + && _nm_utils_dns_option_find_idx (priv->dns_options, strv[i]) < 0) + g_ptr_array_add (priv->dns_options, g_strdup (strv[i])); + } } break; case PROP_ADDRESSES: @@ -2276,7 +2337,7 @@ get_property (GObject *object, guint prop_id, g_value_take_boxed (value, _nm_utils_ptrarray_to_strv (priv->dns_search)); break; case PROP_DNS_OPTIONS: - g_value_take_boxed (value, _nm_utils_ptrarray_to_strv (priv->dns_options)); + g_value_take_boxed (value, priv->dns_options ? _nm_utils_ptrarray_to_strv (priv->dns_options) : NULL); break; case PROP_ADDRESSES: g_value_take_boxed (value, _nm_utils_copy_array (priv->addresses, @@ -2402,6 +2463,10 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) * * Array of DNS options. * + * %NULL means that the options are unset and left at the default. + * In this case NetworkManager will use default options. This is + * distinct from an empty list of properties. + * * Since: 1.2 **/ g_object_class_install_property diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h index b150a3178d..6e8c02021a 100644 --- a/libnm-core/nm-setting-ip-config.h +++ b/libnm-core/nm-setting-ip-config.h @@ -198,6 +198,7 @@ gboolean nm_setting_ip_config_remove_dns_search_by_value (NMSettingIPConfig void nm_setting_ip_config_clear_dns_searches (NMSettingIPConfig *setting); guint nm_setting_ip_config_get_num_dns_options (NMSettingIPConfig *setting); +gboolean nm_setting_ip_config_has_dns_options (NMSettingIPConfig *setting); const char *nm_setting_ip_config_get_dns_option (NMSettingIPConfig *setting, guint idx); gint nm_setting_ip_config_next_valid_dns_option (NMSettingIPConfig *setting, @@ -208,7 +209,7 @@ void nm_setting_ip_config_remove_dns_option (NMSettingIPConfig int idx); gboolean nm_setting_ip_config_remove_dns_option_by_value (NMSettingIPConfig *setting, const char *dns_option); -void nm_setting_ip_config_clear_dns_options (NMSettingIPConfig *setting); +void nm_setting_ip_config_clear_dns_options (NMSettingIPConfig *setting, gboolean is_set); guint nm_setting_ip_config_get_num_addresses (NMSettingIPConfig *setting); NMIPAddress *nm_setting_ip_config_get_address (NMSettingIPConfig *setting, diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 7245ea7af8..c15f0381c0 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -855,6 +855,7 @@ global: nm_setting_ip_config_clear_dns_options; nm_setting_ip_config_get_dns_option; nm_setting_ip_config_get_num_dns_options; + nm_setting_ip_config_has_dns_options; nm_setting_ip_config_remove_dns_option; nm_setting_ip_config_remove_dns_option_by_value; nm_setting_wireless_get_powersave; diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index b1c50fef8e..77021d69a6 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -2635,11 +2635,11 @@ test_write_dns_options (void) unlink (testfile); /* RES_OPTIONS is copied to both IPv4 and IPv6 settings */ - nm_setting_ip_config_clear_dns_options (s_ip4); + nm_setting_ip_config_clear_dns_options (s_ip4, TRUE); nm_setting_ip_config_add_dns_option (s_ip4, "debug"); nm_setting_ip_config_add_dns_option (s_ip4, "timeout:3"); - nm_setting_ip_config_clear_dns_options (s_ip6); + nm_setting_ip_config_clear_dns_options (s_ip6, TRUE); nm_setting_ip_config_add_dns_option (s_ip6, "debug"); nm_setting_ip_config_add_dns_option (s_ip6, "timeout:3");