Allow any kind of VPN as secondaries (Fixed #1395)

As of now, NM allows only connections derived from the
VPN plugin to be used as secondaries. This excludes
non-VPN-plugin connections still providing VPN
functionality, such as Wireguard, to be used as secondary.
This commit extends NetworkManager to allow any kind of VPN
connection to be used as secondary connection.
(Code rework done by Martin Sucha<git@mm.ms47.eu>)
This commit is contained in:
Alexander Lochmann 2023-12-24 14:24:04 +01:00 committed by Alexander Krause
parent e311df0c75
commit 7bc5a1fc26
No known key found for this signature in database
GPG key ID: 593EED05BC3EF6FD
6 changed files with 78 additions and 12 deletions

View file

@ -6196,6 +6196,28 @@ _new_active_connection(NMManager *self,
activation_reason,
initial_state_flags,
subject);
} else if (nm_connection_is_valid_secondary(sett_conn ? nm_settings_connection_get_connection(sett_conn)
: incompl_conn)) {
/**
* For non-plugin VPN connections, re-validate the corresponding device.
* Wireguard, for example, needs its own (virtual) device.
* If it, however, gets activated as secondary device,
* 'device' points to the primary device that is currently starting.
* Bringing up a WG tunnel this way will fail.
*/
NMDevice *_device = NULL;
gs_free_error GError *local = NULL;
_device =
nm_manager_get_best_device_for_connection(self, sett_conn, applied, TRUE, NULL, &local);
if (!_device) {
g_set_error(error,
NM_MANAGER_ERROR,
NM_MANAGER_ERROR_UNKNOWN_DEVICE,
"No suitable device found for non-plugin VPN connection (%s).",
local->message);
return NULL;
}
device = _device;
}
return (NMActiveConnection *) nm_act_request_new(sett_conn,

View file

@ -2163,11 +2163,10 @@ activate_secondary_connections(NMPolicy *self, NMConnection *connection, NMDevic
break;
}
if (!nm_connection_is_type(nm_settings_connection_get_connection(sett_conn),
NM_SETTING_VPN_SETTING_NAME)) {
if (!nm_connection_is_valid_secondary(nm_settings_connection_get_connection(sett_conn))) {
_LOGW(LOGD_DEVICE,
"secondary connection '%s (%s)' auto-activation failed: The connection is not a "
"VPN.",
"valid secondary.",
nm_settings_connection_get_id(sett_conn),
sec_uuid);
success = FALSE;

View file

@ -141,6 +141,7 @@ global:
nm_connection_get_setting_vpn;
nm_connection_get_setting_wimax;
nm_connection_get_setting_wired;
nm_connection_get_setting_wireguard;
nm_connection_get_setting_wireless;
nm_connection_get_setting_wireless_security;
nm_connection_get_type;
@ -2026,6 +2027,7 @@ libnm_1_50_4 {
libnm_1_52_0 {
global:
nm_connection_is_valid_secondary;
nm_device_ipvlan_get_mode;
nm_device_ipvlan_get_parent;
nm_device_ipvlan_get_private;

View file

@ -15,6 +15,7 @@
#include "nm-connection-private.h"
#include "nm-utils.h"
#include "nm-setting-private.h"
#include "nm-setting-wireguard.h"
#include "libnm-core-intern/nm-core-internal.h"
/**
@ -2876,6 +2877,31 @@ nm_connection_is_type(NMConnection *connection, const char *type)
return nm_streq0(type, nm_connection_get_connection_type(connection));
}
/**
* nm_connection_is_valid_secondary:
* @connection: the #NMConnection
*
* Checks whether the given connection can be activated as a secondary.
*
* Returns: %TRUE if the connection is a valid secondary.
*
* Since: 1.52
*/
gboolean
nm_connection_is_valid_secondary(NMConnection *connection)
{
const char *type = nm_connection_get_connection_type(connection);
if (type)
return nm_streq(type, NM_SETTING_VPN_SETTING_NAME)
|| nm_streq(type, NM_SETTING_WIREGUARD_SETTING_NAME);
/* we have an incomplete (invalid) connection at hand. That can only
* happen during AddAndActivate. Determine whether it's VPN type based
* on the existence of a [vpn] section. */
return !!nm_connection_get_setting_vpn(connection)
|| nm_connection_get_setting_wireguard(connection);
}
int
_nm_setting_sort_for_nm_assert(NMSetting *a, NMSetting *b)
{
@ -3822,6 +3848,20 @@ nm_connection_get_setting_vpn(NMConnection *connection)
return _nm_connection_get_setting_by_metatype(connection, NM_META_SETTING_TYPE_VPN);
}
/**
* nm_connection_get_setting_wireguard:
* @connection: the #NMConnection
*
* A shortcut to return any #NMSettingVpn the connection might contain.
*
* Returns: (transfer none): an #NMSettingVpn if the connection contains one, otherwise %NULL
**/
NMSettingVpn *
nm_connection_get_setting_wireguard(NMConnection *connection)
{
return _nm_connection_get_setting_by_metatype(connection, NM_META_SETTING_TYPE_WIREGUARD);
}
/**
* nm_connection_get_setting_vxlan:
* @connection: the #NMConnection

View file

@ -240,12 +240,16 @@ NMSettingVpn *nm_connection_get_setting_vpn(NMConnection *connectio
NMSettingWimax *nm_connection_get_setting_wimax(NMConnection *connection);
NMSettingAdsl *nm_connection_get_setting_adsl(NMConnection *connection);
NMSettingWired *nm_connection_get_setting_wired(NMConnection *connection);
NMSettingVpn *nm_connection_get_setting_wireguard(NMConnection *connection);
NMSettingWireless *nm_connection_get_setting_wireless(NMConnection *connection);
NMSettingWirelessSecurity *nm_connection_get_setting_wireless_security(NMConnection *connection);
NMSettingVlan *nm_connection_get_setting_vlan(NMConnection *connection);
NM_AVAILABLE_IN_1_2
NMSettingVxlan *nm_connection_get_setting_vxlan(NMConnection *connection);
NM_AVAILABLE_IN_1_52
gboolean nm_connection_is_valid_secondary(NMConnection *connection);
G_END_DECLS
#endif /* __NM_CONNECTION_H__ */

View file

@ -378,13 +378,13 @@ _set_fcn_precheck_connection_secondaries(NMClient *client,
con = nmc_find_connection(connections, "uuid", *iter, NULL, FALSE);
if (!con) {
nmc_printerr(_("Warning: %s is not an UUID of any existing connection profile\n"),
*iter);
} else {
*iter);
} else {
/* Currently, NM only supports VPN connections as secondaries */
if (!nm_connection_is_type(con, NM_SETTING_VPN_SETTING_NAME)) {
g_set_error(error, 1, 0, _("'%s' is not a VPN connection profile"), *iter);
if (!nm_connection_is_valid_secondary(con)) {
g_set_error(error, 1, 0, _("'%s' is not a valid secondary profile"), *iter);
return FALSE;
}
}
}
} else {
con = nmc_find_connection(connections, "id", *iter, NULL, FALSE);
@ -392,10 +392,9 @@ _set_fcn_precheck_connection_secondaries(NMClient *client,
g_set_error(error, 1, 0, _("'%s' is not a name of any existing profile"), *iter);
return FALSE;
}
/* Currently, NM only supports VPN connections as secondaries */
if (!nm_connection_is_type(con, NM_SETTING_VPN_SETTING_NAME)) {
g_set_error(error, 1, 0, _("'%s' is not a VPN connection profile"), *iter);
/* Currently, NM only supports VPN connections, including Wireguard, as secondaries */
if (!nm_connection_is_valid_secondary(con)) {
g_set_error(error, 1, 0, _("'%s' is not a valid secondary profile"), *iter);
return FALSE;
}