diff options
Diffstat (limited to 'src/core/settings/plugins')
10 files changed, 158 insertions, 63 deletions
diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c index eb0d733d..0a385247 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c @@ -52,7 +52,6 @@ typedef struct { GHashTable *unmanaged_specs; GHashTable *unrecognized_specs; - } NMSIfcfgRHPluginPrivate; struct _NMSIfcfgRHPlugin { @@ -177,6 +176,7 @@ nm_assert_self(NMSIfcfgRHPlugin *self, gboolean unhandled_specs_consistent) static NMSIfcfgRHStorage * _load_file(NMSIfcfgRHPlugin *self, const char *filename, GError **error) { + NMSIfcfgRHStorage *ret = NULL; gs_unref_object NMConnection *connection = NULL; gs_free_error GError *load_error = NULL; gs_free char *unhandled_spec = NULL; @@ -224,16 +224,16 @@ _load_file(NMSIfcfgRHPlugin *self, const char *filename, GError **error) nm_assert_not_reached(); return NULL; } - return nms_ifcfg_rh_storage_new_unhandled(self, + + ret = nms_ifcfg_rh_storage_new_unhandled(self, filename, unmanaged_spec, unrecognized_spec); + } else { + ret = nms_ifcfg_rh_storage_new_connection(self, filename, - unmanaged_spec, - unrecognized_spec); + g_steal_pointer(&connection), + &st.st_mtim); } - return nms_ifcfg_rh_storage_new_connection(self, - filename, - g_steal_pointer(&connection), - &st.st_mtim); + return ret; } static void diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index 6cfb5705..84a9479d 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -917,7 +917,7 @@ enum { * @options_route: (in-out): when line is from the OPTIONS setting, this is a pre-created * route object that is completed with the settings from options. Otherwise, * it shall point to %NULL and a new route is created and returned. - * @out_route: (out) (transfer-full) (allow-none): the parsed %NMIPRoute instance. + * @out_route: (out) (transfer full) (optional): the parsed %NMIPRoute instance. * In case a @options_route is passed in, it returns the input route that was modified * in-place. But the caller must unref the returned route in either case. * @error: the failure description. @@ -2481,6 +2481,11 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea g_object_set(s_ip6, NM_SETTING_IP_CONFIG_DHCP_IAID, v, NULL); nm_clear_g_free(&value); + v = svGetValueStr(ifcfg, "DHCPV6_PD_HINT", &value); + if (v) + g_object_set(s_ip6, NM_SETTING_IP6_CONFIG_DHCP_PD_HINT, v, NULL); + + nm_clear_g_free(&value); v = svGetValueStr(ifcfg, "DHCPV6_HOSTNAME", &value); /* Use DHCP_HOSTNAME as fallback if it is in FQDN format and ipv6.method is * auto or dhcp: this is required to support old ifcfg files @@ -2591,7 +2596,7 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea &local)) { PARSE_WARNING("%s", local->message); g_clear_error(&local); - } else if (errno == ENOENT) { + } else if (errno == ENOKEY) { /* The key is not specified. If "v" (IPV6_TOKEN) is set, * we default to EUI64. Otherwise, the connection would not verify. */ if (v) @@ -2683,16 +2688,25 @@ make_hostname_setting(shvarFile *ifcfg) NMTernary from_dns_lookup; NMTernary only_from_default; int priority; + gboolean has_setting = FALSE; priority = svGetValueInt64(ifcfg, "HOSTNAME_PRIORITY", 10, G_MININT32, G_MAXINT32, 0); + if (!has_setting && errno != ENOKEY) + has_setting = TRUE; + + from_dhcp = svGetValueTernary(ifcfg, "HOSTNAME_FROM_DHCP"); + if (!has_setting && errno != ENOKEY) + has_setting = TRUE; + + from_dns_lookup = svGetValueTernary(ifcfg, "HOSTNAME_FROM_DNS_LOOKUP"); + if (!has_setting && errno != ENOKEY) + has_setting = TRUE; - from_dhcp = svGetValueTernary(ifcfg, "HOSTNAME_FROM_DHCP"); - from_dns_lookup = svGetValueTernary(ifcfg, "HOSTNAME_FROM_DNS_LOOKUP"); only_from_default = svGetValueTernary(ifcfg, "HOSTNAME_ONLY_FROM_DEFAULT"); + if (!has_setting && errno != ENOKEY) + has_setting = TRUE; - /* Create the setting when at least one key is not default*/ - if (priority == 0 && from_dhcp == NM_TERNARY_DEFAULT && from_dns_lookup == NM_TERNARY_DEFAULT - && only_from_default == NM_TERNARY_DEFAULT) + if (!has_setting) return NULL; setting = nm_setting_hostname_new(); diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c index 207b8700..50e352d3 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c @@ -881,6 +881,7 @@ const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = { _KEY_TYPE("DHCPV6_HOSTNAME", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("DHCPV6_HOSTNAME_FLAGS", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("DHCPV6_IAID", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("DHCPV6_PD_HINT", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("DHCPV6_SEND_HOSTNAME", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("DHCP_CLIENT_ID", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("DHCP_FQDN", NMS_IFCFG_KEY_TYPE_IS_PLAIN), diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h index 51b118e3..eb9e418a 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h @@ -33,7 +33,7 @@ typedef struct { NMSIfcfgKeyTypeFlags key_flags; } NMSIfcfgKeyTypeInfo; -extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[263]; +extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[264]; const NMSIfcfgKeyTypeInfo *nms_ifcfg_well_known_key_find_info(const char *key, gssize *out_idx); diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index 97637063..08deaf5a 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -62,6 +62,24 @@ /*****************************************************************************/ static void +set_error_unsupported(GError **error, + NMConnection *connection, + const char *name, + gboolean is_setting) +{ + g_set_error(error, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_NOT_SUPPORTED_BY_PLUGIN, + "The ifcfg-rh plugin doesn't support %s '%s'. If you are modifying an existing " + "connection profile saved in ifcfg-rh format, please migrate the connection to " + "keyfile using 'nmcli connection migrate %s' or via the Update2() D-Bus API " + "and try again.", + is_setting ? "setting" : "property", + name, + nm_connection_get_uuid(connection)); +}; + +static void save_secret_flags(shvarFile *ifcfg, const char *key, NMSettingSecretFlags flags) { GString *str; @@ -3100,6 +3118,9 @@ write_ip6_setting(NMConnection *connection, shvarFile *ifcfg, GString **out_rout "DHCPV6_DUID", nm_setting_ip6_config_get_dhcp_duid(NM_SETTING_IP6_CONFIG(s_ip6))); svSetValueStr(ifcfg, "DHCPV6_IAID", nm_setting_ip_config_get_dhcp_iaid(s_ip6)); + svSetValueStr(ifcfg, + "DHCPV6_PD_HINT", + nm_setting_ip6_config_get_dhcp_pd_hint(NM_SETTING_IP6_CONFIG(s_ip6))); hostname = nm_setting_ip_config_get_dhcp_hostname(s_ip6); svSetValueStr(ifcfg, "DHCPV6_HOSTNAME", hostname); @@ -3485,6 +3506,11 @@ do_write_construct(NMConnection *connection, write_sriov_setting(connection, ifcfg); write_tc_setting(connection, ifcfg); + if (_nm_connection_get_setting(connection, NM_TYPE_SETTING_LINK)) { + set_error_unsupported(error, connection, "link", TRUE); + return FALSE; + } + route_path_is_svformat = utils_has_route_file_new_syntax(route_path); has_complex_routes_v4 = utils_has_complex_routes(ifcfg_name, AF_INET); diff --git a/src/core/settings/plugins/ifcfg-rh/shvar.c b/src/core/settings/plugins/ifcfg-rh/shvar.c index fe8187c3..1ca2ea60 100644 --- a/src/core/settings/plugins/ifcfg-rh/shvar.c +++ b/src/core/settings/plugins/ifcfg-rh/shvar.c @@ -97,23 +97,32 @@ static void _line_link_parse(shvarFile *s, const char *value, gsize len); * in case no valid value is found, the fallback value. Valid values * are: "yes", "true", "t", "y", "1" and "no", "false", "f", "n", "0". * + * Always sets errno. Either to zero on success, to ENOKEY for NULL + * or to EINVAL otherwise. + * * Returns: the parsed boolean value or @fallback. */ int svParseBoolean(const char *value, int fallback) { - if (!value) + if (!value) { + errno = ENOKEY; return fallback; + } if (!g_ascii_strcasecmp("yes", value) || !g_ascii_strcasecmp("true", value) || !g_ascii_strcasecmp("t", value) || !g_ascii_strcasecmp("y", value) - || !g_ascii_strcasecmp("1", value)) + || !g_ascii_strcasecmp("1", value)) { + errno = 0; return TRUE; - else if (!g_ascii_strcasecmp("no", value) || !g_ascii_strcasecmp("false", value) - || !g_ascii_strcasecmp("f", value) || !g_ascii_strcasecmp("n", value) - || !g_ascii_strcasecmp("0", value)) + } else if (!g_ascii_strcasecmp("no", value) || !g_ascii_strcasecmp("false", value) + || !g_ascii_strcasecmp("f", value) || !g_ascii_strcasecmp("n", value) + || !g_ascii_strcasecmp("0", value)) { + errno = 0; return FALSE; + } + errno = EINVAL; return fallback; } @@ -1253,6 +1262,7 @@ svGetValueStr_cp(shvarFile *s, const char *key) * @fallback: the fallback value in any error case * * Reads a value @key and converts it to a boolean using svParseBoolean(). + * This always sets errno, see svParseBoolean(). * * Returns: the parsed boolean value or @fallback. */ @@ -1271,6 +1281,7 @@ svGetValueBoolean(shvarFile *s, const char *key, int fallback) * @key: the name of the key to read * * Reads a value @key and converts it to a NMTernary value. + * This always sets errno, see svParseBoolean(). * * Returns: the parsed NMTernary */ @@ -1328,7 +1339,7 @@ svGetValueEnum(shvarFile *s, const char *key, GType gtype, int *out_value, GErro if (!svalue) { /* don't touch out_value. The caller is supposed * to initialize it with the default value. */ - errno = ENOENT; + errno = ENOKEY; return TRUE; } diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c index 1d7de8d2..1679cab6 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c @@ -891,6 +891,7 @@ nms_keyfile_plugin_update_connection(NMSKeyfilePlugin *self, gboolean reread_same; const char *uuid; char strbuf[100]; + NMTernary force_rename2; _nm_assert_storage(self, storage, TRUE); nm_assert(NM_IS_CONNECTION(connection)); @@ -910,6 +911,20 @@ nms_keyfile_plugin_update_connection(NMSKeyfilePlugin *self, previous_filename = nms_keyfile_storage_get_filename(storage); uuid = nms_keyfile_storage_get_uuid(storage); + if (force_rename) + force_rename2 = NM_TERNARY_TRUE; + else { + /* If the caller does not force a rename, we honor [keyfile].rename + * setting, and (if enabled) we rename by following the preferred name + * as necessary. That's indicated with NM_TERNARY_DEFAULT. */ + force_rename2 = nm_config_data_get_value_boolean(NM_CONFIG_GET_DATA, + NM_CONFIG_KEYFILE_GROUP_KEYFILE, + NM_CONFIG_KEYFILE_KEY_KEYFILE_RENAME, + FALSE) + ? NM_TERNARY_DEFAULT + : NM_TERNARY_FALSE; + } + if (!nms_keyfile_writer_connection( connection, is_nm_generated, @@ -922,7 +937,7 @@ nms_keyfile_plugin_update_connection(NMSKeyfilePlugin *self, _get_plugin_dir(priv), previous_filename, FALSE, - FALSE, + force_rename2, nm_sett_util_allow_filename_cb, NM_SETT_UTIL_ALLOW_FILENAME_DATA(&priv->storages, previous_filename), &full_filename, @@ -938,7 +953,8 @@ nms_keyfile_plugin_update_connection(NMSKeyfilePlugin *self, return FALSE; } - nm_assert(full_filename && nm_streq(full_filename, previous_filename)); + nm_assert(full_filename); + nm_assert(force_rename2 != NM_TERNARY_FALSE || nm_streq(full_filename, previous_filename)); if (!reread || reread_same) nm_g_object_ref_set(&reread, connection); @@ -957,11 +973,33 @@ nms_keyfile_plugin_update_connection(NMSKeyfilePlugin *self, "\")", "")); - storage->u.conn_data.is_nm_generated = is_nm_generated; - storage->u.conn_data.is_volatile = is_volatile; - storage->u.conn_data.is_external = is_external; - storage->u.conn_data.stat_mtime = *nm_sett_util_stat_mtime(full_filename, FALSE, &mtime); - storage->u.conn_data.shadowed_owned = shadowed_owned; + nm_sett_util_stat_mtime(full_filename, FALSE, &mtime); + + if (nm_streq(full_filename, previous_filename)) { + storage->u.conn_data.is_nm_generated = is_nm_generated; + storage->u.conn_data.is_volatile = is_volatile; + storage->u.conn_data.is_external = is_external; + storage->u.conn_data.stat_mtime = mtime; + storage->u.conn_data.shadowed_owned = shadowed_owned; + } else { + NMSKeyfileStorage *storage_new; + + /* The filename changed. We cannot modify the filename of an NMSettingsStorage. + * We need to create a new one. */ + storage_new = + nms_keyfile_storage_new_connection(NMS_KEYFILE_PLUGIN(storage->parent._plugin), + g_object_ref(reread), + full_filename, + storage->storage_type, + is_nm_generated, + is_volatile, + is_external, + storage->u.conn_data.shadowed_storage, + shadowed_owned, + &mtime); + nm_sett_util_storages_add_take(&priv->storages, storage_new); + storage = storage_new; + } *out_storage = g_object_ref(NM_SETTINGS_STORAGE(storage)); *out_connection = g_steal_pointer(&reread); @@ -1066,12 +1104,12 @@ delete_connection(NMSettingsPlugin *plugin, NMSettingsStorage *storage_x, GError * @shadowed_storage: a tombstone can also shadow an existing storage. * In combination with @set and @in_memory, this is allowed to store * the shadowed storage filename. - * @out_storage: (transfer full) (allow-none): the storage element that changes, or - * NULL if nothing changed. Note that the file on disk is already as - * we want to write it, then this still counts as a change. No change only + * @out_storage: (transfer full) (optional) (nullable): the storage element that + * changes, or %NULL if nothing changed. Note that the file on disk is already + * as we want to write it, then this still counts as a change. No change only * means if we try to delete a storage (@set %FALSE) that did not * exist previously. - * @out_hard_failure: (allow-none): on failure, indicate that this is a hard failure. + * @out_hard_failure: (optional): on failure, indicate that this is a hard failure. * * The function writes or deletes nmmeta files to/from filesystem. In this case, * the nmmeta files can only be symlinks to /dev/null (to indicate tombstones). diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-writer.c b/src/core/settings/plugins/keyfile/nms-keyfile-writer.c index ad6f277c..b1dd2e44 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-writer.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-writer.c @@ -195,7 +195,7 @@ _internal_write_connection(NMConnection *connection, pid_t owner_grp, const char *existing_path, gboolean existing_path_read_only, - gboolean force_rename, + NMTernary force_rename, NMSKeyfileWriterAllowFilenameCb allow_filename_cb, gpointer allow_filename_user_data, char **out_path, @@ -212,6 +212,7 @@ _internal_write_connection(NMConnection *connection, gs_free_error GError *local_err = NULL; int errsv; gboolean rename; + gboolean rename_follow; int i_path; gs_unref_object NMConnection *reread = NULL; gboolean reread_same = FALSE; @@ -223,8 +224,12 @@ _internal_write_connection(NMConnection *connection, nm_assert(!shadowed_owned || shadowed_storage); - rename = force_rename || existing_path_read_only - || (existing_path && !nm_utils_file_is_in_path(existing_path, keyfile_dir)); + rename = existing_path_read_only + || (existing_path && !nm_utils_file_is_in_path(existing_path, keyfile_dir)) + || force_rename == NM_TERNARY_TRUE; + + /* Follow the connection.id upon change. */ + rename_follow = !rename && existing_path && force_rename == NM_TERNARY_DEFAULT; id = nm_connection_get_id(connection); nm_assert(id && *id); @@ -283,7 +288,7 @@ _internal_write_connection(NMConnection *connection, gboolean is_existing_path; if (i_path == -2) { - if (!existing_path || rename) + if (!existing_path || rename || rename_follow) continue; path_candidate = g_strdup(existing_path); } else if (i_path == -1) { @@ -427,7 +432,7 @@ nms_keyfile_writer_connection(NMConnection *connection, const char *profile_dir, const char *existing_path, gboolean existing_path_read_only, - gboolean force_rename, + NMTernary force_rename, NMSKeyfileWriterAllowFilenameCb allow_filename_cb, gpointer allow_filename_user_data, char **out_path, @@ -458,14 +463,14 @@ nms_keyfile_writer_connection(NMConnection *connection, } gboolean -nms_keyfile_writer_test_connection(NMConnection *connection, - const char *keyfile_dir, - uid_t owner_uid, - pid_t owner_grp, - char **out_path, - NMConnection **out_reread, - gboolean *out_reread_same, - GError **error) +nmtst_keyfile_writer_test_connection(NMConnection *connection, + const char *keyfile_dir, + uid_t owner_uid, + pid_t owner_grp, + char **out_path, + NMConnection **out_reread, + gboolean *out_reread_same, + GError **error) { return _internal_write_connection(connection, FALSE, diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-writer.h b/src/core/settings/plugins/keyfile/nms-keyfile-writer.h index 62aaa19d..850d5522 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-writer.h +++ b/src/core/settings/plugins/keyfile/nms-keyfile-writer.h @@ -22,7 +22,7 @@ gboolean nms_keyfile_writer_connection(NMConnection *connectio const char *profile_dir, const char *existing_path, gboolean existing_path_read_only, - gboolean force_rename, + NMTernary force_rename, NMSKeyfileWriterAllowFilenameCb allow_filename_cb, gpointer allow_filename_user_data, char **out_path, @@ -30,13 +30,13 @@ gboolean nms_keyfile_writer_connection(NMConnection *connectio gboolean *out_reread_same, GError **error); -gboolean nms_keyfile_writer_test_connection(NMConnection *connection, - const char *keyfile_dir, - uid_t owner_uid, - pid_t owner_grp, - char **out_path, - NMConnection **out_reread, - gboolean *out_reread_same, - GError **error); +gboolean nmtst_keyfile_writer_test_connection(NMConnection *connection, + const char *keyfile_dir, + uid_t owner_uid, + pid_t owner_grp, + char **out_path, + NMConnection **out_reread, + gboolean *out_reread_same, + GError **error); #endif /* __NMS_KEYFILE_WRITER_H__ */ diff --git a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c index 83019bab..866b1ffd 100644 --- a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c +++ b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c @@ -138,14 +138,14 @@ write_test_connection_reread(NMConnection *connection, connection_normalized = nmtst_connection_duplicate_and_normalize(connection); - success = nms_keyfile_writer_test_connection(connection_normalized, - TEST_SCRATCH_DIR, - owner_uid, - owner_grp, - testfile, - out_reread, - out_reread_same, - p_error); + success = nmtst_keyfile_writer_test_connection(connection_normalized, + TEST_SCRATCH_DIR, + owner_uid, + owner_grp, + testfile, + out_reread, + out_reread_same, + p_error); g_assert_no_error(error); g_assert(success); g_assert(*testfile && (*testfile)[0]); |