core: reject new connections if the feature is disabled or removed

If a feature like Wi-Fi, OVS, team, etc. is disabled or no longer
supported, it is better to report an error when the connection is
added via nmcli than accepting the connection and complaining later
about a "missing plugin"; there is no plugin and the connection will
never be able to activate.

Example errors now:
  # nmcli connection add type team
  Error: Failed to add 'team-nm-team' connection: team support is disabled in this build

  # nmcli connection add type gsm
  Error: Failed to add 'gsm' connection: WWAN support is disabled in this build

  # nmcli connection add type wimax nsp 00:99:88:77:66:55
  Error: Failed to add 'wimax' connection: WiMAX is no longer supported

Note that we don't touch libnm-core (the part defining the settings
and properties), as that defines the API of NetworkManager. The API
should not change according to compile flags.
This commit is contained in:
Beniamino Galvani 2025-10-14 17:38:58 +02:00
parent e5ae988603
commit 247000deed
6 changed files with 119 additions and 0 deletions

View file

@ -239,6 +239,15 @@
/* Whether we build with OVS plugin */
#mesondefine WITH_OPENVSWITCH
/* Whether we build with team support */
#mesondefine WITH_TEAMDCTL
/* Whether we build with Wi-Fi support */
#mesondefine WITH_WIFI
/* Whether we build with WWAN support */
#mesondefine WITH_WWAN
/* Define if you have PPP support */
#mesondefine WITH_PPP

View file

@ -327,6 +327,7 @@ config_h.set10('WITH_CONFIG_PLUGIN_IFUPDOWN', enable_ifupdown)
config_h.set_quoted('NM_DIST_VERSION', dist_version)
enable_wifi = get_option('wifi')
config_h.set10('WITH_WIFI', enable_wifi)
enable_iwd = get_option('iwd')
assert((not enable_iwd) or enable_wifi, 'Enabling iwd support requires Wi-Fi support as well')
@ -507,6 +508,7 @@ if enable_teamdctl
libteamdctl_dep = dependency('libteamdctl', version: '>= 1.9')
assert(libteamdctl_dep.found(), 'You must have libteamdctl installed to build. Use -Dteamdctl=false to disable it')
endif
config_h.set10('WITH_TEAMDCTL', enable_teamdctl)
# polkit
enable_polkit = get_option('polkit')
@ -616,6 +618,7 @@ if enable_modem_manager
endif
config_h.set_quoted('MOBILE_BROADBAND_PROVIDER_INFO_DATABASE', mobile_broadband_provider_info_database)
endif
config_h.set10('WITH_WWAN', enable_modem_manager)
# Bluez5 DUN support
enable_bluez5_dun = get_option('bluez5_dun')

View file

@ -5474,3 +5474,96 @@ nm_utils_shorten_hostname(const char *hostname, char **shortened)
*shortened = g_steal_pointer(&s);
return TRUE;
}
/**
* nm_utils_connection_supported:
* @connection: the connection
* @error: on return, the reason why the connection in not supported
*
* Returns whether the given connection is supported by this version
* of NetworkManager.
*/
gboolean
nm_utils_connection_supported(NMConnection *connection, GError **error)
{
const char *type;
const char *feature = NULL;
g_return_val_if_fail(connection, FALSE);
g_return_val_if_fail(!error || !*error, FALSE);
type = nm_connection_get_connection_type(connection);
if (!WITH_TEAMDCTL) {
NMSettingConnection *s_con;
if (nm_streq0(type, NM_SETTING_TEAM_SETTING_NAME)) {
feature = "team";
goto out_disabled;
}
/* Match team ports */
if ((s_con = nm_connection_get_setting_connection(connection))
&& nm_streq0(nm_setting_connection_get_port_type(s_con),
NM_SETTING_TEAM_SETTING_NAME)) {
feature = "team";
goto out_disabled;
}
}
if (!WITH_OPENVSWITCH) {
if (NM_IN_STRSET(type,
NM_SETTING_OVS_BRIDGE_SETTING_NAME,
NM_SETTING_OVS_PORT_SETTING_NAME,
NM_SETTING_OVS_INTERFACE_SETTING_NAME)) {
feature = "Open vSwitch";
goto out_disabled;
}
/* Match OVS system interfaces */
if (nm_connection_get_setting_ovs_interface(connection)) {
feature = "Open vSwitch";
goto out_disabled;
}
}
if (!WITH_WIFI
&& NM_IN_STRSET(type,
NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_OLPC_MESH_SETTING_NAME,
NM_SETTING_WIFI_P2P_SETTING_NAME)) {
feature = "Wi-Fi";
goto out_disabled;
}
if (!WITH_WWAN
&& NM_IN_STRSET(type, NM_SETTING_GSM_SETTING_NAME, NM_SETTING_CDMA_SETTING_NAME)) {
feature = "WWAN";
goto out_disabled;
}
if (nm_streq0(type, NM_SETTING_WIMAX_SETTING_NAME)) {
feature = "WiMAX";
goto out_removed;
}
return TRUE;
out_disabled:
nm_assert(feature);
g_set_error(error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_FEATURE_DISABLED,
"%s support is disabled in this build",
feature);
return FALSE;
out_removed:
nm_assert(feature);
g_set_error(error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_FEATURE_REMOVED,
"%s is no longer supported",
feature);
return FALSE;
}

View file

@ -490,4 +490,8 @@ uid_t nm_utils_get_nm_uid(void);
gid_t nm_utils_get_nm_gid(void);
/*****************************************************************************/
gboolean nm_utils_connection_supported(NMConnection *connection, GError **error);
#endif /* __NM_CORE_UTILS_H__ */

View file

@ -1851,6 +1851,9 @@ nm_settings_add_connection(NMSettings *self,
NM_SET_OUT(out_sett_conn, NULL);
if (!nm_utils_connection_supported(connection, error))
return FALSE;
uuid = nm_connection_get_uuid(connection);
sett_conn_entry = _sett_conn_entries_get(self, uuid);

View file

@ -256,6 +256,11 @@ GQuark nm_secret_agent_error_quark(void);
* @NM_SETTINGS_ERROR_NOT_SUPPORTED_BY_PLUGIN: the requested operation is not
* supported by the settings plugin currently in use for the specified object.
* Since: 1.44.
* @NM_SETTINGS_ERROR_FEATURE_DISABLED: the requested operation failed because it
* requires a feature that is disabled in this build of NetworkManager.
* Since: 1.56
* @NM_SETTINGS_ERROR_FEATURE_REMOVED: the requested operation failed because it
* requires a feature that is no longer supported. Since: 1.56
*
* Errors related to the settings/persistent configuration interface of
* NetworkManager.
@ -275,6 +280,8 @@ typedef enum {
NM_SETTINGS_ERROR_INVALID_ARGUMENTS, /*< nick=InvalidArguments >*/
NM_SETTINGS_ERROR_VERSION_ID_MISMATCH, /*< nick=VersionIdMismatch >*/
NM_SETTINGS_ERROR_NOT_SUPPORTED_BY_PLUGIN, /*< nick=NotSupportedByPlugin >*/
NM_SETTINGS_ERROR_FEATURE_DISABLED, /*< nick=FeatureDisabled >*/
NM_SETTINGS_ERROR_FEATURE_REMOVED, /*< nick=FeatureRemoved >*/
} NMSettingsError;
GQuark nm_settings_error_quark(void);