summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-02-14 08:00:55 +0100
committerThomas Haller <thaller@redhat.com>2019-02-14 08:00:55 +0100
commitc032690df227a609fc4b47c78269448576b6bda1 (patch)
tree35732416a81e7c3325e4e6c3a96243d7757e645e
parent2c881b8064e1cb5b227e5a3c61abfe95c6ddd05a (diff)
parenta3d4dea61f2de02b075866db412c791320c4cbf8 (diff)
downloadNetworkManager-c032690df227a609fc4b47c78269448576b6bda1.tar.gz
all: merge branch 'th/various-for-wireguard-3'
https://github.com/NetworkManager/NetworkManager/pull/293
-rw-r--r--clients/cli/agent.c5
-rw-r--r--clients/cli/common.c17
-rw-r--r--clients/common/nm-secret-agent-simple.c256
-rw-r--r--clients/common/nm-secret-agent-simple.h5
-rw-r--r--libnm-core/nm-core-internal.h23
-rw-r--r--libnm-core/nm-setting-vpn.c2
-rw-r--r--libnm-core/nm-utils-private.h6
-rw-r--r--libnm-core/nm-utils.c341
-rw-r--r--libnm-core/nm-utils.h2
-rw-r--r--libnm-core/tests/test-general.c154
-rw-r--r--shared/nm-utils/nm-macros-internal.h27
-rw-r--r--shared/nm-utils/nm-secret-utils.h25
-rw-r--r--src/devices/nm-device.c32
-rw-r--r--src/devices/nm-device.h5
-rw-r--r--src/nm-core-utils.h4
-rw-r--r--src/nm-policy.c39
-rw-r--r--src/platform/nm-linux-platform.c144
-rw-r--r--src/platform/nm-platform.c45
-rw-r--r--src/platform/nm-platform.h36
-rw-r--r--src/platform/tests/test-link.c6
-rw-r--r--src/vpn/nm-vpn-connection.h2
21 files changed, 946 insertions, 230 deletions
diff --git a/clients/cli/agent.c b/clients/cli/agent.c
index a18eecc52d..6c116153ac 100644
--- a/clients/cli/agent.c
+++ b/clients/cli/agent.c
@@ -104,7 +104,10 @@ get_secrets_from_user (const NmcConfig *nmc_config,
rl_startup_hook = set_deftext;
pre_input_deftext = g_strdup (secret->value);
}
- pwd = nmc_readline (nmc_config, "%s (%s): ", secret->pretty_name, secret->entry_id);
+ if (secret->no_prompt_entry_id)
+ pwd = nmc_readline (nmc_config, "%s: ", secret->pretty_name);
+ else
+ pwd = nmc_readline (nmc_config, "%s (%s): ", secret->pretty_name, secret->entry_id);
/* No password provided, cancel the secrets. */
if (!pwd)
diff --git a/clients/cli/common.c b/clients/cli/common.c
index b3342c1935..50dd0eb5cb 100644
--- a/clients/cli/common.c
+++ b/clients/cli/common.c
@@ -685,6 +685,8 @@ get_secrets_from_user (const NmcConfig *nmc_config,
pwd = g_strdup (pwd);
} else {
if (ask) {
+ gboolean echo_on;
+
if (secret->value) {
if (!g_strcmp0 (secret->vpn_type, NM_DBUS_INTERFACE ".openconnect")) {
/* Do not present and ask user for openconnect secrets, we already have them */
@@ -697,11 +699,16 @@ get_secrets_from_user (const NmcConfig *nmc_config,
}
if (msg)
g_print ("%s\n", msg);
- pwd = nmc_readline_echo (nmc_config,
- secret->is_secret
- ? nmc_config->show_secrets
- : TRUE,
- "%s (%s): ", secret->pretty_name, secret->entry_id);
+
+ echo_on = secret->is_secret
+ ? nmc_config->show_secrets
+ : TRUE;
+
+ if (secret->no_prompt_entry_id)
+ pwd = nmc_readline_echo (nmc_config, echo_on, "%s: ", secret->pretty_name);
+ else
+ pwd = nmc_readline_echo (nmc_config, echo_on, "%s (%s): ", secret->pretty_name, secret->entry_id);
+
if (!pwd)
pwd = g_strdup ("");
} else {
diff --git a/clients/common/nm-secret-agent-simple.c b/clients/common/nm-secret-agent-simple.c
index 1393793e4c..ffcb7c8978 100644
--- a/clients/common/nm-secret-agent-simple.c
+++ b/clients/common/nm-secret-agent-simple.c
@@ -38,6 +38,7 @@
#include "nm-vpn-service-plugin.h"
#include "nm-vpn-helpers.h"
+#include "nm-utils/nm-secret-utils.h"
/*****************************************************************************/
@@ -47,6 +48,7 @@ typedef struct {
NMSecretAgentSimple *self;
NMConnection *connection;
+ const char *setting_name;
char **hints;
NMSecretAgentOldGetSecretsFunc callback;
gpointer callback_data;
@@ -145,7 +147,7 @@ _secret_real_free (NMSecretAgentSimpleSecret *secret)
g_free ((char *) secret->pretty_name);
g_free ((char *) secret->entry_id);
- g_free (secret->value);
+ nm_free_secret (secret->value);
g_free ((char *) secret->vpn_type);
g_free (real->property);
g_clear_object (&real->setting);
@@ -154,46 +156,61 @@ _secret_real_free (NMSecretAgentSimpleSecret *secret)
}
static NMSecretAgentSimpleSecret *
-_secret_real_new (NMSecretAgentSecretType secret_type,
- const char *pretty_name,
- NMSetting *setting,
- const char *property,
- const char *vpn_type)
+_secret_real_new_plain (NMSecretAgentSecretType secret_type,
+ const char *pretty_name,
+ NMSetting *setting,
+ const char *property)
{
SecretReal *real;
- const char *vpn_prefix;
- const char *value;
+ gs_free char *value= NULL;
nm_assert (property);
nm_assert (NM_IS_SETTING (setting));
+ nm_assert (NM_IN_SET (secret_type, NM_SECRET_AGENT_SECRET_TYPE_PROPERTY, NM_SECRET_AGENT_SECRET_TYPE_SECRET));
+ nm_assert (g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property));
+ nm_assert ((secret_type == NM_SECRET_AGENT_SECRET_TYPE_SECRET) == nm_setting_get_secret_flags (setting, property, NULL, NULL));
+
+ g_object_get (setting, property, &value, NULL);
+
+ real = g_slice_new (SecretReal);
+ *real = (SecretReal) {
+ .base.secret_type = secret_type,
+ .base.pretty_name = g_strdup (pretty_name),
+ .base.entry_id = g_strdup_printf ("%s.%s", nm_setting_get_name (setting), property),
+ .base.value = g_steal_pointer (&value),
+ .base.is_secret = (secret_type != NM_SECRET_AGENT_SECRET_TYPE_PROPERTY),
+ .setting = g_object_ref (setting),
+ .property = g_strdup (property),
+ };
+ return &real->base;
+}
- real = g_slice_new0 (SecretReal);
- *((NMSecretAgentSecretType *) &real->base.secret_type) = secret_type;
- real->setting = g_object_ref (setting);
- real->base.pretty_name = g_strdup (pretty_name);
- real->property = g_strdup (property);
- switch (secret_type) {
- case NM_SECRET_AGENT_SECRET_TYPE_PROPERTY:
- case NM_SECRET_AGENT_SECRET_TYPE_SECRET:
- nm_assert (!vpn_type);
- nm_assert (g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property));
- nm_assert ((secret_type == NM_SECRET_AGENT_SECRET_TYPE_SECRET) == nm_setting_get_secret_flags (setting, property, NULL, NULL));
- real->base.entry_id = g_strdup_printf ("%s.%s", nm_setting_get_name (setting), property);
- g_object_get (setting, property, &real->base.value, NULL);
- real->base.is_secret = (secret_type != NM_SECRET_AGENT_SECRET_TYPE_PROPERTY);
- break;
- case NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET:
- vpn_prefix = NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRETS;
- value = nm_setting_vpn_get_secret (NM_SETTING_VPN (setting), property);
- real->base.entry_id = g_strdup_printf ("%s%s", vpn_prefix, property);
- nm_assert (vpn_type);
- real->base.vpn_type = g_strdup (vpn_type);
- real->base.value = g_strdup (value);
- real->base.is_secret = TRUE;
- break;
- }
- nm_assert (real->base.entry_id);
+static NMSecretAgentSimpleSecret *
+_secret_real_new_vpn_secret (const char *pretty_name,
+ NMSetting *setting,
+ const char *property,
+ const char *vpn_type)
+{
+ SecretReal *real;
+ const char *value;
+ nm_assert (property);
+ nm_assert (NM_IS_SETTING_VPN (setting));
+ nm_assert (vpn_type);
+
+ value = nm_setting_vpn_get_secret (NM_SETTING_VPN (setting), property);
+
+ real = g_slice_new (SecretReal);
+ *real = (SecretReal) {
+ .base.secret_type = NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET,
+ .base.pretty_name = g_strdup (pretty_name),
+ .base.entry_id = g_strdup_printf ("%s%s", NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRETS, property),
+ .base.value = g_strdup (value),
+ .base.is_secret = TRUE,
+ .base.vpn_type = g_strdup (vpn_type),
+ .setting = g_object_ref (setting),
+ .property = g_strdup (property),
+ };
return &real->base;
}
@@ -212,11 +229,10 @@ add_8021x_secrets (RequestData *request,
char **iter;
for (iter = request->hints; *iter; iter++) {
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
- _(*iter),
- NM_SETTING (s_8021x),
- *iter,
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _(*iter),
+ NM_SETTING (s_8021x),
+ *iter);
g_ptr_array_add (secrets, secret);
}
@@ -235,33 +251,29 @@ add_8021x_secrets (RequestData *request,
* is not visible here since we only care about phase2 authentication
* (and don't even care of which one)
*/
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
- _("Username"),
- NM_SETTING (s_8021x),
- NM_SETTING_802_1X_IDENTITY,
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
+ _("Username"),
+ NM_SETTING (s_8021x),
+ NM_SETTING_802_1X_IDENTITY);
g_ptr_array_add (secrets, secret);
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
- _("Password"),
- NM_SETTING (s_8021x),
- NM_SETTING_802_1X_PASSWORD,
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Password"),
+ NM_SETTING (s_8021x),
+ NM_SETTING_802_1X_PASSWORD);
g_ptr_array_add (secrets, secret);
return TRUE;
}
if (nm_streq (eap_method, "tls")) {
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
- _("Identity"),
- NM_SETTING (s_8021x),
- NM_SETTING_802_1X_IDENTITY,
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
+ _("Identity"),
+ NM_SETTING (s_8021x),
+ NM_SETTING_802_1X_IDENTITY);
g_ptr_array_add (secrets, secret);
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
- _("Private key password"),
- NM_SETTING (s_8021x),
- NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Private key password"),
+ NM_SETTING (s_8021x),
+ NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
g_ptr_array_add (secrets, secret);
return TRUE;
}
@@ -281,11 +293,10 @@ add_wireless_secrets (RequestData *request,
return FALSE;
if (NM_IN_STRSET (key_mgmt, "wpa-none", "wpa-psk", "sae")) {
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
- _("Password"),
- NM_SETTING (s_wsec),
- NM_SETTING_WIRELESS_SECURITY_PSK,
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Password"),
+ NM_SETTING (s_wsec),
+ NM_SETTING_WIRELESS_SECURITY_PSK);
g_ptr_array_add (secrets, secret);
return TRUE;
}
@@ -295,22 +306,20 @@ add_wireless_secrets (RequestData *request,
char key[100];
index = nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec);
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
- _("Key"),
- NM_SETTING (s_wsec),
- nm_sprintf_buf (key, "wep-key%u", (guint) index),
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Key"),
+ NM_SETTING (s_wsec),
+ nm_sprintf_buf (key, "wep-key%u", (guint) index));
g_ptr_array_add (secrets, secret);
return TRUE;
}
if (nm_streq (key_mgmt, "iee8021x")) {
if (nm_streq0 (nm_setting_wireless_security_get_auth_alg (s_wsec), "leap")) {
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
- _("Password"),
- NM_SETTING (s_wsec),
- NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Password"),
+ NM_SETTING (s_wsec),
+ NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD);
g_ptr_array_add (secrets, secret);
return TRUE;
} else
@@ -330,23 +339,20 @@ add_pppoe_secrets (RequestData *request,
NMSettingPppoe *s_pppoe = nm_connection_get_setting_pppoe (request->connection);
NMSecretAgentSimpleSecret *secret;
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
- _("Username"),
- NM_SETTING (s_pppoe),
- NM_SETTING_PPPOE_USERNAME,
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
+ _("Username"),
+ NM_SETTING (s_pppoe),
+ NM_SETTING_PPPOE_USERNAME);
g_ptr_array_add (secrets, secret);
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
- _("Service"),
- NM_SETTING (s_pppoe),
- NM_SETTING_PPPOE_SERVICE,
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
+ _("Service"),
+ NM_SETTING (s_pppoe),
+ NM_SETTING_PPPOE_SERVICE);
g_ptr_array_add (secrets, secret);
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
- _("Password"),
- NM_SETTING (s_pppoe),
- NM_SETTING_PPPOE_PASSWORD,
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Password"),
+ NM_SETTING (s_pppoe),
+ NM_SETTING_PPPOE_PASSWORD);
g_ptr_array_add (secrets, secret);
return TRUE;
}
@@ -374,11 +380,10 @@ add_vpn_secret_helper (GPtrArray *secrets, NMSettingVpn *s_vpn, const char *name
flags = get_vpn_secret_flags (s_vpn, name);
if ( flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED
|| flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) {
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET,
- ui_name,
- NM_SETTING (s_vpn),
- name,
- nm_setting_vpn_get_service_type (s_vpn));
+ secret = _secret_real_new_vpn_secret (ui_name,
+ NM_SETTING (s_vpn),
+ name,
+ nm_setting_vpn_get_service_type (s_vpn));
/* Check for duplicates */
for (i = 0; i < secrets->len; i++) {
@@ -506,11 +511,10 @@ _auth_dialog_exited (GPid pid, int status, gpointer user_data)
if (!g_key_file_get_boolean (keyfile, groups[i], "ShouldAsk", NULL))
continue;
- g_ptr_array_add (secrets, _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET,
- g_key_file_get_string (keyfile, groups[i], "Label", NULL),
- NM_SETTING (s_vpn),
- groups[i],
- nm_setting_vpn_get_service_type (s_vpn)));
+ g_ptr_array_add (secrets, _secret_real_new_vpn_secret (g_key_file_get_string (keyfile, groups[i], "Label", NULL),
+ NM_SETTING (s_vpn),
+ groups[i],
+ nm_setting_vpn_get_service_type (s_vpn)));
}
out:
@@ -782,22 +786,20 @@ request_secrets_from_ui (RequestData *request)
title = _("PIN code required");
msg = g_strdup (_("PIN code is needed for the mobile broadband device"));
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
- _("PIN"),
- NM_SETTING (s_gsm),
- NM_SETTING_GSM_PIN,
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
+ _("PIN"),
+ NM_SETTING (s_gsm),
+ NM_SETTING_GSM_PIN);
g_ptr_array_add (secrets, secret);
} else {
title = _("Mobile broadband network password");
msg = g_strdup_printf (_("A password is required to connect to '%s'."),
nm_connection_get_id (request->connection));
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
- _("Password"),
- NM_SETTING (s_gsm),
- NM_SETTING_GSM_PASSWORD,
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Password"),
+ NM_SETTING (s_gsm),
+ NM_SETTING_GSM_PASSWORD);
g_ptr_array_add (secrets, secret);
}
} else if (nm_connection_is_type (request->connection, NM_SETTING_MACSEC_SETTING_NAME)) {
@@ -808,11 +810,10 @@ request_secrets_from_ui (RequestData *request)
if (nm_setting_macsec_get_mode (s_macsec) == NM_SETTING_MACSEC_MODE_PSK) {
title = _("MACsec PSK authentication");
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
- _("MKA CAK"),
- NM_SETTING (s_macsec),
- NM_SETTING_MACSEC_MKA_CAK,
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("MKA CAK"),
+ NM_SETTING (s_macsec),
+ NM_SETTING_MACSEC_MKA_CAK);
g_ptr_array_add (secrets, secret);
} else {
title = _("MACsec EAP authentication");
@@ -826,11 +827,10 @@ request_secrets_from_ui (RequestData *request)
msg = g_strdup_printf (_("A password is required to connect to '%s'."),
nm_connection_get_id (request->connection));
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
- _("Password"),
- NM_SETTING (s_cdma),
- NM_SETTING_CDMA_PASSWORD,
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Password"),
+ NM_SETTING (s_cdma),
+ NM_SETTING_CDMA_PASSWORD);
g_ptr_array_add (secrets, secret);
} else if (nm_connection_is_type (request->connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) {
NMSetting *setting = NULL;
@@ -850,11 +850,10 @@ request_secrets_from_ui (RequestData *request)
msg = g_strdup_printf (_("A password is required to connect to '%s'."),
nm_connection_get_id (request->connection));
- secret = _secret_real_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
- _("Password"),
- setting,
- "password",
- NULL);
+ secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET,
+ _("Password"),
+ setting,
+ "password");
g_ptr_array_add (secrets, secret);
} else if (nm_connection_is_type (request->connection, NM_SETTING_VPN_SETTING_NAME)) {
title = _("VPN password required");
@@ -873,6 +872,9 @@ request_secrets_from_ui (RequestData *request)
} else
goto out_fail;
+ if (secrets->len == 0)
+ goto out_fail;
+
g_signal_emit (request->self, signals[REQUEST_SECRETS], 0,
request->request_id, title, msg, secrets);
return;
@@ -902,6 +904,7 @@ get_secrets (NMSecretAgentOld *agent,
RequestData *request;
gs_free_error GError *error = NULL;
gs_free char *request_id = NULL;
+ const char *request_id_setting_name;
request_id = g_strdup_printf ("%s/%s", connection_path, setting_name);
@@ -921,10 +924,15 @@ get_secrets (NMSecretAgentOld *agent,
return;
}
+ nm_assert (g_str_has_suffix (request_id, setting_name));
+ request_id_setting_name = &request_id[strlen (request_id) - strlen (setting_name)];
+ nm_assert (nm_streq (request_id_setting_name, setting_name));
+
request = g_slice_new (RequestData);
*request = (RequestData) {
.self = self,
.connection = g_object_ref (connection),
+ .setting_name = request_id_setting_name,
.hints = g_strdupv ((char **) hints),
.callback = callback,
.callback_data = callback_data,
diff --git a/clients/common/nm-secret-agent-simple.h b/clients/common/nm-secret-agent-simple.h
index 8cae17a8c2..3e61dace4c 100644
--- a/clients/common/nm-secret-agent-simple.h
+++ b/clients/common/nm-secret-agent-simple.h
@@ -28,12 +28,13 @@ typedef enum {
} NMSecretAgentSecretType;
typedef struct {
- const NMSecretAgentSecretType secret_type;
+ NMSecretAgentSecretType secret_type;
const char *pretty_name;
const char *entry_id;
char *value;
const char *vpn_type;
- gboolean is_secret;
+ bool is_secret:1;
+ bool no_prompt_entry_id:1;
} NMSecretAgentSimpleSecret;
#define NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRETS "vpn.secrets."
diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h
index 2d66eb83fb..19a914956e 100644
--- a/libnm-core/nm-core-internal.h
+++ b/libnm-core/nm-core-internal.h
@@ -129,7 +129,7 @@
/*****************************************************************************/
-#define NM_SETTING_SECRET_FLAGS_ALL \
+#define NM_SETTING_SECRET_FLAG_ALL \
((NMSettingSecretFlags) ( NM_SETTING_SECRET_FLAG_NONE \
| NM_SETTING_SECRET_FLAG_AGENT_OWNED \
| NM_SETTING_SECRET_FLAG_NOT_SAVED \
@@ -138,7 +138,7 @@
static inline gboolean
_nm_setting_secret_flags_valid (NMSettingSecretFlags flags)
{
- return !NM_FLAGS_ANY (flags, ~NM_SETTING_SECRET_FLAGS_ALL);
+ return !NM_FLAGS_ANY (flags, ~NM_SETTING_SECRET_FLAG_ALL);
}
/*****************************************************************************/
@@ -614,6 +614,25 @@ gboolean _nm_setting_sriov_sort_vfs (NMSettingSriov *setting);
/*****************************************************************************/
+typedef struct _NMSockAddrEndpoint NMSockAddrEndpoint;
+
+NMSockAddrEndpoint *nm_sock_addr_endpoint_new (const char *endpoint);
+
+NMSockAddrEndpoint *nm_sock_addr_endpoint_ref (NMSockAddrEndpoint *self);
+void nm_sock_addr_endpoint_unref (NMSockAddrEndpoint *self);
+
+const char *nm_sock_addr_endpoint_get_endpoint (NMSockAddrEndpoint *self);
+const char *nm_sock_addr_endpoint_get_host (NMSockAddrEndpoint *self);
+gint32 nm_sock_addr_endpoint_get_port (NMSockAddrEndpoint *self);
+
+gboolean nm_sock_addr_endpoint_get_fixed_sockaddr (NMSockAddrEndpoint *self,
+ gpointer sockaddr);
+
+#define nm_auto_unref_sockaddrendpoint nm_auto(_nm_auto_unref_sockaddrendpoint)
+NM_AUTO_DEFINE_FCN_VOID0 (NMSockAddrEndpoint *, _nm_auto_unref_sockaddrendpoint, nm_sock_addr_endpoint_unref)
+
+/*****************************************************************************/
+
typedef struct _NMSettInfoSetting NMSettInfoSetting;
typedef struct _NMSettInfoProperty NMSettInfoProperty;
diff --git a/libnm-core/nm-setting-vpn.c b/libnm-core/nm-setting-vpn.c
index e9501ab1f7..a9a9c0df41 100644
--- a/libnm-core/nm-setting-vpn.c
+++ b/libnm-core/nm-setting-vpn.c
@@ -763,7 +763,7 @@ get_secret_flags (NMSetting *setting,
return TRUE;
}
- i64 = _nm_utils_ascii_str_to_int64 (flags_val, 10, 0, NM_SETTING_SECRET_FLAGS_ALL, -1);
+ i64 = _nm_utils_ascii_str_to_int64 (flags_val, 10, 0, NM_SETTING_SECRET_FLAG_ALL, -1);
if ( i64 == -1
|| !_nm_setting_secret_flags_valid (i64)) {
/* The flags keys is set to an unexpected value. That is a configuration
diff --git a/libnm-core/nm-utils-private.h b/libnm-core/nm-utils-private.h
index b61260cb22..46af26ed02 100644
--- a/libnm-core/nm-utils-private.h
+++ b/libnm-core/nm-utils-private.h
@@ -41,6 +41,12 @@ struct _NMVariantAttributeSpec {
gboolean _nm_utils_string_slist_validate (GSList *list,
const char **valid_values);
+gboolean _nm_utils_secret_flags_validate (NMSettingSecretFlags secret_flags,
+ const char *setting_name,
+ const char *property_name,
+ NMSettingSecretFlags disallowed_flags,
+ GError **error);
+
gboolean _nm_utils_wps_method_validate (NMSettingWirelessSecurityWpsMethod wps_method,
const char *setting_name,
const char *property_name,
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index 506f434497..c5855da196 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -59,6 +59,277 @@
* access points and devices, among other things.
*/
+/*****************************************************************************/
+
+struct _NMSockAddrEndpoint {
+ const char *host;
+ guint16 port;
+ guint refcount;
+ char endpoint[];
+};
+
+static gboolean
+NM_IS_SOCK_ADDR_ENDPOINT (const NMSockAddrEndpoint *self)
+{
+ return self && self->refcount > 0;
+}
+
+static const char *
+_parse_endpoint (char *str,
+ guint16 *out_port)
+{
+ char *s;
+ const char *s_port;
+ gint16 port;
+
+ /* Like
+ * - https://git.zx2c4.com/WireGuard/tree/src/tools/config.c?id=5e99a6d43fe2351adf36c786f5ea2086a8fe7ab8#n192
+ * - https://github.com/systemd/systemd/blob/911649fdd43f3a9158b847947724a772a5a45c34/src/network/netdev/wireguard.c#L614
+ */
+
+ g_strstrip (str);
+
+ if (!str[0])
+ return NULL;
+
+ if (str[0] == '[') {
+ str++;
+ s = strchr (str, ']');
+ if (!s)
+ return NULL;
+ if (s == str)
+ return NULL;
+ if (s[1] != ':')
+ return NULL;
+ if (!s[2])
+ return NULL;
+ *s = '\0';
+ s_port = &s[2];
+ } else {
+ s = strrchr (str, ':');
+ if (!s)
+ return NULL;
+ if (s == str)
+ return NULL;
+ if (!s[1])
+ return NULL;
+ *s = '\0';
+ s_port = &s[1];
+ }
+
+ if (!NM_STRCHAR_ALL (s_port, ch, (ch >= '0' && ch <= '9')))
+ return NULL;
+
+ port = _nm_utils_ascii_str_to_int64 (s_port, 10, 1, G_MAXUINT16, 0);
+ if (port == 0)
+ return NULL;
+
+ *out_port = port;
+ return str;
+}
+
+/**
+ * nm_sock_addr_endpoint_new:
+ * @endpoint: the endpoint string.
+ *
+ * This function cannot fail, even if the @endpoint is invalid.
+ * The reason is to allow NMSockAddrEndpoint also to be used
+ * for tracking invalid endpoints. Use nm_sock_addr_endpoint_get_host()
+ * to determine whether the endpoint is valid.
+ *
+ * Returns: (transfer full): the new #NMSockAddrEndpoint endpoint.
+ */
+NMSockAddrEndpoint *
+nm_sock_addr_endpoint_new (const char *endpoint)
+{
+ NMSockAddrEndpoint *ep;
+ gsize l_endpoint;
+ gsize l_host = 0;
+ gsize i;
+ gs_free char *host_clone = NULL;
+ const char *host;
+ guint16 port;
+
+ g_return_val_if_fail (endpoint, NULL);
+
+ l_endpoint = strlen (endpoint) + 1;
+
+ host = _parse_endpoint (nm_strndup_a (200, endpoint, l_endpoint - 1, &host_clone),
+ &port);
+
+ if (host)
+ l_host = strlen (host) + 1;
+
+ ep = g_malloc (sizeof (NMSockAddrEndpoint) + l_endpoint + l_host);
+ ep->refcount = 1;
+ memcpy (ep->endpoint, endpoint, l_endpoint);
+ if (host) {
+ i = l_endpoint;
+ memcpy (&ep->endpoint[i], host, l_host);
+ ep->host = &ep->endpoint[i];
+ ep->port = port;
+ } else {
+ ep->host = NULL;
+ ep->port = 0;
+ }
+ return ep;
+}
+
+/**
+ * nm_sock_addr_endpoint_ref:
+ * @self: (allow-none): the #NMSockAddrEndpoint
+ */
+NMSockAddrEndpoint *
+nm_sock_addr_endpoint_ref (NMSockAddrEndpoint *self)
+{
+ if (!self)
+ return NULL;
+
+ g_return_val_if_fail (NM_IS_SOCK_ADDR_ENDPOINT (self), NULL);
+
+ nm_assert (self->refcount < G_MAXUINT);
+
+ self->refcount++;
+ return self;
+}
+
+/**
+ * nm_sock_addr_endpoint_unref:
+ * @self: (allow-none): the #NMSockAddrEndpoint
+ */
+void
+nm_sock_addr_endpoint_unref (NMSockAddrEndpoint *self)
+{
+ if (!self)
+ return;
+
+ g_return_if_fail (NM_IS_SOCK_ADDR_ENDPOINT (self));
+
+ if (--self->refcount == 0)
+ g_free (self);
+}
+
+/**
+ * nm_sock_addr_endpoint_get_endpoint:
+ * @self: the #NMSockAddrEndpoint
+ *
+ * Gives the endpoint string. Since #NMSockAddrEndpoint's only
+ * information is the endpoint string, this can be used for comparing
+ * to instances for equality and order them lexically.
+ *
+ * Returns: (transfer none): the endpoint.
+ */
+const char *
+nm_sock_addr_endpoint_get_endpoint (NMSockAddrEndpoint *self)
+{
+ g_return_val_if_fail (NM_IS_SOCK_ADDR_ENDPOINT (self), NULL);
+
+ return self->endpoint;
+}
+
+/**
+ * nm_sock_addr_endpoint_get_host:
+ * @self: the #NMSockAddrEndpoint
+ *
+ * Returns: (transfer none): the parsed host part of the endpoint.
+ * If the endpoint is invalid, %NULL will be returned.
+ */
+const char *
+nm_sock_addr_endpoint_get_host (NMSockAddrEndpoint *self)
+{
+ g_return_val_if_fail (NM_IS_SOCK_ADDR_ENDPOINT (self), NULL);
+
+ return self->host;
+}
+
+/**
+ * nm_sock_addr_endpoint_get_port:
+ * @self: the #NMSockAddrEndpoint
+ *
+ * Returns: the parsed port part of the endpoint (the service).
+ * If the endpoint is invalid, -1 will be returned.
+ */
+gint32
+nm_sock_addr_endpoint_get_port (NMSockAddrEndpoint *self)
+{
+ g_return_val_if_fail (NM_IS_SOCK_ADDR_ENDPOINT (self), -1);
+
+ return self->host ? (int) self->port : -1;
+}
+
+gboolean
+nm_sock_addr_endpoint_get_fixed_sockaddr (NMSockAddrEndpoint *self,
+ gpointer sockaddr)
+{
+ int addr_family;
+ NMIPAddr addrbin;
+ const char *s;
+ guint scope_id = 0;
+
+ g_return_val_if_fail (NM_IS_SOCK_ADDR_ENDPOINT (self), FALSE);
+ g_return_val_if_fail (sockaddr, FALSE);
+
+ if (!self->host)
+ return FALSE;
+
+ if (nm_utils_parse_inaddr_bin (AF_UNSPEC, self->host, &addr_family, &addrbin))
+ goto good;
+
+ /* See if there is an IPv6 scope-id...
+ *
+ * Note that it does not make sense to persist connection profiles to disk,
+ * that refenrence a scope-id (because the interface's ifindex changes on
+ * reboot). However, we also support runtime only changes like `nmcli device modify`
+ * where nothing is persisted to disk. At least in that case, passing a scope-id
+ * might be reasonable. So, parse that too. */
+ s = strchr (self->host, '%');
+ if (!s)
+ return FALSE;
+
+ if ( s[1] == '\0'
+ || !NM_STRCHAR_ALL (&s[1], ch, (ch >= '0' && ch <= '9')))
+ return FALSE;
+
+ scope_id = _nm_utils_ascii_str_to_int64 (&s[1], 10, 0, G_MAXINT32, G_MAXUINT);
+ if (scope_id == G_MAXUINT && errno)
+ return FALSE;
+
+ {
+ gs_free char *tmp_str = NULL;
+ const char *host_part;
+
+ host_part = nm_strndup_a (200, self->host, s - self->host, &tmp_str);
+ if (nm_utils_parse_inaddr_bin (AF_INET6, host_part, &addr_family, &addrbin))
+ goto good;
+ }
+
+ return FALSE;
+
+good:
+ switch (addr_family) {
+ case AF_INET:
+ *((struct sockaddr_in *) sockaddr) = (struct sockaddr_in) {
+ .sin_family = AF_INET,
+ .sin_addr = addrbin.addr4_struct,
+ .sin_port = htons (self->port),
+ };
+ return TRUE;
+ case AF_INET6:
+ *((struct sockaddr_in6 *) sockaddr) = (struct sockaddr_in6) {
+ .sin6_family = AF_INET6,
+ .sin6_addr = addrbin.addr6,
+ .sin6_port = htons (self->port),
+ .sin6_scope_id = scope_id,
+ .sin6_flowinfo = 0,
+ };
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*****************************************************************************/
+
struct IsoLangToEncodings
{
const char *lang;
@@ -4309,6 +4580,62 @@ _nm_utils_hwaddr_from_dbus (GVariant *dbus_value,
/*****************************************************************************/
+/* Validate secret-flags. Most settings don't validate them, which is a bug.
+ * But we possibly cannot enforce a strict validation now.
+ *
+ * For new settings, they shall validate the secret-flags strictly. */
+gboolean
+_nm_utils_secret_flags_validate (NMSettingSecretFlags secret_flags,
+ const char *setting_name,
+ const char *property_name,
+ NMSettingSecretFlags disallowed_flags,
+ GError **error)
+{
+ if (secret_flags == NM_SETTING_SECRET_FLAG_NONE)
+ return TRUE;
+
+ if (NM_FLAGS_ANY (secret_flags, ~NM_SETTING_SECRET_FLAG_ALL)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("unknown secret flags"));
+ if (setting_name)
+ g_prefix_error (error, "%s.%s: ", setting_name, property_name);
+ return FALSE;
+ }
+
+ if (!nm_utils_is_power_of_two (secret_flags)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("conflicting secret flags"));
+ if (setting_name)
+ g_prefix_error (error, "%s.%s: ", setting_name, property_name);
+ return FALSE;
+ }
+
+ if (NM_FLAGS_ANY (secret_flags, disallowed_flags)) {
+ if (NM_FLAGS_HAS (secret_flags, NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("secret flags must not be \"not-required\""));
+ if (setting_name)
+ g_prefix_error (error, "%s.%s: ", setting_name, property_name);
+ return FALSE;
+ }
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("unsupported secret flags"));
+ if (setting_name)
+ g_prefix_error (error, "%s.%s: ", setting_name, property_name);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
gboolean
_nm_utils_wps_method_validate (NMSettingWirelessSecurityWpsMethod wps_method,
const char *setting_name,
@@ -6020,15 +6347,15 @@ _nm_utils_team_link_watchers_to_variant (GPtrArray *link_watchers)
name = nm_team_link_watcher_get_name (watcher);
g_variant_builder_add (&watcher_builder, "{sv}",
- "name",
- g_variant_new_string (name));
+ "name",
+ g_variant_new_string (name));
- if nm_streq (name, NM_TEAM_LINK_WATCHER_ETHTOOL) {
+ if (nm_streq (name, NM_TEAM_LINK_WATCHER_ETHTOOL)) {
int_val = nm_team_link_watcher_get_delay_up (watcher);
if (int_val) {
g_variant_builder_add (&watcher_builder, "{sv}",
- "delay-up",
- g_variant_new_int32 (int_val));
+ "delay-up",
+ g_variant_new_int32 (int_val));
}
int_val = nm_team_link_watcher_get_delay_down (watcher);
if (int_val) {
@@ -6063,7 +6390,7 @@ _nm_utils_team_link_watchers_to_variant (GPtrArray *link_watchers)
"target-host",
g_variant_new_string (nm_team_link_watcher_get_target_host (watcher)));
- if nm_streq (name, NM_TEAM_LINK_WATCHER_NSNA_PING) {
+ if (nm_streq (name, NM_TEAM_LINK_WATCHER_NSNA_PING)) {
g_variant_builder_add (&builder, "a{sv}", &watcher_builder);
continue;
}
@@ -6155,7 +6482,7 @@ _nm_utils_team_link_watchers_from_variant (GVariant *value)
val2 = 0;
if (!g_variant_lookup (watcher_var, "missed-max", "i", &val3))
val3 = 3;
- if nm_streq (name, NM_TEAM_LINK_WATCHER_ARP_PING) {
+ if (nm_streq (name, NM_TEAM_LINK_WATCHER_ARP_PING)) {
if (!g_variant_lookup (watcher_var, "vlanid", "i", &val4))
val4 = -1;
if (!g_variant_lookup (watcher_var, "source-host", "&s", &source_host))
diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h
index cf9572b907..34aae560e3 100644
--- a/libnm-core/nm-utils.h
+++ b/libnm-core/nm-utils.h
@@ -40,6 +40,8 @@
G_BEGIN_DECLS
+/*****************************************************************************/
+
typedef struct _NMVariantAttributeSpec NMVariantAttributeSpec;
/* SSID helpers */
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c
index 96eafa3a68..7d97296ab4 100644
--- a/libnm-core/tests/test-general.c
+++ b/libnm-core/tests/test-general.c
@@ -5522,6 +5522,158 @@ test_setting_user_data (void)
/*****************************************************************************/
+typedef union {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+} SockAddrUnion;
+
+static void
+_sock_addr_endpoint (const char *endpoint,
+ const char *host,
+ gint32 port)
+{
+ nm_auto_unref_sockaddrendpoint NMSockAddrEndpoint *ep = NULL;
+ const char *s_endpoint;
+ const char *s_host;
+ gint32 s_port;
+ SockAddrUnion sockaddr = { };
+
+ g_assert (endpoint);
+ g_assert (!host == (port == -1));
+ g_assert (port >= -1 && port <= G_MAXUINT16);
+
+ ep = nm_sock_addr_endpoint_new (endpoint);
+ g_assert (ep);
+
+ s_endpoint = nm_sock_addr_endpoint_get_endpoint (ep);
+ s_host = nm_sock_addr_endpoint_get_host (ep);
+ s_port = nm_sock_addr_endpoint_get_port (ep);
+ g_assert_cmpstr (endpoint, ==, s_endpoint);
+ g_assert_cmpstr (host, ==, s_host);
+ g_assert_cmpint (port, ==, s_port);
+
+ g_assert (!nm_sock_addr_endpoint_get_fixed_sockaddr (ep, &sockaddr));
+
+ if (endpoint[0] != ' ') {
+ gs_free char *endpoint2 = NULL;
+
+ /* also test with a leading space */
+ endpoint2 = g_strdup_printf (" %s", endpoint);
+ _sock_addr_endpoint (endpoint2, host, port);
+ }
+
+ if (endpoint[0] && endpoint[strlen (endpoint) - 1] != ' ') {
+ gs_free char *endpoint2 = NULL;
+
+ /* also test with a trailing space */
+ endpoint2 = g_strdup_printf ("%s ", endpoint);
+ _sock_addr_endpoint (endpoint2, host, port);
+ }
+}
+
+static void
+_sock_addr_endpoint_fixed (const char *endpoint,
+ const char *host,
+ guint16 port,
+ guint scope_id)
+{
+ nm_auto_unref_sockaddrendpoint NMSockAddrEndpoint *ep = NULL;
+ const char *s_endpoint;
+ const char *s_host;
+ gint32 s_port;
+ int addr_family;
+ NMIPAddr addrbin;
+ SockAddrUnion sockaddr = { };
+
+ g_assert (endpoint);
+ g_assert (host);
+ g_assert (port > 0);
+
+ if (!nm_utils_parse_inaddr_bin (AF_UNSPEC, host, &addr_family, &addrbin))
+ g_assert_not_reached ();
+
+ ep = nm_sock_addr_endpoint_new (endpoint);
+ g_assert (ep);
+
+ s_endpoint = nm_sock_addr_endpoint_get_endpoint (ep);
+ s_host = nm_sock_addr_endpoint_get_host (ep);
+ s_port = nm_sock_addr_endpoint_get_port (ep);
+ g_assert_cmpstr (endpoint, ==, s_endpoint);
+ g_assert_cmpstr (NULL, !=, s_host);
+ g_assert_cmpint (port, ==, s_port);
+
+ if (!nm_sock_addr_endpoint_get_fixed_sockaddr (ep, &sockaddr))
+ g_assert_not_reached ();
+
+ g_assert_cmpint (sockaddr.sa.sa_family, ==, addr_family);
+ if (addr_family == AF_INET) {
+ const SockAddrUnion s = {
+ .in = {
+ .sin_family = AF_INET,
+ .sin_addr = addrbin.addr4_struct,
+ .sin_port = htons (port),
+ },
+ };
+
+ g_assert_cmpint (sockaddr.in.sin_addr.s_addr, ==, addrbin.addr4);
+ g_assert_cmpint (sockaddr.in.sin_port, ==, htons (port));
+ g_assert (memcmp (&s, &sockaddr, sizeof (s.in)) == 0);
+ } else if (addr_family == AF_INET6) {
+ const SockAddrUnion s = {
+ .in6 = {
+ .sin6_family = AF_INET6,
+ .sin6_addr = addrbin.addr6,
+ .sin6_scope_id = scope_id,
+ .sin6_port = htons (port),
+ },
+ };
+
+ g_assert (memcmp (&sockaddr.in6.sin6_addr, &addrbin, sizeof (addrbin.addr6)) == 0);
+ g_assert_cmpint (sockaddr.in6.sin6_port, ==, htons (port));
+ g_assert_cmpint (sockaddr.in6.sin6_scope_id, ==, scope_id);
+ g_assert_cmpint (sockaddr.in6.sin6_flowinfo, ==, 0);
+ g_assert (memcmp (&s, &sockaddr, sizeof (s.in6)) == 0);
+ } else
+ g_assert_not_reached ();
+}
+
+static void
+test_sock_addr_endpoint (void)
+{
+ _sock_addr_endpoint ("", NULL, -1);
+ _sock_addr_endpoint (":", NULL, -1);
+ _sock_addr_endpoint ("a", NULL, -1);
+ _sock_addr_endpoint ("a:", NULL, -1);
+ _sock_addr_endpoint (":a", NULL, -1);
+ _sock_addr_endpoint ("[]:a", NULL, -1);
+ _sock_addr_endpoint ("[]a", NULL, -1);
+ _sock_addr_endpoint ("[]:", NULL, -1);
+ _sock_addr_endpoint ("[a]b", NULL, -1);
+ _sock_addr_endpoint ("[a:b", NULL, -1);
+ _sock_addr_endpoint ("[a[:b", NULL, -1);
+ _sock_addr_endpoint ("a:6", "a", 6);
+ _sock_addr_endpoint ("a:6", "a", 6);
+ _sock_addr_endpoint ("[a]:6", "a", 6);
+ _sock_addr_endpoint ("[a]:6", "a", 6);
+ _sock_addr_endpoint ("[a]:655", "a", 655);
+ _sock_addr_endpoint ("[ab]:][6", NULL, -1);
+ _sock_addr_endpoint ("[ab]:]:[6", NULL, -1);
+ _sock_addr_endpoint ("[a[]:b", NULL, -1);
+ _sock_addr_endpoint ("[192.169.6.x]:6", "192.169.6.x", 6);
+ _sock_addr_endpoint ("[192.169.6.x]:0", NULL, -1);
+ _sock_addr_endpoint ("192.169.6.7:0", NULL, -1);
+
+ _sock_addr_endpoint_fixed ("192.169.6.7:6", "192.169.6.7", 6, 0);
+ _sock_addr_endpoint_fixed ("[192.169.6.7]:6", "192.169.6.7", 6, 0);
+ _sock_addr_endpoint_fixed ("[a:b::]:6", "a:b::", 6, 0);
+ _sock_addr_endpoint_fixed ("[a:b::%7]:6", "a:b::", 6, 7);
+ _sock_addr_endpoint_fixed ("a:b::1%75:6", "a:b::1", 6, 75);
+ _sock_addr_endpoint_fixed ("a:b::1%0:64", "a:b::1", 64, 0);
+}
+
+/*****************************************************************************/
+
static void
test_hexstr2bin (void)
{
@@ -7735,6 +7887,8 @@ int main (int argc, char **argv)
g_test_add_func ("/core/general/test_setting_compare_default_strv", test_setting_compare_default_strv);
g_test_add_func ("/core/general/test_setting_user_data", test_setting_user_data);
+ g_test_add_func ("/core/general/test_sock_addr_endpoint", test_sock_addr_endpoint);
+
g_test_add_func ("/core/general/hexstr2bin", test_hexstr2bin);
g_test_add_func ("/core/general/nm_strquote", test_nm_strquote);
g_test_add_func ("/core/general/test_nm_utils_uuid_generate_from_string", test_nm_utils_uuid_generate_from_string);
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h
index 55cdd374da..42299c9635 100644
--- a/shared/nm-utils/nm-macros-internal.h
+++ b/shared/nm-utils/nm-macros-internal.h
@@ -449,7 +449,7 @@ NM_G_ERROR_MSG (GError *error)
/*****************************************************************************/
/* macro to return strlen() of a compile time string. */
-#define NM_STRLEN(str) ( sizeof ("" str) - 1 )
+#define NM_STRLEN(str) ( sizeof (""str"") - 1 )
/* returns the length of a NULL terminated array of pointers,
* like g_strv_length() does. The difference is:
@@ -860,12 +860,33 @@ fcn (void) \
/*****************************************************************************/
-#define nm_streq(s1, s2) (strcmp (s1, s2) == 0)
-#define nm_streq0(s1, s2) (g_strcmp0 (s1, s2) == 0)
+static inline gboolean
+nm_streq (const char *s1, const char *s2)
+{
+ return strcmp (s1, s2) == 0;
+}
+
+static inline gboolean
+nm_streq0 (const char *s1, const char *s2)
+{
+ return (s1 == s2)
+ || (s1 && s2 && strcmp (s1, s2) == 0);
+}
#define NM_STR_HAS_PREFIX(str, prefix) \
(strncmp ((str), ""prefix"", NM_STRLEN (prefix)) == 0)
+#define NM_STR_HAS_SUFFIX(str, suffix) \
+ ({ \
+ const char *_str = (str); \
+ gsize _l = strlen (_str); \
+ \
+ ( (_l >= NM_STRLEN (suffix)) \
+ && (memcmp (&_str[_l - NM_STRLEN (suffix)], \
+ ""suffix"", \
+ NM_STRLEN (suffix)) == 0)); \
+ })
+
/*****************************************************************************/
static inline GString *
diff --git a/shared/nm-utils/nm-secret-utils.h b/shared/nm-utils/nm-secret-utils.h
index 9df31afea1..1bd518704e 100644
--- a/shared/nm-utils/nm-secret-utils.h
+++ b/shared/nm-utils/nm-secret-utils.h
@@ -76,6 +76,19 @@ typedef struct {
} NMSecretPtr;
static inline void
+nm_secret_ptr_bzero (NMSecretPtr *secret)
+{
+ if (secret) {
+ if (secret->len > 0) {
+ if (secret->ptr)
+ nm_explicit_bzero (secret->ptr, secret->len);
+ }
+ }
+}
+
+#define nm_auto_bzero_secret_ptr nm_auto(nm_secret_ptr_bzero)
+
+static inline void
nm_secret_ptr_clear (NMSecretPtr *secret)
{
if (secret) {
@@ -90,12 +103,24 @@ nm_secret_ptr_clear (NMSecretPtr *secret)
#define nm_auto_clear_secret_ptr nm_auto(nm_secret_ptr_clear)
+#define NM_SECRET_PTR_INIT() \
+ ((const NMSecretPtr) { \
+ .len = 0, \
+ .ptr = NULL, \
+ })
+
#define NM_SECRET_PTR_STATIC(_len) \
((const NMSecretPtr) { \
.len = _len, \
.ptr = ((guint8 [_len]) { }), \
})
+#define NM_SECRET_PTR_ARRAY(_arr) \
+ ((const NMSecretPtr) { \
+ .len = G_N_ELEMENTS (_arr) * sizeof ((_arr)[0]), \
+ .ptr = &((_arr)[0]), \
+ })
+
static inline void
nm_secret_ptr_clear_static (const NMSecretPtr *secret)
{
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 8b68469cd9..2d4ae32cd9 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -2042,9 +2042,14 @@ nm_device_get_route_metric_default (NMDeviceType device_type)
*/
switch (device_type) {
- /* 50 is also used for VPN plugins (NM_VPN_ROUTE_METRIC_DEFAULT) */
+
+ /* 50 is also used for VPN plugins (NM_VPN_ROUTE_METRIC_DEFAULT).
+ *
+ * Note that returning 50 from this function means that this device-type is
+ * in some aspects a VPN. */
case NM_DEVICE_TYPE_WIREGUARD:
- return 50;
+ return NM_VPN_ROUTE_METRIC_DEFAULT;
+
case NM_DEVICE_TYPE_ETHERNET:
case NM_DEVICE_TYPE_VETH:
return 100;
@@ -6481,23 +6486,25 @@ static void
activate_stage2_device_config (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ NMDeviceClass *klass;
NMActStageReturn ret;
gboolean no_firmware = FALSE;
CList *iter;
nm_device_state_changed (self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE);
- /* Assumed connections were already set up outside NetworkManager */
- if (!nm_device_sys_iface_state_is_external_or_assume (self)) {
- NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
-
+ if (!nm_device_sys_iface_state_is_external_or_assume (self))
_ethtool_state_set (self);
+ if (!nm_device_sys_iface_state_is_external_or_assume (self)) {
if (!tc_commit (self)) {
_LOGW (LOGD_IP6, "failed applying traffic control rules");
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
+ return;
}
+ }
+ if (!nm_device_sys_iface_state_is_external_or_assume (self)) {
if (!nm_device_bring_up (self, FALSE, &no_firmware)) {
if (no_firmware)
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_FIRMWARE_MISSING);
@@ -6505,15 +6512,21 @@ activate_stage2_device_config (NMDevice *self)
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
return;
}
+ }
- ret = NM_DEVICE_GET_CLASS (self)->act_stage2_config (self, &failure_reason);
+ klass = NM_DEVICE_GET_CLASS (self);
+ if ( klass->act_stage2_config_also_for_external_or_assume
+ || !nm_device_sys_iface_state_is_external_or_assume (self)) {
+ NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
+
+ ret = klass->act_stage2_config (self, &failure_reason);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
return;
- else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
+ if (ret != NM_ACT_STAGE_RETURN_SUCCESS) {
+ nm_assert (ret == NM_ACT_STAGE_RETURN_FAILURE);
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason);
return;
}
- g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
}
/* If we have slaves that aren't yet enslaved, do that now */
@@ -6530,6 +6543,7 @@ activate_stage2_device_config (NMDevice *self)
}
lldp_init (self, TRUE);
+
nm_device_activate_schedule_stage3_ip_config_start (self);
}
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index b684e2f943..303b92325b 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -456,6 +456,11 @@ typedef struct _NMDeviceClass {
guint32 (* get_dhcp_timeout) (NMDevice *self,
int addr_family);
+
+ /* Controls, whether to call act_stage2_config() callback also for assuming
+ * a device or for external activations. In this case, act_stage2_config() must
+ * take care not to touch the device's configuration. */
+ bool act_stage2_config_also_for_external_or_assume:1;
} NMDeviceClass;
typedef void (*NMDeviceAuthRequestFunc) (NMDevice *device,
diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h
index a93854a465..1b0d39ed69 100644
--- a/src/nm-core-utils.h
+++ b/src/nm-core-utils.h
@@ -485,4 +485,8 @@ const char *nm_activation_type_to_string (NMActivationType activation_type);
const char *nm_utils_parse_dns_domain (const char *domain, gboolean *is_routing);
+/*****************************************************************************/
+
+#define NM_VPN_ROUTE_METRIC_DEFAULT 50
+
#endif /* __NM_CORE_UTILS_H__ */
diff --git a/src/nm-policy.c b/src/nm-policy.c
index cb0688f43b..540f406514 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -149,6 +149,25 @@ static NMDevice *get_default_device (NMPolicy *self, int addr_family);
/*****************************************************************************/
+static void
+_dns_manager_set_ip_config (NMDnsManager *dns_manager,
+ NMIPConfig *ip_config,
+ NMDnsIPConfigType ip_config_type,
+ NMDevice *device)
+{
+ if ( NM_IN_SET (ip_config_type, NM_DNS_IP_CONFIG_TYPE_DEFAULT,
+ NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE)
+ && device
+ && nm_device_get_route_metric_default (nm_device_get_device_type (device)) == NM_VPN_ROUTE_METRIC_DEFAULT) {
+ /* some device types are inherently VPN. */
+ ip_config_type = NM_DNS_IP_CONFIG_TYPE_VPN;
+ }
+
+ nm_dns_manager_set_ip_config (dns_manager, ip_config, ip_config_type);
+}
+
+/*****************************************************************************/
+
typedef struct {
NMPlatformIP6Address prefix;
NMDevice *device; /* The requesting ("uplink") device */
@@ -1090,19 +1109,21 @@ update_ip_dns (NMPolicy *self, int addr_family)
gpointer ip_config;
const char *ip_iface = NULL;
NMVpnConnection *vpn = NULL;
+ NMDevice *device = NULL;
nm_assert_addr_family (addr_family);
- ip_config = get_best_ip_config (self, addr_family, &ip_iface, NULL, NULL, &vpn);
+ ip_config = get_best_ip_config (self, addr_family, &ip_iface, NULL, &device, &vpn);
if (ip_config) {
/* Tell the DNS manager this config is preferred by re-adding it with
* a different IP config type.
*/
- nm_dns_manager_set_ip_config (NM_POLICY_GET_PRIVATE (self)->dns_manager,
- ip_config,
- vpn
- ? NM_DNS_IP_CONFIG_TYPE_VPN
- : NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE);
+ _dns_manager_set_ip_config (NM_POLICY_GET_PRIVATE (self)->dns_manager,
+ ip_config,
+ vpn
+ ? NM_DNS_IP_CONFIG_TYPE_VPN
+ : NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE,
+ device);
}
if (addr_family == AF_INET6)
@@ -1849,10 +1870,10 @@ device_state_changed (NMDevice *device,
ip4_config = nm_device_get_ip4_config (device);
if (ip4_config)
- nm_dns_manager_set_ip_config (priv->dns_manager, NM_IP_CONFIG_CAST (ip4_config), NM_DNS_IP_CONFIG_TYPE_DEFAULT);
+ _dns_manager_set_ip_config (priv->dns_manager, NM_IP_CONFIG_CAST (ip4_config), NM_DNS_IP_CONFIG_TYPE_DEFAULT, device);
ip6_config = nm_device_get_ip6_config (device);
if (ip6_config)
- nm_dns_manager_set_ip_config (priv->dns_manager, NM_IP_CONFIG_CAST (ip6_config), NM_DNS_IP_CONFIG_TYPE_DEFAULT);
+ _dns_manager_set_ip_config (priv->dns_manager, NM_IP_CONFIG_CAST (ip6_config), NM_DNS_IP_CONFIG_TYPE_DEFAULT, device);
update_routing_and_dns (self, FALSE);
@@ -1979,7 +2000,7 @@ device_ip_config_changed (NMDevice *device,
if (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) {
if (old_config != new_config) {
if (new_config)
- nm_dns_manager_set_ip_config (priv->dns_manager, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT);
+ _dns_manager_set_ip_config (priv->dns_manager, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT, device);
if (old_config)
nm_dns_manager_set_ip_config (priv->dns_manager, old_config, NM_DNS_IP_CONFIG_TYPE_REMOVED);
}
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index ce96c18426..a7daebf821 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -2371,8 +2371,9 @@ _wireguard_create_change_nlmsgs (NMPlatform *platform,
int wireguard_family_id,
const NMPlatformLnkWireGuard *lnk_wireguard,
const NMPWireGuardPeer *peers,
+ const NMPlatformWireGuardChangePeerFlags *peer_flags,
guint peers_len,
- gboolean replace_peers,
+ NMPlatformWireGuardChangeFlags change_flags,
GPtrArray **out_msgs)
{
gs_unref_ptrarray GPtrArray *msgs = NULL;
@@ -2384,6 +2385,7 @@ _wireguard_create_change_nlmsgs (NMPlatform *platform,
struct nlattr *nest_curr_peer;
struct nlattr *nest_allowed_ips;
struct nlattr *nest_curr_allowed_ip;
+ NMPlatformWireGuardChangePeerFlags p_flags = NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_DEFAULT;
#define _nla_nest_end(msg, nest_start) \
G_STMT_START { \
@@ -2418,12 +2420,19 @@ again:
NLA_PUT_U32 (msg, WGDEVICE_A_IFINDEX, (guint32) ifindex);
if (idx_peer_curr == IDX_NIL) {
- NLA_PUT (msg, WGDEVICE_A_PRIVATE_KEY, sizeof (lnk_wireguard->private_key), lnk_wireguard->private_key);
- NLA_PUT_U16 (msg, WGDEVICE_A_LISTEN_PORT, lnk_wireguard->listen_port);
- NLA_PUT_U32 (msg, WGDEVICE_A_FWMARK, lnk_wireguard->fwmark);
+ guint32 flags;
- NLA_PUT_U32 (msg, WGDEVICE_A_FLAGS,
- replace_peers ? WGDEVICE_F_REPLACE_PEERS : ((guint32) 0u));
+ if (NM_FLAGS_HAS (change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY))
+ NLA_PUT (msg, WGDEVICE_A_PRIVATE_KEY, sizeof (lnk_wireguard->private_key), lnk_wireguard->private_key);
+ if (NM_FLAGS_HAS (change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT))
+ NLA_PUT_U16 (msg, WGDEVICE_A_LISTEN_PORT, lnk_wireguard->listen_port);
+ if (NM_FLAGS_HAS (change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK))
+ NLA_PUT_U32 (msg, WGDEVICE_A_FWMARK, lnk_wireguard->fwmark);
+
+ flags = 0;
+ if (NM_FLAGS_HAS (change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS))
+ flags |= WGDEVICE_F_REPLACE_PEERS;
+ NLA_PUT_U32 (msg, WGDEVICE_A_FLAGS, flags);
}
if (peers_len == 0)
@@ -2442,6 +2451,21 @@ again:
for (; idx_peer_curr < peers_len; idx_peer_curr++) {
const NMPWireGuardPeer *p = &peers[idx_peer_curr];
+ if (peer_flags) {
+ p_flags = peer_flags[idx_peer_curr];
+ if (!NM_FLAGS_ANY (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME
+ | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY
+ | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL
+ | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT
+ | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS
+ | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS)) {
+ /* no flags set. We take that as indication to skip configuring the peer
+ * entirely. */
+ nm_assert (p_flags == NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE);
+ continue;
+ }
+ }
+
nest_curr_peer = nla_nest_start (msg, 0);
if (!nest_curr_peer)
goto toobig_peers;
@@ -2449,63 +2473,77 @@ again:
if (nla_put (msg, WGPEER_A_PUBLIC_KEY, NMP_WIREGUARD_PUBLIC_KEY_LEN, p->public_key) < 0)
goto toobig_peers;
- if (idx_allowed_ips_curr == IDX_NIL) {
-
- if (nla_put (msg, WGPEER_A_PRESHARED_KEY, sizeof (p->preshared_key), p->preshared_key) < 0)
- goto toobig_peers;
-
- if (nla_put_uint16 (msg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, p->persistent_keepalive_interval) < 0)
+ if (NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME)) {
+ /* all other p_flags are silently ignored. */
+ if (nla_put_uint32 (msg, WGPEER_A_FLAGS, WGPEER_F_REMOVE_ME) < 0)
goto toobig_peers;
+ } else {
- if (nla_put_uint32 (msg, WGPEER_A_FLAGS, WGPEER_F_REPLACE_ALLOWEDIPS) < 0)
- goto toobig_peers;
+ if (idx_allowed_ips_curr == IDX_NIL) {
+ if ( NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY)
+ && nla_put (msg, WGPEER_A_PRESHARED_KEY, sizeof (p->preshared_key), p->preshared_key) < 0)
+ goto toobig_peers;
- if (NM_IN_SET (p->endpoint.sa.sa_family, AF_INET, AF_INET6)) {
- if (nla_put (msg,
- WGPEER_A_ENDPOINT,
- p->endpoint.sa.sa_family == AF_INET
- ? sizeof (p->endpoint.in)
- : sizeof (p->endpoint.in6),
- &p->endpoint) < 0)
+ if ( NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL)
+ && nla_put_uint16 (msg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, p->persistent_keepalive_interval) < 0)
goto toobig_peers;
- } else
- nm_assert (p->endpoint.sa.sa_family == AF_UNSPEC);
- }
- if (p->allowed_ips_len > 0) {
- if (idx_allowed_ips_curr == IDX_NIL)
- idx_allowed_ips_curr = 0;
+ if ( NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS)
+ && nla_put_uint32 (msg, WGPEER_A_FLAGS, WGPEER_F_REPLACE_ALLOWEDIPS) < 0)
+ goto toobig_peers;
- nest_allowed_ips = nla_nest_start (msg, WGPEER_A_ALLOWEDIPS);
- if (!nest_allowed_ips)
- goto toobig_allowedips;
+ if (NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT)) {
+ if (NM_IN_SET (p->endpoint.sa.sa_family, AF_INET, AF_INET6)) {
+ if (nla_put (msg,
+ WGPEER_A_ENDPOINT,
+ p->endpoint.sa.sa_family == AF_INET
+ ? sizeof (p->endpoint.in)
+ : sizeof (p->endpoint.in6),
+ &p->endpoint) < 0)
+ goto toobig_peers;
+ } else {
+ /* I think there is no way to clear an endpoint, though there shold be. */
+ nm_assert (p->endpoint.sa.sa_family == AF_UNSPEC);
+ }
+ }
+ }
- for (; idx_allowed_ips_curr < p->allowed_ips_len; idx_allowed_ips_curr++) {
- const NMPWireGuardAllowedIP *aip = &p->allowed_ips[idx_allowed_ips_curr];
+ if ( NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS)
+ && p->allowed_ips_len > 0) {
+ if (idx_allowed_ips_curr == IDX_NIL)
+ idx_allowed_ips_curr = 0;
- nest_curr_allowed_ip = nla_nest_start (msg, 0);
- if (!nest_curr_allowed_ip)
+ nest_allowed_ips = nla_nest_start (msg, WGPEER_A_ALLOWEDIPS);
+ if (!nest_allowed_ips)
goto toobig_allowedips;
- g_return_val_if_fail (NM_IN_SET (aip->family, AF_INET, AF_INET6), -NME_BUG);
+ for (; idx_allowed_ips_curr < p->allowed_ips_len; idx_allowed_ips_curr++) {
+ const NMPWireGuardAllowedIP *aip = &p->allowed_ips[idx_allowed_ips_curr];
- if (nla_put_uint16 (msg, WGALLOWEDIP_A_FAMILY, aip->family) < 0)
- goto toobig_allowedips;
- if (nla_put (msg,
- WGALLOWEDIP_A_IPADDR,
- nm_utils_addr_family_to_size (aip->family),
- &aip->addr) < 0)
- goto toobig_allowedips;
- if (nla_put_uint8 (msg, WGALLOWEDIP_A_CIDR_MASK, aip->mask) < 0)
- goto toobig_allowedips;
+ nest_curr_allowed_ip = nla_nest_start (msg, 0);
+ if (!nest_curr_allowed_ip)
+ goto toobig_allowedips;
- _nla_nest_end (msg, nest_curr_allowed_ip);
- nest_curr_allowed_ip = NULL;
- }
- idx_allowed_ips_curr = IDX_NIL;
+ g_return_val_if_fail (NM_IN_SET (aip->family, AF_INET, AF_INET6), -NME_BUG);
+
+ if (nla_put_uint16 (msg, WGALLOWEDIP_A_FAMILY, aip->family) < 0)
+ goto toobig_allowedips;
+ if (nla_put (msg,
+ WGALLOWEDIP_A_IPADDR,
+ nm_utils_addr_family_to_size (aip->family),
+ &aip->addr) < 0)
+ goto toobig_allowedips;
+ if (nla_put_uint8 (msg, WGALLOWEDIP_A_CIDR_MASK, aip->mask) < 0)
+ goto toobig_allowedips;
- _nla_nest_end (msg, nest_allowed_ips);
- nest_allowed_ips = NULL;
+ _nla_nest_end (msg, nest_curr_allowed_ip);
+ nest_curr_allowed_ip = NULL;
+ }
+ idx_allowed_ips_curr = IDX_NIL;
+
+ _nla_nest_end (msg, nest_allowed_ips);
+ nest_allowed_ips = NULL;
+ }
}
_nla_nest_end (msg, nest_curr_peer);
@@ -2553,8 +2591,9 @@ link_wireguard_change (NMPlatform *platform,
int ifindex,
const NMPlatformLnkWireGuard *lnk_wireguard,
const NMPWireGuardPeer *peers,
+ const NMPlatformWireGuardChangePeerFlags *peer_flags,
guint peers_len,
- gboolean replace_peers)
+ NMPlatformWireGuardChangeFlags change_flags)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
gs_unref_ptrarray GPtrArray *msgs = NULL;
@@ -2571,8 +2610,9 @@ link_wireguard_change (NMPlatform *platform,
wireguard_family_id,
lnk_wireguard,
peers,
+ peer_flags,
peers_len,
- replace_peers,
+ change_flags,
&msgs);
if (r < 0) {
_LOGW ("wireguard: set-device, cannot construct netlink message: %s", nm_strerror (r));
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 021b45d73e..10bf417968 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -1982,6 +1982,24 @@ nm_platform_link_get_lnk_wireguard (NMPlatform *self, int ifindex, const NMPlatf
/*****************************************************************************/
+NM_UTILS_FLAGS2STR_DEFINE_STATIC (_wireguard_change_flags_to_string, NMPlatformWireGuardChangeFlags,
+ NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE, "none"),
+ NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS, "replace-peers"),
+ NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY, "has-private-key"),
+ NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT, "has-listen-port"),
+ NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK, "has-fwmark"),
+);
+
+NM_UTILS_FLAGS2STR_DEFINE_STATIC (_wireguard_change_peer_flags_to_string, NMPlatformWireGuardChangePeerFlags,
+ NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE, "none"),
+ NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME, "remove"),
+ NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY, "psk"),
+ NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL, "ka"),
+ NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT, "ep"),
+ NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS, "aips"),
+ NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS, "remove-aips"),
+);
+
int
nm_platform_link_wireguard_add (NMPlatform *self,
const char *name,
@@ -1995,8 +2013,9 @@ nm_platform_link_wireguard_change (NMPlatform *self,
int ifindex,
const NMPlatformLnkWireGuard *lnk_wireguard,
const NMPWireGuardPeer *peers,
+ const NMPlatformWireGuardChangePeerFlags *peer_flags,
guint peers_len,
- gboolean replace_peers)
+ NMPlatformWireGuardChangeFlags change_flags)
{
_CHECK_SELF (self, klass, -NME_BUG);
@@ -2005,6 +2024,7 @@ nm_platform_link_wireguard_change (NMPlatform *self,
if (_LOGD_ENABLED ()) {
char buf_lnk[256];
char buf_peers[512];
+ char buf_change_flags[100];
buf_peers[0] = '\0';
if (peers_len > 0) {
@@ -2017,25 +2037,31 @@ nm_platform_link_wireguard_change (NMPlatform *self,
nm_utils_strbuf_append_str (&b, &len, " { ");
nm_platform_wireguard_peer_to_string (&peers[i], b, len);
nm_utils_strbuf_seek_end (&b, &len);
+ if (peer_flags) {
+ nm_utils_strbuf_append (&b, &len,
+ " (%s)",
+ _wireguard_change_peer_flags_to_string (peer_flags[i], buf_change_flags, sizeof (buf_change_flags)));
+ }
nm_utils_strbuf_append_str (&b, &len, " } ");
}
nm_utils_strbuf_append_str (&b, &len, "}");
}
- _LOG3D ("link: change wireguard ifindex %d, %s, %u peers%s%s",
+ _LOG3D ("link: change wireguard ifindex %d, %s, (%s), %u peers%s",
ifindex,
nm_platform_lnk_wireguard_to_string (lnk_wireguard, buf_lnk, sizeof (buf_lnk)),
+ _wireguard_change_flags_to_string (change_flags, buf_change_flags, sizeof (buf_change_flags)),
peers_len,
- buf_peers,
- replace_peers ? " (replace-peers)" : " (update-peers)");
+ buf_peers);
}
return klass->link_wireguard_change (self,
ifindex,
lnk_wireguard,
peers,
+ peer_flags,
peers_len,
- replace_peers);
+ change_flags);
}
/*****************************************************************************/
@@ -5607,6 +5633,7 @@ nm_platform_wireguard_peer_to_string (const NMPWireGuardPeer *peer, char *buf, g
char s_sockaddr[NM_UTILS_INET_ADDRSTRLEN + 100];
char s_endpoint[20 + sizeof (s_sockaddr)];
char s_addr[NM_UTILS_INET_ADDRSTRLEN];
+ char s_keepalive[100];
guint i;
nm_utils_to_string_buffer_init (&buf, &len);
@@ -5624,10 +5651,11 @@ nm_platform_wireguard_peer_to_string (const NMPWireGuardPeer *peer, char *buf, g
nm_utils_strbuf_append (&buf, &len,
"public-key %s"
- "%s" /* preshared-key */
- "%s" /* endpoint */
+ "%s" /* preshared-key */
+ "%s" /* endpoint */
" rx %"G_GUINT64_FORMAT
" tx %"G_GUINT64_FORMAT
+ "%s" /* persistent-keepalive */
"%s", /* allowed-ips */
public_key_b64,
nm_utils_memeqzero (peer->preshared_key, sizeof (peer->preshared_key))
@@ -5636,6 +5664,9 @@ nm_platform_wireguard_peer_to_string (const NMPWireGuardPeer *peer, char *buf, g
s_endpoint,
peer->rx_bytes,
peer->tx_bytes,
+ peer->persistent_keepalive_interval > 0
+ ? nm_sprintf_buf (s_keepalive, " keepalive %u", (guint) peer->persistent_keepalive_interval)
+ : "",
peer->allowed_ips_len > 0
? " allowed-ips"
: "");
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 568b1f4b46..37aa58fdc5 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -748,11 +748,35 @@ typedef enum {
} NMPlatformLinkDuplexType;
typedef enum {
- NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS = (1LL << 0),
- NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL = (1LL << 1),
- NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF = (1LL << 2),
+ NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS = (1LL << 0),
+ NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL = (1LL << 1),
+ NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF = (1LL << 2),
} NMPlatformKernelSupportFlags;
+typedef enum {
+ NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE = 0,
+ NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS = (1LL << 0),
+ NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY = (1LL << 1),
+ NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT = (1LL << 2),
+ NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK = (1LL << 3),
+} NMPlatformWireGuardChangeFlags;
+
+typedef enum {
+ NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE = 0,
+ NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME = (1LL << 0),
+ NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY = (1LL << 1),
+ NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL = (1LL << 2),
+ NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT = (1LL << 3),
+ NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS = (1LL << 4),
+ NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS = (1LL << 5),
+
+ NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_DEFAULT = NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY
+ | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL
+ | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT
+ | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS,
+
+} NMPlatformWireGuardChangePeerFlags;
+
/*****************************************************************************/
struct _NMPlatformPrivate;
@@ -830,8 +854,9 @@ typedef struct {
int ifindex,
const NMPlatformLnkWireGuard *lnk_wireguard,
const struct _NMPWireGuardPeer *peers,
+ const NMPlatformWireGuardChangePeerFlags *peer_flags,
guint peers_len,
- gboolean replace_peers);
+ NMPlatformWireGuardChangeFlags change_flags);
gboolean (*vlan_add) (NMPlatform *, const char *name, int parent, int vlanid, guint32 vlanflags, const NMPlatformLink **out_link);
gboolean (*link_vlan_change) (NMPlatform *self,
@@ -1393,8 +1418,9 @@ int nm_platform_link_wireguard_change (NMPlatform *self,
int ifindex,
const NMPlatformLnkWireGuard *lnk_wireguard,
const struct _NMPWireGuardPeer *peers,
+ const NMPlatformWireGuardChangePeerFlags *peer_flags,
guint peers_len,
- gboolean replace_peers);
+ NMPlatformWireGuardChangeFlags change_flags);
const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address);
diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c
index e11858d634..71324301c7 100644
--- a/src/platform/tests/test-link.c
+++ b/src/platform/tests/test-link.c
@@ -912,8 +912,12 @@ _test_wireguard_change (NMPlatform *platform,
ifindex,
&lnk_wireguard,
(const NMPWireGuardPeer *) peers->data,
+ NULL,
peers->len,
- TRUE);
+ NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY
+ | NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT
+ | NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK
+ | NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS);
g_assert (NMTST_NM_ERR_SUCCESS (r));
}
diff --git a/src/vpn/nm-vpn-connection.h b/src/vpn/nm-vpn-connection.h
index 5482fb0d8b..e70590b248 100644
--- a/src/vpn/nm-vpn-connection.h
+++ b/src/vpn/nm-vpn-connection.h
@@ -28,8 +28,6 @@
#include "nm-active-connection.h"
#include "nm-vpn-plugin-info.h"
-#define NM_VPN_ROUTE_METRIC_DEFAULT 50
-
#define NM_TYPE_VPN_CONNECTION (nm_vpn_connection_get_type ())
#define NM_VPN_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_CONNECTION, NMVpnConnection))
#define NM_VPN_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_VPN_CONNECTION, NMVpnConnectionClass))