diff options
| author | Michael Biebl <biebl@debian.org> | 2020-04-11 21:28:04 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2020-04-11 21:28:04 +0200 |
| commit | 1e5977b62f896e844b548c3007ace9e1dfa7f9ed (patch) | |
| tree | 7a7416ed410e72b6200f3d860fd315ec11cc106b /clients/common | |
| parent | b012fa6e1d808e0736c009799c62d835cbfcc1dd (diff) | |
New upstream version 1.23.90 upstream/1.23.90
Diffstat (limited to 'clients/common')
| -rw-r--r-- | clients/common/meson.build | 5 | ||||
| -rw-r--r-- | clients/common/nm-client-utils.c | 1 | ||||
| -rw-r--r-- | clients/common/nm-meta-setting-desc.c | 229 | ||||
| -rw-r--r-- | clients/common/nm-polkit-listener.c | 1090 | ||||
| -rw-r--r-- | clients/common/nm-polkit-listener.h | 121 | ||||
| -rw-r--r-- | clients/common/nm-secret-agent-simple.c | 2 | ||||
| -rw-r--r-- | clients/common/nm-vpn-helpers.c | 28 | ||||
| -rw-r--r-- | clients/common/settings-docs.h | 21 | ||||
| -rw-r--r-- | clients/common/settings-docs.h.in | 21 | ||||
| -rw-r--r-- | clients/common/tests/meson.build | 2 | ||||
| -rw-r--r-- | clients/common/tests/test-clients-common.c | 13 | ||||
| -rw-r--r-- | clients/common/tests/wg-test0.conf | 2 |
12 files changed, 1071 insertions, 464 deletions
diff --git a/clients/common/meson.build b/clients/common/meson.build index afa257b1..c32bb5e7 100644 --- a/clients/common/meson.build +++ b/clients/common/meson.build @@ -1,6 +1,6 @@ -common_inc = include_directories('.') +# SPDX-License-Identifier: LGPL-2.1+ -nm_polkit_listener = files('nm-polkit-listener.c') +common_inc = include_directories('.') common_deps = [ libnm_dep, @@ -13,6 +13,7 @@ sources = files( 'nm-client-utils.c', 'nm-secret-agent-simple.c', 'nm-vpn-helpers.c', + 'nm-polkit-listener.c', ) libnmc_base = static_library( diff --git a/clients/common/nm-client-utils.c b/clients/common/nm-client-utils.c index 4d356edb..cf8b4785 100644 --- a/clients/common/nm-client-utils.c +++ b/clients/common/nm-client-utils.c @@ -525,6 +525,7 @@ nmc_password_subst_char (void) #pragma GCC visibility push(hidden) NM_PRAGMA_WARNING_DISABLE("-Wdeclaration-after-statement") +#undef NDEBUG #define NDEBUG #include "qrcodegen.c" NM_PRAGMA_WARNING_REENABLE diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index d9ccada9..03f9b313 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -190,8 +190,6 @@ _value_strsplit (const char *value, gsize *out_len) { gs_free const char **strv = NULL; - gsize i; - gsize len; /* FIXME: some modes should support backslash escaping. * In particular, to distinguish from _value_str_as_index_list(), which @@ -200,43 +198,24 @@ _value_strsplit (const char *value, /* note that all modes remove empty tokens (",", "a,,b", ",,"). */ switch (split_mode) { case VALUE_STRSPLIT_MODE_OBJLIST: - strv = nm_utils_strsplit_set (value, ESCAPED_TOKENS_DELIMITERS); + strv = nm_utils_strsplit_set_full (value, + ESCAPED_TOKENS_DELIMITERS, + NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP); break; case VALUE_STRSPLIT_MODE_MULTILIST: - strv = nm_utils_strsplit_set (value, ESCAPED_TOKENS_WITH_SPACES_DELIMTERS); + strv = nm_utils_strsplit_set_full (value, + ESCAPED_TOKENS_WITH_SPACES_DELIMTERS, + NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP); break; case VALUE_STRSPLIT_MODE_ESCAPED_TOKENS: strv = nm_utils_escaped_tokens_split (value, ESCAPED_TOKENS_DELIMITERS); - NM_SET_OUT (out_len, NM_PTRARRAY_LEN (strv)); - return g_steal_pointer (&strv); + break; case VALUE_STRSPLIT_MODE_ESCAPED_TOKENS_WITH_SPACES: strv = nm_utils_escaped_tokens_split (value, ESCAPED_TOKENS_WITH_SPACES_DELIMTERS); - NM_SET_OUT (out_len, NM_PTRARRAY_LEN (strv)); - return g_steal_pointer (&strv); - default: - nm_assert_not_reached (); break; } - NM_SET_OUT (out_len, 0); - - if (!strv) - return NULL; - - len = 0; - for (i = 0; strv[i]; i++) { - const char *s = strv[i]; - - s = nm_str_skip_leading_spaces (s); - if (s[0] == '\0') - continue; - - g_strchomp ((char *) s); - strv[len++] = s; - } - strv[len] = NULL; - - NM_SET_OUT (out_len, len); + NM_SET_OUT (out_len, NM_PTRARRAY_LEN (strv)); return g_steal_pointer (&strv); } @@ -364,7 +343,7 @@ _parse_ip_route (int family, for (i = 1; routev[i]; i++) { gint64 tmp64; - if (nm_utils_ipaddr_valid (family, routev[i])) { + if (nm_utils_ipaddr_is_valid (family, routev[i])) { if (metric != -1 || attrs) { g_set_error (error, 1, 0, _("the next hop ('%s') must be first"), routev[i]); return NULL; @@ -638,6 +617,8 @@ _env_warn_fcn (const NMMetaEnvironment *environment, #define ARGS_SETTING_INIT_FCN \ const NMMetaSettingInfoEditor *setting_info, NMSetting *setting, NMMetaAccessorSettingInitType init_type +static gboolean _set_fcn_optionlist (ARGS_SET_FCN); + static gboolean _SET_FCN_DO_RESET_DEFAULT (const NMMetaPropertyInfo *property_info, NMMetaAccessorModifier modifier, const char *value) { @@ -904,6 +885,10 @@ _get_fcn_gobject_impl (const NMMetaPropertyInfo *property_info, GString *str; gsize i; + nm_assert ( property_info->setting_info == &nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_WIRED] + && NM_IN_STRSET (property_info->property_name, NM_SETTING_WIRED_S390_OPTIONS)); + nm_assert (property_info->property_type->set_fcn == _set_fcn_optionlist); + strdict = g_value_get_boxed (&val); keys = nm_utils_strdict_get_keys (strdict, TRUE, NULL); if (!keys) @@ -911,12 +896,16 @@ _get_fcn_gobject_impl (const NMMetaPropertyInfo *property_info, str = g_string_new (NULL); for (i = 0; keys[i]; i++) { + const char *key = keys[i]; + const char *v = g_hash_table_lookup (strdict, key); + gs_free char *escaped_key = NULL; + gs_free char *escaped_val = NULL; + if (str->len > 0) g_string_append_c (str, ','); - g_string_append_printf (str, - "%s=%s", - keys[i], - (const char *) g_hash_table_lookup (strdict, keys[i])); + g_string_append (str, nm_utils_escaped_tokens_options_escape_key (key, &escaped_key)); + g_string_append_c (str, '='); + g_string_append (str, nm_utils_escaped_tokens_options_escape_val (v, &escaped_val)); } RETURN_STR_TO_FREE (g_string_free (str, FALSE)); } @@ -1761,17 +1750,6 @@ secret_flags_to_string (guint32 flags, NMMetaAccessorGetType get_type) return g_string_free (flag_str, FALSE); } -static void -vpn_data_item (const char *key, const char *value, gpointer user_data) -{ - GString *ret_str = (GString *) user_data; - - if (ret_str->len != 0) - g_string_append (ret_str, ", "); - - g_string_append_printf (ret_str, "%s = %s", key, value); -} - static const char * _multilist_do_validate (const NMMetaPropertyInfo *property_info, NMSetting *setting, @@ -1919,6 +1897,7 @@ _set_fcn_optionlist (ARGS_SET_FCN) { gs_free const char **strv = NULL; gs_free const char **strv_val = NULL; + gsize strv_len; gsize i, nstrv; nm_assert (!error || !*error); @@ -1927,24 +1906,16 @@ _set_fcn_optionlist (ARGS_SET_FCN) return _gobject_property_reset_default (setting, property_info->property_name); nstrv = 0; - strv = nm_utils_strsplit_set (value, ","); + strv = nm_utils_escaped_tokens_options_split_list (value); if (strv) { - strv_val = g_new (const char *, NM_PTRARRAY_LEN (strv)); + strv_len = NM_PTRARRAY_LEN (strv); + + strv_val = g_new (const char *, strv_len); for (i = 0; strv[i]; i++) { const char *opt_name; const char *opt_value; - opt_name = nm_str_skip_leading_spaces (strv[i]); - - /* FIXME: support backslash escaping for the option list. */ - opt_value = strchr (opt_name, '='); - if (opt_value) { - ((char *) opt_value)[0] = '\0'; - opt_value++; - opt_value = nm_str_skip_leading_spaces (opt_value); - g_strchomp ((char *) opt_value); - } - g_strchomp ((char *) opt_name); + nm_utils_escaped_tokens_options_split ((char *) strv[i], &opt_name, &opt_value); if ( property_info->property_type->values_fcn || property_info->property_typ_data->values_static) { @@ -2315,33 +2286,41 @@ static gconstpointer _get_fcn_bond_options (ARGS_GET_FCN) { NMSettingBond *s_bond = NM_SETTING_BOND (setting); - GString *bond_options_s; - int i; + GString *str; + guint32 i, len; RETURN_UNSUPPORTED_GET_TYPE (); - bond_options_s = g_string_new (NULL); - for (i = 0; i < nm_setting_bond_get_num_options (s_bond); i++) { - const char *key, *value; - gs_free char *tmp_value = NULL; + str = g_string_new (NULL); + len = nm_setting_bond_get_num_options (s_bond); + for (i = 0; i < len; i++) { + const char *key; + const char *val; + gs_free char *val_tmp = NULL; char *p; + gs_free char *escaped_key = NULL; + gs_free char *escaped_val = NULL; - nm_setting_bond_get_option (s_bond, i, &key, &value); + nm_setting_bond_get_option (s_bond, i, &key, &val); - if (nm_streq0 (key, NM_SETTING_BOND_OPTION_ARP_IP_TARGET)) { - value = tmp_value = g_strdup (value); - for (p = tmp_value; p && *p; p++) { + if (nm_streq (key, NM_SETTING_BOND_OPTION_ARP_IP_TARGET)) { + val_tmp = g_strdup (val); + for (p = val_tmp; p && *p; p++) { if (*p == ',') *p = ' '; } + val = val_tmp; } - g_string_append_printf (bond_options_s, "%s=%s,", key, value); + if (str->len > 0u) + g_string_append_c (str, ','); + g_string_append (str, nm_utils_escaped_tokens_options_escape_key (key, &escaped_key)); + g_string_append_c (str, '='); + g_string_append (str, nm_utils_escaped_tokens_options_escape_val (val, &escaped_val)); } - g_string_truncate (bond_options_s, bond_options_s->len-1); /* chop off trailing ',' */ - NM_SET_OUT (out_is_default, bond_options_s->len == 0); - RETURN_STR_TO_FREE (g_string_free (bond_options_s, FALSE)); + NM_SET_OUT (out_is_default, str->len == 0); + RETURN_STR_TO_FREE (g_string_free (str, FALSE)); } static gboolean @@ -3316,7 +3295,7 @@ _set_fcn_ip_config_gateway (ARGS_SET_FCN) value = nm_strstrip_avoid_copy_a (300, value, &value_to_free); - if (!nm_utils_ipaddr_valid (addr_family, value)) { + if (!nm_utils_ipaddr_is_valid (addr_family, value)) { g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, _("invalid gateway address '%s'"), value); @@ -3815,32 +3794,36 @@ _set_fcn_vlan_xgress_priority_map (ARGS_SET_FCN) return TRUE; } -static gconstpointer -_get_fcn_vpn_data (ARGS_GET_FCN) +static void +_vpn_options_callback (const char *key, const char *val, gpointer user_data) { - NMSettingVpn *s_vpn = NM_SETTING_VPN (setting); - GString *data_item_str; + GString *str = user_data; + gs_free char *escaped_key = NULL; + gs_free char *escaped_val = NULL; - RETURN_UNSUPPORTED_GET_TYPE (); + if (str->len > 0u) + g_string_append (str, ", "); - data_item_str = g_string_new (NULL); - nm_setting_vpn_foreach_data_item (s_vpn, &vpn_data_item, data_item_str); - NM_SET_OUT (out_is_default, data_item_str->len == 0); - RETURN_STR_TO_FREE (g_string_free (data_item_str, FALSE)); + g_string_append (str, nm_utils_escaped_tokens_options_escape_key (key, &escaped_key)); + g_string_append (str, " = "); + g_string_append (str, nm_utils_escaped_tokens_options_escape_val (val, &escaped_val)); } static gconstpointer -_get_fcn_vpn_secrets (ARGS_GET_FCN) +_get_fcn_vpn_options (ARGS_GET_FCN) { NMSettingVpn *s_vpn = NM_SETTING_VPN (setting); - GString *secret_str; + GString *str; RETURN_UNSUPPORTED_GET_TYPE (); - secret_str = g_string_new (NULL); - nm_setting_vpn_foreach_secret (s_vpn, &vpn_data_item, secret_str); - NM_SET_OUT (out_is_default, secret_str->len == 0); - RETURN_STR_TO_FREE (g_string_free (secret_str, FALSE)); + str = g_string_new (NULL); + if (nm_streq (property_info->property_name, NM_SETTING_VPN_SECRETS)) + nm_setting_vpn_foreach_secret (s_vpn, _vpn_options_callback, str); + else + nm_setting_vpn_foreach_data_item (s_vpn, _vpn_options_callback, str); + NM_SET_OUT (out_is_default, str->len == 0); + RETURN_STR_TO_FREE (g_string_free (str, FALSE)); } static gboolean @@ -4562,6 +4545,9 @@ static const NMMetaPropertyInfo *const property_infos_802_1X[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, .property_type = &_pt_gobject_string, ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_DOMAIN_MATCH, + .property_type = &_pt_gobject_string, + ), PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_CLIENT_CERT, .describe_message = N_("Enter file path to client certificate (optionally prefixed with file://).\n" @@ -4659,6 +4645,9 @@ static const NMMetaPropertyInfo *const property_infos_802_1X[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, .property_type = &_pt_gobject_string, ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_DOMAIN_MATCH, + .property_type = &_pt_gobject_string, + ), PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_CLIENT_CERT, .describe_message = N_("Enter file path to client certificate for inner authentication (optionally prefixed\n" @@ -4901,24 +4890,51 @@ static const NMMetaPropertyInfo *const property_infos_BRIDGE[] = { .prompt = N_("MAC address ageing time [300]"), .property_type = &_pt_gobject_int, ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_GROUP_ADDRESS, + .property_type = &_pt_gobject_mac, + ), PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, .is_cli_option = TRUE, .property_alias = "group-forward-mask", .prompt = N_("Group forward mask [0]"), .property_type = &_pt_gobject_int, ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_MULTICAST_QUERIER, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR, + .property_type = &_pt_gobject_bool, + ), PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_MULTICAST_SNOOPING, .is_cli_option = TRUE, .property_alias = "multicast-snooping", .prompt = N_("Enable IGMP snooping [no]"), .property_type = &_pt_gobject_bool, ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_MULTICAST_ROUTER, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = NM_MAKE_STRV ("auto", + "disabled", + "enabled"), + ), + ), PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_VLAN_FILTERING, .property_type = &_pt_gobject_bool, ), PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, .property_type = &_pt_gobject_int, ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_VLAN_STATS_ENABLED, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_VLAN_PROTOCOL, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = NM_MAKE_STRV ("802.1Q", + "802.1ad"), + ), + ), PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_VLANS, .property_type = &_pt_objlist, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( @@ -5123,7 +5139,8 @@ static const NMMetaPropertyInfo *const property_infos_CONNECTION[] = { NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_OVS_BRIDGE_SETTING_NAME, NM_SETTING_OVS_PORT_SETTING_NAME, - NM_SETTING_TEAM_SETTING_NAME), + NM_SETTING_TEAM_SETTING_NAME, + NM_SETTING_VRF_SETTING_NAME), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, @@ -6877,25 +6894,23 @@ static const NMMetaPropertyInfo *const property_infos_VPN[] = { ), PROPERTY_INFO_WITH_DESC (NM_SETTING_VPN_DATA, .property_type = DEFINE_PROPERTY_TYPE ( - .get_fcn = _get_fcn_vpn_data, + .get_fcn = _get_fcn_vpn_options, .set_fcn = _set_fcn_optionlist, .set_supports_remove = TRUE, ), .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (optionlist, .set_fcn = _optionlist_set_fcn_vpn_data, - .no_empty_value = TRUE, ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_VPN_SECRETS, .is_secret = TRUE, .property_type = DEFINE_PROPERTY_TYPE ( - .get_fcn = _get_fcn_vpn_secrets, + .get_fcn = _get_fcn_vpn_options, .set_fcn = _set_fcn_optionlist, .set_supports_remove = TRUE, ), .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (optionlist, .set_fcn = _optionlist_set_fcn_vpn_secrets, - .no_empty_value = TRUE, ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_VPN_PERSISTENT, @@ -6908,6 +6923,20 @@ static const NMMetaPropertyInfo *const property_infos_VPN[] = { }; #undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_VRF +static const NMMetaPropertyInfo *const property_infos_VRF[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_VRF_TABLE, + .is_cli_option = TRUE, + .property_alias = "table", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("Table [0]"), + .property_type = &_pt_gobject_int, + ), + NULL +}; + + +#undef _CURRENT_NM_META_SETTING_TYPE #define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_VXLAN static const NMMetaPropertyInfo *const property_infos_VXLAN[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_PARENT, @@ -7318,7 +7347,7 @@ static const NMMetaPropertyInfo *const property_infos_WIRELESS_SECURITY[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = NM_MAKE_STRV ("none", "ieee8021x", "wpa-psk", "wpa-eap", "sae"), + .values_static = NM_MAKE_STRV ("none", "ieee8021x", "wpa-psk", "wpa-eap", "sae", "owe"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, @@ -7691,6 +7720,7 @@ _setting_init_fcn_wireless (ARGS_SETTING_INIT_FCN) #define SETTING_PRETTY_NAME_USER N_("User settings") #define SETTING_PRETTY_NAME_VLAN N_("VLAN connection") #define SETTING_PRETTY_NAME_VPN N_("VPN connection") +#define SETTING_PRETTY_NAME_VRF N_("VRF connection") #define SETTING_PRETTY_NAME_VXLAN N_("VXLAN connection") #define SETTING_PRETTY_NAME_WIFI_P2P N_("Wi-Fi P2P connection") #define SETTING_PRETTY_NAME_WIMAX N_("WiMAX connection") @@ -7931,6 +7961,13 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (VPN, TRUE), ), ), + SETTING_INFO (VRF, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (VRF, TRUE), + ), + ), + SETTING_INFO (VXLAN, .valid_parts = NM_META_SETTING_VALID_PARTS ( NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), @@ -8055,6 +8092,10 @@ nm_meta_setting_info_valid_parts_for_slave_type (const char *slave_type, const c NM_SET_OUT (out_slave_name, "team-slave"); return valid_settings_slave_team; } + if (nm_streq (slave_type, NM_SETTING_VRF_SETTING_NAME)) { + NM_SET_OUT (out_slave_name, "vrf-slave"); + return valid_settings_noslave; + } return NULL; } diff --git a/clients/common/nm-polkit-listener.c b/clients/common/nm-polkit-listener.c index b2941652..7691ff4e 100644 --- a/clients/common/nm-polkit-listener.c +++ b/clients/common/nm-polkit-listener.c @@ -22,339 +22,965 @@ #include "nm-polkit-listener.h" -#include <stdio.h> -#include <stdlib.h> +#include <gio/gio.h> +#include <pwd.h> +#include <fcntl.h> -#if WITH_POLKIT_AGENT +#include "nm-glib-aux/nm-dbus-aux.h" +#include "nm-glib-aux/nm-str-buf.h" +#include "nm-glib-aux/nm-secret-utils.h" +#include "nm-glib-aux/nm-io-utils.h" +#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "c-list/src/c-list.h" + +#define LOGIND_BUS_NAME "org.freedesktop.login1" +#define POLKIT_BUS_NAME "org.freedesktop.PolicyKit1" + +#define POLKIT_AUTHORITY_OBJ_PATH "/org/freedesktop/PolicyKit1/Authority" +#define POLKIT_AUTHORITY_IFACE_NAME "org.freedesktop.PolicyKit1.Authority" + +#define POLKIT_AGENT_OBJ_PATH "/org/freedesktop/PolicyKit1/AuthenticationAgent" +#define POLKIT_AGENT_DBUS_INTERFACE "org.freedesktop.PolicyKit1.AuthenticationAgent" + +#define LOGIND_OBJ_PATH "/org/freedesktop/login1" +#define LOGIND_MANAGER_INTERFACE "org.freedesktop.login1.Manager" + +#define NM_POLKIT_LISTENER_DBUS_CONNECTION "dbus-connection" +#define NM_POLKIT_LISTENER_SESSION_AGENT "session-agent" + +#define POLKIT_DBUS_ERROR_FAILED "org.freedesktop.PolicyKit1.Error.Failed" /*****************************************************************************/ -typedef struct { - gpointer reg_handle; /* handle of polkit agent registration */ +enum { + REGISTERED, + REQUEST_SYNC, + ERROR, + LAST_SIGNAL +}; - GSimpleAsyncResult *simple; - PolkitAgentSession *active_session; - gulong cancel_id; +static guint signals[LAST_SIGNAL] = { 0 }; + +struct _NMPolkitListener { + GObject parent; + GDBusConnection *dbus_connection; + char *name_owner; GCancellable *cancellable; + GMainContext *main_context; + CList request_lst_head; + guint pk_auth_agent_reg_id; + guint name_owner_changed_id; + bool session_agent:1; +}; + +struct _NMPolkitListenerClass { + GObjectClass parent; +}; +G_DEFINE_TYPE (NMPolkitListener, nm_polkit_listener, G_TYPE_OBJECT); + +/*****************************************************************************/ + +typedef struct { + CList request_lst; + + NMPolkitListener *listener; + GSource *child_stdout_watch_source; + GSource *child_stdin_watch_source; + GDBusMethodInvocation *dbus_invocation; char *action_id; char *message; - char *icon_name; - char *identity; + char *username; + char *cookie; + NMStrBuf in_buffer; + NMStrBuf out_buffer; + gsize out_buffer_offset; + + int child_stdout; + int child_stdin; + + bool request_any_response:1; + bool request_is_completed:1; +} AuthRequest; + +static const GDBusInterfaceInfo interface_info = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( + POLKIT_AGENT_DBUS_INTERFACE, + .methods = NM_DEFINE_GDBUS_METHOD_INFOS ( + NM_DEFINE_GDBUS_METHOD_INFO ( + "BeginAuthentication", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("action_id", "s"), + NM_DEFINE_GDBUS_ARG_INFO ("message", "s"), + NM_DEFINE_GDBUS_ARG_INFO ("icon_name", "s"), + NM_DEFINE_GDBUS_ARG_INFO ("details", "a{ss}"), + NM_DEFINE_GDBUS_ARG_INFO ("cookie", "s"), + NM_DEFINE_GDBUS_ARG_INFO ("identities", "a(sa{sv})"), + ), + ), + NM_DEFINE_GDBUS_METHOD_INFO ( + "CancelAuthentication", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("cookie", "s"), + ), + ), + ), +); + +static void +auth_request_complete (AuthRequest *request, gboolean success) +{ + c_list_unlink (&request->request_lst); - const NMPolkitListenVtable *vtable; - gpointer vtable_user_data; -} NMPolkitListenerPrivate; + if (success) + g_dbus_method_invocation_return_value (request->dbus_invocation, NULL); + else { + g_dbus_method_invocation_return_dbus_error (request->dbus_invocation, + POLKIT_DBUS_ERROR_FAILED, + ""); + } -G_DEFINE_TYPE (NMPolkitListener, nm_polkit_listener, POLKIT_AGENT_TYPE_LISTENER) + nm_clear_g_free (&request->action_id); + nm_clear_g_free (&request->message); + nm_clear_g_free (&request->username); + nm_clear_g_free (&request->cookie); + nm_clear_g_source_inst (&request->child_stdout_watch_source); + nm_clear_g_source_inst (&request->child_stdin_watch_source); -#define NM_POLKIT_LISTENER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_POLKIT_LISTENER, NMPolkitListenerPrivate)) + nm_str_buf_destroy (&request->in_buffer); + nm_str_buf_destroy (&request->out_buffer); -/*****************************************************************************/ + if (request->child_stdout != -1) { + nm_close (request->child_stdout); + request->child_stdout = -1; + } -void -nm_polkit_listener_set_vtable (NMPolkitListener *self, - const NMPolkitListenVtable *vtable, - gpointer user_data) + if (request->child_stdin != -1) { + nm_close (request->child_stdin); + request->child_stdin = -1; + } + + nm_g_slice_free (request); +} + +static gboolean +uid_to_name (uid_t uid, + const char **out_name) { - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self); + const struct passwd *passwd; - priv->vtable = vtable; - priv->vtable_user_data = user_data; + if (*out_name) + return TRUE; + + passwd = getpwuid (uid); + if ( !passwd + || !passwd->pw_name) + return FALSE; + + *out_name = passwd->pw_name; + return TRUE; } -/*****************************************************************************/ +static char * +choose_identity (GVariant *identities) +{ + GVariantIter identity_iter; + GVariant *details_tmp; + const char *kind; + gs_free char *username_first = NULL; + gs_free char *username_root = NULL; + const char *user; + + /* Choose identity. First try current user, then root, and else + * take the first one we find. */ + + user = getenv ("USER"); + + g_variant_iter_init (&identity_iter, identities); + while (g_variant_iter_next (&identity_iter, "(&s@a{sv})", &kind, &details_tmp)) { + gs_unref_variant GVariant *details = g_steal_pointer (&details_tmp); + + if (nm_streq (kind, "unix-user")) { + gs_unref_variant GVariant *v = NULL; + + v = g_variant_lookup_value (details, "uid", G_VARIANT_TYPE_UINT32); + if (v) { + guint32 uid = g_variant_get_uint32 (v); + const char *u = NULL; + + if (user) { + if (!uid_to_name (uid, &u)) + continue; + if (nm_streq (u, user)) + return g_strdup (user); + } + if ( !username_root + && uid == 0) { + if (!uid_to_name (uid, &u)) + continue; + username_root = g_strdup (u); + if (!user) + break; + } + if ( !username_root + && !username_first) { + if (!uid_to_name (uid, &u)) + continue; + username_first = g_strdup (u); + } + } + } + } + + if (username_root) + return g_steal_pointer (&username_root); + + if (username_first) + return g_steal_pointer (&username_first); + + return NULL; +} static void -on_request (PolkitAgentSession *session, - const char *request, - gboolean echo_on, - gpointer user_data) +agent_register_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - NMPolkitListener *self = NM_POLKIT_LISTENER (user_data); - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self); - gs_free char *response = NULL; - - if (priv->vtable && priv->vtable->on_request) { - response = priv->vtable->on_request (self, - request, priv->action_id, - priv->message, priv->icon_name, - priv->identity, echo_on, - priv->vtable_user_data); + NMPolkitListener *listener = NM_POLKIT_LISTENER (user_data); + GDBusConnection *dbus_connection = G_DBUS_CONNECTION (source_object); + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *ret = NULL; + + ret = g_dbus_connection_call_finish (dbus_connection, + res, + &error); + + if (nm_utils_error_is_cancelled (error)) { + return; } - if (response) - polkit_agent_session_response (session, response); - else { - //FIXME: polkit_agent_session_cancel() should emit "completed", but it doesn't work for me ??? - //polkit_agent_session_cancel (session); - polkit_agent_session_response (session, ""); + if (ret) { + g_signal_emit (listener, + signals[REGISTERED], + 0); + } else { + g_signal_emit (listener, + signals[ERROR], + 0, + error->message); } } static void -on_show_info (PolkitAgentSession *session, - const char *text, - gpointer user_data) +agent_register (NMPolkitListener *self, const char *session_id) { - NMPolkitListener *self = NM_POLKIT_LISTENER (user_data); - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self); + const char *locale = NULL; + gs_unref_object NMAuthSubject *subject = NULL; + GVariant *subject_variant = NULL; + + locale = g_getenv ("LANG"); + if (locale == NULL) { + locale = "en_US.UTF-8"; + } - if (priv->vtable && priv->vtable->on_show_info) { - priv->vtable->on_show_info (self, text, - priv->vtable_user_data); + if (self->session_agent) { + subject = nm_auth_subject_new_unix_session (session_id); + } else { + subject = nm_auth_subject_new_unix_process_self (); } + subject_variant = nm_auth_subject_unix_to_polkit_gvariant (subject); + + g_dbus_connection_call (self->dbus_connection, + self->name_owner, + POLKIT_AUTHORITY_OBJ_PATH, + POLKIT_AUTHORITY_IFACE_NAME, + "RegisterAuthenticationAgent", + g_variant_new ("(@(sa{sv})ss)", + subject_variant, + locale, + POLKIT_AGENT_OBJ_PATH), + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + self->cancellable, + agent_register_cb, + self); } static void -on_show_error (PolkitAgentSession *session, - const char *text, - gpointer user_data) +agent_unregister (NMPolkitListener *self) { - NMPolkitListener *self = NM_POLKIT_LISTENER (user_data); - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self); + gs_unref_object NMAuthSubject *subject = NULL; + GVariant *subject_variant = NULL; + + subject = nm_auth_subject_new_unix_process_self (); + subject_variant = nm_auth_subject_unix_to_polkit_gvariant (subject); + + g_dbus_connection_call (self->dbus_connection, + self->name_owner, + POLKIT_AUTHORITY_OBJ_PATH, + POLKIT_AUTHORITY_IFACE_NAME, + "UnregisterAuthenticationAgent", + g_variant_new ("(@(sa{sv})s)", + subject_variant, + POLKIT_AGENT_OBJ_PATH), + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL, + self); +} - if (priv->vtable && priv->vtable->on_show_error) { - priv->vtable->on_show_error (self, text, - priv->vtable_user_data); +static void +retrieve_session_id_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + NMPolkitListener *listener = NM_POLKIT_LISTENER (user_data); + char *session_id; + guint32 session_uid; + nm_auto_free_variant_iter GVariantIter *iter; + gs_unref_variant GVariant *ret = NULL; + gs_free_error GError *error = NULL; + gs_free char *err_str = NULL; + uid_t uid = getuid (); + + ret = g_dbus_connection_call_finish (listener->dbus_connection, + res, + &error); + + if (nm_utils_error_is_cancelled (error)) { + return; } + + if (ret) { + g_variant_get_child (ret, 0, "a(susso)", &iter); + + while (g_variant_iter_next (iter, "(&su@s@s@o)", + &session_id, + &session_uid, + NULL, NULL, NULL)) { + if (session_uid == uid) { + agent_register (listener, session_id); + return; + } + } + err_str = g_strdup_printf (_("Could not find any session id for uid %d"), uid); + } else { + err_str = g_strdup_printf (_("Could not retrieve session id: %s"), + error->message); + } + + g_signal_emit (listener, + signals[ERROR], + 0, + err_str); } static void -on_completed (PolkitAgentSession *session, - gboolean gained_authorization, - gpointer user_data) +retrieve_session_id (NMPolkitListener *self) +{ + g_dbus_connection_call (self->dbus_connection, + LOGIND_BUS_NAME, + LOGIND_OBJ_PATH, + LOGIND_MANAGER_INTERFACE, + "ListSessions", + NULL, + G_VARIANT_TYPE ("(a(susso))"), + G_DBUS_CALL_FLAGS_NONE, + -1, + self->cancellable, + retrieve_session_id_cb, + self); +} + +static gboolean +io_watch_can_write (int fd, + GIOCondition condition, + gpointer user_data) { - NMPolkitListener *self = NM_POLKIT_LISTENER (user_data); - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self); + AuthRequest *request = user_data; + gssize n_written; + + if (NM_FLAGS_ANY (condition, (G_IO_HUP | G_IO_ERR))) + goto done; + + n_written = write (request->child_stdin, + &((nm_str_buf_get_str_unsafe (&request->out_buffer))[request->out_buffer_offset]), + request->out_buffer.len - request->out_buffer_offset); + + if ( n_written < 0 + && errno != EAGAIN) + goto done; + + if (n_written > 0) { + if ((gsize) n_written >= (request->out_buffer.len - request->out_buffer_offset)) { + nm_assert ((gsize) n_written == (request->out_buffer.len - request->out_buffer_offset)); + goto done; + } + request->out_buffer_offset += (gsize) n_written; + } + + return G_SOURCE_CONTINUE; + +done: + nm_str_buf_set_size (&request->out_buffer, 0, TRUE, FALSE); + request->out_buffer_offset = 0; + nm_clear_g_source_inst (&request->child_stdin_watch_source); - if (priv->vtable->on_completed) { - priv->vtable->on_completed (self, gained_authorization, - priv->vtable_user_data); + if (request->request_is_completed) + auth_request_complete (request, TRUE); + + return G_SOURCE_CONTINUE; +} + +static void +queue_string_to_helper (AuthRequest *request, const char *response) +{ + g_return_if_fail (response); + + if (!nm_str_buf_is_initalized (&request->out_buffer)) + nm_str_buf_init (&request->out_buffer, strlen (response) + 2u, TRUE); + + nm_str_buf_append (&request->out_buffer, response); + nm_str_buf_ensure_trailing_c (&request->out_buffer, '\n'); + + if (!request->child_stdin_watch_source) { + request->child_stdin_watch_source = nm_g_unix_fd_source_new (request->child_stdin, + G_IO_OUT | G_IO_ERR | G_IO_HUP, + G_PRIORITY_DEFAULT, + io_watch_can_write, + request, + NULL); + g_source_attach (request->child_stdin_watch_source, + request->listener->main_context); } +} - g_simple_async_result_complete_in_idle (priv->simple); +static gboolean +io_watch_have_data (int fd, + GIOCondition condition, + gpointer user_data) +{ + AuthRequest *request = user_data; + gboolean auth_result; + gssize n_read; - g_object_unref (priv->simple); - g_object_unref (priv->active_session); - if (priv->cancellable) { - g_cancellable_disconnect (priv->cancellable, priv->cancel_id); - g_object_unref (priv->cancellable); + if (NM_FLAGS_ANY (condition, G_IO_HUP | G_IO_ERR)) + n_read = -EIO; + else + n_read = nm_utils_fd_read (fd, &request->in_buffer); + + if (n_read <= 0) { + if (n_read == -EAGAIN) { + /* wait longer. */ + return G_SOURCE_CONTINUE; + } + + /* Either an error or EOF happened. The data we parsed so far was not relevant. + * Regardless of what we still have unprocessed in the receive buffers, we are done. + * + * We would expect that the other side completed with SUCCESS or FAILURE. Apparently + * it didn't. If we had any good request, we assume success. */ + auth_result = request->request_any_response; + goto out; } - priv->simple = NULL; - priv->active_session = NULL; - priv->cancel_id = 0; + while (TRUE) { + char *line_terminator; + const char *line; + + line = nm_str_buf_get_str (&request->in_buffer); + line_terminator = (char *) strchr (line, '\n'); + if (!line_terminator) { + /* We don't have a complete line. Wait longer. */ + return G_SOURCE_CONTINUE; + } + line_terminator[0] = '\0'; + + if ( NM_STR_HAS_PREFIX (line, "PAM_PROMPT_ECHO_OFF ") + || NM_STR_HAS_PREFIX (line, "PAM_PROMPT_ECHO_ON ")) { + nm_auto_free_secret char *response = NULL; + + /* FIXME(cli-async): emit signal and wait for response (blocking) */ + g_signal_emit (request->listener, + signals[REQUEST_SYNC], + 0, + request->action_id, + request->message, + request->username, + &response); + + if (response) { + queue_string_to_helper (request, response); + request->request_any_response = TRUE; + goto erase_line; + } + auth_result = FALSE; + } else if (nm_streq (line, "SUCCESS")) + auth_result = TRUE; + else if (nm_streq (line, "FAILURE")) + auth_result = FALSE; + else if ( NM_STR_HAS_PREFIX (line, "PAM_ERROR_MSG ") + || NM_STR_HAS_PREFIX (line, "PAM_TEXT_INFO ")) { + /* ignore. */ + goto erase_line; + } else { + /* unknown command. Fail. */ + auth_result = FALSE; + } + + break; +erase_line: + nm_str_buf_erase (&request->in_buffer, 0, line_terminator - line + 1u, TRUE); + } + +out: + request->request_is_completed = TRUE; + nm_clear_g_source_inst (&request->child_stdout_watch_source); + if ( auth_result + && request->child_stdin_watch_source) { + /* we need to wait for the buffer to send the response. */ + } else + auth_request_complete (request, auth_result); - g_clear_pointer (&priv->action_id, g_free); - g_clear_pointer (&priv->message, g_free); - g_clear_pointer (&priv->icon_name, g_free); - g_clear_pointer (&priv->identity, g_free); + return G_SOURCE_CONTINUE; } static void -on_cancelled (GCancellable *cancellable, gpointer user_data) +begin_authentication (AuthRequest *request) { - NMPolkitListener *self = NM_POLKIT_LISTENER (user_data); - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self); + int fd_flags; + const char *helper_argv[] = { + POLKIT_PACKAGE_PREFIX "/lib/polkit-1/polkit-agent-helper-1", + request->username, + NULL, + }; + + if (!request->username) { + auth_request_complete (request, FALSE); + return; + } + + if (!g_spawn_async_with_pipes (NULL, + (char **) helper_argv, + NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, + NULL, + NULL, + &request->child_stdin, + &request->child_stdout, + NULL, + NULL)) { + /* not findind the PolicyKit setuid helper is a critical error */ + request->child_stdin = -1; + request->child_stdout = -1; + g_signal_emit (request->listener, + signals[ERROR], + 0, + "The PolicyKit setuid helper 'polkit-agent-helper-1' has not been found"); + + auth_request_complete (request, FALSE); + return; + } + + fd_flags = fcntl (request->child_stdin, F_GETFD, 0); + fcntl (request->child_stdin, F_SETFL, fd_flags | O_NONBLOCK); - polkit_agent_session_cancel (priv->active_session); + fd_flags = fcntl (request->child_stdout, F_GETFD, 0); + fcntl (request->child_stdout, F_SETFL, fd_flags | O_NONBLOCK); + + request->child_stdout_watch_source = nm_g_unix_fd_source_new (request->child_stdout, + G_IO_IN | G_IO_ERR | G_IO_HUP, + G_PRIORITY_DEFAULT, + io_watch_have_data, + request, + NULL); + g_source_attach (request->child_stdout_watch_source, + request->listener->main_context); + + /* Write the cookie on stdin so it can't be seen by other processes */ + queue_string_to_helper (request, request->cookie); + + return; } -static int -compare_users (gconstpointer a, gconstpointer b) +static AuthRequest* +get_request (NMPolkitListener *listener, + const char *cookie) { - char *user; - int ret; + AuthRequest *request; - if (POLKIT_IS_UNIX_USER (a)) - user = g_strdup (polkit_unix_user_get_name (POLKIT_UNIX_USER (a))); - else - user = polkit_identity_to_string (POLKIT_IDENTITY (a)); + c_list_for_each_entry (request, &listener->request_lst_head, request_lst) { + if (nm_streq0 (cookie, request->cookie)) { + return request; + } + } + return NULL; +} - ret = g_strcmp0 ((const char *) user, (const char *) b); - g_free (user); - return ret; +static AuthRequest* +create_request (NMPolkitListener *listener, + GDBusMethodInvocation *invocation, + const char *action_id, + const char *message, + char *username_take, + const char *cookie) +{ + AuthRequest *request; + + request = g_slice_new (AuthRequest); + *request = (AuthRequest) { + .listener = listener, + .dbus_invocation = invocation, + .action_id = g_strdup (action_id), + .message = g_strdup (message), + .username = g_steal_pointer (&username_take), + .cookie = g_strdup (cookie), + .request_any_response = FALSE, + .request_is_completed = FALSE, + }; + + nm_str_buf_init (&request->in_buffer, NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, FALSE); + + c_list_link_tail (&listener->request_lst_head, &request->request_lst); + return request; } -static PolkitIdentity * -choose_identity (GList *identities) +static void +dbus_method_call_cb (GDBusConnection *connection, + const char *sender, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) { - const char *user; - GList *elem; + NMPolkitListener *listener = NM_POLKIT_LISTENER (user_data); + const char *action_id; + const char *message; + const char *cookie; + AuthRequest *request; + gs_unref_variant GVariant *identities_gvariant; + + if (nm_streq (method_name, "BeginAuthentication")) { + g_variant_get (parameters, + "(&s&s&s@a{ss}&s@a(sa{sv}))", + &action_id, + &message, + NULL, + NULL, + &cookie, + &identities_gvariant); + + request = create_request (listener, + invocation, + action_id, + message, + choose_identity (identities_gvariant), + cookie); + begin_authentication (request); + return; + } - /* Choose identity. First try current user, then root, and else - * take the first one */ - user = getenv("USER"); - elem = g_list_find_custom (identities, user, (GCompareFunc) compare_users); - if (!elem) { - elem = g_list_find_custom (identities, "root", (GCompareFunc) compare_users); - if (!elem) - elem = identities; + if (nm_streq (method_name, "CancelAuthentication")) { + g_variant_get (parameters, + "&s", + &cookie); + request = get_request (listener, cookie); + + if (!request) { + gs_free char *msg = NULL; + + msg = g_strdup_printf ("No pending authentication request for cookie '%s'", + cookie); + g_dbus_method_invocation_return_dbus_error (invocation, + POLKIT_DBUS_ERROR_FAILED, + msg); + return; + } + + /* Complete a cancelled request with success. */ + auth_request_complete (request, TRUE); + return; } - return elem->data; + g_dbus_method_invocation_return_error (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_UNKNOWN_METHOD, + "Unknown method %s", + method_name); +} + +static gboolean +export_dbus_iface (NMPolkitListener *self, GError **error) +{ + GDBusInterfaceVTable interface_vtable = { + .method_call = dbus_method_call_cb, + .set_property = NULL, + .get_property = NULL, + }; + + g_return_val_if_fail (NM_IS_POLKIT_LISTENER (self), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* Agent listener iface has been exported already */ + if (self->pk_auth_agent_reg_id) { + return TRUE; + } + + self->pk_auth_agent_reg_id = + g_dbus_connection_register_object (self->dbus_connection, + POLKIT_AGENT_OBJ_PATH, + (GDBusInterfaceInfo*) &interface_info, + &interface_vtable, + self, + NULL, + error); + if (!self->pk_auth_agent_reg_id) { + g_signal_emit (self, + signals[ERROR], + 0, + "Could not register as a PolicyKit Authentication Agent"); + } + return self->pk_auth_agent_reg_id; } static void -initiate_authentication (PolkitAgentListener *listener, - const char *action_id, - const char *message, - const char *icon_name, - PolkitDetails *details, - const char *cookie, - GList *identities, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +name_owner_changed (NMPolkitListener *self, + const char *name_owner) { - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (listener); - GSimpleAsyncResult *simple; - PolkitIdentity *identity; - - simple = g_simple_async_result_new (G_OBJECT (listener), - callback, - user_data, - initiate_authentication); - if (cancellable) - g_simple_async_result_set_check_cancellable (simple, cancellable); - if (priv->active_session != NULL) { - g_simple_async_result_set_error (simple, - POLKIT_ERROR, - POLKIT_ERROR_FAILED, - _("An authentication session is already underway.")); - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + gs_free_error GError *error = NULL; + + name_owner = nm_str_not_empty (name_owner); + + if (nm_streq0 (self->name_owner, name_owner)) { return; } - /* Choose identity */ - identity = choose_identity (identities); - - priv->active_session = polkit_agent_session_new (identity, cookie); - g_signal_connect (priv->active_session, - "completed", - G_CALLBACK (on_completed), - listener); - g_signal_connect (priv->active_session, - "request", - G_CALLBACK (on_request), - listener); - g_signal_connect (priv->active_session, - "show-info", - G_CALLBACK (on_show_info), - listener); - g_signal_connect (priv->active_session, - "show-error", - G_CALLBACK (on_show_error), - listener); - - priv->action_id = g_strdup (action_id); - priv->message = g_strdup (message); - priv->icon_name = g_strdup (icon_name); - if (POLKIT_IS_UNIX_USER (identity)) - priv->identity = g_strdup (polkit_unix_user_get_name (POLKIT_UNIX_USER (identity))); - else - priv->identity = polkit_identity_to_string (identity); + g_free (self->name_owner); + self->name_owner = g_strdup (name_owner); - priv->simple = simple; - priv->cancellable = g_object_ref (cancellable); - priv->cancel_id = g_cancellable_connect (cancellable, - G_CALLBACK (on_cancelled), - listener, - NULL); + if (!self->name_owner) { + return; + } - polkit_agent_session_initiate (priv->active_session); + if (export_dbus_iface (self, &error)) { + if (self->session_agent) { + retrieve_session_id (self); + } else { + agent_register (self, NULL); + } + } else { + g_signal_emit (self, + signals[ERROR], + 0, + "Could not export the PolicyKit Authentication Agent DBus interface"); + } } -static gboolean -initiate_authentication_finish (PolkitAgentListener *listener, - GAsyncResult *result, - GError **error) +static void +name_owner_changed_cb (GDBusConnection *connection, + const char *sender_name, + const char *object_path, + const char *interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) +{ + NMPolkitListener *self = user_data; + const char *new_owner; + + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sss)"))) { + return; + } + + g_variant_get (parameters, + "(&s&s&s)", + NULL, + NULL, + &new_owner); + + name_owner_changed (self, new_owner); +} + +static void +get_name_owner_cb (const char *name_owner, + GError *error, + gpointer user_data) { - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error); + if (!name_owner && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + return; + } + name_owner_changed (user_data, name_owner); } /*****************************************************************************/ +NM_GOBJECT_PROPERTIES_DEFINE (NMPolkitListener, + PROP_DBUS_CONNECTION, + PROP_SESSION_AGENT, +); + +static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + NMPolkitListener *self = NM_POLKIT_LISTENER (object); + + switch (prop_id) { + case PROP_DBUS_CONNECTION: + self->dbus_connection = g_value_dup_object (value); + break; + case PROP_SESSION_AGENT: + self->session_agent = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_polkit_listener_init (NMPolkitListener *self) +{ + c_list_init (&self->request_lst_head); + self->main_context = g_main_context_ref_thread_default (); +} + static void -nm_polkit_listener_init (NMPolkitListener *agent) +constructed (GObject *object) { + NMPolkitListener *self = NM_POLKIT_LISTENER (object); + + self->cancellable = g_cancellable_new (); + + self->name_owner_changed_id = + nm_dbus_connection_signal_subscribe_name_owner_changed (self->dbus_connection, + POLKIT_BUS_NAME, + name_owner_changed_cb, + self, + NULL); + + nm_dbus_connection_call_get_name_owner (self->dbus_connection, + POLKIT_BUS_NAME, + -1, + self->cancellable, + get_name_owner_cb, + self); + + G_OBJECT_CLASS (nm_polkit_listener_parent_class)->constructed (object); } /** * nm_polkit_listener_new: - * @for_session: %TRUE for registering the polkit agent for the user session, - * %FALSE for registering it for the running process - * @vtable: mandatory callbacks - * @user_data: user-data pointer for callbacks - * @error: location to store error, or %NULL + * @dbus_connection: a open DBus connection + * @session_agent: TRUE if a session agent is wanted, FALSE for a process agent * * Creates a new #NMPolkitListener and registers it as a polkit agent. * * Returns: a new #NMPolkitListener */ NMPolkitListener * -nm_polkit_listener_new (gboolean for_session, - GError **error) +nm_polkit_listener_new (GDBusConnection *dbus_connection, gboolean session_agent) { - NMPolkitListener *listener; - PolkitSubject* session; - NMPolkitListenerPrivate *priv; - - g_return_val_if_fail (!error || !*error, NULL); - - listener = g_object_new (NM_TYPE_POLKIT_LISTENER, NULL); - - priv = NM_POLKIT_LISTENER_GET_PRIVATE (listener); - - if (for_session) { - session = polkit_unix_session_new_for_process_sync (getpid (), NULL, error); - if (!session) - return NULL; - } else - session = polkit_unix_process_new_for_owner (getpid (), 0, getuid ()); - - priv->reg_handle = polkit_agent_listener_register (POLKIT_AGENT_LISTENER (listener), - POLKIT_AGENT_REGISTER_FLAGS_NONE, - session, NULL, NULL, error); - if (!priv->reg_handle) { - g_object_unref (listener); - g_object_unref (session); - return NULL; - } - - return listener; + return g_object_new (NM_TYPE_POLKIT_LISTENER, + NM_POLKIT_LISTENER_DBUS_CONNECTION, dbus_connection, + NM_POLKIT_LISTENER_SESSION_AGENT, session_agent, + NULL); } static void -nm_polkit_listener_finalize (GObject *object) +dispose (GObject *object) { - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (object); - - if (priv->reg_handle) - polkit_agent_listener_unregister (priv->reg_handle); + NMPolkitListener *self = NM_POLKIT_LISTENER (object); + AuthRequest *request; + + nm_clear_g_cancellable (&self->cancellable); + + while ((request = c_list_first_entry (&self->request_lst_head, AuthRequest, request_lst))) + auth_request_complete (request, FALSE); + + if (self->dbus_connection) { + nm_clear_g_dbus_connection_signal (self->dbus_connection, + &self->name_owner_changed_id); + g_dbus_connection_unregister_object (self->dbus_connection, + self->pk_auth_agent_reg_id); + agent_unregister (self); + nm_clear_g_free (&self->name_owner); + g_clear_object (&self->dbus_connection); + } - g_free (priv->action_id); - g_free (priv->message); - g_free (priv->icon_name); - g_free (priv->identity); + nm_clear_pointer (&self->main_context, g_main_context_unref); - G_OBJECT_CLASS (nm_polkit_listener_parent_class)->finalize (object); + G_OBJECT_CLASS (nm_polkit_listener_parent_class)->dispose (object); } static void nm_polkit_listener_class_init (NMPolkitListenerClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - PolkitAgentListenerClass *pkal_class = POLKIT_AGENT_LISTENER_CLASS (klass); - - g_type_class_add_private (klass, sizeof (NMPolkitListenerPrivate)); - - gobject_class->finalize = nm_polkit_listener_finalize; - - pkal_class->initiate_authentication = initiate_authentication; - pkal_class->initiate_authentication_finish = initiate_authentication_finish; + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = set_property; + object_class->constructed = constructed; + object_class->dispose = dispose; + + obj_properties[PROP_DBUS_CONNECTION] = + g_param_spec_object (NM_POLKIT_LISTENER_DBUS_CONNECTION, "", "", + G_TYPE_DBUS_CONNECTION, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_WRITABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_SESSION_AGENT] = + g_param_spec_boolean (NM_POLKIT_LISTENER_SESSION_AGENT, "", "", + FALSE, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_WRITABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, + _PROPERTY_ENUMS_LAST, + obj_properties); + + signals[REQUEST_SYNC] = + g_signal_new (NM_POLKIT_LISTENER_SIGNAL_REQUEST_SYNC, + NM_TYPE_POLKIT_LISTENER, + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + NULL, + G_TYPE_STRING, + 3, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); + + signals[REGISTERED] = + g_signal_new (NM_POLKIT_LISTENER_SIGNAL_REGISTERED, + NM_TYPE_POLKIT_LISTENER, + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); + + signals[ERROR] = + g_signal_new (NM_POLKIT_LISTENER_SIGNAL_ERROR, + NM_TYPE_POLKIT_LISTENER, + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + G_TYPE_STRING); } - -#endif /* WITH_POLKIT_AGENT */ diff --git a/clients/common/nm-polkit-listener.h b/clients/common/nm-polkit-listener.h index 42da1bc1..c14d5932 100644 --- a/clients/common/nm-polkit-listener.h +++ b/clients/common/nm-polkit-listener.h @@ -6,67 +6,15 @@ #ifndef __NM_POLKIT_LISTENER_H__ #define __NM_POLKIT_LISTENER_H__ -#if WITH_POLKIT_AGENT +#define NM_POLKIT_LISTENER_SIGNAL_REGISTERED "registered" +#define NM_POLKIT_LISTENER_SIGNAL_REQUEST_SYNC "request-sync" +#define NM_POLKIT_LISTENER_SIGNAL_AUTH_SUCCESS "auth-success" +#define NM_POLKIT_LISTENER_SIGNAL_AUTH_FAILURE "auth-failure" +#define NM_POLKIT_LISTENER_SIGNAL_ERROR "error" typedef struct _NMPolkitListener NMPolkitListener; typedef struct _NMPolkitListenerClass NMPolkitListenerClass; -typedef struct { - - /* - * @request: the request asked by polkit agent - * @action_id: the action_id of the polkit request - * @message: the message of the polkit request - * @icon_name: the icon name of the polkit request - * @user: user name - * @echo_on: whether the response to the request should be echoed to the screen - * @user_data: user data for the callback - * - * Called as a result of a request by polkit. The function should obtain response - * to the request from user, i.e. get the password required. - */ - char *(*on_request) (NMPolkitListener *self, - const char *request, - const char *action_id, - const char *message, - const char *icon_name, - const char *user, - gboolean echo_on, - gpointer user_data); - - /* - * @text: the info text from polkit - * - * Called as a result of show-info signal by polkit. - */ - void (*on_show_info) (NMPolkitListener *self, - const char *text, - gpointer user_data); - - /* - * @text: the error text from polkit - * - * Called as a result of show-error signal by polkit. - */ - void (*on_show_error) (NMPolkitListener *self, - const char *text, - gpointer user_data); - - /* - * @gained_authorization: whether the authorization was successful - * - * Called as a result of completed signal by polkit. - */ - void (*on_completed) (NMPolkitListener *self, - gboolean gained_authorization, - gpointer user_data); -} NMPolkitListenVtable; - -/*****************************************************************************/ - -#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE -#include <polkitagent/polkitagent.h> - #define NM_TYPE_POLKIT_LISTENER (nm_polkit_listener_get_type ()) #define NM_POLKIT_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_POLKIT_LISTENER, NMPolkitListener)) #define NM_POLKIT_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_POLKIT_LISTENER, NMPolkitListenerClass)) @@ -74,65 +22,8 @@ typedef struct { #define NM_IS_POLKIT_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_POLKIT_LISTENER)) #define NM_POLKIT_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_POLKIT_LISTENER, NMPolkitListenerClass)) -/** - * NMPolkitListenerOnRequestFunc: - * @request: the request asked by polkit agent - * @action_id: the action_id of the polkit request - * @message: the message of the polkit request - * @icon_name: the icon name of the polkit request - * @user: user name - * @echo_on: whether the response to the request should be echoed to the screen - * @user_data: user data for the callback - * - * Called as a result of a request by polkit. The function should obtain response - * to the request from user, i.e. get the password required. - */ -typedef char * (*NMPolkitListenerOnRequestFunc) (const char *request, - const char *action_id, - const char *message, - const char *icon_name, - const char *user, - gboolean echo_on, - gpointer user_data); -/** - * NMPolkitListenerOnShowInfoFunc: - * @text: the info text from polkit - * - * Called as a result of show-info signal by polkit. - */ -typedef void (*NMPolkitListenerOnShowInfoFunc) (const char *text); -/** - * NMPolkitListenerOnShowErrorFunc: - * @text: the error text from polkit - * - * Called as a result of show-error signal by polkit. - */ -typedef void (*NMPolkitListenerOnShowErrorFunc) (const char *text); -/** - * NMPolkitListenerCompletedFunc: - * @gained_authorization: whether the authorization was successful - * - * Called as a result of completed signal by polkit. - */ -typedef void (*NMPolkitListenerOnCompletedFunc) (gboolean gained_authorization); - -struct _NMPolkitListener { - PolkitAgentListener parent; -}; - -struct _NMPolkitListenerClass { - PolkitAgentListenerClass parent; -}; - GType nm_polkit_listener_get_type (void); -NMPolkitListener *nm_polkit_listener_new (gboolean for_session, - GError **error); - -void nm_polkit_listener_set_vtable (NMPolkitListener *self, - const NMPolkitListenVtable *vtable, - gpointer user_data); - -#endif +NMPolkitListener *nm_polkit_listener_new (GDBusConnection *dbus_connection, gboolean session_agent); #endif /* __NM_POLKIT_LISTENER_H__ */ diff --git a/clients/common/nm-secret-agent-simple.c b/clients/common/nm-secret-agent-simple.c index 2bf69b20..ca9250ca 100644 --- a/clients/common/nm-secret-agent-simple.c +++ b/clients/common/nm-secret-agent-simple.c @@ -302,7 +302,7 @@ add_wireless_secrets (RequestData *request, const char *key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); NMSecretAgentSimpleSecret *secret; - if (!key_mgmt) + if (!key_mgmt || nm_streq (key_mgmt, "owe")) return FALSE; if (NM_IN_STRSET (key_mgmt, "wpa-psk", "sae")) { diff --git a/clients/common/nm-vpn-helpers.c b/clients/common/nm-vpn-helpers.c index e1d83551..35ed4451 100644 --- a/clients/common/nm-vpn-helpers.c +++ b/clients/common/nm-vpn-helpers.c @@ -368,13 +368,13 @@ nm_vpn_wireguard_import (const char *filename, memcpy (ifname, cstr, len); ifname[len] = '\0'; - if (nm_utils_ifname_valid_kernel (ifname, NULL)) + if (nm_utils_ifname_valid (ifname, NMU_IFACE_KERNEL, NULL)) ifname_valid = TRUE; } } if (!ifname_valid) { nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, - _("The WireGuard config file must be a valid interface name followed by \".conf\"")); + _("The name of the WireGuard config must be a valid interface name followed by \".conf\"")); return FALSE; } @@ -524,7 +524,6 @@ nm_vpn_wireguard_import (const char *filename, char *value_word; while (value_split_word (&value, &value_word)) { - char addr_s[NM_CONST_MAX (INET_ADDRSTRLEN, INET6_ADDRSTRLEN)]; GPtrArray **p_data_dns; NMIPAddr addr_bin; int addr_family; @@ -541,8 +540,8 @@ nm_vpn_wireguard_import (const char *filename, if (!*p_data_dns) *p_data_dns = g_ptr_array_new_with_free_func (g_free); - inet_ntop (addr_family, &addr_bin, addr_s, sizeof (addr_s)); - g_ptr_array_add (*p_data_dns, g_strdup (addr_s)); + g_ptr_array_add (*p_data_dns, + nm_utils_inet_ntop_dup (addr_family, &addr_bin)); } continue; } @@ -745,6 +744,14 @@ fail_invalid_secret: data_addr ? method_manual : method_disabled, NULL); + /* For WireGuard profiles, always set dns-priority to a negative value, + * so that DNS servers on other profiles get ignored. This is also what + * wg-quick does, by calling `resolvconf -x`. */ + g_object_set (s_ip, + NM_SETTING_IP_CONFIG_DNS_PRIORITY, + (int) -10, + NULL); + if (data_addr) { for (i = 0; i < data_addr->len; i++) nm_setting_ip_config_add_address (s_ip, data_addr->pdata[i]); @@ -752,6 +759,10 @@ fail_invalid_secret: if (data_dns) { for (i = 0; i < data_dns->len; i++) nm_setting_ip_config_add_dns (s_ip, data_dns->pdata[i]); + + /* the wg-quick file cannot handle search domains. When configuring a DNS server + * in the wg-quick file, assume that the user want to use it for all searches. */ + nm_setting_ip_config_add_dns_search (s_ip, "~"); } if (data_table == _TABLE_AUTO) { @@ -765,9 +776,10 @@ fail_invalid_secret: * yourself to "ipv4.routes" and "ipv6.routes". * * - With "auto", wg-quick also configures policy routing to handle default-routes (/0) to - * avoid routing loops. That is not yet solved by NetworkManager, you need to configure - * that explicitly (for example, by adding a direct route to the gateway on the interface - * that has the default-route, or by using a script (possibly dispatcher script). + * avoid routing loops. + * The imported connection profile will have wireguard.ip4-auto-default-route and + * wireguard.ip6-auto-default-route set to "default". It will thus configure wg-quick's + * policy routing if the profile has any AllowedIPs ranges with /0. */ } else if (data_table == _TABLE_OFF) { if (is_v4) { diff --git a/clients/common/settings-docs.h b/clients/common/settings-docs.h index 22d537e4..5cbef428 100644 --- a/clients/common/settings-docs.h +++ b/clients/common/settings-docs.h @@ -24,7 +24,7 @@ #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_AUTH_ALG N_("When WEP is used (ie, key-mgmt = \"none\" or \"ieee8021x\") indicate the 802.11 authentication algorithm required by the AP here. One of \"open\" for Open System, \"shared\" for Shared Key, or \"leap\" for Cisco LEAP. When using Cisco LEAP (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\") the \"leap-username\" and \"leap-password\" properties must be specified.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_FILS N_("Indicates whether Fast Initial Link Setup (802.11ai) must be enabled for the connection. One of NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) (use global default value), NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE (1) (disable FILS), NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL (2) (enable FILS if the supplicant and the access point support it) or NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED (3) (enable FILS and fail if not supported). When set to NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) and no global default is set, FILS will be optionally enabled.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_GROUP N_("A list of group/broadcast encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list. For maximum compatibility leave this property empty. Each list element may be one of \"wep40\", \"wep104\", \"tkip\", or \"ccmp\".") -#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_KEY_MGMT N_("Key management used for the connection. One of \"none\" (WEP), \"ieee8021x\" (Dynamic WEP), \"wpa-psk\" (infrastructure WPA-PSK), \"sae\" (SAE) or \"wpa-eap\" (WPA-Enterprise). This property must be set for any Wi-Fi connection that uses security.") +#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_KEY_MGMT N_("Key management used for the connection. One of \"none\" (WEP), \"ieee8021x\" (Dynamic WEP), \"wpa-psk\" (infrastructure WPA-PSK), \"sae\" (SAE), \"owe\" (Opportunistic Wireless Encryption) or \"wpa-eap\" (WPA-Enterprise). This property must be set for any Wi-Fi connection that uses security.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD N_("The login password for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\").") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS N_("Flags indicating how to handle the \"leap-password\" property.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME N_("The login username for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\").") @@ -51,7 +51,8 @@ #define DESCRIBE_DOC_NM_SETTING_802_1X_CLIENT_CERT N_("Contains the client certificate if used by the EAP method specified in the \"eap\" property. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte.") #define DESCRIBE_DOC_NM_SETTING_802_1X_CLIENT_CERT_PASSWORD N_("The password used to access the client certificate stored in \"client-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.") #define DESCRIBE_DOC_NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"client-cert-password\" property.") -#define DESCRIBE_DOC_NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison.") +#define DESCRIBE_DOC_NM_SETTING_802_1X_DOMAIN_MATCH N_("Constraint for server domain name. If set, this list of FQDNs is used as a match requirement for dNSName element(s) of the certificate presented by the authentication server. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using the same comparison. Multiple valid FQDNs can be passed as a \";\" delimited list.") +#define DESCRIBE_DOC_NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison. Since version 1.24, multiple valid FQDNs can be passed as a \";\" delimited list.") #define DESCRIBE_DOC_NM_SETTING_802_1X_EAP N_("The allowed EAP method to be used when authenticating to the network with 802.1x. Valid methods are: \"leap\", \"md5\", \"tls\", \"peap\", \"ttls\", \"pwd\", and \"fast\". Each method requires different configuration using the properties of this setting; refer to wpa_supplicant documentation for the allowed combinations.") #define DESCRIBE_DOC_NM_SETTING_802_1X_IDENTITY N_("Identity string for EAP authentication methods. Often the user's user or login name.") #define DESCRIBE_DOC_NM_SETTING_802_1X_OPTIONAL N_("Whether the 802.1X authentication is optional. If TRUE, the activation will continue even after a timeout or an authentication failure. Setting the property to TRUE is currently allowed only for Ethernet connections. If set to FALSE, the activation can continue only after a successful authentication.") @@ -74,7 +75,8 @@ #define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CLIENT_CERT N_("Contains the \"phase 2\" client certificate if used by the EAP method specified in the \"phase2-auth\" or \"phase2-autheap\" properties. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended.") #define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD N_("The password used to access the \"phase2\" client certificate stored in \"phase2-client-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.") #define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"phase2-client-cert-password\" property.") -#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner \"phase 2\" authentication. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison.") +#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_DOMAIN_MATCH N_("Constraint for server domain name. If set, this list of FQDNs is used as a match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner \"phase 2\" authentication. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using the same comparison. Multiple valid FQDNs can be passed as a \";\" delimited list.") +#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner \"phase 2\" authentication. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison. Since version 1.24, multiple valid FQDNs can be passed as a \";\" delimited list.") #define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_PRIVATE_KEY N_("Contains the \"phase 2\" inner private key when the \"phase2-auth\" or \"phase2-autheap\" property is set to \"tls\". Key data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data. When using private keys with the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte. When using PKCS#12 format private keys and the blob scheme, this property should be set to the PKCS#12 data and the \"phase2-private-key-password\" property must be set to password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files and the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte, and as with the blob scheme the \"phase2-private-key-password\" property must be set to the password used to decode the PKCS#12 private key and certificate.") #define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD N_("The password used to decrypt the \"phase 2\" private key specified in the \"phase2-private-key\" property when the private key either uses the path scheme, or is a PKCS#12 format key.") #define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS N_("Flags indicating how to handle the \"phase2-private-key-password\" property.") @@ -112,15 +114,21 @@ #define DESCRIBE_DOC_NM_SETTING_BOND_OPTIONS N_("Dictionary of key/value pairs of bonding options. Both keys and values must be strings. Option names must contain only alphanumeric characters (ie, [a-zA-Z0-9]).") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_AGEING_TIME N_("The Ethernet MAC address aging time, in seconds.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_FORWARD_DELAY N_("The Spanning Tree Protocol (STP) forwarding delay, in seconds.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_GROUP_ADDRESS N_("If specified, The MAC address of the multicast group this bridge uses for STP. The address must be a link-local address in standard Ethernet MAC address format, ie an address of the form 01:80:C2:00:00:0X, with X in [0, 4..F]. If not specified the default value is 01:80:C2:00:00:00.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_GROUP_FORWARD_MASK N_("A mask of group addresses to forward. Usually, group addresses in the range from 01:80:C2:00:00:00 to 01:80:C2:00:00:0F are not forwarded according to standards. This property is a mask of 16 bits, each corresponding to a group address in that range that must be forwarded. The mask can't have bits 0, 1 or 2 set because they are used for STP, MAC pause frames and LACP.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_HELLO_TIME N_("The Spanning Tree Protocol (STP) hello time, in seconds.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAC_ADDRESS N_("If specified, the MAC address of bridge. When creating a new bridge, this MAC address will be set. If this field is left unspecified, the \"ethernet.cloned-mac-address\" is referred instead to generate the initial MAC address. Note that setting \"ethernet.cloned-mac-address\" anyway overwrites the MAC address of the bridge later while activating the bridge. Hence, this property is deprecated. Deprecated: 1") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAX_AGE N_("The Spanning Tree Protocol (STP) maximum message age, in seconds.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_QUERIER N_("Enable or disable sending of multicast queries by the bridge. If not specified the option is disabled.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR N_("If enabled the bridge's own IP address is used as the source address for IGMP queries otherwise the default of 0.0.0.0 is used.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_ROUTER N_("Sets bridge's multicast router. multicast-snooping must be enabled for this option to work. Supported values are: 'auto', 'disabled', 'enabled'. If not specified the default value is 'auto'.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_SNOOPING N_("Controls whether IGMP snooping is enabled for this bridge. Note that if snooping was automatically disabled due to hash collisions, the system may refuse to enable the feature until the collisions are resolved.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_PRIORITY N_("Sets the Spanning Tree Protocol (STP) priority for this bridge. Lower values are \"better\"; the lowest priority bridge will be elected the root bridge.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_STP N_("Controls whether Spanning Tree Protocol (STP) is enabled for this bridge.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID N_("The default PVID for the ports of the bridge, that is the VLAN id assigned to incoming untagged frames.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_FILTERING N_("Control whether VLAN filtering is enabled on the bridge.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_PROTOCOL N_("If specified, the protocol used for VLAN filtering. Supported values are: '802.1Q', '802.1ad'. If not specified the default value is '802.1Q'.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_STATS_ENABLED N_("Controls whether per-VLAN stats accounting is enabled.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLANS N_("Array of bridge VLAN objects. In addition to the VLANs specified here, the bridge will also have the default-pvid VLAN configured by the bridge.vlan-default-pvid property. In nmcli the VLAN list can be specified with the following syntax: $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... where $vid is either a single id between 1 and 4094 or a range, represented as a couple of ids separated by a dash.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE N_("Enables or disables \"hairpin mode\" for the port, which allows frames to be sent back out through the port the frame was received on.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_PATH_COST N_("The Spanning Tree Protocol (STP) port cost for destinations via this port.") @@ -213,7 +221,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS N_("Array of IP addresses of DNS servers.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_OPTIONS N_("Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties.") -#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_PRIORITY N_("DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored.") +#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_PRIORITY N_("DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_SEARCH N_("Array of DNS search domains. Domains starting with a tilde ('~') are considered 'routing' domains and are used only to decide the interface over which a query must be forwarded; they are not used to complete unqualified host names.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_GATEWAY N_("The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used.") @@ -235,7 +243,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS N_("Array of IP addresses of DNS servers.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_OPTIONS N_("Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties.") -#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_PRIORITY N_("DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored.") +#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_PRIORITY N_("DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_SEARCH N_("Array of DNS search domains. Domains starting with a tilde ('~') are considered 'routing' domains and are used only to decide the interface over which a query must be forwarded; they are not used to complete unqualified host names.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_GATEWAY N_("The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used.") @@ -310,7 +318,7 @@ #define DESCRIBE_DOC_NM_SETTING_SERIAL_SEND_DELAY N_("Time to delay between each byte sent to the modem, in microseconds.") #define DESCRIBE_DOC_NM_SETTING_SERIAL_STOPBITS N_("Number of stop bits for communication on the serial port. Either 1 or 2. The 1 in \"8n1\" for example.") #define DESCRIBE_DOC_NM_SETTING_SRIOV_AUTOPROBE_DRIVERS N_("Whether to autoprobe virtual functions by a compatible driver. If set to NM_TERNARY_TRUE (1), the kernel will try to bind VFs to a compatible driver and if this succeeds a new network interface will be instantiated for each VF. If set to NM_TERNARY_FALSE (0), VFs will not be claimed and no network interfaces will be created for them. When set to NM_TERNARY_DEFAULT (-1), the global default is used; in case the global default is unspecified it is assumed to be NM_TERNARY_TRUE (1).") -#define DESCRIBE_DOC_NM_SETTING_SRIOV_TOTAL_VFS N_("The total number of virtual functions to create. Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface also when it is zero. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection.") +#define DESCRIBE_DOC_NM_SETTING_SRIOV_TOTAL_VFS N_("The total number of virtual functions to create. Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface (also when it is zero) during activation and resets it upon deactivation. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection.") #define DESCRIBE_DOC_NM_SETTING_SRIOV_VFS N_("Array of virtual function descriptors. Each VF descriptor is a dictionary mapping attribute names to GVariant values. The 'index' entry is mandatory for each VF. When represented as string a VF is in the form: \"INDEX [ATTR=VALUE[ ATTR=VALUE]...]\". for example: \"2 mac=00:11:22:33:44:55 spoof-check=true\". Multiple VFs can be specified using a comma as separator. Currently the following attributes are supported: mac, spoof-check, trust, min-tx-rate, max-tx-rate, vlans. The \"vlans\" attribute is represented as a semicolon-separated list of VLAN descriptors, where each descriptor has the form \"ID[.PRIORITY[.PROTO]]\". PROTO can be either 'q' for 802.1Q (the default) or 'ad' for 802.1ad.") #define DESCRIBE_DOC_NM_SETTING_TC_CONFIG_QDISCS N_("Array of TC queueing disciplines.") #define DESCRIBE_DOC_NM_SETTING_TC_CONFIG_TFILTERS N_("Array of TC traffic filters.") @@ -355,6 +363,7 @@ #define DESCRIBE_DOC_NM_SETTING_VPN_SERVICE_TYPE N_("D-Bus service name of the VPN plugin that this setting uses to connect to its network. i.e. org.freedesktop.NetworkManager.vpnc for the vpnc plugin.") #define DESCRIBE_DOC_NM_SETTING_VPN_TIMEOUT N_("Timeout for the VPN service to establish the connection. Some services may take quite a long time to connect. Value of 0 means a default timeout, which is 60 seconds (unless overridden by vpn.timeout in configuration file). Values greater than zero mean timeout in seconds.") #define DESCRIBE_DOC_NM_SETTING_VPN_USER_NAME N_("If the VPN connection requires a user name for authentication, that name should be provided here. If the connection is available to more than one user, and the VPN requires each user to supply a different name, then leave this property empty. If this property is empty, NetworkManager will automatically supply the username of the user which requested the VPN connection.") +#define DESCRIBE_DOC_NM_SETTING_VRF_TABLE N_("The routing table for this VRF.") #define DESCRIBE_DOC_NM_SETTING_VXLAN_AGEING N_("Specifies the lifetime in seconds of FDB entries learnt by the kernel.") #define DESCRIBE_DOC_NM_SETTING_VXLAN_DESTINATION_PORT N_("Specifies the UDP destination port to communicate to the remote VXLAN tunnel endpoint.") #define DESCRIBE_DOC_NM_SETTING_VXLAN_ID N_("Specifies the VXLAN Network Identifier (or VXLAN Segment Identifier) to use.") diff --git a/clients/common/settings-docs.h.in b/clients/common/settings-docs.h.in index 22d537e4..5cbef428 100644 --- a/clients/common/settings-docs.h.in +++ b/clients/common/settings-docs.h.in @@ -24,7 +24,7 @@ #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_AUTH_ALG N_("When WEP is used (ie, key-mgmt = \"none\" or \"ieee8021x\") indicate the 802.11 authentication algorithm required by the AP here. One of \"open\" for Open System, \"shared\" for Shared Key, or \"leap\" for Cisco LEAP. When using Cisco LEAP (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\") the \"leap-username\" and \"leap-password\" properties must be specified.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_FILS N_("Indicates whether Fast Initial Link Setup (802.11ai) must be enabled for the connection. One of NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) (use global default value), NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE (1) (disable FILS), NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL (2) (enable FILS if the supplicant and the access point support it) or NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED (3) (enable FILS and fail if not supported). When set to NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) and no global default is set, FILS will be optionally enabled.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_GROUP N_("A list of group/broadcast encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list. For maximum compatibility leave this property empty. Each list element may be one of \"wep40\", \"wep104\", \"tkip\", or \"ccmp\".") -#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_KEY_MGMT N_("Key management used for the connection. One of \"none\" (WEP), \"ieee8021x\" (Dynamic WEP), \"wpa-psk\" (infrastructure WPA-PSK), \"sae\" (SAE) or \"wpa-eap\" (WPA-Enterprise). This property must be set for any Wi-Fi connection that uses security.") +#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_KEY_MGMT N_("Key management used for the connection. One of \"none\" (WEP), \"ieee8021x\" (Dynamic WEP), \"wpa-psk\" (infrastructure WPA-PSK), \"sae\" (SAE), \"owe\" (Opportunistic Wireless Encryption) or \"wpa-eap\" (WPA-Enterprise). This property must be set for any Wi-Fi connection that uses security.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD N_("The login password for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\").") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS N_("Flags indicating how to handle the \"leap-password\" property.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME N_("The login username for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\").") @@ -51,7 +51,8 @@ #define DESCRIBE_DOC_NM_SETTING_802_1X_CLIENT_CERT N_("Contains the client certificate if used by the EAP method specified in the \"eap\" property. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte.") #define DESCRIBE_DOC_NM_SETTING_802_1X_CLIENT_CERT_PASSWORD N_("The password used to access the client certificate stored in \"client-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.") #define DESCRIBE_DOC_NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"client-cert-password\" property.") -#define DESCRIBE_DOC_NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison.") +#define DESCRIBE_DOC_NM_SETTING_802_1X_DOMAIN_MATCH N_("Constraint for server domain name. If set, this list of FQDNs is used as a match requirement for dNSName element(s) of the certificate presented by the authentication server. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using the same comparison. Multiple valid FQDNs can be passed as a \";\" delimited list.") +#define DESCRIBE_DOC_NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison. Since version 1.24, multiple valid FQDNs can be passed as a \";\" delimited list.") #define DESCRIBE_DOC_NM_SETTING_802_1X_EAP N_("The allowed EAP method to be used when authenticating to the network with 802.1x. Valid methods are: \"leap\", \"md5\", \"tls\", \"peap\", \"ttls\", \"pwd\", and \"fast\". Each method requires different configuration using the properties of this setting; refer to wpa_supplicant documentation for the allowed combinations.") #define DESCRIBE_DOC_NM_SETTING_802_1X_IDENTITY N_("Identity string for EAP authentication methods. Often the user's user or login name.") #define DESCRIBE_DOC_NM_SETTING_802_1X_OPTIONAL N_("Whether the 802.1X authentication is optional. If TRUE, the activation will continue even after a timeout or an authentication failure. Setting the property to TRUE is currently allowed only for Ethernet connections. If set to FALSE, the activation can continue only after a successful authentication.") @@ -74,7 +75,8 @@ #define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CLIENT_CERT N_("Contains the \"phase 2\" client certificate if used by the EAP method specified in the \"phase2-auth\" or \"phase2-autheap\" properties. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended.") #define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD N_("The password used to access the \"phase2\" client certificate stored in \"phase2-client-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.") #define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"phase2-client-cert-password\" property.") -#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner \"phase 2\" authentication. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison.") +#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_DOMAIN_MATCH N_("Constraint for server domain name. If set, this list of FQDNs is used as a match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner \"phase 2\" authentication. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using the same comparison. Multiple valid FQDNs can be passed as a \";\" delimited list.") +#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner \"phase 2\" authentication. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison. Since version 1.24, multiple valid FQDNs can be passed as a \";\" delimited list.") #define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_PRIVATE_KEY N_("Contains the \"phase 2\" inner private key when the \"phase2-auth\" or \"phase2-autheap\" property is set to \"tls\". Key data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data. When using private keys with the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte. When using PKCS#12 format private keys and the blob scheme, this property should be set to the PKCS#12 data and the \"phase2-private-key-password\" property must be set to password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files and the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte, and as with the blob scheme the \"phase2-private-key-password\" property must be set to the password used to decode the PKCS#12 private key and certificate.") #define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD N_("The password used to decrypt the \"phase 2\" private key specified in the \"phase2-private-key\" property when the private key either uses the path scheme, or is a PKCS#12 format key.") #define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS N_("Flags indicating how to handle the \"phase2-private-key-password\" property.") @@ -112,15 +114,21 @@ #define DESCRIBE_DOC_NM_SETTING_BOND_OPTIONS N_("Dictionary of key/value pairs of bonding options. Both keys and values must be strings. Option names must contain only alphanumeric characters (ie, [a-zA-Z0-9]).") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_AGEING_TIME N_("The Ethernet MAC address aging time, in seconds.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_FORWARD_DELAY N_("The Spanning Tree Protocol (STP) forwarding delay, in seconds.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_GROUP_ADDRESS N_("If specified, The MAC address of the multicast group this bridge uses for STP. The address must be a link-local address in standard Ethernet MAC address format, ie an address of the form 01:80:C2:00:00:0X, with X in [0, 4..F]. If not specified the default value is 01:80:C2:00:00:00.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_GROUP_FORWARD_MASK N_("A mask of group addresses to forward. Usually, group addresses in the range from 01:80:C2:00:00:00 to 01:80:C2:00:00:0F are not forwarded according to standards. This property is a mask of 16 bits, each corresponding to a group address in that range that must be forwarded. The mask can't have bits 0, 1 or 2 set because they are used for STP, MAC pause frames and LACP.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_HELLO_TIME N_("The Spanning Tree Protocol (STP) hello time, in seconds.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAC_ADDRESS N_("If specified, the MAC address of bridge. When creating a new bridge, this MAC address will be set. If this field is left unspecified, the \"ethernet.cloned-mac-address\" is referred instead to generate the initial MAC address. Note that setting \"ethernet.cloned-mac-address\" anyway overwrites the MAC address of the bridge later while activating the bridge. Hence, this property is deprecated. Deprecated: 1") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAX_AGE N_("The Spanning Tree Protocol (STP) maximum message age, in seconds.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_QUERIER N_("Enable or disable sending of multicast queries by the bridge. If not specified the option is disabled.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR N_("If enabled the bridge's own IP address is used as the source address for IGMP queries otherwise the default of 0.0.0.0 is used.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_ROUTER N_("Sets bridge's multicast router. multicast-snooping must be enabled for this option to work. Supported values are: 'auto', 'disabled', 'enabled'. If not specified the default value is 'auto'.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_SNOOPING N_("Controls whether IGMP snooping is enabled for this bridge. Note that if snooping was automatically disabled due to hash collisions, the system may refuse to enable the feature until the collisions are resolved.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_PRIORITY N_("Sets the Spanning Tree Protocol (STP) priority for this bridge. Lower values are \"better\"; the lowest priority bridge will be elected the root bridge.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_STP N_("Controls whether Spanning Tree Protocol (STP) is enabled for this bridge.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID N_("The default PVID for the ports of the bridge, that is the VLAN id assigned to incoming untagged frames.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_FILTERING N_("Control whether VLAN filtering is enabled on the bridge.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_PROTOCOL N_("If specified, the protocol used for VLAN filtering. Supported values are: '802.1Q', '802.1ad'. If not specified the default value is '802.1Q'.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_STATS_ENABLED N_("Controls whether per-VLAN stats accounting is enabled.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLANS N_("Array of bridge VLAN objects. In addition to the VLANs specified here, the bridge will also have the default-pvid VLAN configured by the bridge.vlan-default-pvid property. In nmcli the VLAN list can be specified with the following syntax: $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... where $vid is either a single id between 1 and 4094 or a range, represented as a couple of ids separated by a dash.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE N_("Enables or disables \"hairpin mode\" for the port, which allows frames to be sent back out through the port the frame was received on.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_PATH_COST N_("The Spanning Tree Protocol (STP) port cost for destinations via this port.") @@ -213,7 +221,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS N_("Array of IP addresses of DNS servers.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_OPTIONS N_("Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties.") -#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_PRIORITY N_("DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored.") +#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_PRIORITY N_("DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_SEARCH N_("Array of DNS search domains. Domains starting with a tilde ('~') are considered 'routing' domains and are used only to decide the interface over which a query must be forwarded; they are not used to complete unqualified host names.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_GATEWAY N_("The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used.") @@ -235,7 +243,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS N_("Array of IP addresses of DNS servers.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_OPTIONS N_("Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties.") -#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_PRIORITY N_("DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored.") +#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_PRIORITY N_("DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_SEARCH N_("Array of DNS search domains. Domains starting with a tilde ('~') are considered 'routing' domains and are used only to decide the interface over which a query must be forwarded; they are not used to complete unqualified host names.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_GATEWAY N_("The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used.") @@ -310,7 +318,7 @@ #define DESCRIBE_DOC_NM_SETTING_SERIAL_SEND_DELAY N_("Time to delay between each byte sent to the modem, in microseconds.") #define DESCRIBE_DOC_NM_SETTING_SERIAL_STOPBITS N_("Number of stop bits for communication on the serial port. Either 1 or 2. The 1 in \"8n1\" for example.") #define DESCRIBE_DOC_NM_SETTING_SRIOV_AUTOPROBE_DRIVERS N_("Whether to autoprobe virtual functions by a compatible driver. If set to NM_TERNARY_TRUE (1), the kernel will try to bind VFs to a compatible driver and if this succeeds a new network interface will be instantiated for each VF. If set to NM_TERNARY_FALSE (0), VFs will not be claimed and no network interfaces will be created for them. When set to NM_TERNARY_DEFAULT (-1), the global default is used; in case the global default is unspecified it is assumed to be NM_TERNARY_TRUE (1).") -#define DESCRIBE_DOC_NM_SETTING_SRIOV_TOTAL_VFS N_("The total number of virtual functions to create. Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface also when it is zero. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection.") +#define DESCRIBE_DOC_NM_SETTING_SRIOV_TOTAL_VFS N_("The total number of virtual functions to create. Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface (also when it is zero) during activation and resets it upon deactivation. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection.") #define DESCRIBE_DOC_NM_SETTING_SRIOV_VFS N_("Array of virtual function descriptors. Each VF descriptor is a dictionary mapping attribute names to GVariant values. The 'index' entry is mandatory for each VF. When represented as string a VF is in the form: \"INDEX [ATTR=VALUE[ ATTR=VALUE]...]\". for example: \"2 mac=00:11:22:33:44:55 spoof-check=true\". Multiple VFs can be specified using a comma as separator. Currently the following attributes are supported: mac, spoof-check, trust, min-tx-rate, max-tx-rate, vlans. The \"vlans\" attribute is represented as a semicolon-separated list of VLAN descriptors, where each descriptor has the form \"ID[.PRIORITY[.PROTO]]\". PROTO can be either 'q' for 802.1Q (the default) or 'ad' for 802.1ad.") #define DESCRIBE_DOC_NM_SETTING_TC_CONFIG_QDISCS N_("Array of TC queueing disciplines.") #define DESCRIBE_DOC_NM_SETTING_TC_CONFIG_TFILTERS N_("Array of TC traffic filters.") @@ -355,6 +363,7 @@ #define DESCRIBE_DOC_NM_SETTING_VPN_SERVICE_TYPE N_("D-Bus service name of the VPN plugin that this setting uses to connect to its network. i.e. org.freedesktop.NetworkManager.vpnc for the vpnc plugin.") #define DESCRIBE_DOC_NM_SETTING_VPN_TIMEOUT N_("Timeout for the VPN service to establish the connection. Some services may take quite a long time to connect. Value of 0 means a default timeout, which is 60 seconds (unless overridden by vpn.timeout in configuration file). Values greater than zero mean timeout in seconds.") #define DESCRIBE_DOC_NM_SETTING_VPN_USER_NAME N_("If the VPN connection requires a user name for authentication, that name should be provided here. If the connection is available to more than one user, and the VPN requires each user to supply a different name, then leave this property empty. If this property is empty, NetworkManager will automatically supply the username of the user which requested the VPN connection.") +#define DESCRIBE_DOC_NM_SETTING_VRF_TABLE N_("The routing table for this VRF.") #define DESCRIBE_DOC_NM_SETTING_VXLAN_AGEING N_("Specifies the lifetime in seconds of FDB entries learnt by the kernel.") #define DESCRIBE_DOC_NM_SETTING_VXLAN_DESTINATION_PORT N_("Specifies the UDP destination port to communicate to the remote VXLAN tunnel endpoint.") #define DESCRIBE_DOC_NM_SETTING_VXLAN_ID N_("Specifies the VXLAN Network Identifier (or VXLAN Segment Identifier) to use.") diff --git a/clients/common/tests/meson.build b/clients/common/tests/meson.build index 479cb781..43b1f7c9 100644 --- a/clients/common/tests/meson.build +++ b/clients/common/tests/meson.build @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1+ + common_c_flags = clients_c_flags + ['-DNETWORKMANAGER_COMPILATION_TEST'] test_name = 'test-clients-common' diff --git a/clients/common/tests/test-clients-common.c b/clients/common/tests/test-clients-common.c index a5d803df..70ee2cb1 100644 --- a/clients/common/tests/test-clients-common.c +++ b/clients/common/tests/test-clients-common.c @@ -137,6 +137,8 @@ test_client_import_wireguard_test0 (void) { gs_unref_object NMConnection *connection; NMSettingWireGuard *s_wg; + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; NMWireGuardPeer *peer; gs_free_error GError *error = NULL; @@ -175,6 +177,17 @@ test_client_import_wireguard_test0 (void) g_assert_cmpstr (nm_wireguard_peer_get_endpoint (peer), ==, "test.wireguard.com:18981"); g_assert_cmpint (nm_wireguard_peer_get_allowed_ips_len (peer), ==, 1); g_assert_cmpstr (nm_wireguard_peer_get_allowed_ip (peer, 0, NULL), ==, "10.10.10.230/32"); + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + s_ip6 = nm_connection_get_setting_ip6_config (connection); + + g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 1); + g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip6), ==, 0); + + g_assert_cmpint (nm_setting_ip_config_get_num_dns_searches (s_ip4), ==, 1); + g_assert_cmpint (nm_setting_ip_config_get_num_dns_searches (s_ip6), ==, 0); + + g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip4, 0), ==, "~"); } static void diff --git a/clients/common/tests/wg-test0.conf b/clients/common/tests/wg-test0.conf index 61438c29..28af4a00 100644 --- a/clients/common/tests/wg-test0.conf +++ b/clients/common/tests/wg-test0.conf @@ -1,6 +1,8 @@ [Interface] PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= ListenPort = 51820 +Address = 10.10.10.5/32 +DNS = 10.10.10.1 [Peer] PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= |