merge: branch 'fix-wg-not-vpn'

Allow Wireguard as secondary

Closes #1395

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1825
This commit is contained in:
Alexander Lochmann 2026-05-08 17:10:35 +00:00
commit 3f4755282b
8 changed files with 128 additions and 37 deletions

View file

@ -491,23 +491,6 @@ _version_info_get(void)
/*****************************************************************************/
static gboolean
_connection_is_vpn(NMConnection *connection)
{
const char *type;
type = nm_connection_get_connection_type(connection);
if (type)
return nm_streq(type, NM_SETTING_VPN_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);
}
/*****************************************************************************/
static gboolean
concheck_enabled(NMManager *self, gboolean *out_changed)
{
@ -4530,7 +4513,7 @@ _device_get_activation_prio(NMDevice *device)
g_return_val_if_reached(DEVICE_ACTIVATION_PRIO_UNAVAILABLE);
}
static NMDevice *
NMDevice *
nm_manager_get_best_device_for_connection(NMManager *self,
NMSettingsConnection *sett_conn,
NMConnection *connection,
@ -6121,7 +6104,7 @@ _new_active_connection(NMManager *self,
nm_assert((!incompl_conn) ^ (!sett_conn));
nm_assert(NM_IS_AUTH_SUBJECT(subject));
nm_assert(is_vpn
== _connection_is_vpn(sett_conn ? nm_settings_connection_get_connection(sett_conn)
== nm_connection_is_vpn(sett_conn ? nm_settings_connection_get_connection(sett_conn)
: incompl_conn));
nm_assert(is_vpn || NM_IS_DEVICE(device));
nm_assert(!nm_streq0(specific_object, "/"));
@ -6350,7 +6333,7 @@ nm_manager_activate_connection(NMManager *self,
g_return_val_if_fail(NM_IS_MANAGER(self), NULL);
g_return_val_if_fail(NM_IS_SETTINGS_CONNECTION(sett_conn), NULL);
is_vpn = _connection_is_vpn(nm_settings_connection_get_connection(sett_conn));
is_vpn = nm_connection_is_vpn(nm_settings_connection_get_connection(sett_conn));
g_return_val_if_fail(is_vpn || NM_IS_DEVICE(device), NULL);
g_return_val_if_fail(!error || !*error, NULL);
nm_assert(!nm_streq0(specific_object, "/"));
@ -6502,7 +6485,7 @@ find_device_for_activation(NMManager *self,
if (!connection)
connection = nm_settings_connection_get_connection(sett_conn);
is_vpn = _connection_is_vpn(connection);
is_vpn = nm_connection_is_vpn(connection);
if (*out_device) {
device = *out_device;

View file

@ -271,6 +271,13 @@ gboolean nm_manager_devcon_autoconnect_blocked_reason_set(NMManager *
NMSettingsAutoconnectBlockedReason value,
gboolean set);
NMDevice *nm_manager_get_best_device_for_connection(NMManager *self,
NMSettingsConnection *sett_conn,
NMConnection *connection,
gboolean for_user_request,
GHashTable *exclude_devices,
GError **error);
NMConfig *nm_manager_get_config(NMManager *self);
#endif /* __NETWORKMANAGER_MANAGER_H__ */

View file

@ -2153,6 +2153,7 @@ activate_secondary_connections(NMPolicy *self, NMConnection *connection, NMDevic
NMSettingsConnection *sett_conn;
const char *sec_uuid = nm_setting_connection_get_secondary(s_con, i);
NMActRequest *req;
NMConnection *nm_conn;
sett_conn = nm_settings_get_connection_by_uuid(priv->settings, sec_uuid);
if (!sett_conn) {
@ -2162,26 +2163,47 @@ activate_secondary_connections(NMPolicy *self, NMConnection *connection, NMDevic
success = FALSE;
break;
}
nm_conn = nm_settings_connection_get_connection(sett_conn);
if (!nm_connection_is_type(nm_settings_connection_get_connection(sett_conn),
NM_SETTING_VPN_SETTING_NAME)) {
if (!nm_connection_is_valid_secondary(nm_conn)) {
_LOGW(LOGD_DEVICE,
"secondary connection '%s (%s)' auto-activation failed: The connection is not a "
"VPN.",
"secondary connection '%s (%s)' auto-activation failed: The connection is neither a "
"valid VPN nor a Wireguard connection.",
nm_settings_connection_get_id(sett_conn),
sec_uuid);
success = FALSE;
break;
}
if (!nm_connection_is_vpn(nm_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(priv->manager, sett_conn, nm_conn, TRUE, NULL, &local);
if (!_device) {
_LOGW(LOGD_DEVICE,
"No suitable device found for non-plugin VPN connection (%s).",
local->message);
success = FALSE;
break;
}
device = _device;
}
req = nm_device_get_act_request(device);
_LOGD(LOGD_DEVICE,
"activating secondary connection '%s (%s)' for base connection '%s (%s)'",
"activating secondary connection '%s (%s)' for base connection '%s (%s), real: %d, sw:%d, iface: %s'",
nm_settings_connection_get_id(sett_conn),
sec_uuid,
nm_connection_get_id(connection),
nm_connection_get_uuid(connection));
nm_connection_get_uuid(connection), nm_device_is_real(device), nm_device_is_software(device), nm_device_get_iface(device));
ac = nm_manager_activate_connection(
priv->manager,
sett_conn,
@ -2196,6 +2218,10 @@ activate_secondary_connections(NMPolicy *self, NMConnection *connection, NMDevic
if (ac)
secondary_ac_list = g_slist_append(secondary_ac_list, g_object_ref(ac));
else {
_LOGW(LOGD_DEVICE,
"secondary connection '%s (%s)' auto-activation failed:",
nm_settings_connection_get_id(sett_conn),
sec_uuid);
_LOGW(LOGD_DEVICE,
"secondary connection '%s (%s)' auto-activation failed: (%d) %s",
nm_settings_connection_get_id(sett_conn),

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,60 @@ nm_connection_is_type(NMConnection *connection, const char *type)
return nm_streq0(type, nm_connection_get_connection_type(connection));
}
/**
* nm_connection_is_vpn:
* @connection: the #NMConnection
*
* Checks whether the given connection is VPN connection.
* This applies to a connection belonging to a VPN plugin,
* e.g., OpenVPN.
*
* Returns: %TRUE if the connection is a valid secondary.
*
* Since: 1.57
*/
gboolean
nm_connection_is_vpn(NMConnection *connection)
{
const char *type;
type = nm_connection_get_connection_type(connection);
if (type)
return nm_streq(type, NM_SETTING_VPN_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_is_valid_secondary:
* @connection: the #NMConnection
*
* Checks whether the given connection can be activated as a secondary.
* A valid secondary connection is either a Wireguard connection or
* a connection belonging to a VPN plugin, e.g., OpenVPN.
*
* Returns: %TRUE if the connection is a valid secondary.
*
* Since: 1.57
*/
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)
{
@ -3839,6 +3894,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

@ -3159,7 +3159,7 @@ nm_setting_connection_class_init(NMSettingConnectionClass *klass)
*
* List of connection UUIDs that should be activated when the base
* connection itself is activated. Currently, only VPN connections are
* supported.
* supported, i.e., either Wireguard or of type VPN.
**/
/* ---ifcfg-rh---
* property: secondaries

View file

@ -242,12 +242,17 @@ 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);
gboolean nm_connection_is_vpn(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 VPN profile, e.g., Wireguard or OpenVPN."), *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 VPN profile, e.g., Wireguard or OpenVPN."), *iter);
return FALSE;
}