diff --git a/clients/cli/connections.c b/clients/cli/connections.c index a77c2482ca..e13ae9acc3 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -4252,18 +4252,10 @@ set_connection_type (NmCli *nmc, NMConnection *con, const OptionInfo *option, co static gboolean set_connection_iface (NmCli *nmc, NMConnection *con, const OptionInfo *option, const char *value, GError **error) { - GError *tmp_error = NULL; - if (value) { /* Special value of '*' means no specific interface name */ if (strcmp (value, "*") == 0) value = NULL; - else if (!nm_utils_is_valid_iface_name (value, &tmp_error)) { - g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, - _("Error: '%s': %s"), value, tmp_error->message); - g_error_free (tmp_error); - return FALSE; - } } return set_property (nmc->client, diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index 8fb76235b2..d9ccada94b 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -2089,8 +2089,6 @@ _set_fcn_gobject_ifname (ARGS_SET_FCN) if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) return _gobject_property_reset_default (setting, property_info->property_name); - if (!nm_utils_is_valid_iface_name (value, error)) - return FALSE; g_object_set (setting, property_info->property_name, value, NULL); return TRUE; } @@ -2567,24 +2565,6 @@ _multilist_remove_by_value_fcn_connection_permissions (NMSetting *setting, return TRUE; } -static gboolean -_set_fcn_connection_master (ARGS_SET_FCN) -{ - if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) - value = NULL; - else if (!*value) - value = NULL; - else if ( !nm_utils_is_valid_iface_name (value, NULL) - && !nm_utils_is_uuid (value)) { - g_set_error (error, 1, 0, - _("'%s' is not valid master; use ifname or connection UUID"), - value); - return FALSE; - } - g_object_set (setting, property_info->property_name, value, NULL); - return TRUE; -} - static const char *const* _complete_fcn_connection_master (ARGS_COMPLETE_FCN) { @@ -5129,7 +5109,7 @@ static const NMMetaPropertyInfo *const property_infos_CONNECTION[] = { .prompt = NM_META_TEXT_PROMPT_MASTER, .property_type = DEFINE_PROPERTY_TYPE ( .get_fcn = _get_fcn_gobject, - .set_fcn = _set_fcn_connection_master, + .set_fcn = _set_fcn_gobject_string, .complete_fcn = _complete_fcn_connection_master, ), ), diff --git a/clients/common/nm-vpn-helpers.c b/clients/common/nm-vpn-helpers.c index ffae5f5535..e1d8355147 100644 --- a/clients/common/nm-vpn-helpers.c +++ b/clients/common/nm-vpn-helpers.c @@ -368,7 +368,7 @@ nm_vpn_wireguard_import (const char *filename, memcpy (ifname, cstr, len); ifname[len] = '\0'; - if (nm_utils_is_valid_iface_name (ifname, NULL)) + if (nm_utils_ifname_valid_kernel (ifname, NULL)) ifname_valid = TRUE; } } diff --git a/clients/tui/nmt-device-entry.c b/clients/tui/nmt-device-entry.c index 67a66f7257..4ab593299c 100644 --- a/clients/tui/nmt-device-entry.c +++ b/clients/tui/nmt-device-entry.c @@ -103,7 +103,7 @@ device_entry_parse (NmtDeviceEntry *deventry, return TRUE; if (priv->hardware_type == G_TYPE_NONE && !priv->device_filter) { - if (nm_utils_is_valid_iface_name (text, NULL)) { + if (nm_utils_ifname_valid_kernel (text, NULL)) { *interface_name = g_strdup (text); return TRUE; } else @@ -127,12 +127,12 @@ device_entry_parse (NmtDeviceEntry *deventry, len = nm_utils_hwaddr_len (priv->arptype); if ( nm_utils_hwaddr_aton (words[0], buf, len) - && (!words[1] || nm_utils_is_valid_iface_name (words[1], NULL))) { + && (!words[1] || nm_utils_ifname_valid_kernel (words[1], NULL))) { *mac_address = words[0]; *interface_name = NULL; g_free (words); return TRUE; - } else if ( nm_utils_is_valid_iface_name (words[0], NULL) + } else if ( nm_utils_ifname_valid_kernel (words[0], NULL) && (!words[1] || nm_utils_hwaddr_aton (words[1], buf, len))) { *interface_name = words[0]; *mac_address = NULL; diff --git a/libnm-core/nm-connection-private.h b/libnm-core/nm-connection-private.h index ea7583e0e1..034c350f84 100644 --- a/libnm-core/nm-connection-private.h +++ b/libnm-core/nm-connection-private.h @@ -27,6 +27,7 @@ int _nm_setting_ovs_interface_verify_interface_type (NMSettingOvsInterface *self NMConnection *connection, gboolean normalize, gboolean *out_modified, + const char **normalized_type, GError **error); #endif /* __NM_CONNECTION_PRIVATE_H__ */ diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index 307b9d6234..4146fd55d1 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -1235,6 +1235,7 @@ _normalize_ovs_interface_type (NMConnection *self) self, TRUE, &modified, + NULL, NULL); if (v != TRUE) g_return_val_if_reached (modified); diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c index 52da8ccf12..f4c3566334 100644 --- a/libnm-core/nm-setting-bond.c +++ b/libnm-core/nm-setting-bond.c @@ -225,7 +225,7 @@ validate_ifname (const char *name, const char *value) if (!value || !value[0]) return FALSE; - return nm_utils_is_valid_iface_name (value, NULL); + return nm_utils_ifname_valid_kernel (value, NULL); } /** @@ -611,7 +611,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) if (strcmp (mode_new, "active-backup") == 0) { GError *tmp_error = NULL; - if (primary && !nm_utils_is_valid_iface_name (primary, &tmp_error)) { + if (primary && !nm_utils_ifname_valid_kernel (primary, &tmp_error)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c index ef33ecc138..17058ea7a5 100644 --- a/libnm-core/nm-setting-connection.c +++ b/libnm-core/nm-setting-connection.c @@ -973,20 +973,6 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (priv->interface_name) { - GError *tmp_error = NULL; - - if (!nm_utils_is_valid_iface_name (priv->interface_name, &tmp_error)) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - "'%s': %s", priv->interface_name, tmp_error->message); - g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME); - g_error_free (tmp_error); - return FALSE; - } - } - type = priv->type; if (!type) { if ( !connection @@ -1044,6 +1030,34 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } } + if (priv->interface_name) { + GError *tmp_error = NULL; + gboolean valid_ifname = FALSE; + + /* do not perform a interface name length check for OVS connection types + * as they don't have a corresponding kernel link that enforces the 15 bytes limit. + * Here we're whitelisting the OVS interface type as well, even if most OVS + * iface types do have the limit, to let the OVS specific nm-setting verify whether the iface name + * is good or not according to the internal type (internal, patch, ...) */ + if (NM_IN_STRSET (type, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME)) + valid_ifname = nm_utils_ifname_valid (priv->interface_name, NMU_IFACE_OVS, &tmp_error); + else + valid_ifname = nm_utils_ifname_valid (priv->interface_name, NMU_IFACE_KERNEL, &tmp_error); + + if (!valid_ifname) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "'%s': %s", priv->interface_name, tmp_error->message); + g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME); + g_error_free (tmp_error); + return FALSE; + } + } + is_slave = FALSE; slave_setting_type = NULL; slave_type = priv->slave_type; @@ -1276,7 +1290,7 @@ nm_setting_connection_set_interface_name (NMSetting *setting, * overridden by a valid connection.interface-name. */ interface_name = find_virtual_interface_name (connection_dict); - if (!interface_name || nm_utils_is_valid_iface_name (interface_name, NULL)) + if (!interface_name || nm_utils_ifname_valid_kernel (interface_name, NULL)) interface_name = g_variant_get_string (value, NULL); g_object_set (G_OBJECT (setting), diff --git a/libnm-core/nm-setting-infiniband.c b/libnm-core/nm-setting-infiniband.c index d03a7a2aaa..fcaa1f9afb 100644 --- a/libnm-core/nm-setting-infiniband.c +++ b/libnm-core/nm-setting-infiniband.c @@ -177,7 +177,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) if (priv->parent) { GError *tmp_error = NULL; - if (!nm_utils_is_valid_iface_name (priv->parent, &tmp_error)) { + if (!nm_utils_ifname_valid_kernel (priv->parent, &tmp_error)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -214,7 +214,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) if (!interface_name) ; - else if (!nm_utils_is_valid_iface_name (interface_name, &tmp_error)) { + else if (!nm_utils_ifname_valid_kernel (interface_name, &tmp_error)) { /* report the error for NMSettingConnection:interface-name, because * it's that property that is invalid -- although we currently verify() * NMSettingInfiniband. diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c index 7b29a99958..7f1690ac6a 100644 --- a/libnm-core/nm-setting-ip-config.c +++ b/libnm-core/nm-setting-ip-config.c @@ -4921,7 +4921,7 @@ verify_label (const char *label) if (!p) return FALSE; iface = g_strndup (label, p - label); - if (!nm_utils_is_valid_iface_name (iface, NULL)) { + if (!nm_utils_ifname_valid_kernel (iface, NULL)) { g_free (iface); return FALSE; } diff --git a/libnm-core/nm-setting-ip-tunnel.c b/libnm-core/nm-setting-ip-tunnel.c index 3df89cdd69..ae1df194fe 100644 --- a/libnm-core/nm-setting-ip-tunnel.c +++ b/libnm-core/nm-setting-ip-tunnel.c @@ -329,7 +329,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } if ( priv->parent - && !nm_utils_is_valid_iface_name (priv->parent, NULL) + && !nm_utils_ifname_valid_kernel (priv->parent, NULL) && !nm_utils_is_uuid (priv->parent)) { g_set_error (error, NM_CONNECTION_ERROR, diff --git a/libnm-core/nm-setting-macvlan.c b/libnm-core/nm-setting-macvlan.c index cb7778f1e7..d62184c227 100644 --- a/libnm-core/nm-setting-macvlan.c +++ b/libnm-core/nm-setting-macvlan.c @@ -120,7 +120,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) if (priv->parent) { if ( !nm_utils_is_uuid (priv->parent) - && !nm_utils_is_valid_iface_name (priv->parent, NULL)) { + && !nm_utils_ifname_valid_kernel (priv->parent, NULL)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, diff --git a/libnm-core/nm-setting-ovs-interface.c b/libnm-core/nm-setting-ovs-interface.c index ecefd6a5d9..849b9a4eef 100644 --- a/libnm-core/nm-setting-ovs-interface.c +++ b/libnm-core/nm-setting-ovs-interface.c @@ -67,6 +67,7 @@ _nm_setting_ovs_interface_verify_interface_type (NMSettingOvsInterface *self, NMConnection *connection, gboolean normalize, gboolean *out_modified, + const char **normalized_type, GError **error) { const char *type; @@ -82,9 +83,11 @@ _nm_setting_ovs_interface_verify_interface_type (NMSettingOvsInterface *self, } else g_return_val_if_fail (!connection || NM_IS_CONNECTION (connection), FALSE); + g_return_val_if_fail (!normalized_type || !(*normalized_type), FALSE); + NM_SET_OUT (out_modified, FALSE); - type = self ? self->type : NULL; + type = self->type; if ( type && !NM_IN_STRSET (type, "internal", "system", "patch", "dpdk")) { @@ -212,6 +215,10 @@ _nm_setting_ovs_interface_verify_interface_type (NMSettingOvsInterface *self, type = "internal"; else type = "system"; + + if (normalized_type) + *normalized_type = type; + normalize: if (!normalize) { if (!self) { @@ -246,9 +253,11 @@ static int verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingOvsInterface *self = NM_SETTING_OVS_INTERFACE (setting); + NMSettingConnection *s_con = NULL; + const char *normalized_type = NULL; + int result = NM_SETTING_VERIFY_ERROR; if (connection) { - NMSettingConnection *s_con; const char *slave_type; s_con = nm_connection_get_setting_connection (connection); @@ -286,11 +295,39 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } } - return _nm_setting_ovs_interface_verify_interface_type (self, - connection, - FALSE, - NULL, - error); + result = _nm_setting_ovs_interface_verify_interface_type (self, + connection, + FALSE, + NULL, + &normalized_type, + error); + + /* From 'man ovs-vswitchd.conf.db': OVS patch interfaces do not have + * a limit on interface name length, all the other types do */ + if (result != NM_SETTING_VERIFY_ERROR && s_con) { + gs_free_error GError *ifname_error = NULL; + const char *ifname = nm_setting_connection_get_interface_name (s_con); + + normalized_type = self->type ? self->type : normalized_type; + + if ( ifname + && !nm_streq0 (normalized_type, "patch") + && !nm_utils_ifname_valid (ifname, + NMU_IFACE_KERNEL, + &ifname_error)) { + g_clear_error (error); + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "'%s': %s", ifname, ifname_error->message); + g_prefix_error (error, "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_INTERFACE_NAME); + return NM_SETTING_VERIFY_ERROR; + } + } + + return result; } /*****************************************************************************/ diff --git a/libnm-core/nm-setting-pppoe.c b/libnm-core/nm-setting-pppoe.c index d9ff2a80d3..0fee96a166 100644 --- a/libnm-core/nm-setting-pppoe.c +++ b/libnm-core/nm-setting-pppoe.c @@ -149,7 +149,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } if ( priv->parent - && !nm_utils_is_valid_iface_name (priv->parent, &local_error)) { + && !nm_utils_ifname_valid_kernel (priv->parent, &local_error)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, diff --git a/libnm-core/nm-setting-vlan.c b/libnm-core/nm-setting-vlan.c index 84b974dcd4..30f4376037 100644 --- a/libnm-core/nm-setting-vlan.c +++ b/libnm-core/nm-setting-vlan.c @@ -603,7 +603,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } } - } else if (!nm_utils_is_valid_iface_name (priv->parent, NULL)) { + } else if (!nm_utils_ifname_valid_kernel (priv->parent, NULL)) { /* parent must be either a UUID or an interface name */ g_set_error (error, NM_CONNECTION_ERROR, diff --git a/libnm-core/nm-setting-vxlan.c b/libnm-core/nm-setting-vxlan.c index d363ff20a1..4e449bc860 100644 --- a/libnm-core/nm-setting-vxlan.c +++ b/libnm-core/nm-setting-vxlan.c @@ -358,7 +358,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } if ( priv->parent - && !nm_utils_is_valid_iface_name (priv->parent, NULL) + && !nm_utils_ifname_valid_kernel (priv->parent, NULL) && !nm_utils_is_uuid (priv->parent)) { g_set_error (error, NM_CONNECTION_ERROR, diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 4659734b6b..90ae4070fc 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #if WITH_JSON_VALIDATION @@ -4697,7 +4696,7 @@ nm_utils_is_valid_iface_name_utf8safe (const char *utf8safe_name) } } - return nm_utils_is_valid_iface_name (bin, NULL); + return nm_utils_ifname_valid_kernel (bin, NULL); } /** @@ -4718,45 +4717,9 @@ nm_utils_is_valid_iface_name_utf8safe (const char *utf8safe_name) gboolean nm_utils_is_valid_iface_name (const char *name, GError **error) { - int i; + g_return_val_if_fail (!error || !*error, FALSE); - if (!name) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - _("interface name is missing")); - return FALSE; - } - - if (name[0] == '\0') { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - _("interface name is too short")); - return FALSE; - } - - if ( name[0] == '.' - && ( name[1] == '\0' - || ( name[1] == '.' - && name[2] == '\0'))) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - _("interface name is reserved")); - return FALSE; - } - - for (i = 0; i < IFNAMSIZ; i++) { - char ch = name[i]; - - if (ch == '\0') - return TRUE; - if ( NM_IN_SET (ch, '/', ':') - || g_ascii_isspace (ch)) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - _("interface name contains an invalid character")); - return FALSE; - } - } - - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - _("interface name is longer than 15 characters")); - return FALSE; + return nm_utils_ifname_valid_kernel (name, error); } /** diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index c1b7b84a16..4c0b8c5d1f 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -8319,6 +8319,203 @@ test_integrate_maincontext (gconstpointer test_data) } } +static void +test_connection_ovs_ifname (gconstpointer test_data) +{ + const guint TEST_CASE = GPOINTER_TO_UINT (test_data); + gs_unref_object NMConnection *con = NULL; + NMSettingConnection *s_con = NULL; + NMSettingOvsBridge *s_ovs_bridge = NULL; + NMSettingOvsPort *s_ovs_port = NULL; + NMSettingOvsInterface *s_ovs_iface = NULL; + NMSettingOvsPatch *s_ovs_patch = NULL; + const char *ovs_iface_type = NULL; + + switch (TEST_CASE) { + case 1: + con = nmtst_create_minimal_connection ("test_connection_ovs_ifname_bridge", + NULL, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, &s_con); + s_ovs_bridge = nm_connection_get_setting_ovs_bridge (con); + g_assert (s_ovs_bridge); + break; + case 2: + con = nmtst_create_minimal_connection ("test_connection_ovs_ifname_port", + NULL, + NM_SETTING_OVS_PORT_SETTING_NAME, &s_con); + + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + NULL); + + s_ovs_port = nm_connection_get_setting_ovs_port (con); + g_assert (s_ovs_port); + break; + case 3: + con = nmtst_create_minimal_connection ("test_connection_ovs_ifname_interface_patch", + NULL, + NM_SETTING_OVS_INTERFACE_SETTING_NAME, &s_con); + s_ovs_iface = nm_connection_get_setting_ovs_interface (con); + g_assert (s_ovs_iface); + + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + g_object_set (s_ovs_iface, + NM_SETTING_OVS_INTERFACE_TYPE, + "patch", + NULL); + + s_ovs_patch = NM_SETTING_OVS_PATCH (nm_setting_ovs_patch_new()); + g_assert (s_ovs_patch); + + g_object_set (s_ovs_patch, + NM_SETTING_OVS_PATCH_PEER, "1.2.3.4", + NULL); + + nm_connection_add_setting (con, NM_SETTING (s_ovs_patch)); + s_ovs_patch = nm_connection_get_setting_ovs_patch (con); + g_assert (s_ovs_patch); + ovs_iface_type = "patch"; + break; + case 4: + con = nmtst_create_minimal_connection ("test_connection_ovs_ifname_interface_internal", + NULL, + NM_SETTING_OVS_INTERFACE_SETTING_NAME, &s_con); + s_ovs_iface = nm_connection_get_setting_ovs_interface (con); + g_assert (s_ovs_iface); + + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + g_object_set (s_ovs_iface, + NM_SETTING_OVS_INTERFACE_TYPE, + "internal", + NULL); + ovs_iface_type = "internal"; + break; + case 5: + con = nmtst_create_minimal_connection ("test_connection_ovs_ifname_interface_system", + NULL, + NM_SETTING_WIRED_SETTING_NAME, &s_con); + + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + s_ovs_iface = NM_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_new()); + g_assert (s_ovs_iface); + + g_object_set (s_ovs_iface, + NM_SETTING_OVS_INTERFACE_TYPE, + "system", + NULL); + + nm_connection_add_setting (con, NM_SETTING (s_ovs_iface)); + s_ovs_iface = nm_connection_get_setting_ovs_interface (con); + g_assert (s_ovs_iface); + + ovs_iface_type = "system"; + break; + case 6: + con = nmtst_create_minimal_connection ("test_connection_ovs_ifname_interface_dpdk", + NULL, + NM_SETTING_OVS_INTERFACE_SETTING_NAME, &s_con); + s_ovs_iface = nm_connection_get_setting_ovs_interface (con); + g_assert (s_ovs_iface); + + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + g_object_set (s_ovs_iface, + NM_SETTING_OVS_INTERFACE_TYPE, + "dpdk", + NULL); + ovs_iface_type = "dpdk"; + break; + } + + if (!nm_streq0 (ovs_iface_type, "system")) { + /* wrong: contains backward slash */ + g_object_set (s_con, + NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs\\0", + NULL); + nmtst_assert_connection_unnormalizable (con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + + /* wrong: contains forward slash */ + g_object_set (s_con, + NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs/0", + NULL); + nmtst_assert_connection_unnormalizable (con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + + /* wrong: contains non-alphanumerical char */ + g_object_set (s_con, + NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs-0", + NULL); + nmtst_assert_connection_unnormalizable (con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + + g_object_set (s_con, + NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs@0", + NULL); + nmtst_assert_connection_unnormalizable (con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + } + + /* wrong: contains space */ + g_object_set (s_con, + NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs 0", + NULL); + nmtst_assert_connection_unnormalizable (con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + + /* good */ + g_object_set (s_con, + NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs0", + NULL); + nmtst_assert_connection_verifies (con); + + /* good if bridge, port, or patch interface */ + g_object_set (s_con, + NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs123123123123130123123", + NULL); + + if (!ovs_iface_type || nm_streq (ovs_iface_type, "patch")) + nmtst_assert_connection_verifies (con); + else { + nmtst_assert_connection_unnormalizable (con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + } +} + + + /*****************************************************************************/ NMTST_DEFINE (); @@ -8411,6 +8608,13 @@ int main (int argc, char **argv) g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/11", GUINT_TO_POINTER (11), test_connection_normalize_ovs_interface_type_ovs_interface); g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/12", GUINT_TO_POINTER (12), test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func ("/core/general/test_connection_ovs_ifname/1", GUINT_TO_POINTER (1), test_connection_ovs_ifname); + g_test_add_data_func ("/core/general/test_connection_ovs_ifname/2", GUINT_TO_POINTER (2), test_connection_ovs_ifname); + g_test_add_data_func ("/core/general/test_connection_ovs_ifname/3", GUINT_TO_POINTER (3), test_connection_ovs_ifname); + g_test_add_data_func ("/core/general/test_connection_ovs_ifname/4", GUINT_TO_POINTER (4), test_connection_ovs_ifname); + g_test_add_data_func ("/core/general/test_connection_ovs_ifname/5", GUINT_TO_POINTER (5), test_connection_ovs_ifname); + g_test_add_data_func ("/core/general/test_connection_ovs_ifname/6", GUINT_TO_POINTER (6), test_connection_ovs_ifname); + g_test_add_func ("/core/general/test_setting_connection_permissions_helpers", test_setting_connection_permissions_helpers); g_test_add_func ("/core/general/test_setting_connection_permissions_property", test_setting_connection_permissions_property); diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c index 8e1c8b5806..8d82aa118d 100644 --- a/shared/nm-glib-aux/nm-shared-utils.c +++ b/shared/nm-glib-aux/nm-shared-utils.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "nm-errno.h" @@ -3987,3 +3988,91 @@ nm_utils_g_main_context_create_integrate_source (GMainContext *inner_context) return &ctx_src->source; } + +gboolean +nm_utils_ifname_valid_kernel (const char *name, GError **error) +{ + int i; + + if (!name) { + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + _("interface name is missing")); + return FALSE; + } + + if (name[0] == '\0') { + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + _("interface name is too short")); + return FALSE; + } + + if ( name[0] == '.' + && ( name[1] == '\0' + || ( name[1] == '.' + && name[2] == '\0'))) { + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + _("interface name is reserved")); + return FALSE; + } + + for (i = 0; i < IFNAMSIZ; i++) { + char ch = name[i]; + + if (ch == '\0') + return TRUE; + if ( NM_IN_SET (ch, '/', ':') + || g_ascii_isspace (ch)) { + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + _("interface name contains an invalid character")); + return FALSE; + } + } + + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + _("interface name is longer than 15 characters")); + return FALSE; +} + +static gboolean +_nm_utils_ifname_valid_ovs (const char* name, GError **error) +{ + const char *ch; + + for (ch = name; *ch; ++ch) { + if ( *ch == '\\' + || *ch == '/' + || g_ascii_isspace (*ch) + || !g_ascii_isalnum (*ch)) { + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + _("interface name must be alphanumerical with " + "no forward or backward slashes")); + return FALSE; + } + }; + return TRUE; +} + +gboolean +nm_utils_ifname_valid (const char* name, + NMUtilsIfaceType type, + GError **error) +{ + g_return_val_if_fail (!error || !(*error), FALSE); + + if (!name || !(name[0])) { + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + _("interface name must not be empty")); + return FALSE; + } + + g_return_val_if_fail (g_utf8_validate (name, -1, NULL), FALSE); + + switch (type) { + case NMU_IFACE_KERNEL: + return nm_utils_ifname_valid_kernel (name, error); + case NMU_IFACE_OVS: + return _nm_utils_ifname_valid_ovs (name, error); + } + + g_return_val_if_reached (FALSE); +} diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h index 3ec19ee112..740e61d0b8 100644 --- a/shared/nm-glib-aux/nm-shared-utils.h +++ b/shared/nm-glib-aux/nm-shared-utils.h @@ -1440,4 +1440,17 @@ guint nm_utils_parse_debug_string (const char *string, const GDebugKey *keys, guint nkeys); +/*****************************************************************************/ + +typedef enum { + NMU_IFACE_KERNEL = 0, + NMU_IFACE_OVS, +} NMUtilsIfaceType; + +gboolean nm_utils_ifname_valid_kernel (const char *name, GError **error); + +gboolean nm_utils_ifname_valid (const char* name, + NMUtilsIfaceType type, + GError **error); + #endif /* __NM_SHARED_UTILS_H__ */ diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c index 232e69ef2c..1c1d5eaa78 100644 --- a/src/devices/nm-device-factory.c +++ b/src/devices/nm-device-factory.c @@ -143,14 +143,6 @@ nm_device_factory_get_connection_iface (NMDeviceFactory *factory, return NULL; } - if (!nm_utils_is_valid_iface_name (ifname, error)) { - g_prefix_error (error, - "failed to determine interface name: name \"%s\" is invalid", - ifname); - g_free (ifname); - return NULL; - } - return ifname; } diff --git a/src/dhcp/nm-dhcp-client.c b/src/dhcp/nm-dhcp-client.c index 34e515e360..81c4ad9c58 100644 --- a/src/dhcp/nm-dhcp-client.c +++ b/src/dhcp/nm-dhcp-client.c @@ -1010,8 +1010,8 @@ set_property (GObject *object, guint prop_id, case PROP_IFACE: /* construct-only */ priv->iface = g_value_dup_string (value); - g_return_if_fail ( priv->iface - && nm_utils_is_valid_iface_name (priv->iface, NULL)); + g_return_if_fail (priv->iface); + nm_assert (nm_utils_ifname_valid_kernel (priv->iface, NULL)); break; case PROP_IFINDEX: /* construct-only */ diff --git a/src/nm-config.c b/src/nm-config.c index a7bb350302..a0995cf932 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -430,7 +430,7 @@ nm_config_set_no_auto_default_for_device (NMConfig *self, NMDevice *device) * * Instead, try the interface-name... */ ifname = nm_device_get_ip_iface (device); - if (!nm_utils_is_valid_iface_name (ifname, NULL)) + if (!nm_utils_ifname_valid_kernel (ifname, NULL)) return; spec_to_free = g_strdup_printf (NM_MATCH_SPEC_INTERFACE_NAME_TAG"=%s", ifname); diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index fb92289f0d..e059994aeb 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -2145,7 +2145,7 @@ nm_utils_sysctl_ip_conf_path (int addr_family, char *buf, const char *ifname, co nm_assert (buf); nm_assert_addr_family (addr_family); - g_assert (nm_utils_is_valid_iface_name (ifname, NULL)); + g_assert (nm_utils_ifname_valid_kernel (ifname, NULL)); property = NM_ASSERT_VALID_PATH_COMPONENT (property); len = g_snprintf (buf, @@ -2163,7 +2163,7 @@ nm_utils_sysctl_ip_conf_is_path (int addr_family, const char *path, const char * { g_return_val_if_fail (path, FALSE); NM_ASSERT_VALID_PATH_COMPONENT (property); - g_assert (!ifname || nm_utils_is_valid_iface_name (ifname, NULL)); + g_assert (!ifname || nm_utils_ifname_valid_kernel (ifname, NULL)); if (addr_family == AF_INET) { if (!g_str_has_prefix (path, IPV4_PROPERTY_DIR)) @@ -2196,7 +2196,7 @@ nm_utils_sysctl_ip_conf_is_path (int addr_family, const char *path, const char * return FALSE; memcpy (buf, path, l); buf[l] = '\0'; - if (!nm_utils_is_valid_iface_name (buf, NULL)) + if (!nm_utils_ifname_valid_kernel (buf, NULL)) return FALSE; path = slash + 1; } @@ -3635,7 +3635,7 @@ nm_utils_ifname_cpy (char *dst, const char *name) g_return_if_fail (dst); g_return_if_fail (name && name[0]); - nm_assert (nm_utils_is_valid_iface_name (name, NULL)); + nm_assert (nm_utils_ifname_valid_kernel (name, NULL)); /* ensures NUL padding of the entire IFNAMSIZ buffer. */ diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index 9529b9c5f0..b55fbd66c5 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -155,7 +155,7 @@ again: const char *ifname = known_ifnames[try_count % 2]; nm_assert (ifindex > 0); - nm_assert (ifname && nm_utils_is_valid_iface_name (ifname, NULL)); + nm_assert (ifname && nm_utils_ifname_valid_kernel (ifname, NULL)); nm_assert (fd >= 0); memset (&ifr, 0, sizeof (ifr)); @@ -1416,7 +1416,7 @@ nmp_utils_sysctl_open_netdir (int ifindex, return -1; } - nm_assert (nm_utils_is_valid_iface_name (ifname, NULL)); + nm_assert (nm_utils_ifname_valid_kernel (ifname, NULL)); if (g_strlcpy (&sysdir[NM_STRLEN (SYS_CLASS_NET)], ifname, IFNAMSIZ) >= IFNAMSIZ) g_return_val_if_reached (-1); diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index b93213ef74..f831fe9487 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -1175,7 +1175,7 @@ nmtstp_link_veth_add (NMPlatform *platform, const NMPlatformLink *pllink = NULL; gboolean success; - g_assert (nm_utils_is_valid_iface_name (name, NULL)); + g_assert (nm_utils_ifname_valid_kernel (name, NULL)); external_command = nmtstp_run_command_check_external (external_command); @@ -1204,7 +1204,7 @@ nmtstp_link_dummy_add (NMPlatform *platform, const NMPlatformLink *pllink = NULL; gboolean success; - g_assert (nm_utils_is_valid_iface_name (name, NULL)); + g_assert (nm_utils_ifname_valid_kernel (name, NULL)); external_command = nmtstp_run_command_check_external (external_command); @@ -1235,7 +1235,7 @@ nmtstp_link_gre_add (NMPlatform *platform, char b2[INET_ADDRSTRLEN]; NMLinkType link_type; - g_assert (nm_utils_is_valid_iface_name (name, NULL)); + g_assert (nm_utils_ifname_valid_kernel (name, NULL)); external_command = nmtstp_run_command_check_external (external_command); link_type = lnk->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE; @@ -1287,7 +1287,7 @@ nmtstp_link_ip6tnl_add (NMPlatform *platform, gboolean encap_ignore; gboolean tclass_inherit; - g_assert (nm_utils_is_valid_iface_name (name, NULL)); + g_assert (nm_utils_ifname_valid_kernel (name, NULL)); g_assert (!lnk->is_gre); external_command = nmtstp_run_command_check_external (external_command); @@ -1348,7 +1348,7 @@ nmtstp_link_ip6gre_add (NMPlatform *platform, char tclass[20]; gboolean tclass_inherit; - g_assert (nm_utils_is_valid_iface_name (name, NULL)); + g_assert (nm_utils_ifname_valid_kernel (name, NULL)); g_assert (lnk->is_gre); external_command = nmtstp_run_command_check_external (external_command); @@ -1397,7 +1397,7 @@ nmtstp_link_ipip_add (NMPlatform *platform, char b1[INET_ADDRSTRLEN]; char b2[INET_ADDRSTRLEN]; - g_assert (nm_utils_is_valid_iface_name (name, NULL)); + g_assert (nm_utils_ifname_valid_kernel (name, NULL)); external_command = nmtstp_run_command_check_external (external_command); @@ -1438,7 +1438,7 @@ nmtstp_link_macvlan_add (NMPlatform *platform, gboolean success; NMLinkType link_type; - g_assert (nm_utils_is_valid_iface_name (name, NULL)); + g_assert (nm_utils_ifname_valid_kernel (name, NULL)); external_command = nmtstp_run_command_check_external (external_command); @@ -1486,7 +1486,7 @@ nmtstp_link_sit_add (NMPlatform *platform, char b1[INET_ADDRSTRLEN]; char b2[INET_ADDRSTRLEN]; - g_assert (nm_utils_is_valid_iface_name (name, NULL)); + g_assert (nm_utils_ifname_valid_kernel (name, NULL)); external_command = nmtstp_run_command_check_external (external_command); @@ -1532,7 +1532,7 @@ nmtstp_link_tun_add (NMPlatform *platform, int err; int r; - g_assert (nm_utils_is_valid_iface_name (name, NULL)); + g_assert (nm_utils_ifname_valid_kernel (name, NULL)); g_assert (lnk); g_assert (NM_IN_SET (lnk->type, IFF_TUN, IFF_TAP)); g_assert (!out_fd || *out_fd == -1); @@ -1595,7 +1595,7 @@ nmtstp_link_vxlan_add (NMPlatform *platform, int err; int r; - g_assert (nm_utils_is_valid_iface_name (name, NULL)); + g_assert (nm_utils_ifname_valid_kernel (name, NULL)); external_command = nmtstp_run_command_check_external (external_command); @@ -1684,7 +1684,7 @@ nmtstp_link_get_typed (NMPlatform *platform, g_assert_cmpstr (name, ==, pllink->name); } - g_assert (!name || nm_utils_is_valid_iface_name (name, NULL)); + g_assert (!name || nm_utils_ifname_valid_kernel (name, NULL)); if (pllink && link_type != NM_LINK_TYPE_NONE) g_assert_cmpint (pllink->type, ==, link_type); 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 a3a3d159de..e01f7344cd 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,7 @@ make_connection_setting (const char *file, if (v) { GError *error = NULL; - if (nm_utils_is_valid_iface_name (v, &error)) { + if (nm_utils_ifname_valid_kernel (v, &error)) { g_object_set (s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, v, NULL);