diff options
| author | Michael Biebl <biebl@debian.org> | 2020-04-11 21:28:04 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2020-04-11 21:28:04 +0200 |
| commit | 1e5977b62f896e844b548c3007ace9e1dfa7f9ed (patch) | |
| tree | 7a7416ed410e72b6200f3d860fd315ec11cc106b /src/settings/plugins | |
| parent | b012fa6e1d808e0736c009799c62d835cbfcc1dd (diff) | |
New upstream version 1.23.90 upstream/1.23.90
Diffstat (limited to 'src/settings/plugins')
28 files changed, 1388 insertions, 625 deletions
diff --git a/src/settings/plugins/ifcfg-rh/meson.build b/src/settings/plugins/ifcfg-rh/meson.build index d9dd3edb..e193ff96 100644 --- a/src/settings/plugins/ifcfg-rh/meson.build +++ b/src/settings/plugins/ifcfg-rh/meson.build @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1+ + install_data( 'nm-ifcfg-rh.conf', install_dir: dbus_conf_dir, diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c index f57ca1a7..f5c9bb5e 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c @@ -20,6 +20,7 @@ #include "nm-utils.h" #include "nm-core-internal.h" #include "nm-config.h" +#include "nm-dbus-manager.h" #include "settings/nm-settings-plugin.h" #include "settings/nm-settings-utils.h" #include "NetworkManagerUtils.h" @@ -205,9 +206,9 @@ _load_file (NMSIfcfgRHPlugin *self, const char *unmanaged_spec; const char *unrecognized_spec; - if (!nms_ifcfg_rh_util_parse_unhandled_spec (unhandled_spec, - &unmanaged_spec, - &unrecognized_spec)) { + if (!nms_ifcfg_rh_utils_parse_unhandled_spec (unhandled_spec, + &unmanaged_spec, + &unrecognized_spec)) { nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, "invalid unhandled spec \"%s\"", unhandled_spec); @@ -1132,6 +1133,13 @@ _dbus_setup (NMSIfcfgRHPlugin *self) _dbus_clear (self); + if (!NM_MAIN_DBUS_CONNECTION_GET) { + _LOGW ("dbus: don't use D-Bus for %s service", IFCFGRH1_BUS_NAME); + return; + } + + /* We use a separate D-Bus connection so that org.freedesktop.NetworkManager and com.redhat.ifcfgrh1 + * are exported by different connections. */ address = g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SYSTEM, NULL, &error); if (address == NULL) { _LOGW ("dbus: failed getting address for system bus: %s", error->message); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index e01f7344..8e153412 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -399,7 +399,9 @@ make_connection_setting (const char *file, if (v) { GError *error = NULL; - if (nm_utils_ifname_valid_kernel (v, &error)) { + /* Only validate for NMU_IFACE_KERNEL, because ifcfg plugin anyway + * doesn't support OVS types. */ + if (nm_utils_ifname_valid (v, NMU_IFACE_KERNEL, &error)) { g_object_set (s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, v, NULL); @@ -502,6 +504,24 @@ make_connection_setting (const char *file, } nm_clear_g_free (&value); + v = svGetValueStr (ifcfg, "VRF_UUID", &value); + if (!v) + v = svGetValueStr (ifcfg, "VRF", &value); + if (v) { + const char *old_value; + + if ((old_value = nm_setting_connection_get_master (s_con))) { + PARSE_WARNING ("Already configured as slave of %s. Ignoring VRF{_UUID}=\"%s\"", + old_value, v); + } else { + g_object_set (s_con, NM_SETTING_CONNECTION_MASTER, v, NULL); + g_object_set (s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_VRF_SETTING_NAME, NULL); + } + } + + + nm_clear_g_free (&value); v = svGetValueStr (ifcfg, "GATEWAY_PING_TIMEOUT", &value); if (v) { gint64 tmp; @@ -530,16 +550,18 @@ make_connection_setting (const char *file, g_object_set (s_con, NM_SETTING_CONNECTION_AUTH_RETRIES, (int) vint64, NULL); nm_clear_g_free (&value); - v = svGetValueStr (ifcfg, "DEVTIMEOUT", &value); + v = svGetValue (ifcfg, "DEVTIMEOUT", &value); if (v) { + v = nm_str_skip_leading_spaces (v); vint64 = _nm_utils_ascii_str_to_int64 (v, 10, 0, ((gint64) G_MAXINT32) / 1000, -1); if (vint64 != -1) vint64 *= 1000; - else { + else if (v[0] != '\0') { char *endptr; double d; - d = g_ascii_strtod (v, &endptr); + d = nm_g_ascii_strtod (v, &endptr); + endptr = nm_str_skip_leading_spaces (endptr); if ( errno == 0 && endptr[0] == '\0' && d >= 0.0) { @@ -709,7 +731,7 @@ read_full_ip4_address (shvarFile *ifcfg, else { /* Try to autodetermine the prefix for the address' class */ prefix = _nm_utils_ip4_get_default_prefix (ipaddr); - PARSE_WARNING ("missing %s, assuming %s/%d", prefix_tag, nm_utils_inet4_ntop (ipaddr, inet_buf), prefix); + PARSE_WARNING ("missing %s, assuming %s/%d", prefix_tag, _nm_utils_inet4_ntop (ipaddr, inet_buf), prefix); } } } @@ -1287,7 +1309,7 @@ read_one_ip4_route (shvarFile *ifcfg, prefix = nm_utils_ip4_netmask_to_prefix (netmask); if (netmask != _nm_utils_ip4_prefix_to_netmask (prefix)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Invalid IP4 netmask '%s' \"%s\"", netmask_tag, nm_utils_inet4_ntop (netmask, inet_buf)); + "Invalid IP4 netmask '%s' \"%s\"", netmask_tag, _nm_utils_inet4_ntop (netmask, inet_buf)); return FALSE; } } else { @@ -1318,7 +1340,7 @@ read_one_ip4_route (shvarFile *ifcfg, v = svGetValueStr (ifcfg, numbered_tag (tag, "OPTIONS", which), &value); if (v) { if (parse_route_line (v, AF_INET, *out_route, NULL, error) < 0) { - g_clear_pointer (out_route, nm_ip_route_unref); + nm_clear_pointer (out_route, nm_ip_route_unref); return FALSE; } } @@ -1327,39 +1349,40 @@ read_one_ip4_route (shvarFile *ifcfg, } static gboolean -read_route_file (int addr_family, - const char *filename, - NMSettingIPConfig *s_ip, - GError **error) +read_route_file_parse (int addr_family, + const char *filename, + const char *contents, + gsize len, + NMSettingIPConfig *s_ip, + GError **error) { - gs_free char *contents = NULL; - char *contents_rest = NULL; - const char *line; - gsize len = 0; gsize line_num; - g_return_val_if_fail (filename, FALSE); - g_return_val_if_fail ( (addr_family == AF_INET && NM_IS_SETTING_IP4_CONFIG (s_ip)) - || (addr_family == AF_INET6 && NM_IS_SETTING_IP6_CONFIG (s_ip)), FALSE); - g_return_val_if_fail (!error || !*error, FALSE); + nm_assert (filename); + nm_assert (addr_family == nm_setting_ip_config_get_addr_family (s_ip)); + nm_assert (!error || !*error); - if ( !g_file_get_contents (filename, &contents, &len, NULL) - || !len) { + if (len <= 0) return TRUE; /* missing/empty = success */ - } line_num = 0; - for (line = strtok_r (contents, "\n", &contents_rest); - line; - line = strtok_r (NULL, "\n", &contents_rest)) { + while (TRUE) { nm_auto_unref_ip_route NMIPRoute *route = NULL; gs_free_error GError *local = NULL; + const char *line = contents; + char *eol; int e; + eol = strchr (contents, '\n'); + if (eol) { + eol[0] = '\0'; + contents = &eol[1]; + } + line_num++; if (parse_route_line_is_comment (line)) - continue; + goto next; e = parse_route_line (line, addr_family, NULL, &route, &local); @@ -1371,14 +1394,38 @@ read_route_file (int addr_family, * entire connection. */ PARSE_WARNING ("ignoring invalid route at \"%s\" (%s:%lu): %s", line, filename, (long unsigned) line_num, local->message); } - continue; + goto next; } if (!nm_setting_ip_config_add_route (s_ip, route)) PARSE_WARNING ("duplicate IPv%c route", addr_family == AF_INET ? '4' : '6'); + +next: + if (!eol) + return TRUE; + + /* restore original content. */ + eol[0] = '\n'; } +} - return TRUE; +static gboolean +read_route_file (int addr_family, + const char *filename, + NMSettingIPConfig *s_ip, + GError **error) +{ + gs_free char *contents = NULL; + gsize len; + + nm_assert (filename); + nm_assert (addr_family == nm_setting_ip_config_get_addr_family (s_ip)); + nm_assert (!error || !*error); + + if (!g_file_get_contents (filename, &contents, &len, NULL)) + return TRUE; /* missing/empty = success */ + + return read_route_file_parse (addr_family, filename, contents, len, s_ip, error); } static void @@ -1577,7 +1624,6 @@ make_ip4_setting (shvarFile *ifcfg, int i; guint32 a; gboolean has_key; - shvarFile *route_ifcfg; gboolean never_default; gint64 i64; int priority; @@ -1771,10 +1817,10 @@ make_ip4_setting (shvarFile *ifcfg, nm_clear_g_free (&value); v = svGetValueStr (ifcfg, tag, &value); if (v) { - if (nm_utils_ipaddr_valid (AF_INET, v)) { + if (nm_utils_ipaddr_is_valid (AF_INET, v)) { if (!nm_setting_ip_config_add_dns (s_ip4, v)) PARSE_WARNING ("duplicate DNS server %s", tag); - } else if (nm_utils_ipaddr_valid (AF_INET6, v)) { + } else if (nm_utils_ipaddr_is_valid (AF_INET6, v)) { /* Ignore IPv6 addresses */ } else { PARSE_WARNING ("invalid DNS server address %s", v); @@ -1814,32 +1860,34 @@ make_ip4_setting (shvarFile *ifcfg, /* Static routes - route-<name> file */ route_path = utils_get_route_path (svFileGetName (ifcfg)); - if (!routes_read) { - /* NOP */ - } else if (utils_has_route_file_new_syntax (route_path)) { - /* Parse route file in new syntax */ - route_ifcfg = utils_get_route_ifcfg (svFileGetName (ifcfg), FALSE); - if (route_ifcfg) { + if (routes_read) { + gs_free char *contents = NULL; + gsize len; + + if (!g_file_get_contents (route_path, &contents, &len, NULL)) + len = 0; + + if (utils_has_route_file_new_syntax_content (contents, len)) { + nm_auto_shvar_file_close shvarFile *route_ifcfg = NULL; + + /* Parse route file in new syntax */ + route_ifcfg = svFile_new (route_path, -1, contents); for (i = 0;; i++) { - NMIPRoute *route = NULL; + nm_auto_unref_ip_route NMIPRoute *route = NULL; - if (!read_one_ip4_route (route_ifcfg, i, &route, error)) { - svCloseFile (route_ifcfg); + if (!read_one_ip4_route (route_ifcfg, i, &route, error)) return NULL; - } if (!route) break; if (!nm_setting_ip_config_add_route (s_ip4, route)) PARSE_WARNING ("duplicate IP4 route"); - nm_ip_route_unref (route); } - svCloseFile (route_ifcfg); + } else { + if (!read_route_file_parse (AF_INET, route_path, contents, len, s_ip4, error)) + return NULL; } - } else { - if (!read_route_file (AF_INET, route_path, s_ip4, error)) - return NULL; } /* Legacy value NM used for a while but is incorrect (rh #459370) */ @@ -2214,7 +2262,7 @@ make_ip6_setting (shvarFile *ifcfg, char *ptr; if ((ptr = strchr (v, '%')) != NULL) *ptr = '\0'; /* remove %interface prefix if present */ - if (!nm_utils_ipaddr_valid (AF_INET6, v)) { + if (!nm_utils_ipaddr_is_valid (AF_INET6, v)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid IP6 address '%s'", v); return NULL; @@ -2253,10 +2301,10 @@ make_ip6_setting (shvarFile *ifcfg, break; } - if (nm_utils_ipaddr_valid (AF_INET6, v)) { + if (nm_utils_ipaddr_is_valid (AF_INET6, v)) { if (!nm_setting_ip_config_add_dns (s_ip6, v)) PARSE_WARNING ("duplicate DNS server %s", tag); - } else if (nm_utils_ipaddr_valid (AF_INET, v)) { + } else if (nm_utils_ipaddr_is_valid (AF_INET, v)) { /* Ignore IPv4 addresses */ } else { PARSE_WARNING ("invalid DNS server address %s", v); @@ -3623,6 +3671,14 @@ next: v = svGetValueStr (ifcfg, "IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH", &value); g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, v, NULL); + nm_clear_g_free (&value); + v = svGetValueStr (ifcfg, "IEEE_8021X_DOMAIN_MATCH", &value); + g_object_set (s_8021x, NM_SETTING_802_1X_DOMAIN_MATCH, v, NULL); + + nm_clear_g_free (&value); + v = svGetValueStr (ifcfg, "IEEE_8021X_PHASE2_DOMAIN_MATCH", &value); + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_DOMAIN_MATCH, v, NULL); + timeout = svGetValueInt64 (ifcfg, "IEEE_8021X_AUTH_TIMEOUT", 10, 0, G_MAXINT32, 0); g_object_set (s_8021x, NM_SETTING_802_1X_AUTH_TIMEOUT, (int) timeout, NULL); @@ -3645,7 +3701,7 @@ make_wpa_setting (shvarFile *ifcfg, gs_unref_object NMSettingWirelessSecurity *wsec = NULL; gs_free char *value = NULL; const char *v; - gboolean wpa_psk = FALSE, wpa_sae = FALSE, wpa_eap = FALSE, ieee8021x = FALSE; + gboolean wpa_psk = FALSE, wpa_sae = FALSE, wpa_owe = FALSE, wpa_eap = FALSE, ieee8021x = FALSE; int i_val; GError *local = NULL; @@ -3654,10 +3710,12 @@ make_wpa_setting (shvarFile *ifcfg, v = svGetValueStr (ifcfg, "KEY_MGMT", &value); wpa_psk = nm_streq0 (v, "WPA-PSK"); wpa_sae = nm_streq0 (v, "SAE"); + wpa_owe = nm_streq0 (v, "OWE"); wpa_eap = nm_streq0 (v, "WPA-EAP"); ieee8021x = nm_streq0 (v, "IEEE8021X"); if ( !wpa_psk && !wpa_sae + && !wpa_owe && !wpa_eap && !ieee8021x) return NULL; /* Not WPA or Dynamic WEP */ @@ -3673,7 +3731,7 @@ make_wpa_setting (shvarFile *ifcfg, NULL); /* Pairwise and Group ciphers (only relevant for WPA/RSN) */ - if (wpa_psk || wpa_sae || wpa_eap) { + if (wpa_psk || wpa_sae || wpa_owe || wpa_eap) { fill_wpa_ciphers (ifcfg, wsec, FALSE, adhoc); fill_wpa_ciphers (ifcfg, wsec, TRUE, adhoc); } @@ -3722,7 +3780,7 @@ make_wpa_setting (shvarFile *ifcfg, g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "sae", NULL); } } else { - nm_assert (wpa_eap || ieee8021x); + nm_assert (wpa_eap || ieee8021x || wpa_owe); /* Adhoc mode is mutually exclusive with any 802.1x-based authentication */ if (adhoc) { @@ -3731,14 +3789,17 @@ make_wpa_setting (shvarFile *ifcfg, return NULL; } - *s_8021x = fill_8021x (ifcfg, file, v, TRUE, error); - if (!*s_8021x) - return NULL; - - { - gs_free char *lower = g_ascii_strdown (v, -1); + if (wpa_owe) { + g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "owe", NULL); + } else { + *s_8021x = fill_8021x (ifcfg, file, v, TRUE, error); + if (!*s_8021x) + return NULL; - g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, lower, NULL); + { + gs_free char *lower = g_ascii_strdown (v, -1); + g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, lower, NULL); + } } } @@ -3782,7 +3843,7 @@ make_leap_setting (shvarFile *ifcfg, nm_clear_g_free (&value); value = svGetValueStr_cp (ifcfg, "SECURITYMODE"); - if (!value || strcasecmp (value, "leap")) + if (!value || g_ascii_strcasecmp (value, "leap")) return NULL; /* Not LEAP */ nm_clear_g_free (&value); @@ -4339,7 +4400,7 @@ parse_ethtool_option (const char *value, i++; if (nm_utils_hwaddr_valid (opt_val, ETH_ALEN)) { - g_clear_pointer (out_password, g_free); + nm_clear_g_free (out_password); *out_password = g_strdup (opt_val); } else PARSE_WARNING ("Wake-on-LAN password '%s' is invalid", opt_val); @@ -5091,18 +5152,24 @@ handle_bridge_option (NMSetting *setting, gboolean only_with_stp; gboolean extended_bool; } m/*etadata*/[] = { - { "DELAY", NM_SETTING_BRIDGE_FORWARD_DELAY, BRIDGE_OPT_TYPE_MAIN, .only_with_stp = TRUE }, - { "priority", NM_SETTING_BRIDGE_PRIORITY, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, - { "hello_time", NM_SETTING_BRIDGE_HELLO_TIME, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, - { "max_age", NM_SETTING_BRIDGE_MAX_AGE, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, - { "ageing_time", NM_SETTING_BRIDGE_AGEING_TIME, BRIDGE_OPT_TYPE_OPTION }, - { "multicast_snooping", NM_SETTING_BRIDGE_MULTICAST_SNOOPING, BRIDGE_OPT_TYPE_OPTION }, - { "vlan_filtering", NM_SETTING_BRIDGE_VLAN_FILTERING, BRIDGE_OPT_TYPE_OPTION }, - { "default_pvid", NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, BRIDGE_OPT_TYPE_OPTION }, - { "group_fwd_mask", NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, BRIDGE_OPT_TYPE_OPTION }, - { "priority", NM_SETTING_BRIDGE_PORT_PRIORITY, BRIDGE_OPT_TYPE_PORT_OPTION }, - { "path_cost", NM_SETTING_BRIDGE_PORT_PATH_COST, BRIDGE_OPT_TYPE_PORT_OPTION }, - { "hairpin_mode", NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, BRIDGE_OPT_TYPE_PORT_OPTION, .extended_bool = TRUE, }, + { "DELAY", NM_SETTING_BRIDGE_FORWARD_DELAY, BRIDGE_OPT_TYPE_MAIN, .only_with_stp = TRUE }, + { "priority", NM_SETTING_BRIDGE_PRIORITY, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, + { "hello_time", NM_SETTING_BRIDGE_HELLO_TIME, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, + { "max_age", NM_SETTING_BRIDGE_MAX_AGE, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, + { "ageing_time", NM_SETTING_BRIDGE_AGEING_TIME, BRIDGE_OPT_TYPE_OPTION }, + { "multicast_querier", NM_SETTING_BRIDGE_MULTICAST_QUERIER, BRIDGE_OPT_TYPE_OPTION }, + { "multicast_query_use_ifaddr", NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR, BRIDGE_OPT_TYPE_OPTION }, + { "multicast_snooping", NM_SETTING_BRIDGE_MULTICAST_SNOOPING, BRIDGE_OPT_TYPE_OPTION }, + { "multicast_router", NM_SETTING_BRIDGE_MULTICAST_ROUTER, BRIDGE_OPT_TYPE_OPTION }, + { "vlan_filtering", NM_SETTING_BRIDGE_VLAN_FILTERING, BRIDGE_OPT_TYPE_OPTION }, + { "default_pvid", NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, BRIDGE_OPT_TYPE_OPTION }, + { "group_address", NM_SETTING_BRIDGE_GROUP_ADDRESS, BRIDGE_OPT_TYPE_OPTION }, + { "group_fwd_mask", NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, BRIDGE_OPT_TYPE_OPTION }, + { "vlan_protocol", NM_SETTING_BRIDGE_VLAN_PROTOCOL, BRIDGE_OPT_TYPE_OPTION }, + { "vlan_stats_enabled", NM_SETTING_BRIDGE_VLAN_STATS_ENABLED, BRIDGE_OPT_TYPE_OPTION }, + { "priority", NM_SETTING_BRIDGE_PORT_PRIORITY, BRIDGE_OPT_TYPE_PORT_OPTION }, + { "path_cost", NM_SETTING_BRIDGE_PORT_PATH_COST, BRIDGE_OPT_TYPE_PORT_OPTION }, + { "hairpin_mode", NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, BRIDGE_OPT_TYPE_PORT_OPTION, .extended_bool = TRUE, }, }; const char *error_message = NULL; int i; @@ -5124,9 +5191,9 @@ handle_bridge_option (NMSetting *setting, switch (param_spec->value_type) { case G_TYPE_BOOLEAN: if (m[i].extended_bool) { - if (!strcasecmp (value, "on") || !strcasecmp (value, "yes") || !strcmp (value, "1")) + if (!g_ascii_strcasecmp (value, "on") || !g_ascii_strcasecmp (value, "yes") || !strcmp (value, "1")) v = TRUE; - else if (!strcasecmp (value, "off") || !strcasecmp (value, "no")) + else if (!g_ascii_strcasecmp (value, "off") || !g_ascii_strcasecmp (value, "no")) v = FALSE; else { error_message = "is not a boolean"; @@ -5155,6 +5222,9 @@ handle_bridge_option (NMSetting *setting, goto warn; } return; + case G_TYPE_STRING: + nm_g_object_set_property_string (G_OBJECT (setting), m[i].property_name, value, NULL); + return; default: nm_assert_not_reached (); continue; @@ -5259,11 +5329,11 @@ make_bridge_setting (shvarFile *ifcfg, value = svGetValueStr (ifcfg, "STP", &value_to_free); if (value) { - if (!strcasecmp (value, "on") || !strcasecmp (value, "yes")) { + if (!g_ascii_strcasecmp (value, "on") || !g_ascii_strcasecmp (value, "yes")) { g_object_set (s_bridge, NM_SETTING_BRIDGE_STP, TRUE, NULL); stp = TRUE; stp_set = TRUE; - } else if (!strcasecmp (value, "off") || !strcasecmp (value, "no")) { + } else if (!g_ascii_strcasecmp (value, "off") || !g_ascii_strcasecmp (value, "no")) { g_object_set (s_bridge, NM_SETTING_BRIDGE_STP, FALSE, NULL); stp_set = TRUE; } else @@ -5774,9 +5844,9 @@ connection_from_file_full (const char *filename, devtype = svGetValueStr_cp (main_ifcfg, "DEVICETYPE"); if (devtype) { - if (!strcasecmp (devtype, TYPE_TEAM)) + if (!g_ascii_strcasecmp (devtype, TYPE_TEAM)) type = g_strdup (TYPE_TEAM); - else if (!strcasecmp (devtype, TYPE_TEAM_PORT)) { + else if (!g_ascii_strcasecmp (devtype, TYPE_TEAM_PORT)) { gs_free char *device = NULL; type = svGetValueStr_cp (main_ifcfg, "TYPE"); @@ -5910,26 +5980,26 @@ connection_from_file_full (const char *filename, } if (svGetValueBoolean (main_ifcfg, "BONDING_MASTER", FALSE) && - strcasecmp (type, TYPE_BOND)) { + g_ascii_strcasecmp (type, TYPE_BOND)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "BONDING_MASTER=yes key only allowed in TYPE=bond connections"); return NULL; } /* Construct the connection */ - if (!strcasecmp (type, TYPE_ETHERNET)) + if (!g_ascii_strcasecmp (type, TYPE_ETHERNET)) connection = wired_connection_from_ifcfg (filename, main_ifcfg, error); - else if (!strcasecmp (type, TYPE_WIRELESS)) + else if (!g_ascii_strcasecmp (type, TYPE_WIRELESS)) connection = wireless_connection_from_ifcfg (filename, main_ifcfg, error); - else if (!strcasecmp (type, TYPE_INFINIBAND)) + else if (!g_ascii_strcasecmp (type, TYPE_INFINIBAND)) connection = infiniband_connection_from_ifcfg (filename, main_ifcfg, error); - else if (!strcasecmp (type, TYPE_BOND)) + else if (!g_ascii_strcasecmp (type, TYPE_BOND)) connection = bond_connection_from_ifcfg (filename, main_ifcfg, error); - else if (!strcasecmp (type, TYPE_TEAM)) + else if (!g_ascii_strcasecmp (type, TYPE_TEAM)) connection = team_connection_from_ifcfg (filename, main_ifcfg, error); - else if (!strcasecmp (type, TYPE_VLAN)) + else if (!g_ascii_strcasecmp (type, TYPE_VLAN)) connection = vlan_connection_from_ifcfg (filename, main_ifcfg, error); - else if (!strcasecmp (type, TYPE_BRIDGE)) + else if (!g_ascii_strcasecmp (type, TYPE_BRIDGE)) connection = bridge_connection_from_ifcfg (filename, main_ifcfg, error); else { connection = create_unhandled_connection (filename, main_ifcfg, "unrecognized", out_unhandled); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c index ee389bd9..28f57f50 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c @@ -17,9 +17,9 @@ /*****************************************************************************/ gboolean -nms_ifcfg_rh_util_parse_unhandled_spec (const char *unhandled_spec, - const char **out_unmanaged_spec, - const char **out_unrecognized_spec) +nms_ifcfg_rh_utils_parse_unhandled_spec (const char *unhandled_spec, + const char **out_unmanaged_spec, + const char **out_unrecognized_spec) { if (unhandled_spec) { if (NM_STR_HAS_PREFIX (unhandled_spec, "unmanaged:")) { @@ -72,7 +72,7 @@ check_suffix (const char *base, const char *tag) len = strlen (base); tag_len = strlen (tag); - if ((len > tag_len) && !strcasecmp (base + len - tag_len, tag)) + if ((len > tag_len) && !g_ascii_strcasecmp (base + len - tag_len, tag)) return TRUE; return FALSE; } @@ -260,27 +260,60 @@ utils_get_route_ifcfg (const char *parent, gboolean should_create) gboolean utils_has_route_file_new_syntax (const char *filename) { - char *contents = NULL; - gsize len = 0; - gboolean ret = FALSE; - const char *pattern = "^[[:space:]]*ADDRESS[0-9]+="; + gs_free char *contents_data = NULL; + gsize len; g_return_val_if_fail (filename != NULL, TRUE); - if (!g_file_get_contents (filename, &contents, &len, NULL)) + if (!g_file_get_contents (filename, &contents_data, &len, NULL)) return TRUE; - if (len <= 0) { - ret = TRUE; - goto gone; - } + return utils_has_route_file_new_syntax_content (contents_data, len); +} + +gboolean +utils_has_route_file_new_syntax_content (const char *contents, + gsize len) +{ + if (len <= 0) + return TRUE; + + while (TRUE) { + const char *line = contents; + char *eol; + gboolean found = FALSE; + + /* matches regex "^[[:space:]]*ADDRESS[0-9]+=" */ + + eol = (char *) strchr (contents, '\n'); + if (eol) { + eol[0] = '\0'; + contents = &eol[1]; + } - if (g_regex_match_simple (pattern, contents, G_REGEX_MULTILINE, 0)) - ret = TRUE; + line = nm_str_skip_leading_spaces (line); + if (NM_STR_HAS_PREFIX (line, "ADDRESS")) { + line += NM_STRLEN ("ADDRESS"); + if (g_ascii_isdigit (line[0])) { + while (g_ascii_isdigit ((++line)[0])) { + /* pass */ + } + if (line[0] == '=') + found = TRUE; + } + } + + if (eol) { + /* restore the line ending. We don't want to mangle the content from + * POV of the caller. */ + eol[0] = '\n'; + } -gone: - g_free (contents); - return ret; + if (found) + return TRUE; + if (!eol) + return FALSE; + } } gboolean @@ -546,31 +579,15 @@ const char *const _nm_ethtool_ifcfg_names[] = { ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT, "tx-vlan-stag-hw-insert"), }; -const NMEthtoolData * -nms_ifcfg_rh_utils_get_ethtool_by_name (const char *name) -{ - static const struct { - NMEthtoolID ethtool_id; - const char *kernel_name; - } kernel_names[] = { - { NM_ETHTOOL_ID_FEATURE_GRO, "rx-gro" }, - { NM_ETHTOOL_ID_FEATURE_GSO, "tx-generic-segmentation" }, - { NM_ETHTOOL_ID_FEATURE_LRO, "rx-lro" }, - { NM_ETHTOOL_ID_FEATURE_NTUPLE, "rx-ntuple-filter" }, - { NM_ETHTOOL_ID_FEATURE_RX, "rx-checksum" }, - { NM_ETHTOOL_ID_FEATURE_RXHASH, "rx-hashing" }, - { NM_ETHTOOL_ID_FEATURE_RXVLAN, "rx-vlan-hw-parse" }, - { NM_ETHTOOL_ID_FEATURE_TXVLAN, "tx-vlan-hw-insert" }, - }; - guint i; - - for (i = 0; i < G_N_ELEMENTS (_nm_ethtool_ifcfg_names); i++) { - if (nm_streq (name, _nm_ethtool_ifcfg_names[i])) - return nm_ethtool_data[i]; - } +static +NM_UTILS_STRING_TABLE_LOOKUP_DEFINE ( + _get_ethtoolid_by_name, + NMEthtoolID, + { nm_assert (name); }, + { return NM_ETHTOOL_ID_UNKNOWN; }, - /* Option not found. Note that ethtool utility has built-in features and - * NetworkManager's API follows the naming of these built-in features, whenever + /* Map the names from kernel/ethtool/ifcfg to NMEthtoolID. Note that ethtool utility has built-in + * features and NetworkManager's API follows the naming of these built-in features, whenever * they exist. * For example, NM's "ethtool.feature-ntuple" corresponds to ethtool utility's "ntuple" * feature. However the underlying kernel feature is called "rx-ntuple-filter" (as reported @@ -578,10 +595,430 @@ nms_ifcfg_rh_utils_get_ethtool_by_name (const char *name) * * With ethtool utility, whose command line we attempt to parse here, the user can also * specify the name of the underlying kernel feature directly. So, check whether that is - * the case and if yes, map them to the corresponding NetworkManager's features. */ - for (i = 0; i < G_N_ELEMENTS (kernel_names); i++) { - if (nm_streq (name, kernel_names[i].kernel_name)) - return nm_ethtool_data[kernel_names[i].ethtool_id]; + * the case and if yes, map them to the corresponding NetworkManager's features. + * + * That is why there are duplicate IDs in this list. */ + { "esp-hw-offload", NM_ETHTOOL_ID_FEATURE_ESP_HW_OFFLOAD }, + { "esp-tx-csum-hw-offload", NM_ETHTOOL_ID_FEATURE_ESP_TX_CSUM_HW_OFFLOAD }, + { "fcoe-mtu", NM_ETHTOOL_ID_FEATURE_FCOE_MTU }, + { "gro", NM_ETHTOOL_ID_FEATURE_GRO }, + { "gso", NM_ETHTOOL_ID_FEATURE_GSO }, + { "highdma", NM_ETHTOOL_ID_FEATURE_HIGHDMA }, + { "hw-tc-offload", NM_ETHTOOL_ID_FEATURE_HW_TC_OFFLOAD }, + { "l2-fwd-offload", NM_ETHTOOL_ID_FEATURE_L2_FWD_OFFLOAD }, + { "loopback", NM_ETHTOOL_ID_FEATURE_LOOPBACK }, + { "lro", NM_ETHTOOL_ID_FEATURE_LRO }, + { "ntuple", NM_ETHTOOL_ID_FEATURE_NTUPLE }, + { "rx", NM_ETHTOOL_ID_FEATURE_RX }, + { "rx-all", NM_ETHTOOL_ID_FEATURE_RX_ALL }, + { "rx-checksum", NM_ETHTOOL_ID_FEATURE_RX }, // kernel-only name + { "rx-fcs", NM_ETHTOOL_ID_FEATURE_RX_FCS }, + { "rx-gro", NM_ETHTOOL_ID_FEATURE_GRO }, // kernel-only name + { "rx-gro-hw", NM_ETHTOOL_ID_FEATURE_RX_GRO_HW }, + { "rx-hashing", NM_ETHTOOL_ID_FEATURE_RXHASH }, // kernel-only name + { "rx-lro", NM_ETHTOOL_ID_FEATURE_LRO }, // kernel-only name + { "rx-ntuple-filter", NM_ETHTOOL_ID_FEATURE_NTUPLE }, // kernel-only name + { "rx-udp_tunnel-port-offload", NM_ETHTOOL_ID_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD }, + { "rx-vlan-filter", NM_ETHTOOL_ID_FEATURE_RX_VLAN_FILTER }, + { "rx-vlan-hw-parse", NM_ETHTOOL_ID_FEATURE_RXVLAN }, // kernel-only name + { "rx-vlan-stag-filter", NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_FILTER }, + { "rx-vlan-stag-hw-parse", NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_HW_PARSE }, + { "rxhash", NM_ETHTOOL_ID_FEATURE_RXHASH }, + { "rxvlan", NM_ETHTOOL_ID_FEATURE_RXVLAN }, + { "sg", NM_ETHTOOL_ID_FEATURE_SG }, + { "tls-hw-record", NM_ETHTOOL_ID_FEATURE_TLS_HW_RECORD }, + { "tls-hw-tx-offload", NM_ETHTOOL_ID_FEATURE_TLS_HW_TX_OFFLOAD }, + { "tso", NM_ETHTOOL_ID_FEATURE_TSO }, + { "tx", NM_ETHTOOL_ID_FEATURE_TX }, + { "tx-checksum-fcoe-crc", NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_FCOE_CRC }, + { "tx-checksum-ip-generic", NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IP_GENERIC }, + { "tx-checksum-ipv4", NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV4 }, + { "tx-checksum-ipv6", NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV6 }, + { "tx-checksum-sctp", NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_SCTP }, + { "tx-esp-segmentation", NM_ETHTOOL_ID_FEATURE_TX_ESP_SEGMENTATION }, + { "tx-fcoe-segmentation", NM_ETHTOOL_ID_FEATURE_TX_FCOE_SEGMENTATION }, + { "tx-generic-segmentation", NM_ETHTOOL_ID_FEATURE_GSO }, // kernel-only name + { "tx-gre-csum-segmentation", NM_ETHTOOL_ID_FEATURE_TX_GRE_CSUM_SEGMENTATION }, + { "tx-gre-segmentation", NM_ETHTOOL_ID_FEATURE_TX_GRE_SEGMENTATION }, + { "tx-gso-partial", NM_ETHTOOL_ID_FEATURE_TX_GSO_PARTIAL }, + { "tx-gso-robust", NM_ETHTOOL_ID_FEATURE_TX_GSO_ROBUST }, + { "tx-ipxip4-segmentation", NM_ETHTOOL_ID_FEATURE_TX_IPXIP4_SEGMENTATION }, + { "tx-ipxip6-segmentation", NM_ETHTOOL_ID_FEATURE_TX_IPXIP6_SEGMENTATION }, + { "tx-nocache-copy", NM_ETHTOOL_ID_FEATURE_TX_NOCACHE_COPY }, + { "tx-scatter-gather", NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER }, + { "tx-scatter-gather-fraglist", NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER_FRAGLIST }, + { "tx-sctp-segmentation", NM_ETHTOOL_ID_FEATURE_TX_SCTP_SEGMENTATION }, + { "tx-tcp-ecn-segmentation", NM_ETHTOOL_ID_FEATURE_TX_TCP_ECN_SEGMENTATION }, + { "tx-tcp-mangleid-segmentation", NM_ETHTOOL_ID_FEATURE_TX_TCP_MANGLEID_SEGMENTATION }, + { "tx-tcp-segmentation", NM_ETHTOOL_ID_FEATURE_TX_TCP_SEGMENTATION }, + { "tx-tcp6-segmentation", NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION }, + { "tx-udp-segmentation", NM_ETHTOOL_ID_FEATURE_TX_UDP_SEGMENTATION }, + { "tx-udp_tnl-csum-segmentation", NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION }, + { "tx-udp_tnl-segmentation", NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION }, + { "tx-vlan-hw-insert", NM_ETHTOOL_ID_FEATURE_TXVLAN }, // kernel-only name + { "tx-vlan-stag-hw-insert", NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT }, + { "txvlan", NM_ETHTOOL_ID_FEATURE_TXVLAN }, +); + +const NMEthtoolData * +nms_ifcfg_rh_utils_get_ethtool_by_name (const char *name) +{ + NMEthtoolID id; + + id = _get_ethtoolid_by_name (name); + if (id == NM_ETHTOOL_ID_UNKNOWN) + return NULL; + + nm_assert (_NM_INT_NOT_NEGATIVE (id)); + nm_assert (id < G_N_ELEMENTS (nm_ethtool_data)); + nm_assert (nm_ethtool_data[id]); + nm_assert (nm_ethtool_data[id]->id == id); + return nm_ethtool_data[id]; +} + +/*****************************************************************************/ + +gboolean +nms_ifcfg_rh_utils_is_numbered_tag_impl (const char *key, + const char *tag, + gsize tag_len, + gint64 *out_idx) +{ + gint64 idx; + + nm_assert (key); + nm_assert (tag); + nm_assert (tag_len == strlen (tag)); + nm_assert (tag_len > 0); + + if (strncmp (key, tag, tag_len) != 0) + return FALSE; + + key += tag_len; + + if (key[0] == '\0') { + /* The key has no number suffix. We treat this also as a numbered + * tag, and it is for certain tags like "IPADDR", but not so much + * for others like "ROUTING_RULE_". The caller may want to handle + * this case specially. */ + NM_SET_OUT (out_idx, -1); + return TRUE; + } + + if (!NM_STRCHAR_ALL (key, ch, g_ascii_isdigit (ch))) + return FALSE; + + idx = _nm_utils_ascii_str_to_int64 (key, 10, 0, G_MAXINT64, -1); + if (idx == -1) + return FALSE; + + NM_SET_OUT (out_idx, idx); + return TRUE; +} + +/*****************************************************************************/ + +#define _KEY_TYPE(key, flags) { .key_name = ""key"", .key_flags = ((NMS_IFCFG_KEY_TYPE_WELL_KNOWN) | (flags)), } + +const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = { + _KEY_TYPE ("ACD_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("ADDRESS", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ), + _KEY_TYPE ("ARPING_WAIT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("AUTH_RETRIES", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("AUTOCONNECT_PRIORITY", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("AUTOCONNECT_RETRIES", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("AUTOCONNECT_SLAVES", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("BAND", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("BONDING_MASTER", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("BONDING_OPTS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("BOOTPROTO", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("BRIDGE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("BRIDGE_MACADDR", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("BRIDGE_PORT_VLANS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("BRIDGE_UUID", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("BRIDGE_VLANS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("BRIDGING_OPTS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("BROWSER_ONLY", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("BSSID", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("CHANNEL", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("CIPHER_GROUP", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("CIPHER_PAIRWISE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("CONNECTED_MODE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("CONNECTION_METERED", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("CTCPROT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DCB", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_APP_FCOE_ADVERTISE, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_APP_FCOE_ENABLE, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_APP_FCOE_MODE, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DCB_APP_FCOE_PRIORITY", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_APP_FCOE_WILLING, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_APP_FIP_ADVERTISE, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_APP_FIP_ENABLE, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DCB_APP_FIP_PRIORITY", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_APP_FIP_WILLING, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_APP_ISCSI_ADVERTISE, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_APP_ISCSI_ENABLE, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DCB_APP_ISCSI_PRIORITY", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_APP_ISCSI_WILLING, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_PFC_ADVERTISE, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_PFC_ENABLE, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_PFC_UP, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_PFC_WILLING, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_PG_ADVERTISE, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_PG_ENABLE, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_PG_ID, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_PG_PCT, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_PG_STRICT, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_PG_UP2TC, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_PG_UPPCT, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE (KEY_DCB_PG_WILLING, NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DEFAULTKEY", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DEFROUTE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DELAY", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DEVICE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DEVICETYPE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DEVTIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DHCPV6C", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DHCPV6_DUID", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _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_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 ), + _KEY_TYPE ("DHCP_HOSTNAME", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DHCP_HOSTNAME_FLAGS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DHCP_IAID", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DHCP_SEND_HOSTNAME", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DHCPv6_DUID", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DHCPv6_IAID", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("DNS", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ), + _KEY_TYPE ("DOMAIN", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("ESSID", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("ETHTOOL_OPTS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("ETHTOOL_WAKE_ON_LAN", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("FILS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("FILTER", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ), + _KEY_TYPE ("GATEWAY", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ), + _KEY_TYPE ("GATEWAYDEV", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("GATEWAY_PING_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("GENERATE_MAC_ADDRESS_MASK", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("GVRP", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("HWADDR", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("HWADDR_BLACKLIST", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_ALTSUBJECT_MATCHES", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_ANON_IDENTITY", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_AUTH_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_CA_CERT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_CA_CERT_PASSWORD", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_CA_CERT_PASSWORD_FLAGS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_CLIENT_CERT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_CLIENT_CERT_PASSWORD", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_CLIENT_CERT_PASSWORD_FLAGS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_DOMAIN_MATCH", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_DOMAIN_SUFFIX_MATCH", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_EAP_METHODS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_FAST_PROVISIONING", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_IDENTITY", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_INNER_AUTH_METHODS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_INNER_CA_CERT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_INNER_CA_CERT_PASSWORD", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_INNER_CA_CERT_PASSWORD_FLAGS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_INNER_CLIENT_CERT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_INNER_CLIENT_CERT_PASSWORD", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_INNER_CLIENT_CERT_PASSWORD_FLAGS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_INNER_PRIVATE_KEY", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD_FLAGS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_OPTIONAL", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_PAC_FILE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_PASSWORD", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_PASSWORD_FLAGS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_PASSWORD_RAW", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_PASSWORD_RAW_FLAGS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_PEAP_FORCE_NEW_LABEL", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_PEAP_VERSION", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_PHASE1_AUTH_FLAGS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_PHASE2_DOMAIN_MATCH", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_PHASE2_SUBJECT_MATCH", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_PRIVATE_KEY", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_PRIVATE_KEY_PASSWORD", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_PRIVATE_KEY_PASSWORD_FLAGS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_SUBJECT_MATCH", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IEEE_8021X_SYSTEM_CA_CERTS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPADDR", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ), + _KEY_TYPE ("IPV4_DHCP_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV4_DNS_PRIORITY", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV4_FAILURE_FATAL", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV4_ROUTE_METRIC", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV4_ROUTE_TABLE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6ADDR", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6ADDR_SECONDARIES", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6FORWARDING", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6INIT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6TUNNELIPV4", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_ADDR_GEN_MODE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_AUTOCONF", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_DEFAULTDEV", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_DEFAULTGW", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_DEFROUTE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_DHCP_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_DISABLED", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_DNS_PRIORITY", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_DOMAIN", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_FAILURE_FATAL", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_PEERDNS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_PEERROUTES", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_PRIVACY", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_PRIVACY_PREFER_PUBLIC_IP", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_RA_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_RES_OPTIONS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_ROUTE_METRIC", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_ROUTE_TABLE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("IPV6_TOKEN", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("KEY", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ), + _KEY_TYPE ("KEY_MGMT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("KEY_PASSPHRASE", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ), + _KEY_TYPE ("KEY_TYPE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("LLDP", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("LLMNR", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("MACADDR", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("MAC_ADDRESS_RANDOMIZATION", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("MASTER", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("MASTER_UUID", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("MATCH_INTERFACE_NAME", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("MDNS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("METRIC", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ), + _KEY_TYPE ("MODE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("MTU", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("MULTI_CONNECT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("MVRP", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("NAME", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("NETMASK", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ), + _KEY_TYPE ("NETTYPE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("NM_CONTROLLED", NMS_IFCFG_KEY_TYPE_IS_PLAIN | NMS_IFCFG_KEY_TYPE_KEEP_WHEN_DIRTY ), + _KEY_TYPE ("NM_USER_", NMS_IFCFG_KEY_TYPE_IS_PREFIX ), + _KEY_TYPE ("ONBOOT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("OPTIONS", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ), + _KEY_TYPE ("OVS_PORT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("OVS_PORT_UUID", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("PAC_SCRIPT", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("PAC_URL", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("PEERDNS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("PEERROUTES", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("PHYSDEV", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("PKEY", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("PMF", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("PORTNAME", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("POWERSAVE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("PREFIX", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ), + _KEY_TYPE ("PROXY_METHOD", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("QDISC", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ), + _KEY_TYPE ("REORDER_HDR", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("RES_OPTIONS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("ROUTING_RULE6_", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ), + _KEY_TYPE ("ROUTING_RULE_", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ), + _KEY_TYPE ("SEARCH", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("SECONDARY_UUIDS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("SECURITYMODE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("SLAVE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("SRIOV_AUTOPROBE_DRIVERS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("SRIOV_TOTAL_VFS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("SRIOV_VF", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ), + _KEY_TYPE ("SSID_HIDDEN", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("STABLE_ID", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("STP", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("SUBCHANNELS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("TEAM_CONFIG", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("TEAM_MASTER", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("TEAM_MASTER_UUID", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("TEAM_PORT_CONFIG", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("TYPE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("USERS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("UUID", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("VLAN", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("VLAN_EGRESS_PRIORITY_MAP", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("VLAN_FLAGS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("VLAN_ID", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("VLAN_INGRESS_PRIORITY_MAP", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("VRF", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("VRF_UUID", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("WEP_KEY_FLAGS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("WPA_ALLOW_WPA", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("WPA_ALLOW_WPA2", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("WPA_PSK", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("WPA_PSK_FLAGS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("WPS_METHOD", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), + _KEY_TYPE ("ZONE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ), +}; + +const NMSIfcfgKeyTypeInfo * +nms_ifcfg_well_known_key_find_info (const char *key, gssize *out_idx) +{ + gssize idx; + + G_STATIC_ASSERT (G_STRUCT_OFFSET (NMSIfcfgKeyTypeInfo, key_name) == 0); + + idx = nm_utils_array_find_binary_search (nms_ifcfg_well_known_keys, + sizeof (nms_ifcfg_well_known_keys[0]), + G_N_ELEMENTS (nms_ifcfg_well_known_keys), + &key, + nm_strcmp_p_with_data, + NULL); + NM_SET_OUT (out_idx, idx); + if (idx < 0) + return NULL; + return &nms_ifcfg_well_known_keys[idx]; +} + +const NMSIfcfgKeyTypeInfo * +nms_ifcfg_rh_utils_is_well_known_key (const char *key) +{ + const NMSIfcfgKeyTypeInfo *ti; + gssize idx; + + nm_assert (key); + + ti = nms_ifcfg_well_known_key_find_info (key, &idx); + + if (ti) { + if (NM_FLAGS_ANY (ti->key_flags, NMS_IFCFG_KEY_TYPE_IS_PLAIN + | NMS_IFCFG_KEY_TYPE_IS_NUMBERED)) { + /* These tags are valid on full match. + * + * Note that numbered tags we also treat as valid if they have no + * suffix. That is correct for "IPADDR", but less so for "ROUTING_RULE_". */ + return ti; + } + nm_assert (NM_FLAGS_HAS (ti->key_flags, NMS_IFCFG_KEY_TYPE_IS_PREFIX)); + /* a prefix tag needs some extra suffix afterwards to be valid. */ + return NULL; + } + + /* Not found. Maybe it's a numbered/prefixed key? With idx we got the index where + * we should insert the key. Since the numbered/prefixed keys share a prefix, we can + * find the possible prefix at the index before the insert position. */ + idx = ~idx; + if (idx == 0) + return NULL; + + ti = &nms_ifcfg_well_known_keys[idx - 1]; + + if (NM_FLAGS_HAS (ti->key_flags, NMS_IFCFG_KEY_TYPE_IS_NUMBERED)) { + if (nms_ifcfg_rh_utils_is_numbered_tag (key, ti->key_name, NULL)) + return ti; + return NULL; + } + + if (NM_FLAGS_HAS (ti->key_flags, NMS_IFCFG_KEY_TYPE_IS_PREFIX)) { + gsize l = strlen (ti->key_name); + + if ( strncmp (key, ti->key_name, l) == 0 + && key[l] != '\0') + return ti; + return NULL; } return NULL; diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h index 035146ff..8941fc19 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h @@ -11,9 +11,48 @@ #include "shvar.h" -gboolean nms_ifcfg_rh_util_parse_unhandled_spec (const char *unhandled_spec, - const char **out_unmanaged_spec, - const char **out_unrecognized_spec); +/*****************************************************************************/ + +typedef enum { + NMS_IFCFG_KEY_TYPE_UNKNOWN = 0, + NMS_IFCFG_KEY_TYPE_WELL_KNOWN = (1u << 0), + + NMS_IFCFG_KEY_TYPE_IS_PLAIN = (1u << 1), + NMS_IFCFG_KEY_TYPE_IS_NUMBERED = (1u << 2), + NMS_IFCFG_KEY_TYPE_IS_PREFIX = (1u << 3), + + /* by default, well knowns keys that are not explicitly set + * by the writer (the unvisited, dirty ones) are removed. + * With this flag, such keys are kept if they are present. */ + NMS_IFCFG_KEY_TYPE_KEEP_WHEN_DIRTY = (1u << 4), + +} NMSIfcfgKeyTypeFlags; + +typedef struct { + const char *key_name; + NMSIfcfgKeyTypeFlags key_flags; +} NMSIfcfgKeyTypeInfo; + +extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[231]; + +const NMSIfcfgKeyTypeInfo *nms_ifcfg_well_known_key_find_info (const char *key, gssize *out_idx); + +static inline NMSIfcfgKeyTypeFlags +nms_ifcfg_well_known_key_find_info_flags (const char *key) +{ + const NMSIfcfgKeyTypeInfo *ti; + + ti = nms_ifcfg_well_known_key_find_info (key, NULL); + if (!ti) + return NMS_IFCFG_KEY_TYPE_UNKNOWN; + return ti->key_flags; +} + +/*****************************************************************************/ + +gboolean nms_ifcfg_rh_utils_parse_unhandled_spec (const char *unhandled_spec, + const char **out_unmanaged_spec, + const char **out_unrecognized_spec); #define NM_IFCFG_CONNECTION_LOG_PATH(path) ((path) ?: "in-memory") #define NM_IFCFG_CONNECTION_LOG_FMT "%s (%s,\"%s\")" @@ -37,6 +76,8 @@ shvarFile *utils_get_keys_ifcfg (const char *parent, gboolean should_create); shvarFile *utils_get_route_ifcfg (const char *parent, gboolean should_create); gboolean utils_has_route_file_new_syntax (const char *filename); +gboolean utils_has_route_file_new_syntax_content (const char *contents, + gsize len); gboolean utils_has_complex_routes (const char *filename, int addr_family); gboolean utils_is_ifcfg_alias_file (const char *alias, const char *ifcfg); @@ -51,6 +92,12 @@ _nms_ifcfg_rh_utils_numbered_tag (char *buf, gsize buf_len, const char *tag_name { gsize l; +#if NM_MORE_ASSERTS > 5 + nm_assert (NM_FLAGS_ALL (nms_ifcfg_well_known_key_find_info_flags (tag_name), + NMS_IFCFG_KEY_TYPE_WELL_KNOWN + | NMS_IFCFG_KEY_TYPE_IS_NUMBERED)); +#endif + l = g_strlcpy (buf, tag_name, buf_len); nm_assert (l < buf_len); if (which != -1) { @@ -70,6 +117,28 @@ _nms_ifcfg_rh_utils_numbered_tag (char *buf, gsize buf_len, const char *tag_name _nms_ifcfg_rh_utils_numbered_tag (buf, sizeof (buf), ""tag_name"", (which)); \ }) +gboolean nms_ifcfg_rh_utils_is_numbered_tag_impl (const char *key, + const char *tag, + gsize tag_len, + gint64 *out_idx); + +static inline gboolean +nms_ifcfg_rh_utils_is_numbered_tag (const char *key, + const char *tag, + gint64 *out_idx) +{ + nm_assert (tag); + + return nms_ifcfg_rh_utils_is_numbered_tag_impl (key, tag, strlen (tag), out_idx); +} + +#define NMS_IFCFG_RH_UTIL_IS_NUMBERED_TAG(key, tag, out_idx) \ + nms_ifcfg_rh_utils_is_numbered_tag_impl (key, tag, NM_STRLEN (tag), out_idx) + +/*****************************************************************************/ + +const NMSIfcfgKeyTypeInfo *nms_ifcfg_rh_utils_is_well_known_key (const char *key); + /*****************************************************************************/ extern const char *const _nm_ethtool_ifcfg_names[_NM_ETHTOOL_ID_FEATURE_NUM]; diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index 90a1a2b8..a0797fdc 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -66,10 +66,8 @@ save_secret_flags (shvarFile *ifcfg, g_return_if_fail (ifcfg != NULL); g_return_if_fail (key != NULL); - if (flags == NM_SETTING_SECRET_FLAG_NONE) { - svUnsetValue (ifcfg, key); + if (flags == NM_SETTING_SECRET_FLAG_NONE) return; - } /* Convert flags bitfield into string representation */ str = g_string_sized_new (20); @@ -100,9 +98,6 @@ set_secret (shvarFile *ifcfg, const char *flags_key, NMSettingSecretFlags flags) { - /* Clear the secret from the ifcfg and the associated "keys" file */ - svUnsetValue (ifcfg, key); - /* Save secret flags */ save_secret_flags (ifcfg, flags_key, flags); @@ -131,9 +126,6 @@ write_secrets (shvarFile *ifcfg, return FALSE; } - /* we purge all existing secrets. */ - svUnsetAll (keyfile, SV_KEY_TYPE_ANY); - secrets_keys = nm_utils_strdict_get_keys (secrets, TRUE, &secrets_keys_n); for (i = 0; i < secrets_keys_n; i++) { const char *k = secrets_keys[i]; @@ -147,7 +139,7 @@ write_secrets (shvarFile *ifcfg, if (!any_secrets) (void) unlink (svFileGetName (keyfile)); - else if (!svWriteFile (keyfile, 0600, &local)) { + else if (!svWriteFileWithoutDirtyWellknown (keyfile, 0600, &local)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Failure to write secrets to '%s': %s", svFileGetName (keyfile), local->message); return FALSE; @@ -372,12 +364,8 @@ write_8021x_setting (NMConnection *connection, int vint; s_8021x = nm_connection_get_setting_802_1x (connection); - if (!s_8021x) { - /* If wired, clear KEY_MGMT */ - if (wired) - svUnsetValue (ifcfg, "KEY_MGMT"); + if (!s_8021x) return TRUE; - } /* If wired, write KEY_MGMT */ if (wired) @@ -424,10 +412,7 @@ write_8021x_setting (NMConnection *connection, nm_setting_802_1x_get_system_ca_certs (s_8021x)); value = nm_setting_802_1x_get_phase1_peapver (s_8021x); - if (NM_IN_STRSET (value, "0", "1")) - svSetValueStr (ifcfg, "IEEE_8021X_PEAP_VERSION", value); - else - svUnsetValue (ifcfg, "IEEE_8021X_PEAP_VERSION"); + svSetValueStr (ifcfg, "IEEE_8021X_PEAP_VERSION", value); svSetValueBoolean_cond_true (ifcfg, "IEEE_8021X_PEAP_FORCE_NEW_LABEL", @@ -452,7 +437,6 @@ write_8021x_setting (NMConnection *connection, svSetValueStr (ifcfg, "IEEE_8021X_FAST_PROVISIONING", value); /* Phase2 auth methods */ - svUnsetValue (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS"); phase2_auth = g_string_new (NULL); value = nm_setting_802_1x_get_phase2_auth (s_8021x); @@ -473,9 +457,7 @@ write_8021x_setting (NMConnection *connection, } auth_flags = nm_setting_802_1x_get_phase1_auth_flags (s_8021x); - if (auth_flags == NM_SETTING_802_1X_AUTH_FLAGS_NONE) { - svUnsetValue (ifcfg, "IEEE_8021X_PHASE1_AUTH_FLAGS"); - } else { + if (auth_flags != NM_SETTING_802_1X_AUTH_FLAGS_NONE) { svSetValueEnum (ifcfg, "IEEE_8021X_PHASE1_AUTH_FLAGS", nm_setting_802_1x_auth_flags_get_type(), auth_flags); @@ -492,7 +474,6 @@ write_8021x_setting (NMConnection *connection, svSetValueStr (ifcfg, "IEEE_8021X_PHASE2_SUBJECT_MATCH", nm_setting_802_1x_get_phase2_subject_match (s_8021x)); - svUnsetValue (ifcfg, "IEEE_8021X_ALTSUBJECT_MATCHES"); str = g_string_new (NULL); num = nm_setting_802_1x_get_num_altsubject_matches (s_8021x); for (i = 0; i < num; i++) { @@ -505,7 +486,6 @@ write_8021x_setting (NMConnection *connection, svSetValueStr (ifcfg, "IEEE_8021X_ALTSUBJECT_MATCHES", str->str); g_string_free (str, TRUE); - svUnsetValue (ifcfg, "IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES"); str = g_string_new (NULL); num = nm_setting_802_1x_get_num_phase2_altsubject_matches (s_8021x); for (i = 0; i < num; i++) { @@ -523,6 +503,11 @@ write_8021x_setting (NMConnection *connection, svSetValueStr (ifcfg, "IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH", nm_setting_802_1x_get_phase2_domain_suffix_match (s_8021x)); + svSetValueStr (ifcfg, "IEEE_8021X_DOMAIN_MATCH", + nm_setting_802_1x_get_domain_match (s_8021x)); + svSetValueStr (ifcfg, "IEEE_8021X_PHASE2_DOMAIN_MATCH", + nm_setting_802_1x_get_phase2_domain_match (s_8021x)); + vint = nm_setting_802_1x_get_auth_timeout (s_8021x); svSetValueInt64_cond (ifcfg, "IEEE_8021X_AUTH_TIMEOUT", vint > 0, vint); @@ -565,14 +550,11 @@ write_wireless_security_setting (NMConnection *connection, } key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); - g_assert (key_mgmt); + nm_assert (key_mgmt); auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); - svUnsetValue (ifcfg, "DEFAULTKEY"); - if (!strcmp (key_mgmt, "none")) { - svUnsetValue (ifcfg, "KEY_MGMT"); wep = TRUE; *no_8021x = TRUE; } else if (!strcmp (key_mgmt, "wpa-psk")) { @@ -583,6 +565,10 @@ write_wireless_security_setting (NMConnection *connection, svSetValueStr (ifcfg, "KEY_MGMT", "SAE"); wpa = TRUE; *no_8021x = TRUE; + } else if (!strcmp (key_mgmt, "owe")) { + svSetValueStr (ifcfg, "KEY_MGMT", "OWE"); + wpa = FALSE; + *no_8021x = TRUE; } else if (!strcmp (key_mgmt, "ieee8021x")) { svSetValueStr (ifcfg, "KEY_MGMT", "IEEE8021X"); dynamic_wep = TRUE; @@ -591,7 +577,6 @@ write_wireless_security_setting (NMConnection *connection, wpa = TRUE; } - svUnsetValue (ifcfg, "SECURITYMODE"); if (auth_alg) { if (!strcmp (auth_alg, "shared")) svSetValueStr (ifcfg, "SECURITYMODE", "restricted"); @@ -611,11 +596,8 @@ write_wireless_security_setting (NMConnection *connection, } } - /* WPS */ wps_method = nm_setting_wireless_security_get_wps_method (s_wsec); - if (wps_method == NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT) - svUnsetValue (ifcfg, "WPS_METHOD"); - else + if (wps_method != NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT) svSetValueEnum (ifcfg, "WPS_METHOD", nm_setting_wireless_security_wps_method_get_type (), wps_method); /* WEP keys */ @@ -701,8 +683,6 @@ write_wireless_security_setting (NMConnection *connection, } /* WPA protos */ - svUnsetValue (ifcfg, "WPA_ALLOW_WPA"); - svUnsetValue (ifcfg, "WPA_ALLOW_WPA2"); num = nm_setting_wireless_security_get_num_protos (s_wsec); for (i = 0; i < num; i++) { proto = nm_setting_wireless_security_get_proto (s_wsec, i); @@ -713,7 +693,6 @@ write_wireless_security_setting (NMConnection *connection, } /* WPA Pairwise ciphers */ - svUnsetValue (ifcfg, "CIPHER_PAIRWISE"); str = g_string_new (NULL); num = nm_setting_wireless_security_get_num_pairwise (s_wsec); for (i = 0; i < num; i++) { @@ -735,7 +714,6 @@ write_wireless_security_setting (NMConnection *connection, g_string_free (str, TRUE); /* WPA Group ciphers */ - svUnsetValue (ifcfg, "CIPHER_GROUP"); str = g_string_new (NULL); num = nm_setting_wireless_security_get_num_groups (s_wsec); for (i = 0; i < num; i++) { @@ -760,16 +738,12 @@ write_wireless_security_setting (NMConnection *connection, "WPA_PSK_FLAGS", wpa ? nm_setting_wireless_security_get_psk_flags (s_wsec) : NM_SETTING_SECRET_FLAG_NONE); - if (nm_setting_wireless_security_get_pmf (s_wsec) == NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT) - svUnsetValue (ifcfg, "PMF"); - else { + if (nm_setting_wireless_security_get_pmf (s_wsec) != NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT) { svSetValueEnum (ifcfg, "PMF", nm_setting_wireless_security_pmf_get_type (), nm_setting_wireless_security_get_pmf (s_wsec)); } - if (nm_setting_wireless_security_get_fils (s_wsec) == NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT) - svUnsetValue (ifcfg, "FILS"); - else { + if (nm_setting_wireless_security_get_fils (s_wsec) != NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT) { svSetValueEnum (ifcfg, "FILS", nm_setting_wireless_security_fils_get_type (), nm_setting_wireless_security_get_fils (s_wsec)); } @@ -810,14 +784,12 @@ write_wireless_setting (NMConnection *connection, svSetValueStr (ifcfg, "GENERATE_MAC_ADDRESS_MASK", nm_setting_wireless_get_generate_mac_address_mask (s_wireless)); - svUnsetValue (ifcfg, "HWADDR_BLACKLIST"); macaddr_blacklist = nm_setting_wireless_get_mac_address_blacklist (s_wireless); if (macaddr_blacklist[0]) { - char *blacklist_str; + gs_free char *blacklist_str = NULL; blacklist_str = g_strjoinv (" ", (char **) macaddr_blacklist); svSetValueStr (ifcfg, "HWADDR_BLACKLIST", blacklist_str); - g_free (blacklist_str); } mtu = nm_setting_wireless_get_mtu (s_wireless); @@ -879,9 +851,9 @@ write_wireless_setting (NMConnection *connection, } mode = nm_setting_wireless_get_mode (s_wireless); - if (!mode) - svUnsetValue(ifcfg, "MODE"); - else if (nm_streq (mode, NM_SETTING_WIRELESS_MODE_INFRA)) + if (!mode) { + /* pass */ + } else if (nm_streq (mode, NM_SETTING_WIRELESS_MODE_INFRA)) svSetValueStr (ifcfg, "MODE", "Managed"); else if (nm_streq (mode, NM_SETTING_WIRELESS_MODE_ADHOC)) { svSetValueStr (ifcfg, "MODE", "Ad-Hoc"); @@ -895,8 +867,6 @@ write_wireless_setting (NMConnection *connection, return FALSE; } - svUnsetValue (ifcfg, "CHANNEL"); - svUnsetValue (ifcfg, "BAND"); chan = nm_setting_wireless_get_channel (s_wireless); if (chan) { svSetValueInt64 (ifcfg, "CHANNEL", chan); @@ -912,18 +882,13 @@ write_wireless_setting (NMConnection *connection, * otherwise there's no way to detect WEP vs. open when WEP keys aren't * saved. */ - svUnsetValue (ifcfg, "DEFAULTKEY"); - svUnsetValue (ifcfg, "SECURITYMODE"); if (nm_connection_get_setting_wireless_security (connection)) { if (!write_wireless_security_setting (connection, ifcfg, secrets, adhoc, no_8021x, error)) return FALSE; } else { /* Clear out wifi security keys */ - svUnsetValue (ifcfg, "KEY_MGMT"); - svUnsetValue (ifcfg, "IEEE_8021X_IDENTITY"); set_secret (ifcfg, secrets, "IEEE_8021X_PASSWORD", NULL, "IEEE_8021X_PASSWORD_FLAGS", NM_SETTING_SECRET_FLAG_NONE); - svUnsetValue (ifcfg, "SECURITYMODE"); /* Clear existing keys */ set_secret (ifcfg, secrets, "KEY", NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE); @@ -937,11 +902,6 @@ write_wireless_setting (NMConnection *connection, set_secret (ifcfg, secrets, tag, NULL, "WEP_KEY_FLAGS", NM_SETTING_SECRET_FLAG_NONE); } - svUnsetValue (ifcfg, "DEFAULTKEY"); - svUnsetValue (ifcfg, "WPA_ALLOW_WPA"); - svUnsetValue (ifcfg, "WPA_ALLOW_WPA2"); - svUnsetValue (ifcfg, "CIPHER_PAIRWISE"); - svUnsetValue (ifcfg, "CIPHER_GROUP"); set_secret (ifcfg, secrets, "WPA_PSK", NULL, "WPA_PSK_FLAGS", NM_SETTING_SECRET_FLAG_NONE); } @@ -959,7 +919,6 @@ write_wireless_setting (NMConnection *connection, break; default: case NM_SETTING_WIRELESS_POWERSAVE_DEFAULT: - svUnsetValue (ifcfg, "POWERSAVE"); break; } @@ -1050,8 +1009,7 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) blacklist_str = g_strjoinv (" ", (char **) macaddr_blacklist); svSetValueStr (ifcfg, "HWADDR_BLACKLIST", blacklist_str); - } else - svUnsetValue (ifcfg, "HWADDR_BLACKLIST"); + } mtu = nm_setting_wired_get_mtu (s_wired); svSetValueInt64_cond (ifcfg, "MTU", mtu != 0, mtu); @@ -1085,7 +1043,6 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) svSetValueStr (ifcfg, "CTCPROT", nm_setting_wired_get_s390_option_by_key (s_wired, "ctcprot")); - svUnsetValue (ifcfg, "OPTIONS"); num_opts = nm_setting_wired_get_num_s390_options (s_wired); if (s390_subchannels && num_opts) { nm_auto_free_gstring GString *tmp = NULL; @@ -1137,11 +1094,9 @@ write_ethtool_setting (NMConnection *connection, shvarFile *ifcfg, GError **erro s_wired = nm_connection_get_setting_wired (connection); s_ethtool = NM_SETTING_ETHTOOL (nm_connection_get_setting (connection, NM_TYPE_SETTING_ETHTOOL)); - if (!s_wired && !s_ethtool) { - svUnsetValue (ifcfg, "ETHTOOL_WAKE_ON_LAN"); - svUnsetValue (ifcfg, "ETHTOOL_OPTS"); + if ( !s_wired + && !s_ethtool) return TRUE; - } if (s_wired) { auto_negotiate = nm_setting_wired_get_auto_negotiate (s_wired); @@ -1200,8 +1155,7 @@ write_ethtool_setting (NMConnection *connection, shvarFile *ifcfg, GError **erro if (wol_password && NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) g_string_append_printf (str, "s sopass %s", wol_password); } - } else - svUnsetValue (ifcfg, "ETHTOOL_WAKE_ON_LAN"); + } if (s_ethtool) { NMEthtoolID ethtool_id; @@ -1246,8 +1200,7 @@ write_ethtool_setting (NMConnection *connection, shvarFile *ifcfg, GError **erro if (str) { svSetValueStr (ifcfg, "ETHTOOL_OPTS", str->str); g_string_free (str, TRUE); - } else - svUnsetValue (ifcfg, "ETHTOOL_OPTS"); + } return TRUE; } @@ -1346,10 +1299,6 @@ write_vlan_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired, svSetValueStr (ifcfg, "VLAN_EGRESS_PRIORITY_MAP", tmp); g_free (tmp); - svUnsetValue (ifcfg, "HWADDR"); - svUnsetValue (ifcfg, "MACADDR"); - svUnsetValue (ifcfg, "MTU"); - *wired = write_wired_for_virtual (connection, ifcfg); return TRUE; @@ -1368,8 +1317,6 @@ write_bond_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired, return FALSE; } - svUnsetValue (ifcfg, "BONDING_OPTS"); - num_opts = nm_setting_bond_get_num_options (s_bond); if (num_opts) { nm_auto_free_gstring GString *str = NULL; @@ -1463,10 +1410,9 @@ write_bridge_vlans (NMSetting *setting, g_object_get (setting, property_name, &vlans, NULL); - if (!vlans || !vlans->len) { - svUnsetValue (ifcfg, key); + if ( !vlans + || !vlans->len) return TRUE; - } string = g_string_new (""); for (i = 0; i < vlans->len; i++) { @@ -1492,8 +1438,8 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire NMSettingBridge *s_bridge; guint32 i; gboolean b; + const char *s; GString *opts; - const char *mac; s_bridge = nm_connection_get_setting_bridge (connection); if (!s_bridge) { @@ -1502,12 +1448,10 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire return FALSE; } - svUnsetValue (ifcfg, "BRIDGING_OPTS"); svSetValueBoolean (ifcfg, "STP", FALSE); - svUnsetValue (ifcfg, "DELAY"); - mac = nm_setting_bridge_get_mac_address (s_bridge); - svSetValueStr (ifcfg, "BRIDGE_MACADDR", mac); + s = nm_setting_bridge_get_mac_address (s_bridge); + svSetValueStr (ifcfg, "BRIDGE_MACADDR", s); /* Bridge options */ opts = g_string_sized_new (32); @@ -1543,6 +1487,13 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire g_string_append_printf (opts, "ageing_time=%u", i); } + s = nm_setting_bridge_get_group_address (s_bridge); + if (s) { + if (opts->len) + g_string_append_c (opts, ' '); + g_string_append_printf (opts, "group_address=%s", s); + } + i = nm_setting_bridge_get_group_forward_mask (s_bridge); if (i != get_setting_default_uint (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_GROUP_FORWARD_MASK)) { if (opts->len) @@ -1550,6 +1501,20 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire g_string_append_printf (opts, "group_fwd_mask=%u", i); } + b = nm_setting_bridge_get_multicast_querier (s_bridge); + if (b != get_setting_default_boolean (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_MULTICAST_QUERIER)) { + if (opts->len) + g_string_append_c (opts, ' '); + g_string_append_printf (opts, "multicast_querier=%u", (guint) b); + } + + b = nm_setting_bridge_get_multicast_query_use_ifaddr (s_bridge); + if (b != get_setting_default_boolean (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR)) { + if (opts->len) + g_string_append_c (opts, ' '); + g_string_append_printf (opts, "multicast_query_use_ifaddr=%u", (guint) b); + } + b = nm_setting_bridge_get_multicast_snooping (s_bridge); if (b != get_setting_default_boolean (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_MULTICAST_SNOOPING)) { if (opts->len) @@ -1557,6 +1522,13 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire g_string_append_printf (opts, "multicast_snooping=%u", (guint32) b); } + s = nm_setting_bridge_get_multicast_router (s_bridge); + if (s) { + if (opts->len) + g_string_append_c (opts, ' '); + g_string_append_printf (opts, "multicast_router=%s", s); + } + b = nm_setting_bridge_get_vlan_filtering (s_bridge); if (b != get_setting_default_boolean (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_VLAN_FILTERING)) { if (opts->len) @@ -1571,6 +1543,20 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire g_string_append_printf (opts, "default_pvid=%u", i); } + s = nm_setting_bridge_get_vlan_protocol (s_bridge); + if (s) { + if (opts->len) + g_string_append_c (opts, ' '); + g_string_append_printf (opts, "vlan_protocol=%s", s); + } + + b = nm_setting_bridge_get_vlan_stats_enabled (s_bridge); + if (b != get_setting_default_boolean (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_VLAN_STATS_ENABLED)) { + if (opts->len) + g_string_append_c (opts, ' '); + g_string_append_printf (opts, "vlan_stats_enabled=%u", (guint) b); + } + if (opts->len) svSetValueStr (ifcfg, "BRIDGING_OPTS", opts->str); g_string_free (opts, TRUE); @@ -1600,8 +1586,6 @@ write_bridge_port_setting (NMConnection *connection, shvarFile *ifcfg, GError ** if (!s_port) return TRUE; - svUnsetValue (ifcfg, "BRIDGING_OPTS"); - /* Bridge options */ string = g_string_sized_new (32); @@ -1677,11 +1661,11 @@ write_dcb_app (shvarFile *ifcfg, write_dcb_flags (ifcfg, tag, flags); - nm_sprintf_buf (prop, "DCB_%s_PRIORITY", tag); - if ((flags & NM_SETTING_DCB_FLAG_ENABLE) && (priority >= 0)) + if ( (flags & NM_SETTING_DCB_FLAG_ENABLE) + && (priority >= 0)) { + nm_sprintf_buf (prop, "DCB_%s_PRIORITY", tag); svSetValueInt64 (ifcfg, prop, priority); - else - svUnsetValue (ifcfg, prop); + } } typedef gboolean (*DcbGetBoolFunc) (NMSettingDcb *, guint); @@ -1696,10 +1680,8 @@ write_dcb_bool_array (shvarFile *ifcfg, char str[9]; guint i; - if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) { - svUnsetValue (ifcfg, key); + if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) return; - } str[8] = 0; for (i = 0; i < 8; i++) @@ -1719,10 +1701,8 @@ write_dcb_uint_array (shvarFile *ifcfg, char str[9]; guint i, num; - if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) { - svUnsetValue (ifcfg, key); + if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) return; - } str[8] = 0; for (i = 0; i < 8; i++) { @@ -1747,10 +1727,8 @@ write_dcb_percent_array (shvarFile *ifcfg, GString *str; guint i; - if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) { - svUnsetValue (ifcfg, key); + if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) return; - } str = g_string_sized_new (30); for (i = 0; i < 8; i++) { @@ -1769,38 +1747,8 @@ write_dcb_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) NMSettingDcbFlags flags; s_dcb = nm_connection_get_setting_dcb (connection); - if (!s_dcb) { - static const char *clear_keys[] = { - "DCB", - KEY_DCB_APP_FCOE_ENABLE, - KEY_DCB_APP_FCOE_ADVERTISE, - KEY_DCB_APP_FCOE_WILLING, - KEY_DCB_APP_FCOE_MODE, - KEY_DCB_APP_ISCSI_ENABLE, - KEY_DCB_APP_ISCSI_ADVERTISE, - KEY_DCB_APP_ISCSI_WILLING, - KEY_DCB_APP_FIP_ENABLE, - KEY_DCB_APP_FIP_ADVERTISE, - KEY_DCB_APP_FIP_WILLING, - KEY_DCB_PFC_ENABLE, - KEY_DCB_PFC_ADVERTISE, - KEY_DCB_PFC_WILLING, - KEY_DCB_PFC_UP, - KEY_DCB_PG_ENABLE, - KEY_DCB_PG_ADVERTISE, - KEY_DCB_PG_WILLING, - KEY_DCB_PG_ID, - KEY_DCB_PG_PCT, - KEY_DCB_PG_UPPCT, - KEY_DCB_PG_STRICT, - KEY_DCB_PG_UP2TC, - NULL }; - const char **iter; - - for (iter = clear_keys; *iter; iter++) - svUnsetValue (ifcfg, *iter); + if (!s_dcb) return TRUE; - } svSetValueStr (ifcfg, "DCB", "yes"); @@ -1809,8 +1757,6 @@ write_dcb_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) nm_setting_dcb_get_app_fcoe_priority (s_dcb)); if (nm_setting_dcb_get_app_fcoe_flags (s_dcb) & NM_SETTING_DCB_FLAG_ENABLE) svSetValueStr (ifcfg, KEY_DCB_APP_FCOE_MODE, nm_setting_dcb_get_app_fcoe_mode (s_dcb)); - else - svUnsetValue (ifcfg, KEY_DCB_APP_FCOE_MODE); write_dcb_app (ifcfg, "APP_ISCSI", nm_setting_dcb_get_app_iscsi_flags (s_dcb), @@ -1877,9 +1823,7 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) svSetValueStr (ifcfg, "AUTOCONNECT_SLAVES", autoconnect_slaves == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_YES ? "yes" : autoconnect_slaves == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_NO ? "no" : NULL); - } else - svUnsetValue (ifcfg, "AUTOCONNECT_SLAVES"); - + } switch (nm_setting_connection_get_lldp (s_con)) { case NM_SETTING_CONNECTION_LLDP_ENABLE_RX: tmp = "rx"; @@ -1893,7 +1837,6 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) svSetValueStr (ifcfg, "LLDP", tmp); /* Permissions */ - svUnsetValue (ifcfg, "USERS"); n = nm_setting_connection_get_num_permissions (s_con); if (n > 0) { str = g_string_sized_new (n * 20); @@ -1923,8 +1866,6 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) svSetValueStr (ifcfg, "BRIDGE", NULL); svSetValueStr (ifcfg, "TEAM_MASTER_UUID", NULL); svSetValueStr (ifcfg, "TEAM_MASTER", NULL); - svSetValueStr (ifcfg, "OVS_PORT_UUID", NULL); - svSetValueStr (ifcfg, "OVS_PORT", NULL); master = nm_setting_connection_get_master (s_con); if (master) { @@ -1957,6 +1898,9 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) } else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_OVS_PORT_SETTING_NAME)) { svSetValueStr (ifcfg, "OVS_PORT_UUID", master); svSetValueStr (ifcfg, "OVS_PORT", master_iface); + } else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_VRF_SETTING_NAME)) { + svSetValueStr (ifcfg, "VRF_UUID", master); + svSetValueStr (ifcfg, "VRF", master_iface); } else { _LOGW ("don't know how to set master for a %s slave", nm_setting_connection_get_slave_type (s_con)); @@ -1967,11 +1911,8 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) svSetValueStr (ifcfg, "DEVICETYPE", TYPE_TEAM); else if (master_iface && nm_setting_connection_is_slave_type (s_con, NM_SETTING_TEAM_SETTING_NAME)) svSetValueStr (ifcfg, "DEVICETYPE", TYPE_TEAM_PORT); - else - svUnsetValue (ifcfg, "DEVICETYPE"); /* secondary connection UUIDs */ - svUnsetValue (ifcfg, "SECONDARY_UUIDS"); n = nm_setting_connection_get_num_secondaries (s_con); if (n > 0) { str = g_string_sized_new (n * 37); @@ -2004,17 +1945,19 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) case NM_METERED_NO: svSetValueStr (ifcfg, "CONNECTION_METERED", "no"); break; - default: - svUnsetValue (ifcfg, "CONNECTION_METERED"); + case NM_METERED_UNKNOWN: + case NM_METERED_GUESS_YES: + case NM_METERED_GUESS_NO: + break; } vint = nm_setting_connection_get_auth_retries (s_con); svSetValueInt64_cond (ifcfg, "AUTH_RETRIES", vint >= 0, vint); vint32 = nm_setting_connection_get_wait_device_timeout (s_con); - if (vint32 == -1) - svUnsetValue (ifcfg, "DEVTIMEOUT"); - else if ((vint32 % 1000) == 0) + if (vint32 == -1) { + /* pass */ + } else if ((vint32 % 1000) == 0) svSetValueInt64 (ifcfg, "DEVTIMEOUT", vint32 / 1000); else { char b[100]; @@ -2028,15 +1971,13 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) if (mdns != NM_SETTING_CONNECTION_MDNS_DEFAULT) { svSetValueEnum (ifcfg, "MDNS", nm_setting_connection_mdns_get_type (), mdns); - } else - svUnsetValue (ifcfg, "MDNS"); + } llmnr = nm_setting_connection_get_llmnr (s_con); if (llmnr != NM_SETTING_CONNECTION_LLMNR_DEFAULT) { svSetValueEnum (ifcfg, "LLMNR", nm_setting_connection_llmnr_get_type (), llmnr); - } else - svUnsetValue (ifcfg, "LLMNR"); + } } static char * @@ -2119,8 +2060,6 @@ write_route_file_svformat (const char *filename, NMSettingIPConfig *s_ip4) routefile = utils_get_route_ifcfg (filename, TRUE); - svUnsetAll (routefile, SV_KEY_TYPE_ROUTE_SVFORMAT); - num = nm_setting_ip_config_get_num_routes (s_ip4); for (i = 0; i < num; i++) { char buf[INET_ADDRSTRLEN]; @@ -2144,7 +2083,7 @@ write_route_file_svformat (const char *filename, NMSettingIPConfig *s_ip4) netmask = _nm_utils_ip4_prefix_to_netmask (nm_ip_route_get_prefix (route)); svSetValueStr (routefile, netmask_key, - nm_utils_inet4_ntop (netmask, buf)); + _nm_utils_inet4_ntop (netmask, buf)); svSetValueStr (routefile, gw_key, nm_ip_route_get_next_hop (route)); @@ -2221,10 +2160,6 @@ write_proxy_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) if (!s_proxy) return TRUE; - svUnsetValue (ifcfg, "BROWSER_ONLY"); - svUnsetValue (ifcfg, "PAC_URL"); - svUnsetValue (ifcfg, "PAC_SCRIPT"); - method = nm_setting_proxy_get_method (s_proxy); switch (method) { case NM_SETTING_PROXY_METHOD_AUTO: @@ -2258,8 +2193,6 @@ write_user_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) s_user = NM_SETTING_USER (nm_connection_get_setting (connection, NM_TYPE_SETTING_USER)); - svUnsetAll (ifcfg, SV_KEY_TYPE_USER); - if (!s_user) return TRUE; @@ -2292,13 +2225,9 @@ write_sriov_setting (NMConnection *connection, shvarFile *ifcfg) char key[32]; char *str; - svUnsetAll (ifcfg, SV_KEY_TYPE_SRIOV_VF); - s_sriov = NM_SETTING_SRIOV (nm_connection_get_setting (connection, NM_TYPE_SETTING_SRIOV)); if (!s_sriov) { - svUnsetValue (ifcfg, "SRIOV_TOTAL_VFS"); - svUnsetValue (ifcfg, "SRIOV_AUTOPROBE_DRIVERS"); return; } @@ -2307,8 +2236,6 @@ write_sriov_setting (NMConnection *connection, shvarFile *ifcfg) b = nm_setting_sriov_get_autoprobe_drivers (s_sriov); if (b != NM_TERNARY_DEFAULT) svSetValueInt64 (ifcfg, "SRIOV_AUTOPROBE_DRIVERS", b); - else - svUnsetValue (ifcfg, "SRIOV_AUTOPROBE_DRIVERS"); num = nm_setting_sriov_get_num_vfs (s_sriov); for (i = 0; i < num; i++) { @@ -2327,8 +2254,6 @@ write_tc_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) guint i, num, n; char tag[64]; - svUnsetAll (ifcfg, SV_KEY_TYPE_TC); - s_tc = nm_connection_get_setting_tc_config (connection); if (!s_tc) return TRUE; @@ -2371,8 +2296,6 @@ write_match_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) nm_auto_free_gstring GString *str = NULL; guint i, num; - svUnsetValue (ifcfg, "MATCH_INTERFACE_NAME"); - s_match = (NMSettingMatch *) nm_connection_get_setting (connection, NM_TYPE_SETTING_MATCH); if (!s_match) return TRUE; @@ -2404,10 +2327,8 @@ write_res_options (shvarFile *ifcfg, NMSettingIPConfig *s_ip, const char *var) nm_auto_free_gstring GString *value = NULL; guint i, num_options; - if (!nm_setting_ip_config_has_dns_options (s_ip)) { - svUnsetValue (ifcfg, var); + if (!nm_setting_ip_config_has_dns_options (s_ip)) return; - } value = g_string_new (NULL); num_options = nm_setting_ip_config_get_num_dns_options (s_ip); @@ -2420,6 +2341,47 @@ write_res_options (shvarFile *ifcfg, NMSettingIPConfig *s_ip, const char *var) svSetValue (ifcfg, var, value->str); } +static void +write_dns_setting (shvarFile *ifcfg, + NMConnection *connection, + int addr_family) +{ + NMSettingIPConfig *s_ip; + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6 = NULL; + guint num4; + guint num6 = 0; + guint num; + guint i; + guint offset; + + if (addr_family == AF_INET6) { + s_ip6 = nm_connection_get_setting_ip6_config (connection); + num6 = s_ip6 ? nm_setting_ip_config_get_num_dns (s_ip6) : 0u; + } + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + num4 = s_ip4 ? nm_setting_ip_config_get_num_dns (s_ip4) : 0u; + + if (addr_family == AF_INET6) { + num = num6; + offset = num4; + s_ip = s_ip6; + } else { + num = num4; + offset = 0; + s_ip = s_ip4; + } + + for (i = 0; i < num; i++) { + char tag[64]; + + svSetValueStr (ifcfg, + numbered_tag (tag, "DNS", offset + i + 1u), + nm_setting_ip_config_get_dns (s_ip, i)); + } +} + static gboolean write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, @@ -2446,16 +2408,8 @@ write_ip4_setting (NMConnection *connection, NM_SET_OUT (out_route_content, NULL); s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (!s_ip4) { - /* slave-type: clear IPv4 settings. - * - * Some IPv4 setting related options are not cleared, - * for no strong reason. */ - svUnsetValue (ifcfg, "BOOTPROTO"); - svUnsetValue (ifcfg, "RES_OPTIONS"); - svUnsetAll (ifcfg, SV_KEY_TYPE_IP4_ADDRESS); + if (!s_ip4) return TRUE; - } method = nm_setting_ip_config_get_method (s_ip4); @@ -2463,17 +2417,8 @@ write_ip4_setting (NMConnection *connection, if (!method) method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; - if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) { - /* IPv4 disabled, clear IPv4 related parameters */ - svUnsetValue (ifcfg, "BOOTPROTO"); - for (j = -1; j < 256; j++) { - svUnsetValue (ifcfg, numbered_tag (tag, "IPADDR", j)); - svUnsetValue (ifcfg, numbered_tag (tag, "PREFIX", j)); - svUnsetValue (ifcfg, numbered_tag (tag, "NETMASK", j)); - svUnsetValue (ifcfg, numbered_tag (tag, "GATEWAY", j)); - } + if (nm_streq (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) return TRUE; - } num = nm_setting_ip_config_get_num_addresses (s_ip4); @@ -2490,7 +2435,7 @@ write_ip4_setting (NMConnection *connection, else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) svSetValueStr (ifcfg, "BOOTPROTO", "shared"); - has_netmask = !!svFindFirstKeyWithPrefix (ifcfg, "NETMASK"); + has_netmask = !!svFindFirstNumberedKey (ifcfg, "NETMASK"); /* Write out IPADDR<n>, PREFIX<n>, GATEWAY<n> for current IP addresses * without labels. Unset obsolete NETMASK<n>. @@ -2532,45 +2477,15 @@ write_ip4_setting (NMConnection *connection, char buf[INET_ADDRSTRLEN]; svSetValueStr (ifcfg, tag, - nm_utils_inet4_ntop (_nm_utils_ip4_prefix_to_netmask (prefix), buf)); - } else - svUnsetValue (ifcfg, tag); + _nm_utils_inet4_ntop (_nm_utils_ip4_prefix_to_netmask (prefix), buf)); + } n++; } - svUnsetValue (ifcfg, numbered_tag (tag, "IPADDR", 0)); - svUnsetValue (ifcfg, numbered_tag (tag, "PREFIX", 0)); - svUnsetValue (ifcfg, numbered_tag (tag, "NETMASK", 0)); - if (n == 0) { - svUnsetValue (ifcfg, "IPADDR"); - svUnsetValue (ifcfg, "PREFIX"); - svUnsetValue (ifcfg, "NETMASK"); - } - for (j = n; j < 256; j++) { - svUnsetValue (ifcfg, numbered_tag (tag, "IPADDR", j)); - svUnsetValue (ifcfg, numbered_tag (tag, "PREFIX", j)); - svUnsetValue (ifcfg, numbered_tag (tag, "NETMASK", j)); - } - - for (j = -1; j < 256; j++) { - if (j != 0) - svUnsetValue (ifcfg, numbered_tag (tag, "GATEWAY", j)); - } svSetValueStr (ifcfg, "GATEWAY", nm_setting_ip_config_get_gateway (s_ip4)); - num = nm_setting_ip_config_get_num_dns (s_ip4); - for (i = 0; i < 254; i++) { - const char *dns; - - numbered_tag (tag, "DNS", i + 1); - if (i >= num) - svUnsetValue (ifcfg, tag); - else { - dns = nm_setting_ip_config_get_dns (s_ip4, i); - svSetValueStr (ifcfg, tag, dns); - } - } + write_dns_setting (ifcfg, connection, AF_INET); num = nm_setting_ip_config_get_num_dns_searches (s_ip4); if (num > 0) { @@ -2582,8 +2497,7 @@ write_ip4_setting (NMConnection *connection, } svSetValueStr (ifcfg, "DOMAIN", searches->str); g_string_free (searches, TRUE); - } else - svUnsetValue (ifcfg, "DOMAIN"); + } /* DEFROUTE; remember that it has the opposite meaning from never-default */ svSetValueBoolean (ifcfg, "DEFROUTE", !nm_setting_ip_config_get_never_default (s_ip4)); @@ -2644,8 +2558,7 @@ write_ip4_setting (NMConnection *connection, timeout = nm_setting_ip_config_get_dad_timeout (s_ip4); if (timeout < 0) { - svUnsetValue (ifcfg, "ACD_TIMEOUT"); - svUnsetValue (ifcfg, "ARPING_WAIT"); + /* pass */ } else if (timeout == 0) { svSetValueStr (ifcfg, "ACD_TIMEOUT", "0"); svSetValueStr (ifcfg, "ARPING_WAIT", "0"); @@ -2658,8 +2571,6 @@ write_ip4_setting (NMConnection *connection, priority = nm_setting_ip_config_get_dns_priority (s_ip4); if (priority) svSetValueInt64 (ifcfg, "IPV4_DNS_PRIORITY", priority); - else - svUnsetValue (ifcfg, "IPV4_DNS_PRIORITY"); write_res_options (ifcfg, s_ip4, "RES_OPTIONS"); @@ -2745,7 +2656,7 @@ write_ip4_aliases (NMConnection *connection, const char *base_ifcfg_path) svSetValueInt64 (ifcfg, "PREFIX", nm_ip_address_get_prefix(addr)); - svWriteFile (ifcfg, 0644, NULL); + svWriteFileWithoutDirtyWellknown (ifcfg, 0644, NULL); svCloseFile (ifcfg); } } @@ -2757,12 +2668,10 @@ write_ip6_setting (NMConnection *connection, GError **error) { NMSettingIPConfig *s_ip6; - NMSettingIPConfig *s_ip4; const char *value; - guint i, num, num4; + guint i, num; int priority; NMIPAddress *addr; - const char *dns; gint64 route_metric; NMIPRouteTableSyncMode route_table; GString *ip_str1, *ip_str2, *ip_ptr; @@ -2774,45 +2683,21 @@ write_ip6_setting (NMConnection *connection, NM_SET_OUT (out_route6_content, NULL); s_ip6 = nm_connection_get_setting_ip6_config (connection); - if (!s_ip6) { - /* slave-type: clear IPv6 settings - * - * Some IPv6 setting related options are not cleared, - * for no strong reason. */ - svUnsetValue (ifcfg, "IPV6INIT"); - svUnsetValue (ifcfg, "IPV6_AUTOCONF"); - svUnsetValue (ifcfg, "DHCPV6C"); - svUnsetValue (ifcfg, "DHCPv6_DUID"); - svUnsetValue (ifcfg, "DHCPv6_IAID"); - svUnsetValue (ifcfg, "DHCPV6_HOSTNAME"); - svUnsetValue (ifcfg, "DHCPV6_SEND_HOSTNAME"); - svUnsetValue (ifcfg, "IPV6_DEFROUTE"); - svUnsetValue (ifcfg, "IPV6_PEERDNS"); - svUnsetValue (ifcfg, "IPV6_PEERROUTES"); - svUnsetValue (ifcfg, "IPV6_FAILURE_FATAL"); - svUnsetValue (ifcfg, "IPV6_ROUTE_METRIC"); - svUnsetValue (ifcfg, "IPV6_ADDR_GEN_MODE"); - svUnsetValue (ifcfg, "IPV6_RES_OPTIONS"); + if (!s_ip6) return TRUE; - } value = nm_setting_ip_config_get_method (s_ip6); g_assert (value); - svUnsetValue (ifcfg, "IPV6_DISABLED"); if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) { svSetValueStr (ifcfg, "IPV6INIT", "no"); - svUnsetValue (ifcfg, "DHCPV6C"); return TRUE; } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) { svSetValueStr (ifcfg, "IPV6_DISABLED", "yes"); svSetValueStr (ifcfg, "IPV6INIT", "no"); - svUnsetValue (ifcfg, "DHCPV6C"); - svUnsetValue (ifcfg, "IPV6_AUTOCONF"); return TRUE; } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) { svSetValueStr (ifcfg, "IPV6INIT", "yes"); svSetValueStr (ifcfg, "IPV6_AUTOCONF", "yes"); - svUnsetValue (ifcfg, "DHCPV6C"); } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) { svSetValueStr (ifcfg, "IPV6INIT", "yes"); svSetValueStr (ifcfg, "IPV6_AUTOCONF", "no"); @@ -2820,15 +2705,12 @@ write_ip6_setting (NMConnection *connection, } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) { svSetValueStr (ifcfg, "IPV6INIT", "yes"); svSetValueStr (ifcfg, "IPV6_AUTOCONF", "no"); - svUnsetValue (ifcfg, "DHCPV6C"); } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) { svSetValueStr (ifcfg, "IPV6INIT", "yes"); svSetValueStr (ifcfg, "IPV6_AUTOCONF", "no"); - svUnsetValue (ifcfg, "DHCPV6C"); } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) { svSetValueStr (ifcfg, "IPV6INIT", "yes"); svSetValueStr (ifcfg, "IPV6_AUTOCONF", "shared"); - svUnsetValue (ifcfg, "DHCPV6C"); } svSetValueStr (ifcfg, "DHCPV6_DUID", @@ -2842,9 +2724,7 @@ write_ip6_setting (NMConnection *connection, /* Missing DHCPV6_SEND_HOSTNAME means TRUE, and we prefer not write it * explicitly in that case, because it is NM-specific variable */ - if (nm_setting_ip_config_get_dhcp_send_hostname (s_ip6)) - svUnsetValue (ifcfg, "DHCPV6_SEND_HOSTNAME"); - else + if (!nm_setting_ip_config_get_dhcp_send_hostname (s_ip6)) svSetValueStr (ifcfg, "DHCPV6_SEND_HOSTNAME", "no"); timeout = nm_setting_ip6_config_get_ra_timeout (NM_SETTING_IP6_CONFIG (s_ip6)); @@ -2889,22 +2769,7 @@ write_ip6_setting (NMConnection *connection, g_string_free (ip_str1, TRUE); g_string_free (ip_str2, TRUE); - /* Write out DNS - 'DNS' key is used both for IPv4 and IPv6 */ - s_ip4 = nm_connection_get_setting_ip4_config (connection); - num4 = s_ip4 ? nm_setting_ip_config_get_num_dns (s_ip4) : 0; /* from where to start with IPv6 entries */ - num = nm_setting_ip_config_get_num_dns (s_ip6); - for (i = 0; i < 254; i++) { - char tag[64]; - - numbered_tag (tag, "DNS", i + num4 + 1); - - if (i >= num) - svUnsetValue (ifcfg, tag); - else { - dns = nm_setting_ip_config_get_dns (s_ip6, i); - svSetValueStr (ifcfg, tag, dns); - } - } + write_dns_setting (ifcfg, connection, AF_INET6); /* Write out DNS domains */ num = nm_setting_ip_config_get_num_dns_searches (s_ip6); @@ -2918,15 +2783,11 @@ write_ip6_setting (NMConnection *connection, g_string_append (searches, nm_setting_ip_config_get_dns_search (s_ip6, i)); } svSetValueStr (ifcfg, "IPV6_DOMAIN", searches->str); - } else - svUnsetValue (ifcfg, "IPV6_DOMAIN"); + } /* handle IPV6_DEFROUTE */ /* IPV6_DEFROUTE has the opposite meaning from 'never-default' */ - if (nm_setting_ip_config_get_never_default (s_ip6)) - svSetValueStr (ifcfg, "IPV6_DEFROUTE", "no"); - else - svSetValueStr (ifcfg, "IPV6_DEFROUTE", "yes"); + svSetValueBoolean (ifcfg, "IPV6_DEFROUTE", !nm_setting_ip_config_get_never_default (s_ip6)); svSetValueStr (ifcfg, "IPV6_PEERDNS", nm_setting_ip_config_get_ignore_auto_dns (s_ip6) ? "no" : NULL); @@ -2950,8 +2811,6 @@ write_ip6_setting (NMConnection *connection, route_table); /* IPv6 Privacy Extensions */ - svUnsetValue (ifcfg, "IPV6_PRIVACY"); - svUnsetValue (ifcfg, "IPV6_PRIVACY_PREFER_PUBLIC_IP"); switch (nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6))) { case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: svSetValueStr (ifcfg, "IPV6_PRIVACY", "no"); @@ -2972,8 +2831,6 @@ write_ip6_setting (NMConnection *connection, if (addr_gen_mode != NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) { svSetValueEnum (ifcfg, "IPV6_ADDR_GEN_MODE", nm_setting_ip6_config_addr_gen_mode_get_type (), addr_gen_mode); - } else { - svUnsetValue (ifcfg, "IPV6_ADDR_GEN_MODE"); } /* IPv6 tokenized interface identifier */ @@ -2983,8 +2840,6 @@ write_ip6_setting (NMConnection *connection, priority = nm_setting_ip_config_get_dns_priority (s_ip6); if (priority) svSetValueInt64 (ifcfg, "IPV6_DNS_PRIORITY", priority); - else - svUnsetValue (ifcfg, "IPV6_DNS_PRIORITY"); write_res_options (ifcfg, s_ip6, "IPV6_RES_OPTIONS"); @@ -3001,8 +2856,6 @@ write_ip_routing_rules (NMConnection *connection, gsize idx; int is_ipv4; - svUnsetAll (ifcfg, SV_KEY_TYPE_ROUTING_RULE4 | SV_KEY_TYPE_ROUTING_RULE6); - if (route_ignore) return; @@ -3233,8 +3086,6 @@ do_write_construct (NMConnection *connection, if (!write_tc_setting (connection, ifcfg, error)) return FALSE; - svUnsetValue (ifcfg, "DHCP_HOSTNAME"); - svUnsetValue (ifcfg, "DHCP_FQDN"); route_path_is_svformat = utils_has_route_file_new_syntax (route_path); @@ -3321,7 +3172,7 @@ do_write_to_disk (NMConnection *connection, * only. But we loaded the ifcfg files from disk, and managled our * new settings (in-memory). */ - if (!svWriteFile (ifcfg, 0644, error)) + if (!svWriteFileWithoutDirtyWellknown (ifcfg, 0644, error)) return FALSE; write_ip4_aliases (connection, svFileGetName (ifcfg)); @@ -3340,7 +3191,7 @@ do_write_to_disk (NMConnection *connection, else { nm_assert (route_content_svformat || route_content); if (route_content_svformat) { - if (!svWriteFile (route_content_svformat, 0644, error)) + if (!svWriteFileWithoutDirtyWellknown (route_content_svformat, 0644, error)) return FALSE; } else { if (!g_file_set_contents (route_path, route_content->str, route_content->len, NULL)) { @@ -3450,6 +3301,11 @@ nms_ifcfg_rh_writer_write_connection (NMConnection *connection, _LOGW ("write: failure to re-read connection \"%s\": %s", svFileGetName (ifcfg), "connection is unhandled"); } else { + /* ifcfg-rh doesn't support the 'timestamp' property, let's add it here */ + g_object_set (nm_connection_get_setting_connection (reread), + NM_SETTING_CONNECTION_TIMESTAMP, + nm_setting_connection_get_timestamp (nm_connection_get_setting_connection (connection)), + NULL); if (out_reread_same) { reread_same = nm_connection_compare (reread, connection, NM_SETTING_COMPARE_FLAG_EXACT); if (!reread_same) { diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c index 16b2dd37..f2a1dd78 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.c +++ b/src/settings/plugins/ifcfg-rh/shvar.c @@ -19,13 +19,23 @@ #include "nm-glib-aux/nm-enum-utils.h" #include "nm-glib-aux/nm-io-utils.h" #include "c-list/src/c-list.h" +#include "nms-ifcfg-rh-utils.h" /*****************************************************************************/ struct _shvarLine { + const char *key; + CList lst; + /* We index variables by their key in shvarFile.lst_idx. One shell variable might + * occur multiple times in a file (in which case the last occurrence wins). + * Hence, we need to keep a list of all the same keys. + * + * This is a pointer to the next shadowed line. */ + struct _shvarLine *prev_shadowed; + /* There are three cases: * * 1) the line is not a valid variable assignment (that is, it doesn't @@ -43,21 +53,41 @@ struct _shvarLine { * @key/@key_with_prefix. * */ char *line; - const char *key; char *key_with_prefix; + + /* svSetValue() will clear the dirty flag. */ + bool dirty:1; }; typedef struct _shvarLine shvarLine; struct _shvarFile { - char *fileName; - int fd; - CList lst_head; - gboolean modified; + char *fileName; + CList lst_head; + GHashTable *lst_idx; + int fd; + bool modified:1; }; /*****************************************************************************/ +static void _line_link_parse (shvarFile *s, const char *value, gsize len); + +/*****************************************************************************/ + +#define ASSERT_key_is_well_known(key) \ + nm_assert ( ({ \ + const char *_key = (key); \ + gboolean _is_wellknown = TRUE; \ + \ + if (!nms_ifcfg_rh_utils_is_well_known_key (_key)) { \ + _is_wellknown = FALSE; \ + g_critical ("ifcfg-rh key \"%s\" is not well-known", _key); \ + } \ + \ + _is_wellknown; \ + }) ) + /** * svParseBoolean: * @value: the input string @@ -603,15 +633,33 @@ out_error: /*****************************************************************************/ -static shvarFile * -svFile_new (const char *name) +shvarFile * +svFile_new (const char *name, + int fd, + const char *content) { shvarFile *s; + const char *p; + const char *q; + + nm_assert (name); + nm_assert (fd >= -1); + + s = g_slice_new (shvarFile); + *s = (shvarFile) { + .fileName = g_strdup (name), + .fd = fd, + .lst_head = C_LIST_INIT (s->lst_head), + .lst_idx = g_hash_table_new (nm_pstr_hash, nm_pstr_equal), + }; + + if (content) { + for (p = content; (q = strchr (p, '\n')) != NULL; p = q + 1) + _line_link_parse (s, p, q - p); + if (p[0]) + _line_link_parse (s, p, strlen (p)); + } - s = g_slice_new0 (shvarFile); - s->fd = -1; - s->fileName = g_strdup (name); - c_list_init (&s->lst_head); return s; } @@ -671,8 +719,11 @@ line_new_parse (const char *value, gsize len) nm_assert (value); - line = g_slice_new0 (shvarLine); - c_list_init (&line->lst); + line = g_slice_new (shvarLine); + *line = (shvarLine) { + .lst = C_LIST_INIT (line->lst), + .dirty = TRUE, + }; for (k = 0; k < len; k++) { if (g_ascii_isspace (value[k])) @@ -706,14 +757,19 @@ line_new_build (const char *key, const char *value) { char *value_escaped = NULL; shvarLine *line; + char *new_key; value = svEscape (value, &value_escaped); line = g_slice_new (shvarLine); - c_list_init (&line->lst); - line->line = value_escaped ?: g_strdup (value); - line->key_with_prefix = g_strdup (key); - line->key = line->key_with_prefix; + new_key = g_strdup (key), + *line = (shvarLine) { + .lst = C_LIST_INIT (line->lst), + .line = value_escaped ?: g_strdup (value), + .key_with_prefix = new_key, + .key = new_key, + .dirty = FALSE, + }; ASSERT_shvarLine (line); return line; } @@ -727,6 +783,8 @@ line_set (shvarLine *line, const char *value) ASSERT_shvarLine (line); nm_assert (line->key); + line->dirty = FALSE; + if (line->key != line->key_with_prefix) { memmove (line->key_with_prefix, line->key, strlen (line->key) + 1); line->key = line->key_with_prefix; @@ -753,14 +811,48 @@ static void line_free (shvarLine *line) { ASSERT_shvarLine (line); + c_list_unlink_stale (&line->lst); g_free (line->line); g_free (line->key_with_prefix); - c_list_unlink_stale (&line->lst); g_slice_free (shvarLine, line); } /*****************************************************************************/ +static void +_line_link_parse (shvarFile *s, const char *value, gsize len) +{ + shvarLine *line; + + line = line_new_parse (value, len); + if (!line->key) + goto do_link; + + if (G_UNLIKELY (!g_hash_table_insert (s->lst_idx, line, line))) { + shvarLine *existing_key; + shvarLine *existing_val; + + /* Slow-path: we have duplicate keys. Fix the mess we created. + * Unfortunately, g_hash_table_insert() now had to allocate an extra + * array to track the keys/values differently. I wish there was an + * GHashTable API to add a key only if it does not exist yet. */ + + if (!g_hash_table_lookup_extended (s->lst_idx, line, (gpointer *) &existing_key, (gpointer *) &existing_val)) + nm_assert_not_reached (); + + nm_assert (existing_val == line); + nm_assert (existing_key != line); + line->prev_shadowed = existing_key; + g_hash_table_replace (s->lst_idx, line, line); + } + +do_link: + c_list_link_tail (&s->lst_head, &line->lst); +} + +/*****************************************************************************/ + + /* Open the file <name>, returning a shvarFile on success and NULL on failure. * Add a wrinkle to let the caller specify whether or not to create the file * (actually, return a structure anyway) if it doesn't exist. @@ -768,11 +860,9 @@ line_free (shvarLine *line) static shvarFile * svOpenFileInternal (const char *name, gboolean create, GError **error) { - shvarFile *s; gboolean closefd = FALSE; int errsv = 0; - gs_free char *arena = NULL; - const char *p, *q; + gs_free char *content = NULL; gs_free_error GError *local = NULL; nm_auto_close int fd = -1; @@ -789,7 +879,7 @@ svOpenFileInternal (const char *name, gboolean create, GError **error) if (fd < 0) { if (create) - return svFile_new (name); + return svFile_new (name, -1, NULL); g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errsv), "Could not read file '%s': %s", @@ -801,12 +891,12 @@ svOpenFileInternal (const char *name, gboolean create, GError **error) closefd, 10 * 1024 * 1024, NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &arena, + &content, NULL, NULL, &local)) { if (create) - return svFile_new (name); + return svFile_new (name, -1, NULL); g_set_error (error, G_FILE_ERROR, local->domain == G_FILE_ERROR ? local->code : G_FILE_ERROR_FAILED, @@ -815,21 +905,14 @@ svOpenFileInternal (const char *name, gboolean create, GError **error) return NULL; } - s = svFile_new (name); - - for (p = arena; (q = strchr (p, '\n')) != NULL; p = q + 1) - c_list_link_tail (&s->lst_head, &line_new_parse (p, q - p)->lst); - if (p[0]) - c_list_link_tail (&s->lst_head, &line_new_parse (p, strlen (p))->lst); - /* closefd is set if we opened the file read-only, so go ahead and * close it, because we can't write to it anyway */ - if (!closefd) { - nm_assert (fd > 0); - s->fd = nm_steal_fd (&fd); - } - - return s; + nm_assert (closefd || fd >= 0); + return svFile_new (name, + !closefd + ? nm_steal_fd (&fd) + : -1, + content); } /* Open the file <name>, return shvarFile on success, NULL on failure */ @@ -851,54 +934,32 @@ svCreateFile (const char *name) /*****************************************************************************/ static gboolean -_is_all_digits (const char *str) +_svKeyMatchesType (const char *key, SvKeyType match_key_type) { - return str[0] - && NM_STRCHAR_ALL (str, ch, g_ascii_isdigit (ch)); -} - -#define IS_NUMBERED_TAG(key, tab_name) \ - ({ \ - const char *_key2 = (key); \ - \ - ( (strncmp (_key2, tab_name, NM_STRLEN (tab_name)) == 0) \ - && _is_all_digits (&_key2[NM_STRLEN (tab_name)])); \ - }) + if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_ANY)) + return TRUE; -#define IS_NUMBERED_TAG_PARSE(key, tab_name, out_idx) \ +#define _IS_NUMBERED(key, tag) \ ({ \ - const char *_key = (key); \ gint64 _idx; \ - gboolean _good = FALSE; \ - gint64 *_out_idx = (out_idx); \ \ - if ( IS_NUMBERED_TAG (_key, ""tab_name"") \ - && (_idx = _nm_utils_ascii_str_to_int64 (&_key[NM_STRLEN (tab_name)], 10, 0, G_MAXINT64, -1)) != -1) { \ - NM_SET_OUT (_out_idx, _idx); \ - _good = TRUE; \ - } \ - _good; \ + NMS_IFCFG_RH_UTIL_IS_NUMBERED_TAG (key, tag, &_idx) \ + && _idx >= 0; \ }) -static gboolean -_svKeyMatchesType (const char *key, SvKeyType match_key_type) -{ - if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_ANY)) - return TRUE; - if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_ROUTE_SVFORMAT)) { - if ( IS_NUMBERED_TAG (key, "ADDRESS") - || IS_NUMBERED_TAG (key, "NETMASK") - || IS_NUMBERED_TAG (key, "GATEWAY") - || IS_NUMBERED_TAG (key, "METRIC") - || IS_NUMBERED_TAG (key, "OPTIONS")) + if ( _IS_NUMBERED (key, "ADDRESS") + || _IS_NUMBERED (key, "NETMASK") + || _IS_NUMBERED (key, "GATEWAY") + || _IS_NUMBERED (key, "METRIC") + || _IS_NUMBERED (key, "OPTIONS")) return TRUE; } if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_IP4_ADDRESS)) { - if ( IS_NUMBERED_TAG (key, "IPADDR") - || IS_NUMBERED_TAG (key, "PREFIX") - || IS_NUMBERED_TAG (key, "NETMASK") - || IS_NUMBERED_TAG (key, "GATEWAY")) + if ( _IS_NUMBERED (key, "IPADDR") + || _IS_NUMBERED (key, "PREFIX") + || _IS_NUMBERED (key, "NETMASK") + || _IS_NUMBERED (key, "GATEWAY")) return TRUE; } if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_USER)) { @@ -906,20 +967,20 @@ _svKeyMatchesType (const char *key, SvKeyType match_key_type) return TRUE; } if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_TC)) { - if ( IS_NUMBERED_TAG (key, "QDISC") - || IS_NUMBERED_TAG (key, "FILTER")) + if ( _IS_NUMBERED (key, "QDISC") + || _IS_NUMBERED (key, "FILTER")) return TRUE; } if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_SRIOV_VF)) { - if (IS_NUMBERED_TAG (key, "SRIOV_VF")) + if (_IS_NUMBERED (key, "SRIOV_VF")) return TRUE; } if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_ROUTING_RULE4)) { - if (IS_NUMBERED_TAG_PARSE (key, "ROUTING_RULE_", NULL)) + if (_IS_NUMBERED (key, "ROUTING_RULE_")) return TRUE; } if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_ROUTING_RULE6)) { - if (IS_NUMBERED_TAG_PARSE (key, "ROUTING_RULE6_", NULL)) + if (_IS_NUMBERED (key, "ROUTING_RULE6_")) return TRUE; } @@ -931,9 +992,8 @@ svNumberedParseKey (const char *key) { gint64 idx; - if (IS_NUMBERED_TAG_PARSE (key, "ROUTING_RULE_", &idx)) - return idx; - if (IS_NUMBERED_TAG_PARSE (key, "ROUTING_RULE6_", &idx)) + if ( NMS_IFCFG_RH_UTIL_IS_NUMBERED_TAG (key, "ROUTING_RULE_", &idx) + || NMS_IFCFG_RH_UTIL_IS_NUMBERED_TAG (key, "ROUTING_RULE6_", &idx)) return idx; return -1; } @@ -1001,20 +1061,18 @@ svGetKeysSorted (shvarFile *s, /*****************************************************************************/ const char * -svFindFirstKeyWithPrefix (shvarFile *s, const char *key_prefix) +svFindFirstNumberedKey (shvarFile *s, const char *key_prefix) { - CList *current; - const shvarLine *l; + const shvarLine *line; g_return_val_if_fail (s, NULL); g_return_val_if_fail (key_prefix, NULL); - c_list_for_each (current, &s->lst_head) { - l = c_list_entry (current, shvarLine, lst); - if ( l->key - && l->line - && g_str_has_prefix (l->key, key_prefix)) - return l->key; + c_list_for_each_entry (line, &s->lst_head, lst) { + if ( line->key + && line->line + && nms_ifcfg_rh_utils_is_numbered_tag (line->key, key_prefix, NULL)) + return line->key; } return NULL; @@ -1025,20 +1083,16 @@ svFindFirstKeyWithPrefix (shvarFile *s, const char *key_prefix) static const char * _svGetValue (shvarFile *s, const char *key, char **to_free) { - CList *current; - const shvarLine *line, *l; + const shvarLine *line; const char *v; nm_assert (s); nm_assert (_shell_is_name (key, -1)); nm_assert (to_free); - line = NULL; - c_list_for_each (current, &s->lst_head) { - l = c_list_entry (current, shvarLine, lst); - if (l->key && nm_streq (l->key, key)) - line = l; - } + ASSERT_key_is_well_known (key); + + line = g_hash_table_lookup (s->lst_idx, &key); if (line && line->line) { v = svUnescape (line->line, to_free); @@ -1229,24 +1283,53 @@ svGetValueEnum (shvarFile *s, const char *key, gboolean svUnsetAll (shvarFile *s, SvKeyType match_key_type) { - CList *current; shvarLine *line; gboolean changed = FALSE; g_return_val_if_fail (s, FALSE); - c_list_for_each (current, &s->lst_head) { - line = c_list_entry (current, shvarLine, lst); + c_list_for_each_entry (line, &s->lst_head, lst) { ASSERT_shvarLine (line); - if (!line->key) - continue; + if ( line->key + && _svKeyMatchesType (line->key, match_key_type)) { + if (nm_clear_g_free (&line->line)) { + ASSERT_shvarLine (line); + changed = TRUE; + } + } + } - if (_svKeyMatchesType (line->key, match_key_type)) { + if (changed) + s->modified = TRUE; + return changed; +} + +gboolean +svUnsetDirtyWellknown (shvarFile *s, NMTernary new_dirty_value) +{ + shvarLine *line; + gboolean changed = FALSE; + + g_return_val_if_fail (s, FALSE); + + c_list_for_each_entry (line, &s->lst_head, lst) { + const NMSIfcfgKeyTypeInfo *ti; + + ASSERT_shvarLine (line); + + if ( line->dirty + && line->key + && line->line + && (ti = nms_ifcfg_rh_utils_is_well_known_key (line->key)) + && !NM_FLAGS_HAS (ti->key_flags, NMS_IFCFG_KEY_TYPE_KEEP_WHEN_DIRTY)) { if (nm_clear_g_free (&line->line)) { ASSERT_shvarLine (line); changed = TRUE; } } + + if (new_dirty_value != NM_TERNARY_DEFAULT) + line->dirty = (new_dirty_value != NM_TERNARY_FALSE); } if (changed) @@ -1259,8 +1342,8 @@ svUnsetAll (shvarFile *s, SvKeyType match_key_type) gboolean svSetValue (shvarFile *s, const char *key, const char *value) { - CList *current; - shvarLine *line, *l; + shvarLine *line; + shvarLine *l_shadowed; gboolean changed = FALSE; g_return_val_if_fail (s, FALSE); @@ -1268,29 +1351,37 @@ svSetValue (shvarFile *s, const char *key, const char *value) nm_assert (_shell_is_name (key, -1)); - line = NULL; - c_list_for_each (current, &s->lst_head) { - l = c_list_entry (current, shvarLine, lst); - if (l->key && nm_streq (l->key, key)) { - if (line) { - /* if we find multiple entries for the same key, we can - * delete all but the last. */ - line_free (line); - changed = TRUE; - } - line = l; - } + ASSERT_key_is_well_known (key); + + line = g_hash_table_lookup (s->lst_idx, &key); + if ( line + && (l_shadowed = line->prev_shadowed)) { + /* if we find multiple entries for the same key, we can + * delete the shadowed ones. */ + line->prev_shadowed = NULL; + changed = TRUE; + do { + shvarLine *l = l_shadowed; + + l_shadowed = l_shadowed->prev_shadowed; + line_free (l); + } while (l_shadowed); } if (!value) { if (line) { + /* We only clear the value, but leave the line entry. This way, if we + * happen to re-add the value, we write it to the same line again. */ if (nm_clear_g_free (&line->line)) { changed = TRUE; } } } else { if (!line) { - c_list_link_tail (&s->lst_head, &line_new_build (key, value)->lst); + line = line_new_build (key, value); + if (!g_hash_table_add (s->lst_idx, line)) + nm_assert_not_reached (); + c_list_link_tail (&s->lst_head, &line->lst); changed = TRUE; } else { if (line_set (line, value)) @@ -1442,14 +1533,15 @@ svWriteFile (shvarFile *s, int mode, GError **error) void svCloseFile (shvarFile *s) { - CList *current, *safe; + shvarLine *line; g_return_if_fail (s != NULL); if (s->fd >= 0) nm_close (s->fd); g_free (s->fileName); - c_list_for_each_safe (current, safe, &s->lst_head) - line_free (c_list_entry (current, shvarLine, lst)); + g_hash_table_destroy (s->lst_idx); + while ((line = c_list_first_entry (&s->lst_head, shvarLine, lst))) + line_free (line); g_slice_free (shvarFile, s); } diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/settings/plugins/ifcfg-rh/shvar.h index c3bbabab..410284f8 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.h +++ b/src/settings/plugins/ifcfg-rh/shvar.h @@ -24,13 +24,21 @@ const char *svFileGetName (const shvarFile *s); void _nmtst_svFileSetName (shvarFile *s, const char *fileName); void _nmtst_svFileSetModified (shvarFile *s); +/*****************************************************************************/ + +shvarFile *svFile_new (const char *name, + int fd, + const char *content); + /* Create the file <name>, return a shvarFile (never fails) */ shvarFile *svCreateFile (const char *name); /* Open the file <name>, return shvarFile on success, NULL on failure */ shvarFile *svOpenFile (const char *name, GError **error); -const char *svFindFirstKeyWithPrefix (shvarFile *s, const char *key_prefix); +/*****************************************************************************/ + +const char *svFindFirstNumberedKey (shvarFile *s, const char *key_prefix); /* Get the value associated with the key, and leave the current pointer * pointing at the line containing the value. The char* returned MUST @@ -79,6 +87,7 @@ gboolean svSetValueEnum (shvarFile *s, const char *key, GType gtype, int value); gboolean svUnsetValue (shvarFile *s, const char *key); gboolean svUnsetAll (shvarFile *s, SvKeyType match_key_type); +gboolean svUnsetDirtyWellknown (shvarFile *s, NMTernary new_dirty_value); /* Write the current contents iff modified. Returns FALSE on error * and TRUE on success. Do not write if no values have been modified. @@ -88,6 +97,13 @@ gboolean svUnsetAll (shvarFile *s, SvKeyType match_key_type); */ gboolean svWriteFile (shvarFile *s, int mode, GError **error); +static inline gboolean +svWriteFileWithoutDirtyWellknown (shvarFile *s, int mode, GError **error) +{ + svUnsetDirtyWellknown (s, NM_TERNARY_FALSE); + return svWriteFile (s, mode, error); +} + /* Close the file descriptor (if open) and free the shvarFile. */ void svCloseFile (shvarFile *s); diff --git a/src/settings/plugins/ifcfg-rh/tests/meson.build b/src/settings/plugins/ifcfg-rh/tests/meson.build index 21699045..1ce61c90 100644 --- a/src/settings/plugins/ifcfg-rh/tests/meson.build +++ b/src/settings/plugins/ifcfg-rh/tests/meson.build @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1+ + test_unit = 'test-ifcfg-rh' exe = executable( diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected index d4785ff5..2e69c5e7 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected @@ -1,6 +1,5 @@ HWADDR=00:22:15:59:62:97 TYPE=Ethernet -BRIDGING_OPTS="priority=28 hairpin_mode=1" NAME="System test-bridge-component" UUID=${UUID} DEVICE=eth0 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected index 36df7712..b288c04a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected @@ -1,4 +1,4 @@ -BONDING_OPTS="downdelay=5 miimon=100 mode=balance-rr updelay=10" +BONDING_OPTS="mode=balance-rr downdelay=5 miimon=100 updelay=10" TYPE=Bond BONDING_MASTER=yes HWADDR= diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected index 5dfdce4d..87493ac2 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected @@ -2,7 +2,6 @@ DNS1=192.0.2.1 IPADDR=102.0.2.2 GATEWAY=192.0.2.1 NETMASK=255.254.0.0 -BOOTPROTO="static" DEVICE=eth1 ONBOOT=yes IPV6INIT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-owe b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-owe new file mode 100644 index 00000000..354046ad --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-owe @@ -0,0 +1,5 @@ +TYPE=Wireless +DEVICE=wlan1 +ESSID=blahblah_owe +MODE=Managed +KEY_MGMT=OWE diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk index a78051aa..4ab45ae3 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk @@ -16,4 +16,4 @@ CIPHER_GROUP="TKIP CCMP WEP40 WEP104" KEY_MGMT=WPA-PSK WPA_ALLOW_WPA=yes WPA_ALLOW_WPA2=yes -LAST_ENTRY=no-newline \ No newline at end of file +CTCPROT=no-newline \ No newline at end of file diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip index dc47126c..e683db3c 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip @@ -3,3 +3,4 @@ DEVICE=eth0 BOOTPROTO=autoip IPV4_FAILURE_FATAL=yes PEERDNS=no +DEVTIMEOUT=2.6 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4 index 2c1b7fb4..f834464e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4 +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4 @@ -5,32 +5,32 @@ # don't consider only line-by-line, thus this is # expected. # -# Also note that setting NAME will replace the last +# Also note that setting IPADDR will replace the last # occurrence, and delete all previous once. #L1 -NAME=l2 +IPADDR=l2 #L2 -NAME=l3 +IPADDR=l3 -some_key1='' -some_key2=$'\U0x' -some_key3=$'x\U0' +METRIC1='' +METRIC2=$'\U0x' +METRIC3=$'x\U0' #L4 -NAME=' -NAME=l4x +IPADDR=' +IPADDR=l4x ' #Lx-1 -NAME2=not-visible +IPADDR2=not-visible #Lx-2 -NAME2='invalid +IPADDR2='invalid #Lx-3 #Ly-1 -NAME3='invalid +IPADDR3='invalid #Ly-2 -NAME3=name3-value +IPADDR3=name3-value #Ly-3 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4.expected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4.expected index cf3f45bd..040ddc9d 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4.expected +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4.expected @@ -5,27 +5,27 @@ # don't consider only line-by-line, thus this is # expected. # -# Also note that setting NAME will replace the last +# Also note that setting IPADDR will replace the last # occurrence, and delete all previous once. #L1 #L2 -some_key1='' -some_key2=$'\U0x' -some_key3=$'x\U0' +METRIC1='' +METRIC2=$'\U0x' +METRIC3=$'x\U0' #L4 -NAME=set-by-test1 +IPADDR=set-by-test1 #NM: ' #Lx-1 #Lx-2 -NAME2=set-by-test2 +IPADDR2=set-by-test2 #Lx-3 #Ly-1 #Ly-2 -NAME3=set-by-test3 +IPADDR3=set-by-test3 #Ly-3 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 675421d3..efa9ea9b 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -1738,6 +1738,7 @@ static void test_read_wired_autoip (void) { gs_unref_object NMConnection *connection = NULL; + NMSettingConnection *s_con; NMSettingIPConfig *s_ip4; char *unmanaged = NULL; @@ -1751,6 +1752,9 @@ test_read_wired_autoip (void) g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL); g_assert (!nm_setting_ip_config_get_may_fail (s_ip4)); g_assert (nm_setting_ip_config_get_ignore_auto_dns (s_ip4)); + + s_con = nm_connection_get_setting_connection (connection); + g_assert_cmpint (nm_setting_connection_get_wait_device_timeout (s_con), ==, 2600); } static void @@ -2094,7 +2098,7 @@ test_read_wired_aliases_good (gconstpointer test_data) g_assert (ip4_addr != NULL); addr = nm_ip_address_get_address (ip4_addr); - g_assert (nm_utils_ipaddr_valid (AF_INET, addr)); + g_assert (nm_utils_ipaddr_is_valid (AF_INET, addr)); for (j = 0; j < expected_num_addresses; j++) { if (!g_strcmp0 (addr, expected_address[j])) @@ -2868,7 +2872,7 @@ test_ifcfg_no_trailing_newline (void) shvarFile *sv; sv = _svOpenFile (TEST_IFCFG_DIR"/ifcfg-test-wifi-wpa-psk"); - _svGetValue_check (sv, "LAST_ENTRY", "no-newline"); + _svGetValue_check (sv, "CTCPROT", "no-newline"); svCloseFile (sv); } @@ -3035,6 +3039,45 @@ test_read_wifi_sae (void) } static void +test_read_wifi_owe (void) +{ + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection *s_con; + NMSettingWireless *s_wireless; + NMSettingWirelessSecurity *s_wsec; + GBytes *ssid; + const char *expected_ssid = "blahblah_owe"; + + connection = _connection_from_file (TEST_IFCFG_DIR"/ifcfg-test-wifi-owe", + NULL, TYPE_WIRELESS, NULL); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System blahblah_owe (test-wifi-owe)"); + + g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, 0); + g_assert (nm_setting_connection_get_autoconnect (s_con)); + + s_wireless = nm_connection_get_setting_wireless (connection); + g_assert (s_wireless); + + g_assert_cmpint (nm_setting_wireless_get_mtu (s_wireless), ==, 0); + + ssid = nm_setting_wireless_get_ssid (s_wireless); + g_assert (ssid); + g_assert_cmpmem (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid), expected_ssid, strlen (expected_ssid)); + + g_assert (!nm_setting_wireless_get_bssid (s_wireless)); + g_assert_cmpstr (nm_setting_wireless_get_mode (s_wireless), ==, "infrastructure"); + + s_wsec = nm_connection_get_setting_wireless_security (connection); + g_assert (s_wsec); + g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "owe"); + g_assert (!nm_setting_wireless_security_get_psk (s_wsec)); + g_assert (!nm_setting_wireless_security_get_auth_alg (s_wsec)); +} + +static void test_read_wifi_wpa_psk_2 (void) { NMConnection *connection; @@ -9742,23 +9785,23 @@ test_write_unknown (gconstpointer test_data) _nmtst_svFileSetModified (sv); if (g_str_has_suffix (testfile, "ifcfg-test-write-unknown-4")) { - _svGetValue_check (sv, "NAME", "l4x"); - _svGetValue_check (sv, "NAME2", ""); - _svGetValue_check (sv, "NAME3", "name3-value"); - - svSetValue (sv, "NAME", "set-by-test1"); - svSetValue (sv, "NAME2", NULL); - svSetValue (sv, "NAME2", "set-by-test2"); - svSetValue (sv, "NAME3", "set-by-test3"); - - _svGetValue_check (sv, "some_key", NULL); - _svGetValue_check (sv, "some_key1", ""); - _svGetValue_check (sv, "some_key2", ""); - _svGetValue_check (sv, "some_key3", "x"); - - _svGetValue_check (sv, "NAME", "set-by-test1"); - _svGetValue_check (sv, "NAME2", "set-by-test2"); - _svGetValue_check (sv, "NAME3", "set-by-test3"); + _svGetValue_check (sv, "IPADDR", "l4x"); + _svGetValue_check (sv, "IPADDR2", ""); + _svGetValue_check (sv, "IPADDR3", "name3-value"); + + svSetValue (sv, "IPADDR", "set-by-test1"); + svSetValue (sv, "IPADDR2", NULL); + svSetValue (sv, "IPADDR2", "set-by-test2"); + svSetValue (sv, "IPADDR3", "set-by-test3"); + + _svGetValue_check (sv, "METRIC", NULL); + _svGetValue_check (sv, "METRIC1", ""); + _svGetValue_check (sv, "METRIC2", ""); + _svGetValue_check (sv, "METRIC3", "x"); + + _svGetValue_check (sv, "IPADDR", "set-by-test1"); + _svGetValue_check (sv, "IPADDR2", "set-by-test2"); + _svGetValue_check (sv, "IPADDR3", "set-by-test3"); } success = svWriteFile (sv, 0644, &error); @@ -10203,6 +10246,160 @@ test_tc_write (void) /*****************************************************************************/ +static void +test_well_known_keys (void) +{ + gsize i; + + for (i = 0; i < G_N_ELEMENTS (nms_ifcfg_well_known_keys); i++) { + const NMSIfcfgKeyTypeInfo *ti = &nms_ifcfg_well_known_keys[i]; + + g_assert (ti->key_name); + g_assert (ti->key_name[0]); + g_assert (NM_FLAGS_HAS (ti->key_flags, NMS_IFCFG_KEY_TYPE_WELL_KNOWN)); + g_assert (nm_utils_is_power_of_two (ti->key_flags & ( NMS_IFCFG_KEY_TYPE_IS_PLAIN + | NMS_IFCFG_KEY_TYPE_IS_NUMBERED + | NMS_IFCFG_KEY_TYPE_IS_PREFIX))); + } + + for (i = 1; i < G_N_ELEMENTS (nms_ifcfg_well_known_keys); i++) { + const NMSIfcfgKeyTypeInfo *ti_prev = &nms_ifcfg_well_known_keys[i - 1]; + const NMSIfcfgKeyTypeInfo *ti = &nms_ifcfg_well_known_keys[i]; + + g_assert_cmpstr (ti_prev->key_name, <, ti->key_name); + } + + for (i = 0; i < G_N_ELEMENTS (nms_ifcfg_well_known_keys); i++) { + const NMSIfcfgKeyTypeInfo *ti = &nms_ifcfg_well_known_keys[i]; + gs_free char *key_name = NULL; + gssize idx; + + g_assert (ti == nms_ifcfg_well_known_key_find_info (ti->key_name, &idx)); + g_assert_cmpint (i, ==, idx); + + key_name = g_strdup (ti->key_name); + g_assert (ti == nms_ifcfg_well_known_key_find_info (key_name, &idx)); + g_assert_cmpint (i, ==, idx); + } + +#define _test_well_known(key, expected) \ + G_STMT_START { \ + const NMSIfcfgKeyTypeInfo *_ti; \ + const char *_expected = (expected); \ + \ + _ti = nms_ifcfg_rh_utils_is_well_known_key (""key""); \ + if (!_expected) { \ + g_assert (!_ti); \ + } else { \ + g_assert (_ti); \ + g_assert_cmpstr (_ti->key_name, ==, _expected); \ + } \ + } G_STMT_END + +#define _test_well_known_plain(key) \ + _test_well_known (""key"", ""key"") + + _test_well_known_plain ("ONBOOT"); + _test_well_known ("NM_USER_", NULL); + _test_well_known ("NM_USER_x", "NM_USER_"); + _test_well_known ("IPADDR", "IPADDR"); + _test_well_known ("IPADDR1", "IPADDR"); + _test_well_known ("IPADDRx", NULL); +} + +/*****************************************************************************/ + +static void +_do_utils_has_route_file_new_syntax_size (gboolean has_new_syntax, + const char *content, + gssize content_len) +{ + nmtst_auto_unlinkfile char *testfile = g_strdup (TEST_SCRATCH_DIR"/utils-has-route-file-new-syntax-test.txt"); + gboolean val; + + nmtst_file_set_contents_size (testfile, content, content_len); + + val = utils_has_route_file_new_syntax (testfile); + + g_assert_cmpint (val, ==, has_new_syntax); +} +#define _do_utils_has_route_file_new_syntax(has_new_syntax, content) \ + _do_utils_has_route_file_new_syntax_size (has_new_syntax, (content), NM_STRLEN (content)) + +static void +test_utils_has_route_file_new_syntax (void) +{ + _do_utils_has_route_file_new_syntax (TRUE, ""); + _do_utils_has_route_file_new_syntax (FALSE, "\0"); + _do_utils_has_route_file_new_syntax (FALSE, "\n"); + _do_utils_has_route_file_new_syntax (FALSE, "ADDRESS=bogus"); + _do_utils_has_route_file_new_syntax (FALSE, "ADDRESS=bogus\0"); + _do_utils_has_route_file_new_syntax (TRUE, "ADDRESS1=b\0ogus\0"); + _do_utils_has_route_file_new_syntax (TRUE, "ADDRESS1=bogus\0"); + _do_utils_has_route_file_new_syntax (TRUE, "\n\n\tADDRESS1=bogus\0"); + _do_utils_has_route_file_new_syntax (FALSE, "\n\n\tADDRESS=bogus\n"); + _do_utils_has_route_file_new_syntax (TRUE, "\n\n\tADDRESS=bogus\n ADDRESS000=\n"); + _do_utils_has_route_file_new_syntax (FALSE, "\n\n\tROUTE1=bogus\n ADDRES=\n"); + _do_utils_has_route_file_new_syntax (FALSE, "\n\n\tADDRESS=bogus\n ADDRESS\000000=\n"); +} + +/*****************************************************************************/ + +static void +test_ethtool_names (void) +{ + static const struct { + NMEthtoolID ethtool_id; + const char *kernel_name; + } kernel_names[] = { + { NM_ETHTOOL_ID_FEATURE_GRO, "rx-gro" }, + { NM_ETHTOOL_ID_FEATURE_GSO, "tx-generic-segmentation" }, + { NM_ETHTOOL_ID_FEATURE_LRO, "rx-lro" }, + { NM_ETHTOOL_ID_FEATURE_NTUPLE, "rx-ntuple-filter" }, + { NM_ETHTOOL_ID_FEATURE_RX, "rx-checksum" }, + { NM_ETHTOOL_ID_FEATURE_RXHASH, "rx-hashing" }, + { NM_ETHTOOL_ID_FEATURE_RXVLAN, "rx-vlan-hw-parse" }, + { NM_ETHTOOL_ID_FEATURE_TXVLAN, "tx-vlan-hw-insert" }, + }; + const NMEthtoolData *data; + NMEthtoolID id; + int i; + + for (id = _NM_ETHTOOL_ID_FEATURE_FIRST; id <= _NM_ETHTOOL_ID_FEATURE_LAST; id++) { + const char *ifcfg_rh_name; + int idx; + + idx = id - _NM_ETHTOOL_ID_FEATURE_FIRST; + g_assert (idx >= 0); + g_assert (idx < G_N_ELEMENTS (_nm_ethtool_ifcfg_names)); + ifcfg_rh_name = _nm_ethtool_ifcfg_names[idx]; + g_assert (ifcfg_rh_name && ifcfg_rh_name[0]); + + for (i = 0; i < G_N_ELEMENTS (_nm_ethtool_ifcfg_names); i++) { + if (i != idx) + g_assert_cmpstr (ifcfg_rh_name, !=, _nm_ethtool_ifcfg_names[i]); + } + + g_assert_cmpstr (nms_ifcfg_rh_utils_get_ethtool_name (id), ==, ifcfg_rh_name); + + data = nms_ifcfg_rh_utils_get_ethtool_by_name (ifcfg_rh_name); + g_assert (data); + g_assert (data->id == id); + } + + for (i = 0; i < G_N_ELEMENTS (kernel_names); i++) { + const char *name = kernel_names[i].kernel_name; + + id = kernel_names[i].ethtool_id; + data = nms_ifcfg_rh_utils_get_ethtool_by_name (name); + g_assert (data); + g_assert (data->id == id); + g_assert_cmpstr (nms_ifcfg_rh_utils_get_ethtool_name (id), !=, name); + } +} + +/*****************************************************************************/ + #define TPATH "/settings/plugins/ifcfg-rh/" #define TEST_IFCFG_WIFI_OPEN_SSID_LONG_QUOTED TEST_IFCFG_DIR"/ifcfg-test-wifi-open-ssid-long-quoted" @@ -10322,6 +10519,7 @@ int main (int argc, char **argv) g_test_add_func (TPATH "wifi/read/wpa-psk/adhoc", test_read_wifi_wpa_psk_adhoc); g_test_add_func (TPATH "wifi/read/wpa-psk/hex", test_read_wifi_wpa_psk_hex); g_test_add_func (TPATH "wifi/read/sae", test_read_wifi_sae); + g_test_add_func (TPATH "wifi/read/owe", test_read_wifi_owe); g_test_add_func (TPATH "wifi/read/dynamic-wep/leap", test_read_wifi_dynamic_wep_leap); g_test_add_func (TPATH "wifi/read/wpa/eap/tls", test_read_wifi_wpa_eap_tls); g_test_add_func (TPATH "wifi/read/wpa/eap/ttls/tls", test_read_wifi_wpa_eap_ttls_tls); @@ -10498,6 +10696,10 @@ int main (int argc, char **argv) g_test_add_func (TPATH "tc/read", test_tc_read); g_test_add_func (TPATH "tc/write", test_tc_write); + g_test_add_func (TPATH "utils/test_well_known_keys", test_well_known_keys); + g_test_add_func (TPATH "utils/test_utils_has_route_file_new_syntax", test_utils_has_route_file_new_syntax); + + g_test_add_func (TPATH "utils/test_ethtool_names", test_ethtool_names); return g_test_run (); } diff --git a/src/settings/plugins/ifupdown/meson.build b/src/settings/plugins/ifupdown/meson.build index 0cabe771..7e2b44fb 100644 --- a/src/settings/plugins/ifupdown/meson.build +++ b/src/settings/plugins/ifupdown/meson.build @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1+ + sources = files( 'nms-ifupdown-interface-parser.c', 'nms-ifupdown-parser.c', diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-parser.c b/src/settings/plugins/ifupdown/nms-ifupdown-parser.c index 1db9ef15..ac3ed1ce 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-parser.c +++ b/src/settings/plugins/ifupdown/nms-ifupdown-parser.c @@ -484,7 +484,7 @@ update_ip4_setting_from_if_block (NMConnection *connection, /* gateway */ gateway_v = ifparser_getkey (block, "gateway"); if (gateway_v) { - if (!nm_utils_ipaddr_valid (AF_INET, gateway_v)) { + if (!nm_utils_ipaddr_is_valid (AF_INET, gateway_v)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid IPv4 gateway '%s'", gateway_v); return FALSE; @@ -565,9 +565,8 @@ update_ip6_setting_from_if_block (NMConnection *connection, const char *nameserver_v; const char *nameservers_v; const char *search_v; - int prefix_int = 128; + guint prefix_int; - /* Address */ address_v = ifparser_getkey (block, "address"); if (!address_v) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -575,12 +574,12 @@ update_ip6_setting_from_if_block (NMConnection *connection, return FALSE; } - /* Prefix */ prefix_v = ifparser_getkey (block, "netmask"); if (prefix_v) - prefix_int = g_ascii_strtoll (prefix_v, NULL, 10); + prefix_int = _nm_utils_ascii_str_to_int64 (prefix_v, 10, 0, 128, G_MAXINT); + else + prefix_int = 128; - /* Add the new address to the setting */ addr = nm_ip_address_new (AF_INET6, address_v, prefix_int, error); if (!addr) return FALSE; @@ -593,10 +592,9 @@ update_ip6_setting_from_if_block (NMConnection *connection, } nm_ip_address_unref (addr); - /* gateway */ gateway_v = ifparser_getkey (block, "gateway"); if (gateway_v) { - if (!nm_utils_ipaddr_valid (AF_INET6, gateway_v)) { + if (!nm_utils_ipaddr_is_valid (AF_INET6, gateway_v)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid IPv6 gateway '%s'", gateway_v); return FALSE; @@ -614,7 +612,6 @@ update_ip6_setting_from_if_block (NMConnection *connection, if (!nm_setting_ip_config_get_num_dns (s_ip6)) _LOGI ("No dns-nameserver configured in /etc/network/interfaces"); - /* DNS searches */ search_v = ifparser_getkey (block, "dns-search"); if (search_v) { gs_free const char **list = NULL; diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c index d19db0fd..808df49f 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c +++ b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c @@ -376,7 +376,7 @@ dispose (GObject *object) NMSIfupdownPlugin *plugin = NMS_IFUPDOWN_PLUGIN (object); NMSIfupdownPluginPrivate *priv = NMS_IFUPDOWN_PLUGIN_GET_PRIVATE (plugin); - g_clear_pointer (&priv->eni_ifaces, g_hash_table_destroy); + nm_clear_pointer (&priv->eni_ifaces, g_hash_table_destroy); G_OBJECT_CLASS (nms_ifupdown_plugin_parent_class)->dispose (object); } diff --git a/src/settings/plugins/ifupdown/tests/meson.build b/src/settings/plugins/ifupdown/tests/meson.build index 1ca094b5..a39e4e21 100644 --- a/src/settings/plugins/ifupdown/tests/meson.build +++ b/src/settings/plugins/ifupdown/tests/meson.build @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1+ + test_unit = 'test-ifupdown' exe = executable( diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/settings/plugins/keyfile/nms-keyfile-plugin.c index fdb88d2a..2906b399 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-plugin.c +++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.c @@ -23,7 +23,7 @@ #include "nm-utils.h" #include "nm-config.h" #include "nm-core-internal.h" -#include "nm-keyfile-internal.h" +#include "nm-keyfile/nm-keyfile-internal.h" #include "systemd/nm-sd-utils-shared.h" diff --git a/src/settings/plugins/keyfile/nms-keyfile-reader.c b/src/settings/plugins/keyfile/nms-keyfile-reader.c index af9e6726..e8c9f9fe 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-reader.c +++ b/src/settings/plugins/keyfile/nms-keyfile-reader.c @@ -9,7 +9,7 @@ #include <sys/stat.h> -#include "nm-keyfile-internal.h" +#include "nm-keyfile/nm-keyfile-internal.h" #include "NetworkManagerUtils.h" #include "nms-keyfile-utils.h" diff --git a/src/settings/plugins/keyfile/nms-keyfile-utils.c b/src/settings/plugins/keyfile/nms-keyfile-utils.c index f03c601a..bc8dfd12 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-utils.c +++ b/src/settings/plugins/keyfile/nms-keyfile-utils.c @@ -11,7 +11,7 @@ #include <sys/stat.h> #include "nm-glib-aux/nm-io-utils.h" -#include "nm-keyfile-internal.h" +#include "nm-keyfile/nm-keyfile-internal.h" #include "nm-utils.h" #include "nm-setting-wired.h" #include "nm-setting-wireless.h" diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.c b/src/settings/plugins/keyfile/nms-keyfile-writer.c index fa95198c..7554becc 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-writer.c +++ b/src/settings/plugins/keyfile/nms-keyfile-writer.c @@ -12,7 +12,7 @@ #include <sys/stat.h> #include <unistd.h> -#include "nm-keyfile-internal.h" +#include "nm-keyfile/nm-keyfile-internal.h" #include "nms-keyfile-utils.h" #include "nms-keyfile-reader.h" @@ -60,7 +60,7 @@ cert_writer (NMConnection *connection, * that would be interpreted as legacy binary format by reader. */ tmp = nm_keyfile_detect_unqualified_path_scheme (info->keyfile_dir, p, -1, FALSE, NULL); if (tmp) { - g_clear_pointer (&tmp, g_free); + nm_clear_g_free (&tmp); accepted_path = p; } } @@ -71,7 +71,7 @@ cert_writer (NMConnection *connection, * Otherwise, add a file:// prefix */ tmp = nm_keyfile_detect_unqualified_path_scheme (info->keyfile_dir, path, -1, FALSE, NULL); if (tmp) { - g_clear_pointer (&tmp, g_free); + nm_clear_g_free (&tmp); accepted_path = path; } } diff --git a/src/settings/plugins/keyfile/tests/meson.build b/src/settings/plugins/keyfile/tests/meson.build index 7bf9fda0..cd1dc3aa 100644 --- a/src/settings/plugins/keyfile/tests/meson.build +++ b/src/settings/plugins/keyfile/tests/meson.build @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1+ + test_unit = 'test-keyfile-settings' exe = executable( diff --git a/src/settings/plugins/meson.build b/src/settings/plugins/meson.build index 83981aab..cde0844b 100644 --- a/src/settings/plugins/meson.build +++ b/src/settings/plugins/meson.build @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1+ + if enable_ifcfg_rh subdir('ifcfg-rh') endif |