From 964ae8cc391520440cf5aa13e2b9cc34850ea6c2 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Tue, 26 Feb 2019 19:01:41 +0100 Subject: New upstream version 1.14.6 --- clients/common/meson.build | 14 ++-- clients/common/nm-meta-setting-desc.c | 129 ++++++++-------------------------- clients/common/settings-docs.h | 10 +-- clients/common/settings-docs.h.in | 10 +-- 4 files changed, 43 insertions(+), 120 deletions(-) (limited to 'clients/common') diff --git a/clients/common/meson.build b/clients/common/meson.build index 0db2868e..30fd2cfa 100644 --- a/clients/common/meson.build +++ b/clients/common/meson.build @@ -37,15 +37,11 @@ if enable_introspection command: [xsltproc, '--output', '@OUTPUT@', join_paths(meson.current_source_dir(), 'settings-docs.xsl'), '@INPUT@'] ) - # FIXME: if enabled the check happens even if the settings_docs_source is not set - ''' - if get_option('check_settings_docs') - res = run_command(find_program('cmp'), '-s', settings_docs + '.in', settings_docs_source.full_path()) - if res.returncode() != 0 - message('The generated file ' + settings_docs_source.full_path() + ' differs from the source file ' + settings_docs + '.in' + '. You probably should copy the generated file over to the source file. You can skip this test by setting -Dcheck_settings_docs=false') - endif - endif - ''' + test( + 'check-settings-docs', + find_program(join_paths(meson.source_root(), 'tools', 'check-settings-docs.sh')), + args: [meson.source_root(), meson.build_root(), 'clients/common/' + settings_docs] + ) else settings_docs_source = configure_file( input: settings_docs + '.in', diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index d291732a..d13ee4ce 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -283,7 +283,7 @@ _dump_team_link_watcher (NMTeamLinkWatcher *watcher) } /* NM_TEAM_LINK_WATCHER_NSNA_PING and NM_TEAM_LINK_WATCHER_ARP_PING */ DUMP_WATCHER_INT (w_dump, watcher, "init-wait", init_wait); - DUMP_WATCHER_INT (w_dump, watcher, "initerval", interval); + DUMP_WATCHER_INT (w_dump, watcher, "interval", interval); DUMP_WATCHER_INT (w_dump, watcher, "missed-max", missed_max); #undef DUMP_WATCHER_INT g_string_append_printf (w_dump, " target-host=%s", @@ -2190,7 +2190,7 @@ _get_fcn_802_1x_phase2_private_key (ARGS_GET_FCN) strv = nm_utils_strsplit_set (value, " \t,", FALSE); \ if (strv) { \ for (i = 0; strv[i]; i++) \ - set_func (NM_SETTING_802_1X (setting), strv[i++]); \ + set_func (NM_SETTING_802_1X (setting), strv[i]); \ } \ return TRUE; \ } @@ -3349,7 +3349,7 @@ DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv4_config_dns, _validate_and_remove_ipv4_dns) static gboolean -_set_fcn_ip4_config_dns_search (ARGS_SET_FCN) +_set_fcn_ip_config_dns_search (ARGS_SET_FCN) { gs_free const char **strv = NULL; gsize i; @@ -3368,9 +3368,9 @@ _set_fcn_ip4_config_dns_search (ARGS_SET_FCN) } static gboolean -_validate_and_remove_ipv4_dns_search (NMSettingIPConfig *setting, - const char *dns_search, - GError **error) +_validate_and_remove_ip_dns_search (NMSettingIPConfig *setting, + const char *dns_search, + GError **error) { gboolean ret; @@ -3381,33 +3381,36 @@ _validate_and_remove_ipv4_dns_search (NMSettingIPConfig *setting, dns_search); return ret; } -DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv4_config_dns_search, +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ip_config_dns_search, NM_SETTING_IP_CONFIG, nm_setting_ip_config_get_num_dns_searches, nm_setting_ip_config_remove_dns_search, - _validate_and_remove_ipv4_dns_search) + _validate_and_remove_ip_dns_search) static gboolean -_set_fcn_ip4_config_dns_options (ARGS_SET_FCN) +_set_fcn_ip_config_dns_options (ARGS_SET_FCN) { gs_free const char **strv = NULL; + NMSettingIPConfig *s_ip; gsize i; nm_assert (!error || !*error); + s_ip = NM_SETTING_IP_CONFIG (setting); - nm_setting_ip_config_clear_dns_options (NM_SETTING_IP_CONFIG (setting), TRUE); strv = nm_utils_strsplit_set (value, " \t,", FALSE); if (strv) { - for (i = 0; strv[i]; i++) - nm_setting_ip_config_add_dns_option (NM_SETTING_IP_CONFIG (setting), strv[i]); + for (i = 0; strv[i]; i++) { + nm_setting_ip_config_remove_dns_option_by_value (s_ip, strv[i]); + nm_setting_ip_config_add_dns_option (s_ip, strv[i]); + } } return TRUE; } static gboolean -_validate_and_remove_ipv4_dns_option (NMSettingIPConfig *setting, - const char *dns_option, - GError **error) +_validate_and_remove_ip_dns_option (NMSettingIPConfig *setting, + const char *dns_option, + GError **error) { gboolean ret; @@ -3418,11 +3421,11 @@ _validate_and_remove_ipv4_dns_option (NMSettingIPConfig *setting, dns_option); return ret; } -DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv4_config_dns_options, +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ip_config_dns_options, NM_SETTING_IP_CONFIG, nm_setting_ip_config_get_num_dns_options, nm_setting_ip_config_remove_dns_option, - _validate_and_remove_ipv4_dns_option) + _validate_and_remove_ip_dns_option) static gboolean _set_fcn_ip4_config_addresses (ARGS_SET_FCN) @@ -3592,82 +3595,6 @@ DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv6_config_dns, nm_setting_ip_config_remove_dns, _validate_and_remove_ipv6_dns) -static gboolean -_set_fcn_ip6_config_dns_search (ARGS_SET_FCN) -{ - gs_free const char **strv = NULL; - gsize i; - - nm_assert (!error || !*error); - - strv = nm_utils_strsplit_set (value, " \t,", FALSE); - if (!verify_string_list (strv, property_info->property_name, nmc_util_is_domain, error)) - return FALSE; - - if (strv) { - for (i = 0; strv[i]; i++) - nm_setting_ip_config_add_dns_search (NM_SETTING_IP_CONFIG (setting), strv[i]); - } - return TRUE; -} - -static gboolean -_validate_and_remove_ipv6_dns_search (NMSettingIPConfig *setting, - const char *dns_search, - GError **error) -{ - gboolean ret; - - ret = nm_setting_ip_config_remove_dns_search_by_value (setting, dns_search); - if (!ret) - g_set_error (error, 1, 0, - _("the property doesn't contain DNS search domain '%s'"), - dns_search); - return ret; -} -DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv6_config_dns_search, - NM_SETTING_IP_CONFIG, - nm_setting_ip_config_get_num_dns_searches, - nm_setting_ip_config_remove_dns_search, - _validate_and_remove_ipv6_dns_search) - -static gboolean -_set_fcn_ip6_config_dns_options (ARGS_SET_FCN) -{ - gs_free const char **strv = NULL; - gsize i; - - nm_assert (!error || !*error); - - nm_setting_ip_config_clear_dns_options (NM_SETTING_IP_CONFIG (setting), TRUE); - strv = nm_utils_strsplit_set (value, " \t,", FALSE); - if (strv) { - for (i = 0; strv[i]; i++) - nm_setting_ip_config_add_dns_option (NM_SETTING_IP_CONFIG (setting), strv[i]); - } - return TRUE; -} - -static gboolean -_validate_and_remove_ipv6_dns_option (NMSettingIPConfig *setting, - const char *dns_option, - GError **error) -{ - gboolean ret; - - ret = nm_setting_ip_config_remove_dns_option_by_value (setting, dns_option); - if (!ret) - g_set_error (error, 1, 0, - _("the property doesn't contain DNS option '%s'"), - dns_option); - return ret; -} -DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv6_config_dns_options, - NM_SETTING_IP_CONFIG, - nm_setting_ip_config_get_num_dns_options, - nm_setting_ip_config_remove_dns_option, - _validate_and_remove_ipv6_dns_option) - static gboolean _dns_options_is_default (NMSettingIPConfig *setting) { @@ -6183,15 +6110,15 @@ static const NMMetaPropertyInfo *const property_infos_IP4_CONFIG[] = { PROPERTY_INFO (NM_SETTING_IP_CONFIG_DNS_SEARCH, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_SEARCH, .property_type = DEFINE_PROPERTY_TYPE ( .get_fcn = _get_fcn_gobject, - .set_fcn = _set_fcn_ip4_config_dns_search, - .remove_fcn = _remove_fcn_ipv4_config_dns_search, + .set_fcn = _set_fcn_ip_config_dns_search, + .remove_fcn = _remove_fcn_ip_config_dns_search, ), ), PROPERTY_INFO (NM_SETTING_IP_CONFIG_DNS_OPTIONS, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_OPTIONS, .property_type = DEFINE_PROPERTY_TYPE ( .get_fcn = _get_fcn_nmc_with_default, - .set_fcn = _set_fcn_ip4_config_dns_options, - .remove_fcn = _remove_fcn_ipv4_config_dns_options, + .set_fcn = _set_fcn_ip_config_dns_options, + .remove_fcn = _remove_fcn_ip_config_dns_options, ), .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (get_with_default, .fcn = GET_FCN_WITH_DEFAULT (NMSettingIPConfig, _dns_options_is_default), @@ -6346,15 +6273,15 @@ static const NMMetaPropertyInfo *const property_infos_IP6_CONFIG[] = { PROPERTY_INFO (NM_SETTING_IP_CONFIG_DNS_SEARCH, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_SEARCH, .property_type = DEFINE_PROPERTY_TYPE ( .get_fcn = _get_fcn_gobject, - .set_fcn = _set_fcn_ip6_config_dns_search, - .remove_fcn = _remove_fcn_ipv6_config_dns_search, + .set_fcn = _set_fcn_ip_config_dns_search, + .remove_fcn = _remove_fcn_ip_config_dns_search, ), ), PROPERTY_INFO (NM_SETTING_IP_CONFIG_DNS_OPTIONS, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_OPTIONS, .property_type = DEFINE_PROPERTY_TYPE ( .get_fcn = _get_fcn_nmc_with_default, - .set_fcn = _set_fcn_ip6_config_dns_options, - .remove_fcn = _remove_fcn_ipv6_config_dns_options, + .set_fcn = _set_fcn_ip_config_dns_options, + .remove_fcn = _remove_fcn_ip_config_dns_options, ), .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (get_with_default, .fcn = GET_FCN_WITH_DEFAULT (NMSettingIPConfig, _dns_options_is_default), diff --git a/clients/common/settings-docs.h b/clients/common/settings-docs.h index f07769c0..bc56edae 100644 --- a/clients/common/settings-docs.h +++ b/clients/common/settings-docs.h @@ -144,7 +144,7 @@ #define DESCRIBE_DOC_NM_SETTING_CONNECTION_READ_ONLY N_("FALSE if the connection can be modified using the provided settings service's D-Bus interface with the right privileges, or TRUE if the connection is read-only and cannot be modified.") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_SECONDARIES N_("List of connection UUIDs that should be activated when the base connection itself is activated. Currently only VPN connections are supported.") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_SLAVE_TYPE N_("Setting name of the device type of this slave's master connection (eg, \"bond\"), or NULL if this connection is not a slave.") -#define DESCRIBE_DOC_NM_SETTING_CONNECTION_STABLE_ID N_("This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are \"${CONNECTION}\", \"${DEVICE}\", \"${BOOT}\", \"${RANDOM}\". These effectively create unique IDs per-connection, per-device, per-boot, or every time. Note that \"${DEVICE}\" corresponds the the interface name of the device. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as \"$$\". For example, set it to \"${CONNECTION}-${BOOT}-${DEVICE}\" to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is similar to \"${CONNECTION}\" and uses a unique, fixed ID for the connection.") +#define DESCRIBE_DOC_NM_SETTING_CONNECTION_STABLE_ID N_("This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are \"${CONNECTION}\", \"${DEVICE}\", \"${MAC}\", \"${BOOT}\", \"${RANDOM}\". These effectively create unique IDs per-connection, per-device, per-boot, or every time. Note that \"${DEVICE}\" corresponds the the interface name of the device and \"${MAC}\" is the permanent MAC address of the device. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as \"$$\". For example, set it to \"${CONNECTION}-${BOOT}-${DEVICE}\" to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is similar to \"${CONNECTION}\" and uses a unique, fixed ID for the connection.") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_TIMESTAMP N_("The time, in seconds since the Unix Epoch, that the connection was last _successfully_ fully activated. NetworkManager updates the connection timestamp periodically when the connection is active to ensure that an active connection has the latest timestamp. The property is only meant for reading (changes to this property will not be preserved).") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_TYPE N_("Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, \"802-3-ethernet\" or \"802-11-wireless\" or \"bluetooth\", etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, \"vpn\" or \"bridge\", etc).") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_UUID N_("A universally unique identifier for the connection, for example generated with libuuid. It should be assigned when the connection is created, and never changed as long as the connection still applies to the same network. For example, it should not be changed when the \"id\" property or NMSettingIP4Config changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband network provider, or \"type\" property changes. The UUID must be in the format \"2815492f-7e56-435e-b2e9-246bd7cdc664\" (ie, contains only hexadecimal characters and \"-\").") @@ -197,7 +197,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_TTL N_("The TTL to assign to tunneled packets. 0 is a special value meaning that packets inherit the TTL value.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ADDRESSES N_("Array of IP addresses.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DAD_TIMEOUT N_("Timeout in milliseconds used to check for the presence of duplicate IP addresses on the network. If an address conflict is detected, the activation will fail. A zero value means that no duplicate address detection is performed, -1 means the default value (either configuration ipvx.dad-timeout override or zero). A value greater than zero is a timeout in milliseconds. The property is currently implemented only for IPv4.") -#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID N_("A string sent to the DHCP server to identify the local machine which the DHCP server may use to customize the DHCP lease and options. When the property is a hex string ('aa:bb:cc') it is interpreted as a binary client ID, in which case the first byte is assumed to be the 'type' field as per RFC 2132 section 9.14 and the remaining bytes may be an hardware address (e.g. '01:xx:xx:xx:xx:xx:xx' where 1 is the Ethernet ARP type and the rest is a MAC address). If the property is not a hex string it is considered as a non-hardware-address client ID and the 'type' field is set to 0. The special values \"mac\" and \"perm-mac\" are supported, which use the current or permanent MAC address of the device to generate a client identifier with type ethernet (01). Currently, these options only work for ethernet type of links. The special value \"stable\" is supported to generate a type 0 client identifier based on the stable-id (see connection.stable-id) and a per-host key. If unset, a globally configured default is used. If still unset, the client-id from the last lease is reused.") +#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID N_("A string sent to the DHCP server to identify the local machine which the DHCP server may use to customize the DHCP lease and options. When the property is a hex string ('aa:bb:cc') it is interpreted as a binary client ID, in which case the first byte is assumed to be the 'type' field as per RFC 2132 section 9.14 and the remaining bytes may be an hardware address (e.g. '01:xx:xx:xx:xx:xx:xx' where 1 is the Ethernet ARP type and the rest is a MAC address). If the property is not a hex string it is considered as a non-hardware-address client ID and the 'type' field is set to 0. The special values \"mac\" and \"perm-mac\" are supported, which use the current or permanent MAC address of the device to generate a client identifier with type ethernet (01). Currently, these options only work for ethernet type of links. The special value \"duid\" generates a RFC4361-compliant client identifier based on a hash of the interface name as IAID and /etc/machine-id. The special value \"stable\" is supported to generate a type 0 client identifier based on the stable-id (see connection.stable-id) and a per-host key. If you set the stable-id, you may want to include the \"${DEVICE}\" or \"${MAC}\" specifier to get a per-device key. If unset, a globally configured default is used. If still unset, the default depends on the DHCP plugin.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_FQDN N_("If the \"dhcp-send-hostname\" property is TRUE, then the specified FQDN will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-hostname\" are mutually exclusive and cannot be set at the same time.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME N_("If the \"dhcp-send-hostname\" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-fqdn\" are mutually exclusive and cannot be set at the same time.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME N_("If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the \"dhcp-hostname\" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.") @@ -218,7 +218,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE N_("Configure method for creating the address for use with RFC4862 IPv6 Stateless Address Autoconfiguration. The permitted values are: NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 (0) or NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY (1). If the property is set to EUI64, the addresses will be generated using the interface tokens derived from hardware address. This makes the host part of the address to stay constant, making it possible to track host's presence when it changes networks. The address changes when the interface hardware is replaced. The value of stable-privacy enables use of cryptographically secure hash of a secret host-specific key along with the connection's stable-id and the network address as specified by RFC7217. This makes it impossible to use the address track host's presence, and makes the address stable when the network interface hardware is replaced. On D-Bus, the absence of an addr-gen-mode setting equals enabling stable-privacy. For keyfile plugin, the absence of the setting on disk means EUI64 so that the property doesn't change on upgrade from older versions. Note that this setting is distinct from the Privacy Extensions as configured by \"ip6-privacy\" property and it does not affect the temporary addresses configured with this option.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ADDRESSES N_("Array of IP addresses.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DAD_TIMEOUT N_("Timeout in milliseconds used to check for the presence of duplicate IP addresses on the network. If an address conflict is detected, the activation will fail. A zero value means that no duplicate address detection is performed, -1 means the default value (either configuration ipvx.dad-timeout override or zero). A value greater than zero is a timeout in milliseconds. The property is currently implemented only for IPv4.") -#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_DUID N_("A string containing the DHCPv6 Unique Identifier (DUID) used by the dhcp client to identify itself to DHCPv6 servers (RFC 3315). The DUID is carried in the Client Identifier option. If the property is a hex string ('aa:bb:cc') it is interpreted as a binary DUID and filled as an opaque value in the Client Identifier option. The special value \"lease\" will retrieve the DUID previously used from the lease file belonging to the connection. If no DUID is found and \"dhclient\" is the configured dhcp client, the DUID is searched in the system-wide dhclient lease file. If still no DUID is found, or another dhcp client is used, a global and permanent DUID-UUID (RFC 6355) will be generated based on the machine-id. The special values \"llt\" and \"ll\" will generate a DUID of type LLT or LL (see RFC 3315) based on the current MAC address of the device. In order to try providing a stable DUID-LLT, the time field will contain a constant timestamp that is used globally (for all profiles) and persisted to disk. The special values \"stable-llt\", \"stable-ll\" and \"stable-uuid\" will generate a DUID of the corresponding type, derived from the connection's stable-id and a per-host unique key. So, the link-layer address of \"stable-ll\" and \"stable-llt\" will be a generated address derived from the stable id. The DUID-LLT time value in the \"stable-llt\" option will be picked among a static timespan of three years (the upper bound of the interval is the same constant timestamp used in \"llt\"). When the property is unset, the global value provided for \"ipv6.dhcp-duid\" is used. If no global value is provided, the default \"lease\" value is assumed.") +#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_DUID N_("A string containing the DHCPv6 Unique Identifier (DUID) used by the dhcp client to identify itself to DHCPv6 servers (RFC 3315). The DUID is carried in the Client Identifier option. If the property is a hex string ('aa:bb:cc') it is interpreted as a binary DUID and filled as an opaque value in the Client Identifier option. The special value \"lease\" will retrieve the DUID previously used from the lease file belonging to the connection. If no DUID is found and \"dhclient\" is the configured dhcp client, the DUID is searched in the system-wide dhclient lease file. If still no DUID is found, or another dhcp client is used, a global and permanent DUID-UUID (RFC 6355) will be generated based on the machine-id. The special values \"llt\" and \"ll\" will generate a DUID of type LLT or LL (see RFC 3315) based on the current MAC address of the device. In order to try providing a stable DUID-LLT, the time field will contain a constant timestamp that is used globally (for all profiles) and persisted to disk. The special values \"stable-llt\", \"stable-ll\" and \"stable-uuid\" will generate a DUID of the corresponding type, derived from the connection's stable-id and a per-host unique key. You may want to include the \"${DEVICE}\" or \"${MAC}\" specifier in the stable-id, in case this profile gets activated on multiple devices. So, the link-layer address of \"stable-ll\" and \"stable-llt\" will be a generated address derived from the stable id. The DUID-LLT time value in the \"stable-llt\" option will be picked among a static timespan of three years (the upper bound of the interval is the same constant timestamp used in \"llt\"). When the property is unset, the global value provided for \"ipv6.dhcp-duid\" is used. If no global value is provided, the default \"lease\" value is assumed.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME N_("If the \"dhcp-send-hostname\" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-fqdn\" are mutually exclusive and cannot be set at the same time.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_SEND_HOSTNAME N_("If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the \"dhcp-hostname\" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds.") @@ -296,8 +296,8 @@ #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.") -#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\". The \"vlans\" attribute is represented as a semicolor-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_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_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.") #define DESCRIBE_DOC_NM_SETTING_TEAM_CONFIG N_("The JSON configuration for the team network interface. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details.") diff --git a/clients/common/settings-docs.h.in b/clients/common/settings-docs.h.in index f07769c0..bc56edae 100644 --- a/clients/common/settings-docs.h.in +++ b/clients/common/settings-docs.h.in @@ -144,7 +144,7 @@ #define DESCRIBE_DOC_NM_SETTING_CONNECTION_READ_ONLY N_("FALSE if the connection can be modified using the provided settings service's D-Bus interface with the right privileges, or TRUE if the connection is read-only and cannot be modified.") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_SECONDARIES N_("List of connection UUIDs that should be activated when the base connection itself is activated. Currently only VPN connections are supported.") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_SLAVE_TYPE N_("Setting name of the device type of this slave's master connection (eg, \"bond\"), or NULL if this connection is not a slave.") -#define DESCRIBE_DOC_NM_SETTING_CONNECTION_STABLE_ID N_("This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are \"${CONNECTION}\", \"${DEVICE}\", \"${BOOT}\", \"${RANDOM}\". These effectively create unique IDs per-connection, per-device, per-boot, or every time. Note that \"${DEVICE}\" corresponds the the interface name of the device. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as \"$$\". For example, set it to \"${CONNECTION}-${BOOT}-${DEVICE}\" to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is similar to \"${CONNECTION}\" and uses a unique, fixed ID for the connection.") +#define DESCRIBE_DOC_NM_SETTING_CONNECTION_STABLE_ID N_("This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are \"${CONNECTION}\", \"${DEVICE}\", \"${MAC}\", \"${BOOT}\", \"${RANDOM}\". These effectively create unique IDs per-connection, per-device, per-boot, or every time. Note that \"${DEVICE}\" corresponds the the interface name of the device and \"${MAC}\" is the permanent MAC address of the device. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as \"$$\". For example, set it to \"${CONNECTION}-${BOOT}-${DEVICE}\" to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is similar to \"${CONNECTION}\" and uses a unique, fixed ID for the connection.") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_TIMESTAMP N_("The time, in seconds since the Unix Epoch, that the connection was last _successfully_ fully activated. NetworkManager updates the connection timestamp periodically when the connection is active to ensure that an active connection has the latest timestamp. The property is only meant for reading (changes to this property will not be preserved).") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_TYPE N_("Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, \"802-3-ethernet\" or \"802-11-wireless\" or \"bluetooth\", etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, \"vpn\" or \"bridge\", etc).") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_UUID N_("A universally unique identifier for the connection, for example generated with libuuid. It should be assigned when the connection is created, and never changed as long as the connection still applies to the same network. For example, it should not be changed when the \"id\" property or NMSettingIP4Config changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband network provider, or \"type\" property changes. The UUID must be in the format \"2815492f-7e56-435e-b2e9-246bd7cdc664\" (ie, contains only hexadecimal characters and \"-\").") @@ -197,7 +197,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_TTL N_("The TTL to assign to tunneled packets. 0 is a special value meaning that packets inherit the TTL value.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ADDRESSES N_("Array of IP addresses.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DAD_TIMEOUT N_("Timeout in milliseconds used to check for the presence of duplicate IP addresses on the network. If an address conflict is detected, the activation will fail. A zero value means that no duplicate address detection is performed, -1 means the default value (either configuration ipvx.dad-timeout override or zero). A value greater than zero is a timeout in milliseconds. The property is currently implemented only for IPv4.") -#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID N_("A string sent to the DHCP server to identify the local machine which the DHCP server may use to customize the DHCP lease and options. When the property is a hex string ('aa:bb:cc') it is interpreted as a binary client ID, in which case the first byte is assumed to be the 'type' field as per RFC 2132 section 9.14 and the remaining bytes may be an hardware address (e.g. '01:xx:xx:xx:xx:xx:xx' where 1 is the Ethernet ARP type and the rest is a MAC address). If the property is not a hex string it is considered as a non-hardware-address client ID and the 'type' field is set to 0. The special values \"mac\" and \"perm-mac\" are supported, which use the current or permanent MAC address of the device to generate a client identifier with type ethernet (01). Currently, these options only work for ethernet type of links. The special value \"stable\" is supported to generate a type 0 client identifier based on the stable-id (see connection.stable-id) and a per-host key. If unset, a globally configured default is used. If still unset, the client-id from the last lease is reused.") +#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID N_("A string sent to the DHCP server to identify the local machine which the DHCP server may use to customize the DHCP lease and options. When the property is a hex string ('aa:bb:cc') it is interpreted as a binary client ID, in which case the first byte is assumed to be the 'type' field as per RFC 2132 section 9.14 and the remaining bytes may be an hardware address (e.g. '01:xx:xx:xx:xx:xx:xx' where 1 is the Ethernet ARP type and the rest is a MAC address). If the property is not a hex string it is considered as a non-hardware-address client ID and the 'type' field is set to 0. The special values \"mac\" and \"perm-mac\" are supported, which use the current or permanent MAC address of the device to generate a client identifier with type ethernet (01). Currently, these options only work for ethernet type of links. The special value \"duid\" generates a RFC4361-compliant client identifier based on a hash of the interface name as IAID and /etc/machine-id. The special value \"stable\" is supported to generate a type 0 client identifier based on the stable-id (see connection.stable-id) and a per-host key. If you set the stable-id, you may want to include the \"${DEVICE}\" or \"${MAC}\" specifier to get a per-device key. If unset, a globally configured default is used. If still unset, the default depends on the DHCP plugin.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_FQDN N_("If the \"dhcp-send-hostname\" property is TRUE, then the specified FQDN will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-hostname\" are mutually exclusive and cannot be set at the same time.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME N_("If the \"dhcp-send-hostname\" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-fqdn\" are mutually exclusive and cannot be set at the same time.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME N_("If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the \"dhcp-hostname\" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.") @@ -218,7 +218,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE N_("Configure method for creating the address for use with RFC4862 IPv6 Stateless Address Autoconfiguration. The permitted values are: NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 (0) or NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY (1). If the property is set to EUI64, the addresses will be generated using the interface tokens derived from hardware address. This makes the host part of the address to stay constant, making it possible to track host's presence when it changes networks. The address changes when the interface hardware is replaced. The value of stable-privacy enables use of cryptographically secure hash of a secret host-specific key along with the connection's stable-id and the network address as specified by RFC7217. This makes it impossible to use the address track host's presence, and makes the address stable when the network interface hardware is replaced. On D-Bus, the absence of an addr-gen-mode setting equals enabling stable-privacy. For keyfile plugin, the absence of the setting on disk means EUI64 so that the property doesn't change on upgrade from older versions. Note that this setting is distinct from the Privacy Extensions as configured by \"ip6-privacy\" property and it does not affect the temporary addresses configured with this option.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ADDRESSES N_("Array of IP addresses.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DAD_TIMEOUT N_("Timeout in milliseconds used to check for the presence of duplicate IP addresses on the network. If an address conflict is detected, the activation will fail. A zero value means that no duplicate address detection is performed, -1 means the default value (either configuration ipvx.dad-timeout override or zero). A value greater than zero is a timeout in milliseconds. The property is currently implemented only for IPv4.") -#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_DUID N_("A string containing the DHCPv6 Unique Identifier (DUID) used by the dhcp client to identify itself to DHCPv6 servers (RFC 3315). The DUID is carried in the Client Identifier option. If the property is a hex string ('aa:bb:cc') it is interpreted as a binary DUID and filled as an opaque value in the Client Identifier option. The special value \"lease\" will retrieve the DUID previously used from the lease file belonging to the connection. If no DUID is found and \"dhclient\" is the configured dhcp client, the DUID is searched in the system-wide dhclient lease file. If still no DUID is found, or another dhcp client is used, a global and permanent DUID-UUID (RFC 6355) will be generated based on the machine-id. The special values \"llt\" and \"ll\" will generate a DUID of type LLT or LL (see RFC 3315) based on the current MAC address of the device. In order to try providing a stable DUID-LLT, the time field will contain a constant timestamp that is used globally (for all profiles) and persisted to disk. The special values \"stable-llt\", \"stable-ll\" and \"stable-uuid\" will generate a DUID of the corresponding type, derived from the connection's stable-id and a per-host unique key. So, the link-layer address of \"stable-ll\" and \"stable-llt\" will be a generated address derived from the stable id. The DUID-LLT time value in the \"stable-llt\" option will be picked among a static timespan of three years (the upper bound of the interval is the same constant timestamp used in \"llt\"). When the property is unset, the global value provided for \"ipv6.dhcp-duid\" is used. If no global value is provided, the default \"lease\" value is assumed.") +#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_DUID N_("A string containing the DHCPv6 Unique Identifier (DUID) used by the dhcp client to identify itself to DHCPv6 servers (RFC 3315). The DUID is carried in the Client Identifier option. If the property is a hex string ('aa:bb:cc') it is interpreted as a binary DUID and filled as an opaque value in the Client Identifier option. The special value \"lease\" will retrieve the DUID previously used from the lease file belonging to the connection. If no DUID is found and \"dhclient\" is the configured dhcp client, the DUID is searched in the system-wide dhclient lease file. If still no DUID is found, or another dhcp client is used, a global and permanent DUID-UUID (RFC 6355) will be generated based on the machine-id. The special values \"llt\" and \"ll\" will generate a DUID of type LLT or LL (see RFC 3315) based on the current MAC address of the device. In order to try providing a stable DUID-LLT, the time field will contain a constant timestamp that is used globally (for all profiles) and persisted to disk. The special values \"stable-llt\", \"stable-ll\" and \"stable-uuid\" will generate a DUID of the corresponding type, derived from the connection's stable-id and a per-host unique key. You may want to include the \"${DEVICE}\" or \"${MAC}\" specifier in the stable-id, in case this profile gets activated on multiple devices. So, the link-layer address of \"stable-ll\" and \"stable-llt\" will be a generated address derived from the stable id. The DUID-LLT time value in the \"stable-llt\" option will be picked among a static timespan of three years (the upper bound of the interval is the same constant timestamp used in \"llt\"). When the property is unset, the global value provided for \"ipv6.dhcp-duid\" is used. If no global value is provided, the default \"lease\" value is assumed.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME N_("If the \"dhcp-send-hostname\" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-fqdn\" are mutually exclusive and cannot be set at the same time.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_SEND_HOSTNAME N_("If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the \"dhcp-hostname\" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds.") @@ -296,8 +296,8 @@ #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.") -#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\". The \"vlans\" attribute is represented as a semicolor-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_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_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.") #define DESCRIBE_DOC_NM_SETTING_TEAM_CONFIG N_("The JSON configuration for the team network interface. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details.") -- cgit 1.3.0-6-gf8a5 From 9a6dcbf895f9da01768e64b73cec88c16157d91e Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Tue, 26 Mar 2019 23:25:23 +0100 Subject: New upstream version 1.16.0 --- clients/common/meson.build | 18 +- clients/common/nm-client-utils.c | 3 +- clients/common/nm-client-utils.h | 7 + clients/common/nm-meta-setting-desc.c | 695 ++++++++++--------- clients/common/nm-meta-setting-desc.h | 5 +- clients/common/nm-polkit-listener.c | 3 +- clients/common/nm-polkit-listener.h | 4 +- clients/common/nm-secret-agent-simple.c | 1155 ++++++++++++++++++++++--------- clients/common/nm-secret-agent-simple.h | 42 +- clients/common/nm-vpn-helpers.c | 569 ++++++++++++++- clients/common/nm-vpn-helpers.h | 3 + clients/common/settings-docs.h | 27 +- clients/common/settings-docs.h.in | 27 +- clients/common/tests/meson.build | 4 +- clients/common/tests/test-general.c | 96 +++ clients/common/tests/wg-test0.conf | 18 + clients/common/tests/wg-test1.conf | 3 + clients/common/tests/wg-test2.conf | 8 + clients/common/tests/wg-test3.conf | 3 + 19 files changed, 1978 insertions(+), 712 deletions(-) create mode 100644 clients/common/tests/wg-test0.conf create mode 100644 clients/common/tests/wg-test1.conf create mode 100644 clients/common/tests/wg-test2.conf create mode 100644 clients/common/tests/wg-test3.conf (limited to 'clients/common') diff --git a/clients/common/meson.build b/clients/common/meson.build index 30fd2cfa..b4b6bcac 100644 --- a/clients/common/meson.build +++ b/clients/common/meson.build @@ -4,7 +4,7 @@ nm_polkit_listener = files('nm-polkit-listener.c') deps = [ libnm_dep, - nm_core_dep + nm_core_dep, ] cflags = clients_cflags + [ @@ -13,18 +13,18 @@ cflags = clients_cflags + [ libnmc_base = static_library( 'nmc-base', - sources: shared_files_clients_common + files( + sources: files( 'nm-client-utils.c', 'nm-secret-agent-simple.c', 'nm-vpn-helpers.c', ), dependencies: deps, - c_args: cflags + c_args: cflags, ) libnmc_base_dep = declare_dependency( include_directories: common_inc, - link_with: libnmc_base + link_with: libnmc_base, ) settings_docs = 'settings-docs.h' @@ -34,7 +34,7 @@ if enable_introspection settings_docs, input: nm_property_docs, output: settings_docs, - command: [xsltproc, '--output', '@OUTPUT@', join_paths(meson.current_source_dir(), 'settings-docs.xsl'), '@INPUT@'] + command: [xsltproc, '--output', '@OUTPUT@', join_paths(meson.current_source_dir(), 'settings-docs.xsl'), '@INPUT@'], ) test( @@ -46,7 +46,7 @@ else settings_docs_source = configure_file( input: settings_docs + '.in', output: settings_docs, - configuration: configuration_data() + configuration: configuration_data(), ) endif @@ -54,17 +54,17 @@ libnmc = static_library( 'nmc', sources: files( 'nm-meta-setting-access.c', - 'nm-meta-setting-desc.c' + 'nm-meta-setting-desc.c', ) + shared_nm_meta_setting_c + shared_nm_ethtool_utils_c + [settings_docs_source], dependencies: deps, c_args: cflags, link_with: libnmc_base, - link_depends: settings_docs_source + link_depends: settings_docs_source, ) libnmc_dep = declare_dependency( include_directories: common_inc, - link_with: libnmc + link_with: libnmc, ) if (enable_introspection or enable_nmtui) and enable_tests diff --git a/clients/common/nm-client-utils.c b/clients/common/nm-client-utils.c index 8c7553d8..1241131a 100644 --- a/clients/common/nm-client-utils.c +++ b/clients/common/nm-client-utils.c @@ -348,10 +348,11 @@ NM_UTILS_LOOKUP_STR_DEFINE (nmc_device_reason_to_string, NMDeviceStateReason, NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_NEW_ACTIVATION, N_("New connection activation was enqueued")), NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_PARENT_CHANGED, N_("The device's parent changed")), NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED, N_("The device parent's management changed")), - NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_OVSDB_FAILED, N_("OpenVSwitch database connection failed")), + NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_OVSDB_FAILED, N_("Open vSwitch database connection failed")), NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE, N_("A duplicate IP address was detected")), NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED, N_("The selected IP method is not supported")), NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED, N_("Failed to configure SR-IOV parameters")), + NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_PEER_NOT_FOUND, N_("The Wi-Fi P2P peer could not be found")), ) NM_UTILS_LOOKUP_STR_DEFINE (nm_active_connection_state_reason_to_string, NMActiveConnectionStateReason, diff --git a/clients/common/nm-client-utils.h b/clients/common/nm-client-utils.h index 9d818873..a5bc05fa 100644 --- a/clients/common/nm-client-utils.h +++ b/clients/common/nm-client-utils.h @@ -24,6 +24,13 @@ #include "nm-active-connection.h" #include "nm-device.h" + +#define nm_auto_unref_ip_address nm_auto (_nm_ip_address_unref) +NM_AUTO_DEFINE_FCN0 (NMIPAddress *, _nm_ip_address_unref, nm_ip_address_unref) + +#define nm_auto_unref_wgpeer nm_auto (_nm_auto_unref_wgpeer) +NM_AUTO_DEFINE_FCN0 (NMWireGuardPeer *, _nm_auto_unref_wgpeer, nm_wireguard_peer_unref) + const NMObject **nmc_objects_sort_by_path (const NMObject *const*objs, gssize len); const char *nmc_string_is_valid (const char *input, const char **allowed, GError **error); diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index d13ee4ce..6e35228a 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -117,7 +117,6 @@ _parse_ip_route (int family, { const int MAX_PREFIX = (family == AF_INET) ? 32 : 128; const char *next_hop = NULL; - const char *canon_dest; int prefix; NMIPRoute *route = NULL; GError *local = NULL; @@ -229,18 +228,6 @@ _parse_ip_route (int family, return NULL; } - /* We don't accept default routes as NetworkManager handles it - * itself. But we have to check this after @route has normalized the - * dest string. - */ - canon_dest = nm_ip_route_get_dest (route); - if (!strcmp (canon_dest, "0.0.0.0") || !strcmp (canon_dest, "::")) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, - _("default route cannot be added (NetworkManager handles it by itself)")); - g_clear_pointer (&route, nm_ip_route_unref); - return NULL; - } - if (attrs) { GHashTableIter iter; char *name; @@ -285,13 +272,14 @@ _dump_team_link_watcher (NMTeamLinkWatcher *watcher) DUMP_WATCHER_INT (w_dump, watcher, "init-wait", init_wait); DUMP_WATCHER_INT (w_dump, watcher, "interval", interval); DUMP_WATCHER_INT (w_dump, watcher, "missed-max", missed_max); -#undef DUMP_WATCHER_INT g_string_append_printf (w_dump, " target-host=%s", nm_team_link_watcher_get_target_host (watcher)); if (nm_streq (name, NM_TEAM_LINK_WATCHER_NSNA_PING)) return g_string_free (w_dump, FALSE); + DUMP_WATCHER_INT (w_dump, watcher, "vlanid", vlanid); +#undef DUMP_WATCHER_INT g_string_append_printf (w_dump, " source-host=%s", nm_team_link_watcher_get_source_host (watcher)); flags = nm_team_link_watcher_get_flags (watcher); @@ -313,7 +301,7 @@ _parse_team_link_watcher (const char *str, gs_free char *str_clean = NULL; guint i; gs_free const char *name = NULL; - int val1 = 0, val2 = 0, val3 = 3; + int val1 = 0, val2 = 0, val3 = 3, val4 = -1; gs_free const char *target_host = NULL; gs_free const char *source_host = NULL; NMTeamLinkWatcherArpPingFlags flags = 0; @@ -358,6 +346,8 @@ _parse_team_link_watcher (const char *str, val2 = _nm_utils_ascii_str_to_int64 (pair[1], 10, 0, G_MAXINT32, -1); else if (nm_streq (pair[0], "missed-max")) val3 = _nm_utils_ascii_str_to_int64 (pair[1], 10, 0, G_MAXINT32, -1); + else if (nm_streq (pair[0], "vlanid")) + val4 = _nm_utils_ascii_str_to_int64 (pair[1], 10, -1, 4094, -2); else if (nm_streq (pair[0], "target-host")) target_host = g_strdup (pair[1]); else if (nm_streq (pair[0], "source-host")) @@ -382,6 +372,11 @@ _parse_team_link_watcher (const char *str, "value is not a valid number [0, MAXINT]"); return NULL; } + if (val4 < -1) { + g_set_error (error, 1, 0, "'%s' is not valid: %s", watcherv[i], + "value is not a valid number [-1, 4094]"); + return NULL; + } } if (nm_streq0 (name, NM_TEAM_LINK_WATCHER_ETHTOOL)) @@ -389,7 +384,7 @@ _parse_team_link_watcher (const char *str, else if (nm_streq0 (name, NM_TEAM_LINK_WATCHER_NSNA_PING)) return nm_team_link_watcher_new_nsna_ping (val1, val2, val3, target_host, error); else if (nm_streq0 (name, NM_TEAM_LINK_WATCHER_ARP_PING)) - return nm_team_link_watcher_new_arp_ping (val1, val2, val3, target_host, source_host, flags, error); + return nm_team_link_watcher_new_arp_ping2 (val1, val2, val3, val4, target_host, source_host, flags, error); if (!name) g_set_error (error, 1, 0, "link watcher name missing"); @@ -1518,18 +1513,16 @@ bytes_to_string (GBytes *bytes) { const guint8 *data; gsize len; - GString *cert = NULL; - int i; if (!bytes) return NULL; - data = g_bytes_get_data (bytes, &len); - cert = g_string_new (NULL); - for (i = 0; i < len; i++) - g_string_append_printf (cert, "%02X", data[i]); - - return g_string_free (cert, FALSE); + data = g_bytes_get_data (bytes, &len); + return nm_utils_bin2hexstr_full (data, + len, + '\0', + TRUE, + NULL); } static char * @@ -1948,26 +1941,36 @@ nmc_util_is_domain (const char *domain) } static gboolean -nmc_property_set_bytes (NMSetting *setting, const char *prop, const char *value, GError **error) +_set_fcn_gobject_bytes (ARGS_SET_FCN) { - gs_free char *val_strip = NULL; + gs_free char *val_strip_free = NULL; gs_free const char **strv = NULL; + const char *val_strip; const char **iter; - GBytes *bytes; - GByteArray *array = NULL; - gboolean success = TRUE; + gs_unref_bytes GBytes *bytes = NULL; + GByteArray *array; nm_assert (!error || !*error); - val_strip = g_strstrip (g_strdup (value)); + val_strip = nm_strstrip_avoid_copy (value, &val_strip_free); /* First try hex string in the format of AAbbCCDd */ bytes = nm_utils_hexstr2bin (val_strip); if (bytes) goto done; + if ( !property_info->property_typ_data + || !property_info->property_typ_data->subtype.gobject_bytes.legacy_format) { + if (value && value[0]) { + g_set_error_literal (error, 1, 0, _("not a valid hex-string")); + return FALSE; + } + /* accept the empty word to reset the property to %NULL. */ + goto done; + } + /* Otherwise, consider the following format: AA b 0xCc D */ - strv = nm_utils_strsplit_set (val_strip, " \t", FALSE); + strv = nm_utils_strsplit_set (value, " \t", FALSE); array = g_byte_array_sized_new (NM_PTRARRAY_LEN (strv)); for (iter = strv; iter && *iter; iter++) { int v; @@ -1977,8 +1980,7 @@ nmc_property_set_bytes (NMSetting *setting, const char *prop, const char *value, if (v == -1) { g_set_error (error, 1, 0, _("'%s' is not a valid hex character"), *iter); g_byte_array_free (array, TRUE); - success = FALSE; - goto done; + return FALSE; } v8 = v; g_byte_array_append (array, &v8, 1); @@ -1986,13 +1988,8 @@ nmc_property_set_bytes (NMSetting *setting, const char *prop, const char *value, bytes = g_byte_array_free_to_bytes (array); done: - if (success) - g_object_set (setting, prop, bytes, NULL); - - if (bytes) - g_bytes_unref (bytes); - - return success; + g_object_set (setting, property_info->property_name, bytes, NULL); + return TRUE; } /*****************************************************************************/ @@ -2108,14 +2105,16 @@ _get_fcn_802_1x_phase2_client_cert (ARGS_GET_FCN) } static gconstpointer -_get_fcn_802_1x_password_raw (ARGS_GET_FCN) +_get_fcn_gobject_bytes (ARGS_GET_FCN) { - NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting); + gs_unref_bytes GBytes *bytes = NULL; char *str; RETURN_UNSUPPORTED_GET_TYPE (); - str = bytes_to_string (nm_setting_802_1x_get_password_raw (s_8021X)); + g_object_get (setting, property_info->property_name, &bytes, NULL); + + str = bytes_to_string (bytes); NM_SET_OUT (out_is_default, !str || !str[0]); RETURN_STR_TO_FREE (str); } @@ -2333,12 +2332,6 @@ DEFINE_SETTER_PRIV_KEY (_set_fcn_802_1x_phase2_private_key, nm_setting_802_1x_get_phase2_private_key_password, nm_setting_802_1x_set_phase2_private_key) -static gboolean -_set_fcn_802_1x_password_raw (ARGS_SET_FCN) -{ - return nmc_property_set_bytes (setting, property_info->property_name, value, error); -} - static gconstpointer _get_fcn_bond_options (ARGS_GET_FCN) { @@ -4847,16 +4840,6 @@ _gobject_enum_pre_set_notify_fcn_wireless_security_wep_key_type (const NMMetaPro } } -static const char * -_validate_fcn_wireless_security_psk (const char *value, char **out_to_free, GError **error) -{ - if (!nm_utils_wpa_psk_valid (value)) { - g_set_error (error, 1, 0, _("'%s' is not a valid PSK"), value); - return NULL; - } - return value; -} - /*****************************************************************************/ static gconstpointer @@ -5071,6 +5054,11 @@ static const NMMetaPropertyType _pt_gobject_mtu = { .set_fcn = _set_fcn_gobject_mtu, }; +static const NMMetaPropertyType _pt_gobject_bytes = { + .get_fcn = _get_fcn_gobject_bytes, + .set_fcn = _set_fcn_gobject_bytes, +}; + static const NMMetaPropertyType _pt_gobject_mac = { .get_fcn = _get_fcn_gobject, .set_fcn = _set_fcn_gobject_mac, @@ -5121,10 +5109,8 @@ static const NMMetaPropertyType _pt_ethtool = { #define PROPERTY_INFO_WITH_DESC(name, ...) \ PROPERTY_INFO (name, DESCRIBE_DOC_##name, ##__VA_ARGS__) -#define VALUES_STATIC(...) (((const char *[]) { __VA_ARGS__, NULL })) - -#define ENUM_VALUE_INFOS(...) (((const NMUtilsEnumValueInfo []) { __VA_ARGS__, { 0 } })) -#define INT_VALUE_INFOS(...) (((const NMMetaUtilsIntValueInfo []) { __VA_ARGS__, { 0 } })) +#define ENUM_VALUE_INFOS(...) (((const NMUtilsEnumValueInfo []) { __VA_ARGS__ { .nick = NULL, }, })) +#define INT_VALUE_INFOS(...) (((const NMMetaUtilsIntValueInfo []) { __VA_ARGS__ { .nick = NULL, }, })) #define GET_FCN_WITH_DEFAULT(type, func) \ /* macro that returns @func as const (gboolean(*)(NMSetting*)) type, but checks @@ -5166,12 +5152,25 @@ static const NMMetaPropertyType _pt_ethtool = { .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, \ .value_infos = INT_VALUE_INFOS ( \ { \ - .value = -1, \ + .value.i64 = -1, \ .nick = "unset", \ - } \ + }, \ ), \ ), +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_6LOWPAN +static const NMMetaPropertyInfo *const property_infos_6LOWPAN[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_6LOWPAN_PARENT, + .is_cli_option = TRUE, + .property_alias = "dev", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("IEEE 802.15.4 (WPAN) parent device or connection UUID"), + .property_type = &_pt_gobject_string, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE #define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_802_1X static const NMMetaPropertyInfo *const property_infos_802_1X[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_EAP, @@ -5181,7 +5180,7 @@ static const NMMetaPropertyInfo *const property_infos_802_1X[] = { .remove_fcn = _remove_fcn_802_1x_eap, ), .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("leap", "md5", "tls", "peap", "ttls", "sim", "fast", "pwd"), + .values_static = NM_MAKE_STRV ("leap", "md5", "tls", "peap", "ttls", "sim", "fast", "pwd"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_IDENTITY, @@ -5248,19 +5247,19 @@ static const NMMetaPropertyInfo *const property_infos_802_1X[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE1_PEAPVER, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("0", "1"), + .values_static = NM_MAKE_STRV ("0", "1"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE1_PEAPLABEL, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("0", "1"), + .values_static = NM_MAKE_STRV ("0", "1"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("0", "1", "2", "3"), + .values_static = NM_MAKE_STRV ("0", "1", "2", "3"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE1_AUTH_FLAGS, @@ -5275,13 +5274,13 @@ static const NMMetaPropertyInfo *const property_infos_802_1X[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_AUTH, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5", "tls"), + .values_static = NM_MAKE_STRV ("pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5", "tls"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_AUTHEAP, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("md5", "mschapv2", "otp", "gtc", "tls"), + .values_static = NM_MAKE_STRV ("md5", "mschapv2", "otp", "gtc", "tls"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_CA_CERT, @@ -5355,9 +5354,9 @@ static const NMMetaPropertyInfo *const property_infos_802_1X[] = { "(with optional 0x/0X prefix, and optional leading 0).\n\n" "Examples: ab0455a6ea3a74C2\n" " ab 4 55 0xa6 ea 3a 74 C2\n"), - .property_type = DEFINE_PROPERTY_TYPE ( - .get_fcn = _get_fcn_802_1x_password_raw, - .set_fcn = _set_fcn_802_1x_password_raw, + .property_type = &_pt_gobject_bytes, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_bytes, + .legacy_format = TRUE, ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PASSWORD_RAW_FLAGS, @@ -5443,9 +5442,9 @@ static const NMMetaPropertyInfo *const property_infos_ADSL[] = { .def_hint = NM_META_TEXT_PROMPT_ADSL_PROTO_CHOICES, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC (NM_SETTING_ADSL_PROTOCOL_PPPOA, - NM_SETTING_ADSL_PROTOCOL_PPPOE, - NM_SETTING_ADSL_PROTOCOL_IPOATM), + .values_static = NM_MAKE_STRV (NM_SETTING_ADSL_PROTOCOL_PPPOA, + NM_SETTING_ADSL_PROTOCOL_PPPOE, + NM_SETTING_ADSL_PROTOCOL_IPOATM), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_ADSL_ENCAPSULATION, @@ -5455,8 +5454,8 @@ static const NMMetaPropertyInfo *const property_infos_ADSL[] = { .def_hint = NM_META_TEXT_PROMPT_ADSL_ENCAP_CHOICES, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC (NM_SETTING_ADSL_ENCAPSULATION_VCMUX, - NM_SETTING_ADSL_ENCAPSULATION_LLC), + .values_static = NM_MAKE_STRV (NM_SETTING_ADSL_ENCAPSULATION_VCMUX, + NM_SETTING_ADSL_ENCAPSULATION_LLC), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_ADSL_VPI, @@ -5484,9 +5483,9 @@ static const NMMetaPropertyInfo *const property_infos_BLUETOOTH[] = { .def_hint = NM_META_TEXT_PROMPT_BT_TYPE_CHOICES, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC (NM_SETTING_BLUETOOTH_TYPE_DUN, - NM_SETTING_BLUETOOTH_TYPE_PANU, - NM_SETTING_BLUETOOTH_TYPE_NAP), + .values_static = NM_MAKE_STRV (NM_SETTING_BLUETOOTH_TYPE_DUN, + NM_SETTING_BLUETOOTH_TYPE_PANU, + NM_SETTING_BLUETOOTH_TYPE_NAP), ), ), NULL @@ -5680,13 +5679,13 @@ static const NMMetaPropertyInfo *const property_infos_CONNECTION[] = { .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, .value_infos = INT_VALUE_INFOS ( { - .value = -1, + .value.i64 = -1, .nick = "default", }, { - .value = 0, + .value.i64 = 0, .nick = "forever", - } + }, ), ), ), @@ -5739,11 +5738,11 @@ static const NMMetaPropertyInfo *const property_infos_CONNECTION[] = { .inf_flags = NM_META_PROPERTY_INF_FLAG_DONT_ASK, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC (NM_SETTING_BOND_SETTING_NAME, - NM_SETTING_BRIDGE_SETTING_NAME, - NM_SETTING_OVS_BRIDGE_SETTING_NAME, - NM_SETTING_OVS_PORT_SETTING_NAME, - NM_SETTING_TEAM_SETTING_NAME), + .values_static = NM_MAKE_STRV (NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BRIDGE_SETTING_NAME, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_TEAM_SETTING_NAME), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, @@ -5778,7 +5777,7 @@ static const NMMetaPropertyInfo *const property_infos_CONNECTION[] = { .set_fcn = _set_fcn_connection_metered, ), .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("yes", "no", "unknown"), + .values_static = NM_MAKE_STRV ("yes", "no", "unknown"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_LLDP, @@ -5790,7 +5789,7 @@ static const NMMetaPropertyInfo *const property_infos_CONNECTION[] = { { .value = NM_SETTING_CONNECTION_LLDP_ENABLE_RX, .nick = "enable", - } + }, ), ), .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT @@ -5831,7 +5830,7 @@ static const NMMetaPropertyInfo *const property_infos_DCB[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_APP_FCOE_MODE, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC (NM_SETTING_DCB_FCOE_MODE_FABRIC, + .values_static = NM_MAKE_STRV (NM_SETTING_DCB_FCOE_MODE_FABRIC, NM_SETTING_DCB_FCOE_MODE_VN2VN), ), ), @@ -6061,7 +6060,7 @@ static const NMMetaPropertyInfo *const property_infos_INFINIBAND[] = { .def_hint = NM_META_TEXT_PROMPT_IB_MODE_CHOICES, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("datagram", "connected"), + .values_static = NM_MAKE_STRV ("datagram", "connected"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_INFINIBAND_P_KEY, @@ -6173,15 +6172,15 @@ static const NMMetaPropertyInfo *const property_infos_IP4_CONFIG[] = { PROPERTY_INFO (NM_SETTING_IP_CONFIG_ROUTE_TABLE, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTE_TABLE, .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, - .value_infos = INT_VALUE_INFOS ( + .value_infos = INT_VALUE_INFOS ( { - .value = 0, + .value.i64 = 0, .nick = "unspec", }, { - .value = 254, + .value.i64 = 254, .nick = "main", - } + }, ), ), ), @@ -6197,15 +6196,15 @@ static const NMMetaPropertyInfo *const property_infos_IP4_CONFIG[] = { PROPERTY_INFO (NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT, .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, - .value_infos = INT_VALUE_INFOS ( + .value_infos = INT_VALUE_INFOS ( { - .value = 0, + .value.i64 = 0, .nick = "default", }, { - .value = G_MAXINT32, + .value.i64 = G_MAXINT32, .nick = "infinity", - } + }, ), ), ), @@ -6229,13 +6228,13 @@ static const NMMetaPropertyInfo *const property_infos_IP4_CONFIG[] = { .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, .value_infos = INT_VALUE_INFOS ( { - .value = -1, + .value.i64 = -1, .nick = "default", }, { - .value = 0, + .value.i64 = 0, .nick = "off", - } + }, ), ), ), @@ -6336,15 +6335,15 @@ static const NMMetaPropertyInfo *const property_infos_IP6_CONFIG[] = { PROPERTY_INFO (NM_SETTING_IP_CONFIG_ROUTE_TABLE, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTE_TABLE, .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, - .value_infos = INT_VALUE_INFOS ( + .value_infos = INT_VALUE_INFOS ( { - .value = 0, + .value.i64 = 0, .nick = "unspec", }, { - .value = 254, + .value.i64 = 254, .nick = "main", - } + }, ), ), ), @@ -6371,7 +6370,7 @@ static const NMMetaPropertyInfo *const property_infos_IP6_CONFIG[] = { { .value = NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, .nick = "enabled, prefer temporary IP", - } + }, ), ), ), @@ -6620,48 +6619,13 @@ static const NMMetaPropertyInfo *const property_infos_OLPC_MESH[] = { NULL }; -#undef _CURRENT_NM_META_SETTING_TYPE -#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_PPPOE -static const NMMetaPropertyInfo *const property_infos_PPPOE[] = { - PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_PARENT, - .is_cli_option = TRUE, - .property_alias = "parent", - .prompt = N_("PPPoE parent device"), - .property_type = &_pt_gobject_string, - ), - PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_SERVICE, - .is_cli_option = TRUE, - .property_alias = "service", - .prompt = N_("Service [none]"), - .property_type = &_pt_gobject_string, - ), - PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_USERNAME, - .is_cli_option = TRUE, - .property_alias = "username", - .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, - .prompt = N_("PPPoE username"), - .property_type = &_pt_gobject_string, - ), - PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_PASSWORD, - .is_cli_option = TRUE, - .property_alias = "password", - .prompt = N_("Password [none]"), - .is_secret = TRUE, - .property_type = &_pt_gobject_string, - ), - PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_PASSWORD_FLAGS, - .property_type = &_pt_gobject_secret_flags, - ), - NULL -}; - #undef _CURRENT_NM_META_SETTING_TYPE #define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_OVS_BRIDGE static const NMMetaPropertyInfo *const property_infos_OVS_BRIDGE[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_BRIDGE_FAIL_MODE, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("secure", "standalone"), + .values_static = NM_MAKE_STRV ("secure", "standalone"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_BRIDGE_MCAST_SNOOPING_ENABLE, @@ -6682,7 +6646,7 @@ static const NMMetaPropertyInfo *const property_infos_OVS_INTERFACE[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_INTERFACE_TYPE, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("internal", "patch"), + .values_static = NM_MAKE_STRV ("internal", "patch"), ), ), NULL @@ -6703,7 +6667,7 @@ static const NMMetaPropertyInfo *const property_infos_OVS_PORT[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_PORT_VLAN_MODE, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("access", "native-tagged", "native-untagged", "trunk"), + .values_static = NM_MAKE_STRV ("access", "native-tagged", "native-untagged", "trunk"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_PORT_TAG, @@ -6712,13 +6676,13 @@ static const NMMetaPropertyInfo *const property_infos_OVS_PORT[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_PORT_LACP, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("active", "off", "passive"), + .values_static = NM_MAKE_STRV ("active", "off", "passive"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_PORT_BOND_MODE, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("active-backup", "balance-slb", "balance-tcp"), + .values_static = NM_MAKE_STRV ("active-backup", "balance-slb", "balance-tcp"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_PORT_BOND_UPDELAY, @@ -6793,6 +6757,41 @@ static const NMMetaPropertyInfo *const property_infos_PPP[] = { NULL }; +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_PPPOE +static const NMMetaPropertyInfo *const property_infos_PPPOE[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_PARENT, + .is_cli_option = TRUE, + .property_alias = "parent", + .prompt = N_("PPPoE parent device"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_SERVICE, + .is_cli_option = TRUE, + .property_alias = "service", + .prompt = N_("Service [none]"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_USERNAME, + .is_cli_option = TRUE, + .property_alias = "username", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("PPPoE username"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_PASSWORD, + .is_cli_option = TRUE, + .property_alias = "password", + .prompt = N_("Password [none]"), + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_PASSWORD_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + NULL +}; + #undef _CURRENT_NM_META_SETTING_TYPE #define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_PROXY static const NMMetaPropertyInfo *const property_infos_PROXY[] = { @@ -6834,6 +6833,78 @@ static const NMMetaPropertyInfo *const property_infos_PROXY[] = { NULL }; +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_SERIAL +static const NMMetaPropertyInfo *const property_infos_SERIAL[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_SERIAL_BAUD, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_SERIAL_BITS, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_SERIAL_PARITY, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .value_infos = ENUM_VALUE_INFOS ( + { + .value = NM_SETTING_SERIAL_PARITY_EVEN, + .nick = "E", + }, + { + .value = NM_SETTING_SERIAL_PARITY_EVEN, + .nick = "e", + }, + { + .value = NM_SETTING_SERIAL_PARITY_ODD, + .nick = "O", + }, + { + .value = NM_SETTING_SERIAL_PARITY_ODD, + .nick = "o", + }, + { + .value = NM_SETTING_SERIAL_PARITY_NONE, + .nick = "N", + }, + { + .value = NM_SETTING_SERIAL_PARITY_NONE, + .nick = "n", + }, + ), + ), + .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_SERIAL_STOPBITS, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_SERIAL_SEND_DELAY, + .property_type = &_pt_gobject_int, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_SRIOV +static const NMMetaPropertyInfo *const property_infos_SRIOV[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_SRIOV_TOTAL_VFS, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_SRIOV_VFS, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_sriov_vfs, + .set_fcn = _set_fcn_sriov_vfs, + .remove_fcn = _remove_fcn_sriov_vfs, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_SRIOV_AUTOPROBE_DRIVERS, + .property_type = &_pt_gobject_enum, + ), + NULL +}; + #undef _CURRENT_NM_META_SETTING_TYPE #define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_TC_CONFIG static const NMMetaPropertyInfo *const property_infos_TC_CONFIG[] = { @@ -6870,64 +6941,64 @@ static const NMMetaPropertyInfo *const property_infos_TEAM[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_NOTIFY_PEERS_COUNT, .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, - .value_infos = INT_VALUE_INFOS ( + .value_infos = INT_VALUE_INFOS ( { - .value = 0, + .value.i64 = 0, .nick = "disabled", - } + }, ), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL, .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, - .value_infos = INT_VALUE_INFOS ( + .value_infos = INT_VALUE_INFOS ( { - .value = 0, + .value.i64 = 0, .nick = "default", - } + }, ), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_MCAST_REJOIN_COUNT, .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, - .value_infos = INT_VALUE_INFOS ( + .value_infos = INT_VALUE_INFOS ( { - .value = 0, + .value.i64 = 0, .nick = "disabled", - } + }, ), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL, .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, - .value_infos = INT_VALUE_INFOS ( + .value_infos = INT_VALUE_INFOS ( { - .value = 0, + .value.i64 = 0, .nick = "default", - } + }, ), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC (NM_SETTING_TEAM_RUNNER_BROADCAST, - NM_SETTING_TEAM_RUNNER_ROUNDROBIN, - NM_SETTING_TEAM_RUNNER_RANDOM, - NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP, - NM_SETTING_TEAM_RUNNER_LOADBALANCE, - NM_SETTING_TEAM_RUNNER_LACP), + .values_static = NM_MAKE_STRV (NM_SETTING_TEAM_RUNNER_BROADCAST, + NM_SETTING_TEAM_RUNNER_ROUNDROBIN, + NM_SETTING_TEAM_RUNNER_RANDOM, + NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP, + NM_SETTING_TEAM_RUNNER_LOADBALANCE, + NM_SETTING_TEAM_RUNNER_LACP), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_HWADDR_POLICY, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC (NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_SAME_ALL, - NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_BY_ACTIVE, - NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_ONLY_ACTIVE), + .values_static = NM_MAKE_STRV (NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_SAME_ALL, + NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_BY_ACTIVE, + NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_ONLY_ACTIVE), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_TX_HASH, @@ -6940,17 +7011,17 @@ static const NMMetaPropertyInfo *const property_infos_TEAM[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_TX_BALANCER, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("basic"), + .values_static = NM_MAKE_STRV ("basic"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL, .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, - .value_infos = INT_VALUE_INFOS ( + .value_infos = INT_VALUE_INFOS ( { - .value = NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT, + .value.i64 = NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT, .nick = "default", - } + }, ), ), ), @@ -6963,33 +7034,33 @@ static const NMMetaPropertyInfo *const property_infos_TEAM[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_SYS_PRIO, .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, - .value_infos = INT_VALUE_INFOS ( + .value_infos = INT_VALUE_INFOS ( { - .value = NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT, + .value.i64 = NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT, .nick = "default", - } + }, ), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_MIN_PORTS, .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, - .value_infos = INT_VALUE_INFOS ( + .value_infos = INT_VALUE_INFOS ( { - .value = 0, + .value.i64 = 0, .nick = "default", - } + }, ), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC (NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO, - NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO_STABLE, - NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_BANDWIDTH, - NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_COUNT, - NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_PORT_CONFIG), + .values_static = NM_MAKE_STRV (NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO, + NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO_STABLE, + NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_BANDWIDTH, + NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_COUNT, + NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_PORT_CONFIG), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_LINK_WATCHERS, @@ -7019,22 +7090,22 @@ static const NMMetaPropertyInfo *const property_infos_TEAM_PORT[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_PORT_QUEUE_ID, .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, - .value_infos = INT_VALUE_INFOS ( + .value_infos = INT_VALUE_INFOS ( { - .value = NM_SETTING_TEAM_PORT_QUEUE_ID_DEFAULT, + .value.i64 = NM_SETTING_TEAM_PORT_QUEUE_ID_DEFAULT, .nick = "default", - } + }, ), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_PORT_PRIO, .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, - .value_infos = INT_VALUE_INFOS ( + .value_infos = INT_VALUE_INFOS ( { - .value = 0, + .value.i64 = 0, .nick = "default", - } + }, ), ), ), @@ -7044,22 +7115,22 @@ static const NMMetaPropertyInfo *const property_infos_TEAM_PORT[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_PORT_LACP_PRIO, .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, - .value_infos = INT_VALUE_INFOS ( + .value_infos = INT_VALUE_INFOS ( { - .value = NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT, + .value.i64 = NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT, .nick = "default", - } + }, ), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_PORT_LACP_KEY, .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, - .value_infos = INT_VALUE_INFOS ( + .value_infos = INT_VALUE_INFOS ( { - .value = 0, + .value.i64 = 0, .nick = "default", - } + }, ), ), ), @@ -7074,78 +7145,6 @@ static const NMMetaPropertyInfo *const property_infos_TEAM_PORT[] = { NULL }; -#undef _CURRENT_NM_META_SETTING_TYPE -#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_SERIAL -static const NMMetaPropertyInfo *const property_infos_SERIAL[] = { - PROPERTY_INFO_WITH_DESC (NM_SETTING_SERIAL_BAUD, - .property_type = &_pt_gobject_int, - ), - PROPERTY_INFO_WITH_DESC (NM_SETTING_SERIAL_BITS, - .property_type = &_pt_gobject_int, - ), - PROPERTY_INFO_WITH_DESC (NM_SETTING_SERIAL_PARITY, - .property_type = &_pt_gobject_enum, - .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, - .value_infos = ENUM_VALUE_INFOS ( - { - .value = NM_SETTING_SERIAL_PARITY_EVEN, - .nick = "E", - }, - { - .value = NM_SETTING_SERIAL_PARITY_EVEN, - .nick = "e", - }, - { - .value = NM_SETTING_SERIAL_PARITY_ODD, - .nick = "O", - }, - { - .value = NM_SETTING_SERIAL_PARITY_ODD, - .nick = "o", - }, - { - .value = NM_SETTING_SERIAL_PARITY_NONE, - .nick = "N", - }, - { - .value = NM_SETTING_SERIAL_PARITY_NONE, - .nick = "n", - } - ), - ), - .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT - | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT, - ), - ), - PROPERTY_INFO_WITH_DESC (NM_SETTING_SERIAL_STOPBITS, - .property_type = &_pt_gobject_int, - ), - PROPERTY_INFO_WITH_DESC (NM_SETTING_SERIAL_SEND_DELAY, - .property_type = &_pt_gobject_int, - ), - NULL -}; - -#undef _CURRENT_NM_META_SETTING_TYPE -#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_SRIOV -static const NMMetaPropertyInfo *const property_infos_SRIOV[] = { - PROPERTY_INFO_WITH_DESC (NM_SETTING_SRIOV_TOTAL_VFS, - .property_type = &_pt_gobject_int, - ), - PROPERTY_INFO_WITH_DESC (NM_SETTING_SRIOV_VFS, - .property_type = DEFINE_PROPERTY_TYPE ( - .get_fcn = _get_fcn_sriov_vfs, - .set_fcn = _set_fcn_sriov_vfs, - .remove_fcn = _remove_fcn_sriov_vfs, - ), - ), - PROPERTY_INFO_WITH_DESC (NM_SETTING_SRIOV_AUTOPROBE_DRIVERS, - .property_type = &_pt_gobject_enum, - ), - NULL -}; - #undef _CURRENT_NM_META_SETTING_TYPE #define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_TUN static const NMMetaPropertyInfo *const property_infos_TUN[] = { @@ -7365,6 +7364,30 @@ static const NMMetaPropertyInfo *const property_infos_VXLAN[] = { NULL }; +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_WIFI_P2P +static const NMMetaPropertyInfo *const property_infos_WIFI_P2P[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIFI_P2P_PEER, + .is_cli_option = TRUE, + .property_alias = "peer", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("Peer"), + .property_type = &_pt_gobject_mac, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIFI_P2P_WPS_METHOD, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_wireless_security_wps_method_get_type, + ), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIFI_P2P_WFD_IES, + .property_type = &_pt_gobject_bytes, + ), + NULL +}; + #undef _CURRENT_NM_META_SETTING_TYPE #define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_WIMAX static const NMMetaPropertyInfo *const property_infos_WIMAX[] = { @@ -7400,7 +7423,7 @@ static const NMMetaPropertyInfo *const property_infos_WIRED[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_DUPLEX, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("half", "full"), + .values_static = NM_MAKE_STRV ("half", "full"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_AUTO_NEGOTIATE, @@ -7452,7 +7475,7 @@ static const NMMetaPropertyInfo *const property_infos_WIRED[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_S390_NETTYPE, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("qeth", "lcs", "ctc"), + .values_static = NM_MAKE_STRV ("qeth", "lcs", "ctc"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_S390_OPTIONS, @@ -7481,7 +7504,7 @@ static const NMMetaPropertyInfo *const property_infos_WIRED[] = { { .value = NM_SETTING_WIRED_WAKE_ON_LAN_NONE, .nick = "disabled", - } + }, ), ), .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT @@ -7494,6 +7517,34 @@ static const NMMetaPropertyInfo *const property_infos_WIRED[] = { NULL }; +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_WIREGUARD +static const NMMetaPropertyInfo *const property_infos_WIREGUARD[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIREGUARD_PRIVATE_KEY, + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIREGUARD_LISTEN_PORT, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIREGUARD_FWMARK, + .property_type = &_pt_gobject_int, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, \ + .base = 16, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIREGUARD_PEER_ROUTES, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIREGUARD_MTU, + .property_type = &_pt_gobject_mtu, + ), + NULL +}; + #undef _CURRENT_NM_META_SETTING_TYPE #define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_WIRELESS static const NMMetaPropertyInfo *const property_infos_WIRELESS[] = { @@ -7514,15 +7565,15 @@ static const NMMetaPropertyInfo *const property_infos_WIRELESS[] = { .def_hint = NM_META_TEXT_PROMPT_WIFI_MODE_CHOICES, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC (NM_SETTING_WIRELESS_MODE_INFRA, - NM_SETTING_WIRELESS_MODE_ADHOC, - NM_SETTING_WIRELESS_MODE_AP), + .values_static = NM_MAKE_STRV (NM_SETTING_WIRELESS_MODE_INFRA, + NM_SETTING_WIRELESS_MODE_ADHOC, + NM_SETTING_WIRELESS_MODE_AP), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_BAND, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("a", "bg"), + .values_static = NM_MAKE_STRV ("a", "bg"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_CHANNEL, @@ -7610,7 +7661,7 @@ static const NMMetaPropertyInfo *const property_infos_WIRELESS[] = { { .value = NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE, .nick = "disabled", - } + }, ), ), ), @@ -7624,7 +7675,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 = VALUES_STATIC ("none", "ieee8021x", "wpa-none", "wpa-psk", "wpa-eap"), + .values_static = NM_MAKE_STRV ("none", "ieee8021x", "wpa-none", "wpa-psk", "wpa-eap", "sae"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, @@ -7633,7 +7684,7 @@ static const NMMetaPropertyInfo *const property_infos_WIRELESS_SECURITY[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( - .values_static = VALUES_STATIC ("open", "shared", "leap"), + .values_static = NM_MAKE_STRV ("open", "shared", "leap"), ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_PROTO, @@ -7724,9 +7775,6 @@ static const NMMetaPropertyInfo *const property_infos_WIRELESS_SECURITY[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_PSK, .is_secret = TRUE, .property_type = &_pt_gobject_string, - .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_string, - .validate_fcn = _validate_fcn_wireless_security_psk, - ), ), PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS, .property_type = &_pt_gobject_secret_flags, @@ -7775,12 +7823,12 @@ static const NMMetaPropertyInfo *const property_infos_WPAN[] = { .prompt = N_("Short address (<0x0000-0xffff>)"), .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, \ - .base = 16, - .value_infos = INT_VALUE_INFOS ( + .base = 16, + .value_infos = INT_VALUE_INFOS ( { - .value = G_MAXUINT16, + .value.i64 = G_MAXUINT16, .nick = "unset", - } + }, ), ), ), @@ -7791,27 +7839,42 @@ static const NMMetaPropertyInfo *const property_infos_WPAN[] = { .prompt = N_("PAN Identifier (<0x0000-0xffff>)"), .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, \ - .base = 16, - .value_infos = INT_VALUE_INFOS ( + .base = 16, + .value_infos = INT_VALUE_INFOS ( { - .value = G_MAXUINT16, + .value.i64 = G_MAXUINT16, .nick = "unset", - } + }, ), ), ), - NULL -}; - -#undef _CURRENT_NM_META_SETTING_TYPE -#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_6LOWPAN -static const NMMetaPropertyInfo *const property_infos_6LOWPAN[] = { - PROPERTY_INFO_WITH_DESC (NM_SETTING_6LOWPAN_PARENT, + PROPERTY_INFO_WITH_DESC (NM_SETTING_WPAN_PAGE, .is_cli_option = TRUE, - .property_alias = "dev", - .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, - .prompt = N_("IEEE 802.15.4 (WPAN) parent device or connection UUID"), - .property_type = &_pt_gobject_string, + .property_alias = "page", + .prompt = N_("Page ()"), + .property_type = &_pt_gobject_int, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, \ + .value_infos = INT_VALUE_INFOS ( + { + .value.i64 = NM_SETTING_WPAN_PAGE_DEFAULT, + .nick = "default", + }, + ), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WPAN_CHANNEL, + .is_cli_option = TRUE, + .property_alias = "channel", + .prompt = N_("Channel ()"), + .property_type = &_pt_gobject_int, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, \ + .value_infos = INT_VALUE_INFOS ( + { + .value.i64 = NM_SETTING_WPAN_CHANNEL_DEFAULT, + .nick = "default", + }, + ), + ), ), NULL }; @@ -7844,9 +7907,9 @@ static void _setting_init_fcn_gsm (ARGS_SETTING_INIT_FCN) { if (init_type == NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI) { - /* Initialize 'number' so that 'gsm' is valid */ + /* Initialize 'apn' so that 'gsm' is valid */ g_object_set (NM_SETTING_GSM (setting), - NM_SETTING_GSM_NUMBER, "*99#", + NM_SETTING_GSM_APN, "internet", NULL); } } @@ -7937,6 +8000,7 @@ _setting_init_fcn_wireless (ARGS_SETTING_INIT_FCN) /*****************************************************************************/ +#define SETTING_PRETTY_NAME_6LOWPAN N_("6LOWPAN settings") #define SETTING_PRETTY_NAME_802_1X N_("802-1x settings") #define SETTING_PRETTY_NAME_ADSL N_("ADSL connection") #define SETTING_PRETTY_NAME_BLUETOOTH N_("bluetooth connection") @@ -7958,10 +8022,10 @@ _setting_init_fcn_wireless (ARGS_SETTING_INIT_FCN) #define SETTING_PRETTY_NAME_MACVLAN N_("macvlan connection") #define SETTING_PRETTY_NAME_MATCH N_("Match") #define SETTING_PRETTY_NAME_OLPC_MESH N_("OLPC Mesh connection") -#define SETTING_PRETTY_NAME_OVS_BRIDGE N_("OpenVSwitch bridge settings") -#define SETTING_PRETTY_NAME_OVS_INTERFACE N_("OpenVSwitch interface settings") -#define SETTING_PRETTY_NAME_OVS_PATCH N_("OpenVSwitch patch interface settings") -#define SETTING_PRETTY_NAME_OVS_PORT N_("OpenVSwitch port settings") +#define SETTING_PRETTY_NAME_OVS_BRIDGE N_("Open vSwitch bridge settings") +#define SETTING_PRETTY_NAME_OVS_INTERFACE N_("Open vSwitch interface settings") +#define SETTING_PRETTY_NAME_OVS_PATCH N_("Open vSwitch patch interface settings") +#define SETTING_PRETTY_NAME_OVS_PORT N_("Open vSwitch port settings") #define SETTING_PRETTY_NAME_PPP N_("PPP settings") #define SETTING_PRETTY_NAME_PPPOE N_("PPPoE") #define SETTING_PRETTY_NAME_PROXY N_("Proxy") @@ -7975,12 +8039,13 @@ _setting_init_fcn_wireless (ARGS_SETTING_INIT_FCN) #define SETTING_PRETTY_NAME_VLAN N_("VLAN connection") #define SETTING_PRETTY_NAME_VPN N_("VPN 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") #define SETTING_PRETTY_NAME_WIRED N_("Wired Ethernet") +#define SETTING_PRETTY_NAME_WIREGUARD N_("WireGuard VPN settings") #define SETTING_PRETTY_NAME_WIRELESS N_("Wi-Fi connection") #define SETTING_PRETTY_NAME_WIRELESS_SECURITY N_("Wi-Fi security settings") #define SETTING_PRETTY_NAME_WPAN N_("WPAN settings") -#define SETTING_PRETTY_NAME_6LOWPAN N_("6LOWPAN settings") #define NM_META_SETTING_VALID_PARTS(...) \ ((const NMMetaSettingValidPartItem *const[]) { __VA_ARGS__ NULL }) @@ -8218,6 +8283,12 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), ), + SETTING_INFO (WIFI_P2P, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIFI_P2P, TRUE), + ), + ), SETTING_INFO (WIMAX, .valid_parts = NM_META_SETTING_VALID_PARTS ( NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), @@ -8235,6 +8306,12 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), ), + SETTING_INFO (WIREGUARD, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIREGUARD, TRUE), + ), + ), SETTING_INFO (WIRELESS, .alias = "wifi", .valid_parts = NM_META_SETTING_VALID_PARTS ( diff --git a/clients/common/nm-meta-setting-desc.h b/clients/common/nm-meta-setting-desc.h index 163dcf2e..e3f9d230 100644 --- a/clients/common/nm-meta-setting-desc.h +++ b/clients/common/nm-meta-setting-desc.h @@ -268,6 +268,9 @@ struct _NMMetaPropertyTypData { struct { const char *(*validate_fcn) (const char *value, char **out_to_free, GError **error); } gobject_string; + struct { + bool legacy_format:1; + } gobject_bytes; struct { guint32 (*get_fcn) (NMSetting *setting); } mtu; @@ -412,7 +415,7 @@ typedef enum { /* the settings-meta data is supposed to be independent of an actual client * implementation. Hence, there is a need for hooks to the meta-data. - * The meta-data handlers may call back to the enviroment with certain + * The meta-data handlers may call back to the environment with certain * actions. */ struct _NMMetaEnvironment { diff --git a/clients/common/nm-polkit-listener.c b/clients/common/nm-polkit-listener.c index a7bce6ad..7367459d 100644 --- a/clients/common/nm-polkit-listener.c +++ b/clients/common/nm-polkit-listener.c @@ -35,7 +35,6 @@ #include "nm-polkit-listener.h" -#include #include #include @@ -198,7 +197,7 @@ choose_identity (GList *identities) GList *elem; /* Choose identity. First try current user, then root, and else - * take the firts one */ + * take the first one */ user = getenv("USER"); elem = g_list_find_custom (identities, user, (GCompareFunc) compare_users); if (!elem) { diff --git a/clients/common/nm-polkit-listener.h b/clients/common/nm-polkit-listener.h index d69f8eca..ee86104b 100644 --- a/clients/common/nm-polkit-listener.h +++ b/clients/common/nm-polkit-listener.h @@ -66,7 +66,7 @@ typedef struct { gpointer user_data); /* - * @gained_authorization: whether the autorization was successful + * @gained_authorization: whether the authorization was successful * * Called as a result of completed signal by polkit. */ @@ -123,7 +123,7 @@ typedef void (*NMPolkitListenerOnShowInfoFunc) (const char *text); typedef void (*NMPolkitListenerOnShowErrorFunc) (const char *text); /** * NMPolkitListenerCompletedFunc: - * @gained_authorization: whether the autorization was successful + * @gained_authorization: whether the authorization was successful * * Called as a result of completed signal by polkit. */ diff --git a/clients/common/nm-secret-agent-simple.c b/clients/common/nm-secret-agent-simple.c index cab0c15a..cd3ce2ee 100644 --- a/clients/common/nm-secret-agent-simple.c +++ b/clients/common/nm-secret-agent-simple.c @@ -31,16 +31,30 @@ #include "nm-default.h" -#include +#include "nm-secret-agent-simple.h" -#include "nm-vpn-service-plugin.h" +#include +#include +#include "nm-vpn-service-plugin.h" #include "nm-vpn-helpers.h" -#include "nm-secret-agent-simple.h" +#include "nm-utils/nm-secret-utils.h" -G_DEFINE_TYPE (NMSecretAgentSimple, nm_secret_agent_simple, NM_TYPE_SECRET_AGENT_OLD) +/*****************************************************************************/ + +typedef struct { + char *request_id; + + NMSecretAgentSimple *self; -#define NM_SECRET_AGENT_SIMPLE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SECRET_AGENT_SIMPLE, NMSecretAgentSimplePrivate)) + NMConnection *connection; + const char *setting_name; + char **hints; + NMSecretAgentOldGetSecretsFunc callback; + gpointer callback_data; + GCancellable *cancellable; + NMSecretAgentGetSecretsFlags flags; +} RequestData; enum { REQUEST_SECRETS, @@ -51,89 +65,65 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { - NMSecretAgentSimple *self; - - char *request_id; - NMConnection *connection; - char **hints; - NMSecretAgentOldGetSecretsFunc callback; - gpointer callback_data; -} NMSecretAgentSimpleRequest; - -typedef struct { - /* */ GHashTable *requests; char *path; gboolean enabled; } NMSecretAgentSimplePrivate; -static void -nm_secret_agent_simple_request_free (gpointer data) -{ - NMSecretAgentSimpleRequest *request = data; +struct _NMSecretAgentSimple { + NMSecretAgentOld parent; + NMSecretAgentSimplePrivate _priv; +}; - g_object_unref (request->self); - g_object_unref (request->connection); - g_strfreev (request->hints); +struct _NMSecretAgentSimpleClass { + NMSecretAgentOldClass parent; +}; - g_slice_free (NMSecretAgentSimpleRequest, request); -} +G_DEFINE_TYPE (NMSecretAgentSimple, nm_secret_agent_simple, NM_TYPE_SECRET_AGENT_OLD) -static void -nm_secret_agent_simple_init (NMSecretAgentSimple *agent) -{ - NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (agent); +#define NM_SECRET_AGENT_SIMPLE_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMSecretAgentSimple, NM_IS_SECRET_AGENT_SIMPLE, NMSecretAgentOld) - priv->requests = g_hash_table_new_full (nm_str_hash, g_str_equal, - g_free, nm_secret_agent_simple_request_free); -} +/*****************************************************************************/ static void -nm_secret_agent_simple_finalize (GObject *object) +_request_data_free (gpointer data) { - NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (object); - GError *error; - GHashTableIter iter; - gpointer key; - gpointer value; - - error = g_error_new (NM_SECRET_AGENT_ERROR, - NM_SECRET_AGENT_ERROR_AGENT_CANCELED, - "The secret agent is going away"); - - g_hash_table_iter_init (&iter, priv->requests); - while (g_hash_table_iter_next (&iter, &key, &value)) { - NMSecretAgentSimpleRequest *request = value; - - request->callback (NM_SECRET_AGENT_OLD (object), - request->connection, - NULL, error, - request->callback_data); - } - - g_hash_table_destroy (priv->requests); - g_error_free (error); + RequestData *request = data; - g_free (priv->path); + g_free (request->request_id); + nm_clear_g_cancellable (&request->cancellable); + g_object_unref (request->connection); + g_strfreev (request->hints); - G_OBJECT_CLASS (nm_secret_agent_simple_parent_class)->finalize (object); + g_slice_free (RequestData, request); } -static gboolean -strv_has (char **haystack, - char *needle) +static void +_request_data_complete (RequestData *request, + GVariant *secrets, + GError *error, + GHashTableIter *iter_to_remove) { - char **iter; + NMSecretAgentSimple *self = request->self; + NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (self); - for (iter = haystack; iter && *iter; iter++) { - if (g_strcmp0 (*iter, needle) == 0) - return TRUE; - } + nm_assert ((secrets != NULL) != (error != NULL)); - return FALSE; + request->callback (NM_SECRET_AGENT_OLD (request->self), + request->connection, + secrets, + error, + request->callback_data); + + if (iter_to_remove) + g_hash_table_iter_remove (iter_to_remove); + else + g_hash_table_remove (priv->requests, request); } +/*****************************************************************************/ + /** * NMSecretAgentSimpleSecret: * @name: the user-visible name of the secret. Eg, "WEP Passphrase". @@ -148,70 +138,113 @@ typedef struct { NMSecretAgentSimpleSecret base; NMSetting *setting; char *property; -} NMSecretAgentSimpleSecretReal; +} SecretReal; static void -nm_secret_agent_simple_secret_free (NMSecretAgentSimpleSecret *secret) +_secret_real_free (NMSecretAgentSimpleSecret *secret) { - NMSecretAgentSimpleSecretReal *real = (NMSecretAgentSimpleSecretReal *)secret; + SecretReal *real = (SecretReal *)secret; g_free ((char *) secret->pretty_name); g_free ((char *) secret->entry_id); - g_free (secret->value); + nm_free_secret (secret->value); g_free ((char *) secret->vpn_type); g_free (real->property); g_clear_object (&real->setting); - g_slice_free (NMSecretAgentSimpleSecretReal, real); + g_slice_free (SecretReal, real); } static NMSecretAgentSimpleSecret * -nm_secret_agent_simple_secret_new (NMSecretAgentSecretType secret_type, - const char *pretty_name, - NMSetting *setting, - const char *property, - const char *vpn_type) -{ - NMSecretAgentSimpleSecretReal *real; - const char *vpn_prefix; - const char *value; +_secret_real_new_plain (NMSecretAgentSecretType secret_type, + const char *pretty_name, + NMSetting *setting, + const char *property) +{ + SecretReal *real; + gs_free char *value= NULL; nm_assert (property); nm_assert (NM_IS_SETTING (setting)); + nm_assert (NM_IN_SET (secret_type, NM_SECRET_AGENT_SECRET_TYPE_PROPERTY, NM_SECRET_AGENT_SECRET_TYPE_SECRET)); + nm_assert (g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property)); + nm_assert ((secret_type == NM_SECRET_AGENT_SECRET_TYPE_SECRET) == nm_setting_get_secret_flags (setting, property, NULL, NULL)); + + g_object_get (setting, property, &value, NULL); + + real = g_slice_new (SecretReal); + *real = (SecretReal) { + .base.secret_type = secret_type, + .base.pretty_name = g_strdup (pretty_name), + .base.entry_id = g_strdup_printf ("%s.%s", nm_setting_get_name (setting), property), + .base.value = g_steal_pointer (&value), + .base.is_secret = (secret_type != NM_SECRET_AGENT_SECRET_TYPE_PROPERTY), + .setting = g_object_ref (setting), + .property = g_strdup (property), + }; + return &real->base; +} - real = g_slice_new0 (NMSecretAgentSimpleSecretReal); - *((NMSecretAgentSecretType *) &real->base.secret_type) = secret_type; - real->setting = g_object_ref (setting); - real->base.pretty_name = g_strdup (pretty_name); - real->property = g_strdup (property); - switch (secret_type) { - case NM_SECRET_AGENT_SECRET_TYPE_PROPERTY: - case NM_SECRET_AGENT_SECRET_TYPE_SECRET: - nm_assert (!vpn_type); - nm_assert (g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property)); - nm_assert ((secret_type == NM_SECRET_AGENT_SECRET_TYPE_SECRET) == nm_setting_get_secret_flags (setting, property, NULL, NULL)); - real->base.entry_id = g_strdup_printf ("%s.%s", nm_setting_get_name (setting), property); - g_object_get (setting, property, &real->base.value, NULL); - real->base.is_secret = (secret_type != NM_SECRET_AGENT_SECRET_TYPE_PROPERTY); - break; - case NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET: - vpn_prefix = NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRETS; - value = nm_setting_vpn_get_secret (NM_SETTING_VPN (setting), property); - real->base.entry_id = g_strdup_printf ("%s%s", vpn_prefix, property); - nm_assert (vpn_type); - real->base.vpn_type = g_strdup (vpn_type); - real->base.value = g_strdup (value); - real->base.is_secret = TRUE; - break; - } - nm_assert (real->base.entry_id); +static NMSecretAgentSimpleSecret * +_secret_real_new_vpn_secret (const char *pretty_name, + NMSetting *setting, + const char *property, + const char *vpn_type) +{ + SecretReal *real; + const char *value; + + nm_assert (property); + nm_assert (NM_IS_SETTING_VPN (setting)); + nm_assert (vpn_type); + + value = nm_setting_vpn_get_secret (NM_SETTING_VPN (setting), property); + + real = g_slice_new (SecretReal); + *real = (SecretReal) { + .base.secret_type = NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET, + .base.pretty_name = g_strdup (pretty_name), + .base.entry_id = g_strdup_printf ("%s%s", NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRETS, property), + .base.value = g_strdup (value), + .base.is_secret = TRUE, + .base.vpn_type = g_strdup (vpn_type), + .setting = g_object_ref (setting), + .property = g_strdup (property), + }; + return &real->base; +} +static NMSecretAgentSimpleSecret * +_secret_real_new_wireguard_peer_psk (NMSettingWireGuard *s_wg, + const char *public_key, + const char *preshared_key) +{ + SecretReal *real; + + nm_assert (NM_IS_SETTING_WIREGUARD (s_wg)); + nm_assert (public_key); + + real = g_slice_new (SecretReal); + *real = (SecretReal) { + .base.secret_type = NM_SECRET_AGENT_SECRET_TYPE_WIREGUARD_PEER_PSK, + .base.pretty_name = g_strdup_printf (_("Preshared-key for %s"), + public_key), + .base.entry_id = g_strdup_printf (NM_SETTING_WIREGUARD_SETTING_NAME"."NM_SETTING_WIREGUARD_PEERS".%s."NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, + public_key), + .base.value = g_strdup (preshared_key), + .base.is_secret = TRUE, + .base.no_prompt_entry_id = TRUE, + .setting = NM_SETTING (g_object_ref (s_wg)), + .property = g_strdup (public_key), + }; return &real->base; } +/*****************************************************************************/ + static gboolean -add_8021x_secrets (NMSecretAgentSimpleRequest *request, - GPtrArray *secrets) +add_8021x_secrets (RequestData *request, + GPtrArray *secrets) { NMSetting8021x *s_8021x = nm_connection_get_setting_802_1x (request->connection); const char *eap_method; @@ -222,11 +255,10 @@ add_8021x_secrets (NMSecretAgentSimpleRequest *request, char **iter; for (iter = request->hints; *iter; iter++) { - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET, - _(*iter), - NM_SETTING (s_8021x), - *iter, - NULL); + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET, + _(*iter), + NM_SETTING (s_8021x), + *iter); g_ptr_array_add (secrets, secret); } @@ -237,41 +269,37 @@ add_8021x_secrets (NMSecretAgentSimpleRequest *request, if (!eap_method) return FALSE; - if ( !strcmp (eap_method, "md5") - || !strcmp (eap_method, "leap") - || !strcmp (eap_method, "ttls") - || !strcmp (eap_method, "peap")) { + if (NM_IN_STRSET (eap_method, "md5", + "leap", + "ttls", + "peap")) { /* TTLS and PEAP are actually much more complicated, but this complication * is not visible here since we only care about phase2 authentication * (and don't even care of which one) */ - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY, - _("Username"), - NM_SETTING (s_8021x), - NM_SETTING_802_1X_IDENTITY, - NULL); + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY, + _("Username"), + NM_SETTING (s_8021x), + NM_SETTING_802_1X_IDENTITY); g_ptr_array_add (secrets, secret); - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET, - _("Password"), - NM_SETTING (s_8021x), - NM_SETTING_802_1X_PASSWORD, - NULL); + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET, + _("Password"), + NM_SETTING (s_8021x), + NM_SETTING_802_1X_PASSWORD); g_ptr_array_add (secrets, secret); return TRUE; } - if (!strcmp (eap_method, "tls")) { - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY, - _("Identity"), - NM_SETTING (s_8021x), - NM_SETTING_802_1X_IDENTITY, - NULL); + if (nm_streq (eap_method, "tls")) { + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY, + _("Identity"), + NM_SETTING (s_8021x), + NM_SETTING_802_1X_IDENTITY); g_ptr_array_add (secrets, secret); - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET, - _("Private key password"), - NM_SETTING (s_8021x), - NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, - NULL); + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET, + _("Private key password"), + NM_SETTING (s_8021x), + NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); g_ptr_array_add (secrets, secret); return TRUE; } @@ -280,7 +308,7 @@ add_8021x_secrets (NMSecretAgentSimpleRequest *request, } static gboolean -add_wireless_secrets (NMSecretAgentSimpleRequest *request, +add_wireless_secrets (RequestData *request, GPtrArray *secrets) { NMSettingWirelessSecurity *s_wsec = nm_connection_get_setting_wireless_security (request->connection); @@ -290,76 +318,67 @@ add_wireless_secrets (NMSecretAgentSimpleRequest *request, if (!key_mgmt) return FALSE; - if (!strcmp (key_mgmt, "wpa-none") || !strcmp (key_mgmt, "wpa-psk")) { - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET, - _("Password"), - NM_SETTING (s_wsec), - NM_SETTING_WIRELESS_SECURITY_PSK, - NULL); + if (NM_IN_STRSET (key_mgmt, "wpa-none", "wpa-psk", "sae")) { + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET, + _("Password"), + NM_SETTING (s_wsec), + NM_SETTING_WIRELESS_SECURITY_PSK); g_ptr_array_add (secrets, secret); return TRUE; } - if (!strcmp (key_mgmt, "none")) { - int index; - char *key; + if (nm_streq (key_mgmt, "none")) { + guint32 index; + char key[100]; index = nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec); - key = g_strdup_printf ("wep-key%d", index); - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET, - _("Key"), - NM_SETTING (s_wsec), - key, - NULL); - g_free (key); - + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET, + _("Key"), + NM_SETTING (s_wsec), + nm_sprintf_buf (key, "wep-key%u", (guint) index)); g_ptr_array_add (secrets, secret); return TRUE; } - if (!strcmp (key_mgmt, "iee8021x")) { - if (!g_strcmp0 (nm_setting_wireless_security_get_auth_alg (s_wsec), "leap")) { - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET, - _("Password"), - NM_SETTING (s_wsec), - NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, - NULL); + if (nm_streq (key_mgmt, "iee8021x")) { + if (nm_streq0 (nm_setting_wireless_security_get_auth_alg (s_wsec), "leap")) { + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET, + _("Password"), + NM_SETTING (s_wsec), + NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD); g_ptr_array_add (secrets, secret); return TRUE; } else return add_8021x_secrets (request, secrets); } - if (!strcmp (key_mgmt, "wpa-eap")) + if (nm_streq (key_mgmt, "wpa-eap")) return add_8021x_secrets (request, secrets); return FALSE; } static gboolean -add_pppoe_secrets (NMSecretAgentSimpleRequest *request, +add_pppoe_secrets (RequestData *request, GPtrArray *secrets) { NMSettingPppoe *s_pppoe = nm_connection_get_setting_pppoe (request->connection); NMSecretAgentSimpleSecret *secret; - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY, - _("Username"), - NM_SETTING (s_pppoe), - NM_SETTING_PPPOE_USERNAME, - NULL); + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY, + _("Username"), + NM_SETTING (s_pppoe), + NM_SETTING_PPPOE_USERNAME); g_ptr_array_add (secrets, secret); - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY, - _("Service"), - NM_SETTING (s_pppoe), - NM_SETTING_PPPOE_SERVICE, - NULL); + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY, + _("Service"), + NM_SETTING (s_pppoe), + NM_SETTING_PPPOE_SERVICE); g_ptr_array_add (secrets, secret); - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET, - _("Password"), - NM_SETTING (s_pppoe), - NM_SETTING_PPPOE_PASSWORD, - NULL); + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET, + _("Password"), + NM_SETTING (s_pppoe), + NM_SETTING_PPPOE_PASSWORD); g_ptr_array_add (secrets, secret); return TRUE; } @@ -387,11 +406,10 @@ add_vpn_secret_helper (GPtrArray *secrets, NMSettingVpn *s_vpn, const char *name flags = get_vpn_secret_flags (s_vpn, name); if ( flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED || flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) { - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET, - ui_name, - NM_SETTING (s_vpn), - name, - nm_setting_vpn_get_service_type (s_vpn)); + secret = _secret_real_new_vpn_secret (ui_name, + NM_SETTING (s_vpn), + name, + nm_setting_vpn_get_service_type (s_vpn)); /* Check for duplicates */ for (i = 0; i < secrets->len; i++) { @@ -400,7 +418,7 @@ add_vpn_secret_helper (GPtrArray *secrets, NMSettingVpn *s_vpn, const char *name if ( s->secret_type == secret->secret_type && nm_streq0 (s->vpn_type, secret->vpn_type) && nm_streq0 (s->entry_id, secret->entry_id)) { - nm_secret_agent_simple_secret_free (secret); + _secret_real_free (secret); return; } } @@ -412,9 +430,9 @@ add_vpn_secret_helper (GPtrArray *secrets, NMSettingVpn *s_vpn, const char *name #define VPN_MSG_TAG "x-vpn-message:" static gboolean -add_vpn_secrets (NMSecretAgentSimpleRequest *request, - GPtrArray *secrets, - char **msg) +add_vpn_secrets (RequestData *request, + GPtrArray *secrets, + char **msg) { NMSettingVpn *s_vpn = nm_connection_get_setting_vpn (request->connection); const VpnPasswordName *secret_names, *p; @@ -443,33 +461,397 @@ add_vpn_secrets (NMSecretAgentSimpleRequest *request, return TRUE; } -static void -request_secrets_from_ui (NMSecretAgentSimpleRequest *request) +static gboolean +add_wireguard_secrets (RequestData *request, + GPtrArray *secrets, + char **msg, + GError **error) { + NMSettingWireGuard *s_wg; + NMSecretAgentSimpleSecret *secret; + guint i; + + s_wg = NM_SETTING_WIREGUARD (nm_connection_get_setting (request->connection, NM_TYPE_SETTING_WIREGUARD)); + if (!s_wg) { + g_set_error (error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED, + "Cannot service a WireGuard secrets request %s for a connection without WireGuard settings", + request->request_id); + return FALSE; + } + + if ( !request->hints + || !request->hints[0] + || g_strv_contains (NM_CAST_STRV_CC (request->hints), NM_SETTING_WIREGUARD_PRIVATE_KEY)) { + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET, + _("WireGuard private-key"), + NM_SETTING (s_wg), + NM_SETTING_WIREGUARD_PRIVATE_KEY); + g_ptr_array_add (secrets, secret); + } + + if (request->hints) { + + for (i = 0; request->hints[i]; i++) { + NMWireGuardPeer *peer; + const char *name = request->hints[i]; + gs_free char *public_key = NULL; + + if (nm_streq (name, NM_SETTING_WIREGUARD_PRIVATE_KEY)) + continue; + + if (NM_STR_HAS_PREFIX (name, NM_SETTING_WIREGUARD_PEERS".")) { + const char *tmp; + + tmp = &name[NM_STRLEN (NM_SETTING_WIREGUARD_PEERS".")]; + if (NM_STR_HAS_SUFFIX (tmp, "."NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY)) { + public_key = g_strndup (tmp, + strlen (tmp) - NM_STRLEN ("."NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY)); + } + } + + if (!public_key) + continue; + + peer = nm_setting_wireguard_get_peer_by_public_key (s_wg, public_key, NULL); + + g_ptr_array_add (secrets, _secret_real_new_wireguard_peer_psk (s_wg, + ( peer + ? nm_wireguard_peer_get_public_key (peer) + : public_key), + ( peer + ? nm_wireguard_peer_get_preshared_key (peer) + : NULL))); + } + } + + *msg = g_strdup_printf (_("Secrets are required to connect WireGuard VPN '%s'"), + nm_connection_get_id (request->connection)); + return TRUE; +} + +typedef struct { + GPid auth_dialog_pid; + GString *auth_dialog_response; + RequestData *request; GPtrArray *secrets; + GCancellable *cancellable; + gulong cancellable_id; + guint child_watch_id; + GInputStream *input_stream; + GOutputStream *output_stream; + char read_buf[5]; +} AuthDialogData; + +static void +_auth_dialog_data_free (AuthDialogData *data) +{ + nm_clear_g_signal_handler (data->cancellable, &data->cancellable_id); + g_clear_object (&data->cancellable); + nm_clear_g_source (&data->child_watch_id); + g_ptr_array_unref (data->secrets); + g_spawn_close_pid (data->auth_dialog_pid); + g_string_free (data->auth_dialog_response, TRUE); + g_object_unref (data->input_stream); + g_object_unref (data->output_stream); + g_slice_free (AuthDialogData, data); +} + +static void +_auth_dialog_exited (GPid pid, int status, gpointer user_data) +{ + AuthDialogData *data = user_data; + RequestData *request = data->request; + GPtrArray *secrets = data->secrets; + NMSettingVpn *s_vpn = nm_connection_get_setting_vpn (request->connection); + gs_unref_keyfile GKeyFile *keyfile = NULL; + gs_strfreev char **groups = NULL; + gs_free char *title = NULL; + gs_free char *message = NULL; + int i; + gs_free_error GError *error = NULL; + + data->child_watch_id = 0; + + nm_clear_g_cancellable_disconnect (data->cancellable, &data->cancellable_id); + + if (status != 0) { + g_set_error (&error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED, + "Auth dialog failed with error code %d\n", status); + goto out; + } + + keyfile = g_key_file_new (); + if (!g_key_file_load_from_data (keyfile, + data->auth_dialog_response->str, + data->auth_dialog_response->len, G_KEY_FILE_NONE, + &error)) { + goto out; + } + + groups = g_key_file_get_groups (keyfile, NULL); + if (!nm_streq0 (groups[0], "VPN Plugin UI")) { + g_set_error (&error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED, + "Expected [VPN Plugin UI] in auth dialog response"); + goto out; + } + + title = g_key_file_get_string (keyfile, "VPN Plugin UI", "Title", &error); + if (!title) + goto out; + + message = g_key_file_get_string (keyfile, "VPN Plugin UI", "Description", &error); + if (!message) + goto out; + + for (i = 1; groups[i]; i++) { + gs_free char *pretty_name = NULL; + + if (!g_key_file_get_boolean (keyfile, groups[i], "IsSecret", NULL)) + continue; + if (!g_key_file_get_boolean (keyfile, groups[i], "ShouldAsk", NULL)) + continue; + + pretty_name = g_key_file_get_string (keyfile, groups[i], "Label", NULL); + g_ptr_array_add (secrets, _secret_real_new_vpn_secret (pretty_name, + NM_SETTING (s_vpn), + groups[i], + nm_setting_vpn_get_service_type (s_vpn))); + } + +out: + /* Try to fall back to the hardwired VPN support if the auth dialog fails. + * We may eventually get rid of the whole hardwired secrets handling at some point, + * when the auth helpers are goode enough.. */ + if (error && add_vpn_secrets (request, secrets, &message)) { + g_clear_error (&error); + if (!message) { + message = g_strdup_printf (_("A password is required to connect to '%s'."), + nm_connection_get_id (request->connection)); + } + } + + if (error) + _request_data_complete (request, NULL, error, NULL); + else { + g_signal_emit (request->self, signals[REQUEST_SECRETS], 0, + request->request_id, title, message, secrets); + } + + _auth_dialog_data_free (data); +} + +static void +_request_cancelled (GObject *object, gpointer user_data) +{ + _auth_dialog_data_free (user_data); +} + +static void +_auth_dialog_read_done (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GInputStream *auth_dialog_out = G_INPUT_STREAM (source_object); + AuthDialogData *data = user_data; + gssize read_size; + gs_free_error GError *error = NULL; + + read_size = g_input_stream_read_finish (auth_dialog_out, res, &error); + switch (read_size) { + case -1: + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + _request_data_complete (data->request, NULL, error, NULL); + _auth_dialog_data_free (data); + break; + case 0: + /* Done reading. Let's wait for the auth dialog to exit so that we're able to collect the status. + * Remember we can be cancelled in between. */ + data->child_watch_id = g_child_watch_add (data->auth_dialog_pid, _auth_dialog_exited, data); + data->cancellable = g_object_ref (data->request->cancellable); + data->cancellable_id = g_cancellable_connect (data->cancellable, + G_CALLBACK (_request_cancelled), data, NULL); + break; + default: + g_string_append_len (data->auth_dialog_response, data->read_buf, read_size); + g_input_stream_read_async (auth_dialog_out, + data->read_buf, + sizeof (data->read_buf), + G_PRIORITY_DEFAULT, + NULL, + _auth_dialog_read_done, + data); + return; + } + + g_input_stream_close (auth_dialog_out, NULL, NULL); +} + +static void +_auth_dialog_write_done (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GOutputStream *auth_dialog_out = G_OUTPUT_STREAM (source_object); + _nm_unused gs_free char *auth_dialog_request_free = user_data; + + /* We don't care about write errors. If there are any problems, the + * reader shall notice. */ + g_output_stream_write_finish (auth_dialog_out, res, NULL); + g_output_stream_close (auth_dialog_out, NULL, NULL); +} + +static void +_add_to_string (GString *string, const char *key, const char *value) +{ + gs_strfreev char **lines = NULL; + int i; + + lines = g_strsplit (value, "\n", -1); + + g_string_append (string, key); + for (i = 0; lines[i]; i++) { + g_string_append_c (string, '='); + g_string_append (string, lines[i]); + g_string_append_c (string, '\n'); + } +} + +static void +_add_data_item_to_string (const char *key, const char *value, gpointer user_data) +{ + GString *string = user_data; + + _add_to_string (string, "DATA_KEY", key); + _add_to_string (string, "DATA_VAL", value); + g_string_append_c (string, '\n'); +} + +static void +_add_secret_to_string (const char *key, const char *value, gpointer user_data) +{ + GString *string = user_data; + + _add_to_string (string, "SECRET_KEY", key); + _add_to_string (string, "SECRET_VAL", value); + g_string_append_c (string, '\n'); +} + +static gboolean +try_spawn_vpn_auth_helper (RequestData *request, + GPtrArray *secrets) +{ + NMSettingVpn *s_vpn = nm_connection_get_setting_vpn (request->connection); + NMVpnPluginInfo *plugin_info; + gboolean supports_external; + const char *auth_dialog_argv[] = { NULL, + "-u", nm_connection_get_uuid (request->connection), + "-n", nm_connection_get_id (request->connection), + "-s", nm_setting_vpn_get_service_type (s_vpn), + "--external-ui-mode", + "-i", + NULL, /* [9], slot for "-r" */ + NULL }; + const char *s; + GPid auth_dialog_pid; + int auth_dialog_in_fd; + int auth_dialog_out_fd; + GOutputStream *auth_dialog_in; + GInputStream *auth_dialog_out; + GError *error = NULL; + GString *auth_dialog_request; + char *auth_dialog_request_str; + gsize auth_dialog_request_len; + AuthDialogData *data; + + plugin_info = nm_vpn_plugin_info_list_find_by_service (nm_vpn_get_plugin_infos (), + nm_setting_vpn_get_service_type (s_vpn)); + if (!plugin_info) + return FALSE; + + s = nm_vpn_plugin_info_lookup_property (plugin_info, "GNOME", "supports-external-ui-mode"); + supports_external = _nm_utils_ascii_str_to_bool (s, FALSE); + if (!supports_external) + return FALSE; + + auth_dialog_argv[0] = nm_vpn_plugin_info_lookup_property (plugin_info, "GNOME", "auth-dialog"); + g_return_val_if_fail (auth_dialog_argv[0], FALSE); + + if (request->flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW) + auth_dialog_argv[9] = "-r"; + + if (!g_spawn_async_with_pipes (NULL, (char **)auth_dialog_argv, NULL, + G_SPAWN_DO_NOT_REAP_CHILD, + NULL, NULL, + &auth_dialog_pid, + &auth_dialog_in_fd, + &auth_dialog_out_fd, + NULL, + &error)) { + g_warning ("Failed to spawn the auth dialog%s\n", error->message); + return FALSE; + } + + auth_dialog_in = g_unix_output_stream_new (auth_dialog_in_fd, TRUE); + auth_dialog_out = g_unix_input_stream_new (auth_dialog_out_fd, TRUE); + + auth_dialog_request = g_string_new_len (NULL, 1024); + nm_setting_vpn_foreach_data_item (s_vpn, _add_data_item_to_string, auth_dialog_request); + nm_setting_vpn_foreach_secret (s_vpn, _add_secret_to_string, auth_dialog_request); + g_string_append (auth_dialog_request, "DONE\nQUIT\n"); + auth_dialog_request_len = auth_dialog_request->len; + auth_dialog_request_str = g_string_free (auth_dialog_request, FALSE); + + data = g_slice_new (AuthDialogData); + *data = (AuthDialogData) { + .auth_dialog_response = g_string_new_len (NULL, sizeof (data->read_buf)), + .auth_dialog_pid = auth_dialog_pid, + .request = request, + .secrets = g_ptr_array_ref (secrets), + .input_stream = auth_dialog_out, + .output_stream = auth_dialog_in, + }; + + g_output_stream_write_async (auth_dialog_in, + auth_dialog_request_str, + auth_dialog_request_len, + G_PRIORITY_DEFAULT, + request->cancellable, + _auth_dialog_write_done, + auth_dialog_request_str); + + g_input_stream_read_async (auth_dialog_out, + data->read_buf, + sizeof (data->read_buf), + G_PRIORITY_DEFAULT, + request->cancellable, + _auth_dialog_read_done, + data); + + return TRUE; +} + +static void +request_secrets_from_ui (RequestData *request) +{ + gs_unref_ptrarray GPtrArray *secrets = NULL; + gs_free_error GError *error = NULL; NMSecretAgentSimplePrivate *priv; NMSecretAgentSimpleSecret *secret; const char *title; - char *msg; - gboolean ok = TRUE; + gs_free char *msg = NULL; priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (request->self); g_return_if_fail (priv->enabled); /* We only handle requests for connection with @path if set. */ if (priv->path && !g_str_has_prefix (request->request_id, priv->path)) { - gs_free_error GError *error = NULL; - - error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED, - "Request for %s secrets doesn't match path %s", - request->request_id, priv->path); - request->callback (NM_SECRET_AGENT_OLD (request->self), request->connection, - NULL, error, request->callback_data); - g_hash_table_remove (priv->requests, request->request_id); - return; + g_set_error (&error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED, + "Request for %s secrets doesn't match path %s", + request->request_id, priv->path); + goto out_fail_error; } - secrets = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_secret_agent_simple_secret_free); + secrets = g_ptr_array_new_with_free_func ((GDestroyNotify) _secret_real_free); if (nm_connection_is_type (request->connection, NM_SETTING_WIRELESS_SETTING_NAME)) { NMSettingWireless *s_wireless; @@ -484,42 +866,43 @@ request_secrets_from_ui (NMSecretAgentSimpleRequest *request) title = _("Authentication required by wireless network"); msg = g_strdup_printf (_("Passwords or encryption keys are required to access the wireless network '%s'."), ssid_utf8); - ok = add_wireless_secrets (request, secrets); + if (!add_wireless_secrets (request, secrets)) + goto out_fail; } else if (nm_connection_is_type (request->connection, NM_SETTING_WIRED_SETTING_NAME)) { title = _("Wired 802.1X authentication"); msg = g_strdup_printf (_("Secrets are required to access the wired network '%s'"), nm_connection_get_id (request->connection)); - ok = add_8021x_secrets (request, secrets); + if (!add_8021x_secrets (request, secrets)) + goto out_fail; } else if (nm_connection_is_type (request->connection, NM_SETTING_PPPOE_SETTING_NAME)) { title = _("DSL authentication"); msg = g_strdup_printf (_("Secrets are required for the DSL connection '%s'"), nm_connection_get_id (request->connection)); - ok = add_pppoe_secrets (request, secrets); + if (!add_pppoe_secrets (request, secrets)) + goto out_fail; } else if (nm_connection_is_type (request->connection, NM_SETTING_GSM_SETTING_NAME)) { NMSettingGsm *s_gsm = nm_connection_get_setting_gsm (request->connection); - if (strv_has (request->hints, "pin")) { + if (g_strv_contains (NM_CAST_STRV_CC (request->hints), NM_SETTING_GSM_PIN)) { title = _("PIN code required"); msg = g_strdup (_("PIN code is needed for the mobile broadband device")); - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY, - _("PIN"), - NM_SETTING (s_gsm), - NM_SETTING_GSM_PIN, - NULL); + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_PROPERTY, + _("PIN"), + NM_SETTING (s_gsm), + NM_SETTING_GSM_PIN); g_ptr_array_add (secrets, secret); } else { title = _("Mobile broadband network password"); msg = g_strdup_printf (_("A password is required to connect to '%s'."), nm_connection_get_id (request->connection)); - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET, - _("Password"), - NM_SETTING (s_gsm), - NM_SETTING_GSM_PASSWORD, - NULL); + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET, + _("Password"), + NM_SETTING (s_gsm), + NM_SETTING_GSM_PASSWORD); g_ptr_array_add (secrets, secret); } } else if (nm_connection_is_type (request->connection, NM_SETTING_MACSEC_SETTING_NAME)) { @@ -530,16 +913,20 @@ request_secrets_from_ui (NMSecretAgentSimpleRequest *request) if (nm_setting_macsec_get_mode (s_macsec) == NM_SETTING_MACSEC_MODE_PSK) { title = _("MACsec PSK authentication"); - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET, - _("MKA CAK"), - NM_SETTING (s_macsec), - NM_SETTING_MACSEC_MKA_CAK, - NULL); + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET, + _("MKA CAK"), + NM_SETTING (s_macsec), + NM_SETTING_MACSEC_MKA_CAK); g_ptr_array_add (secrets, secret); } else { title = _("MACsec EAP authentication"); - ok = add_8021x_secrets (request, secrets); + if (!add_8021x_secrets (request, secrets)) + goto out_fail; } + } else if (nm_connection_is_type (request->connection, NM_SETTING_WIREGUARD_SETTING_NAME)) { + title = _("WireGuard VPN secret"); + if (!add_wireguard_secrets (request, secrets, &msg, &error)) + goto out_fail_error; } else if (nm_connection_is_type (request->connection, NM_SETTING_CDMA_SETTING_NAME)) { NMSettingCdma *s_cdma = nm_connection_get_setting_cdma (request->connection); @@ -547,11 +934,10 @@ request_secrets_from_ui (NMSecretAgentSimpleRequest *request) msg = g_strdup_printf (_("A password is required to connect to '%s'."), nm_connection_get_id (request->connection)); - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET, - _("Password"), - NM_SETTING (s_cdma), - NM_SETTING_CDMA_PASSWORD, - NULL); + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET, + _("Password"), + NM_SETTING (s_cdma), + NM_SETTING_CDMA_PASSWORD); g_ptr_array_add (secrets, secret); } else if (nm_connection_is_type (request->connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) { NMSetting *setting = NULL; @@ -564,73 +950,76 @@ request_secrets_from_ui (NMSecretAgentSimpleRequest *request) setting = nm_connection_get_setting_by_name (request->connection, NM_SETTING_CDMA_SETTING_NAME); } - if (setting) { - title = _("Mobile broadband network password"); - msg = g_strdup_printf (_("A password is required to connect to '%s'."), - nm_connection_get_id (request->connection)); + if (!setting) + goto out_fail; - secret = nm_secret_agent_simple_secret_new (NM_SECRET_AGENT_SECRET_TYPE_SECRET, - _("Password"), - setting, - "password", - NULL); - g_ptr_array_add (secrets, secret); - } else - ok = FALSE; + title = _("Mobile broadband network password"); + msg = g_strdup_printf (_("A password is required to connect to '%s'."), + nm_connection_get_id (request->connection)); + + secret = _secret_real_new_plain (NM_SECRET_AGENT_SECRET_TYPE_SECRET, + _("Password"), + setting, + "password"); + g_ptr_array_add (secrets, secret); } else if (nm_connection_is_type (request->connection, NM_SETTING_VPN_SETTING_NAME)) { title = _("VPN password required"); - msg = NULL; - ok = add_vpn_secrets (request, secrets, &msg); - if (!msg) + if (try_spawn_vpn_auth_helper (request, secrets)) { + /* This will emit REQUEST_SECRETS when ready */ + return; + } + + if (!add_vpn_secrets (request, secrets, &msg)) + goto out_fail; + if (!msg) { msg = g_strdup_printf (_("A password is required to connect to '%s'."), nm_connection_get_id (request->connection)); + } } else - ok = FALSE; - - if (!ok) { - gs_free_error GError *error = NULL; + goto out_fail; - error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED, - "Cannot service a secrets request %s for a %s connection", - request->request_id, - nm_connection_get_connection_type (request->connection)); - request->callback (NM_SECRET_AGENT_OLD (request->self), request->connection, - NULL, error, request->callback_data); - g_hash_table_remove (priv->requests, request->request_id); - g_ptr_array_unref (secrets); - return; - } + if (secrets->len == 0) + goto out_fail; g_signal_emit (request->self, signals[REQUEST_SECRETS], 0, request->request_id, title, msg, secrets); + return; + +out_fail: + g_set_error (&error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED, + "Cannot service a secrets request %s for a %s connection", + request->request_id, + nm_connection_get_connection_type (request->connection)); +out_fail_error: + _request_data_complete (request, NULL, error, NULL); + } static void -nm_secret_agent_simple_get_secrets (NMSecretAgentOld *agent, - NMConnection *connection, - const char *connection_path, - const char *setting_name, - const char **hints, - NMSecretAgentGetSecretsFlags flags, - NMSecretAgentOldGetSecretsFunc callback, - gpointer callback_data) +get_secrets (NMSecretAgentOld *agent, + NMConnection *connection, + const char *connection_path, + const char *setting_name, + const char **hints, + NMSecretAgentGetSecretsFlags flags, + NMSecretAgentOldGetSecretsFunc callback, + gpointer callback_data) { NMSecretAgentSimple *self = NM_SECRET_AGENT_SIMPLE (agent); NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (self); - NMSecretAgentSimpleRequest *request; - char *request_id; - GError *error; + RequestData *request; + gs_free_error GError *error = NULL; + gs_free char *request_id = NULL; + const char *request_id_setting_name; request_id = g_strdup_printf ("%s/%s", connection_path, setting_name); - if (g_hash_table_lookup (priv->requests, request_id) != NULL) { + + if (g_hash_table_contains (priv->requests, &request_id)) { /* We already have a request pending for this (connection, setting) */ error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED, "Request for %s secrets already pending", request_id); - nope: callback (agent, connection, NULL, error, callback_data); - g_error_free (error); - g_free (request_id); return; } @@ -638,17 +1027,27 @@ nm_secret_agent_simple_get_secrets (NMSecretAgentOld *agent, /* We don't do stored passwords */ error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_NO_SECRETS, "Stored passwords not supported"); - goto nope; + callback (agent, connection, NULL, error, callback_data); + return; } - request = g_slice_new (NMSecretAgentSimpleRequest); - request->self = g_object_ref (self); - request->connection = g_object_ref (connection); - request->hints = g_strdupv ((char **)hints); - request->callback = callback; - request->callback_data = callback_data; - request->request_id = request_id; - g_hash_table_replace (priv->requests, request->request_id, request); + nm_assert (g_str_has_suffix (request_id, setting_name)); + request_id_setting_name = &request_id[strlen (request_id) - strlen (setting_name)]; + nm_assert (nm_streq (request_id_setting_name, setting_name)); + + request = g_slice_new (RequestData); + *request = (RequestData) { + .self = self, + .connection = g_object_ref (connection), + .setting_name = request_id_setting_name, + .hints = g_strdupv ((char **) hints), + .callback = callback, + .callback_data = callback_data, + .request_id = g_steal_pointer (&request_id), + .flags = flags, + .cancellable = g_cancellable_new (), + }; + g_hash_table_add (priv->requests, request); if (priv->enabled) request_secrets_from_ui (request); @@ -674,28 +1073,34 @@ nm_secret_agent_simple_response (NMSecretAgentSimple *self, GPtrArray *secrets) { NMSecretAgentSimplePrivate *priv; - NMSecretAgentSimpleRequest *request; - GVariant *dict = NULL; - GError *error = NULL; + RequestData *request; + gs_unref_variant GVariant *secrets_dict = NULL; + gs_free_error GError *error = NULL; int i; g_return_if_fail (NM_IS_SECRET_AGENT_SIMPLE (self)); priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (self); - request = g_hash_table_lookup (priv->requests, request_id); + request = g_hash_table_lookup (priv->requests, &request_id); g_return_if_fail (request != NULL); if (secrets) { GVariantBuilder conn_builder, *setting_builder; GVariantBuilder vpn_secrets_builder; + GVariantBuilder wg_secrets_builder; + GVariantBuilder wg_peer_builder; GHashTable *settings; GHashTableIter iter; const char *name; gboolean has_vpn = FALSE; + gboolean has_wg = FALSE; - settings = g_hash_table_new (nm_str_hash, g_str_equal); + settings = g_hash_table_new_full (nm_str_hash, + g_str_equal, + NULL, + (GDestroyNotify) g_variant_builder_unref); for (i = 0; i < secrets->len; i++) { - NMSecretAgentSimpleSecretReal *secret = secrets->pdata[i]; + SecretReal *secret = secrets->pdata[i]; setting_builder = g_hash_table_lookup (settings, nm_setting_get_name (secret->setting)); if (!setting_builder) { @@ -719,6 +1124,19 @@ nm_secret_agent_simple_response (NMSecretAgentSimple *self, g_variant_builder_add (&vpn_secrets_builder, "{ss}", secret->property, secret->base.value); break; + case NM_SECRET_AGENT_SECRET_TYPE_WIREGUARD_PEER_PSK: + if (!has_wg) { + g_variant_builder_init (&wg_secrets_builder, G_VARIANT_TYPE ("aa{sv}")); + has_wg = TRUE; + } + g_variant_builder_init (&wg_peer_builder, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_add (&wg_peer_builder, "{sv}", + NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY, g_variant_new_string (secret->property)); + g_variant_builder_add (&wg_peer_builder, "{sv}", + NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, g_variant_new_string (secret->base.value)); + g_variant_builder_add (&wg_secrets_builder, "a{sv}", + &wg_peer_builder); + break; } } @@ -728,53 +1146,69 @@ nm_secret_agent_simple_response (NMSecretAgentSimple *self, g_variant_builder_end (&vpn_secrets_builder)); } + if (has_wg) { + g_variant_builder_add (setting_builder, "{sv}", + NM_SETTING_WIREGUARD_PEERS, + g_variant_builder_end (&wg_secrets_builder)); + } + g_variant_builder_init (&conn_builder, NM_VARIANT_TYPE_CONNECTION); g_hash_table_iter_init (&iter, settings); while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &setting_builder)) g_variant_builder_add (&conn_builder, "{sa{sv}}", name, setting_builder); - dict = g_variant_builder_end (&conn_builder); + secrets_dict = g_variant_ref_sink (g_variant_builder_end (&conn_builder)); g_hash_table_destroy (settings); } else { error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_USER_CANCELED, "User cancelled"); } - request->callback (NM_SECRET_AGENT_OLD (self), request->connection, dict, error, request->callback_data); - - g_clear_error (&error); - g_hash_table_remove (priv->requests, request_id); + _request_data_complete (request, secrets_dict, error, NULL); } static void -nm_secret_agent_simple_cancel_get_secrets (NMSecretAgentOld *agent, - const char *connection_path, - const char *setting_name) +cancel_get_secrets (NMSecretAgentOld *agent, + const char *connection_path, + const char *setting_name) { NMSecretAgentSimple *self = NM_SECRET_AGENT_SIMPLE (agent); NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (self); + gs_free_error GError *error = NULL; gs_free char *request_id = NULL; + RequestData *request; request_id = g_strdup_printf ("%s/%s", connection_path, setting_name); - g_hash_table_remove (priv->requests, request_id); + request = g_hash_table_lookup (priv->requests, &request_id); + if (!request) { + /* this is really a bug of the caller (or us?). We cannot invoke a callback, + * hence the caller cannot cleanup the request. */ + g_return_if_reached (); + } + + g_set_error (&error, + NM_SECRET_AGENT_ERROR, + NM_SECRET_AGENT_ERROR_AGENT_CANCELED, + "The secret agent is going away"); + _request_data_complete (request, NULL, error, NULL); } static void -nm_secret_agent_simple_save_secrets (NMSecretAgentOld *agent, - NMConnection *connection, - const char *connection_path, - NMSecretAgentOldSaveSecretsFunc callback, - gpointer callback_data) +save_secrets (NMSecretAgentOld *agent, + NMConnection *connection, + const char *connection_path, + NMSecretAgentOldSaveSecretsFunc callback, + gpointer callback_data) { /* We don't support secret storage */ callback (agent, connection, NULL, callback_data); } static void -nm_secret_agent_simple_delete_secrets (NMSecretAgentOld *agent, - NMConnection *connection, - const char *connection_path, - NMSecretAgentOldDeleteSecretsFunc callback, - gpointer callback_data) +delete_secrets (NMSecretAgentOld *agent, + NMConnection *connection, + const char *connection_path, + NMSecretAgentOldDeleteSecretsFunc callback, + gpointer callback_data) { /* We don't support secret storage, so there's nothing to delete. */ callback (agent, connection, NULL, callback_data); @@ -794,7 +1228,8 @@ void nm_secret_agent_simple_enable (NMSecretAgentSimple *self, const char *path) { NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (self); - GList *requests, *iter; + gs_free RequestData **requests = NULL; + gsize i; gs_free char *path_full = NULL; /* The path is only used to match a request_id with the current @@ -803,10 +1238,9 @@ nm_secret_agent_simple_enable (NMSecretAgentSimple *self, const char *path) */ path_full = path ? g_strdup_printf ("%s/", path) : NULL; - if (g_strcmp0 (path_full, priv->path) != 0) { + if (!nm_streq0 (path_full, priv->path)) { g_free (priv->path); - priv->path = path_full; - path_full = NULL; + priv->path = g_steal_pointer (&path_full); } if (priv->enabled) @@ -814,27 +1248,85 @@ nm_secret_agent_simple_enable (NMSecretAgentSimple *self, const char *path) priv->enabled = TRUE; /* Service pending secret requests. */ - requests = g_hash_table_get_values (priv->requests); - for (iter = requests; iter; iter = g_list_next (iter)) - request_secrets_from_ui (iter->data); + requests = (RequestData **) g_hash_table_get_keys_as_array (priv->requests, NULL); + for (i = 0; requests[i]; i++) + request_secrets_from_ui (requests[i]); +} + +/*****************************************************************************/ + +static void +nm_secret_agent_simple_init (NMSecretAgentSimple *agent) +{ + NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (agent); + + G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (RequestData, request_id) == 0); + priv->requests = g_hash_table_new_full (nm_pstr_hash, nm_pstr_equal, + NULL, _request_data_free); +} + +/** + * nm_secret_agent_simple_new: + * @name: the identifier of secret agent + * + * Creates a new #NMSecretAgentSimple. It does not serve any requests until + * nm_secret_agent_simple_enable() is called. + * + * Returns: a new #NMSecretAgentSimple if the agent creation is successful + * or %NULL in case of a failure. + */ +NMSecretAgentSimple * +nm_secret_agent_simple_new (const char *name) +{ + return g_initable_new (NM_TYPE_SECRET_AGENT_SIMPLE, NULL, NULL, + NM_SECRET_AGENT_OLD_IDENTIFIER, name, + NM_SECRET_AGENT_OLD_CAPABILITIES, NM_SECRET_AGENT_CAPABILITY_VPN_HINTS, + NULL); +} + +static void +dispose (GObject *object) +{ + NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (object); + gs_free_error GError *error = NULL; + GHashTableIter iter; + RequestData *request; + + g_hash_table_iter_init (&iter, priv->requests); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &request)) { + if (!error) + nm_utils_error_set_cancelled (&error, TRUE, "NMSecretAgentSimple"); + _request_data_complete (request, NULL, error, &iter); + } + + G_OBJECT_CLASS (nm_secret_agent_simple_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMSecretAgentSimplePrivate *priv = NM_SECRET_AGENT_SIMPLE_GET_PRIVATE (object); + + g_hash_table_destroy (priv->requests); - g_list_free (requests); + g_free (priv->path); + + G_OBJECT_CLASS (nm_secret_agent_simple_parent_class)->finalize (object); } void nm_secret_agent_simple_class_init (NMSecretAgentSimpleClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); NMSecretAgentOldClass *agent_class = NM_SECRET_AGENT_OLD_CLASS (klass); - g_type_class_add_private (klass, sizeof (NMSecretAgentSimplePrivate)); - - gobject_class->finalize = nm_secret_agent_simple_finalize; + object_class->dispose = dispose; + object_class->finalize = finalize; - agent_class->get_secrets = nm_secret_agent_simple_get_secrets; - agent_class->cancel_get_secrets = nm_secret_agent_simple_cancel_get_secrets; - agent_class->save_secrets = nm_secret_agent_simple_save_secrets; - agent_class->delete_secrets = nm_secret_agent_simple_delete_secrets; + agent_class->get_secrets = get_secrets; + agent_class->cancel_get_secrets = cancel_get_secrets; + agent_class->save_secrets = save_secrets; + agent_class->delete_secrets = delete_secrets; /** * NMSecretAgentSimple::request-secrets: @@ -868,22 +1360,3 @@ nm_secret_agent_simple_class_init (NMSecretAgentSimpleClass *klass) G_TYPE_STRING, /* prompt */ G_TYPE_PTR_ARRAY); } - -/** - * nm_secret_agent_simple_new: - * @name: the identifier of secret agent - * - * Creates a new #NMSecretAgentSimple. It does not serve any requests until - * nm_secret_agent_simple_enable() is called. - * - * Returns: a new #NMSecretAgentSimple if the agent creation is successful - * or %NULL in case of a failure. - */ -NMSecretAgentOld * -nm_secret_agent_simple_new (const char *name) -{ - return g_initable_new (NM_TYPE_SECRET_AGENT_SIMPLE, NULL, NULL, - NM_SECRET_AGENT_OLD_IDENTIFIER, name, - NM_SECRET_AGENT_OLD_CAPABILITIES, NM_SECRET_AGENT_CAPABILITY_VPN_HINTS, - NULL); -} diff --git a/clients/common/nm-secret-agent-simple.h b/clients/common/nm-secret-agent-simple.h index 529aaeac..4a666d17 100644 --- a/clients/common/nm-secret-agent-simple.h +++ b/clients/common/nm-secret-agent-simple.h @@ -21,48 +21,44 @@ #include "nm-secret-agent-old.h" -#define NM_TYPE_SECRET_AGENT_SIMPLE (nm_secret_agent_simple_get_type ()) -#define NM_SECRET_AGENT_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SECRET_AGENT_SIMPLE, NMSecretAgentSimple)) -#define NM_SECRET_AGENT_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SECRET_AGENT_SIMPLE, NMSecretAgentSimpleClass)) -#define NM_IS_SECRET_AGENT_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SECRET_AGENT_SIMPLE)) -#define NM_IS_SECRET_AGENT_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SECRET_AGENT_SIMPLE)) -#define NM_SECRET_AGENT_SIMPLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SECRET_AGENT_SIMPLE, NMSecretAgentSimpleClass)) - -/* Signals */ -#define NM_SECRET_AGENT_SIMPLE_REQUEST_SECRETS "request-secrets" - -typedef struct { - NMSecretAgentOld parent; - -} NMSecretAgentSimple; - -typedef struct { - NMSecretAgentOldClass parent; - -} NMSecretAgentSimpleClass; - typedef enum { NM_SECRET_AGENT_SECRET_TYPE_PROPERTY, NM_SECRET_AGENT_SECRET_TYPE_SECRET, NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET, + NM_SECRET_AGENT_SECRET_TYPE_WIREGUARD_PEER_PSK, } NMSecretAgentSecretType; typedef struct { - const NMSecretAgentSecretType secret_type; + NMSecretAgentSecretType secret_type; const char *pretty_name; const char *entry_id; char *value; const char *vpn_type; - gboolean is_secret; + bool is_secret:1; + bool no_prompt_entry_id:1; } NMSecretAgentSimpleSecret; #define NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRETS "vpn.secrets." #define NM_SECRET_AGENT_VPN_TYPE_OPENCONNECT NM_DBUS_INTERFACE".openconnect" +/*****************************************************************************/ + +#define NM_TYPE_SECRET_AGENT_SIMPLE (nm_secret_agent_simple_get_type ()) +#define NM_SECRET_AGENT_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SECRET_AGENT_SIMPLE, NMSecretAgentSimple)) +#define NM_SECRET_AGENT_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SECRET_AGENT_SIMPLE, NMSecretAgentSimpleClass)) +#define NM_IS_SECRET_AGENT_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SECRET_AGENT_SIMPLE)) +#define NM_IS_SECRET_AGENT_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SECRET_AGENT_SIMPLE)) +#define NM_SECRET_AGENT_SIMPLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SECRET_AGENT_SIMPLE, NMSecretAgentSimpleClass)) + +#define NM_SECRET_AGENT_SIMPLE_REQUEST_SECRETS "request-secrets" + +typedef struct _NMSecretAgentSimple NMSecretAgentSimple; +typedef struct _NMSecretAgentSimpleClass NMSecretAgentSimpleClass; + GType nm_secret_agent_simple_get_type (void); -NMSecretAgentOld *nm_secret_agent_simple_new (const char *name); +NMSecretAgentSimple *nm_secret_agent_simple_new (const char *name); void nm_secret_agent_simple_response (NMSecretAgentSimple *self, const char *request_id, diff --git a/clients/common/nm-vpn-helpers.c b/clients/common/nm-vpn-helpers.c index c3237f12..ea905972 100644 --- a/clients/common/nm-vpn-helpers.c +++ b/clients/common/nm-vpn-helpers.c @@ -25,9 +25,13 @@ #include "nm-vpn-helpers.h" -#include +#include +#include +#include "nm-client-utils.h" #include "nm-utils.h" +#include "nm-utils/nm-io-utils.h" +#include "nm-utils/nm-secret-utils.h" /*****************************************************************************/ @@ -115,27 +119,27 @@ nm_vpn_supports_ipv6 (NMConnection *connection) const VpnPasswordName * nm_vpn_get_secret_names (const char *service_type) { - static const VpnPasswordName const generic_vpn_secrets[] = { + static const VpnPasswordName generic_vpn_secrets[] = { { "password", N_("Password") }, { 0 } }; - static const VpnPasswordName const openvpn_secrets[] = { + static const VpnPasswordName openvpn_secrets[] = { { "password", N_("Password") }, { "cert-pass", N_("Certificate password") }, { "http-proxy-password", N_("HTTP proxy password") }, { 0 } }; - static const VpnPasswordName const vpnc_secrets[] = { + static const VpnPasswordName vpnc_secrets[] = { { "Xauth password", N_("Password") }, { "IPSec secret", N_("Group password") }, { 0 } }; - static const VpnPasswordName const swan_secrets[] = { + static const VpnPasswordName swan_secrets[] = { { "xauthpassword", N_("Password") }, { "pskvalue", N_("Group password") }, { 0 } }; - static const VpnPasswordName const openconnect_secrets[] = { + static const VpnPasswordName openconnect_secrets[] = { { "gateway", N_("Gateway") }, { "cookie", N_("Cookie") }, { "gwcert", N_("Gateway certificate hash") }, @@ -249,3 +253,556 @@ nm_vpn_openconnect_authenticate_helper (const char *host, return TRUE; } +static gboolean +_wg_complete_peer (GPtrArray **p_peers, + NMWireGuardPeer *peer_take, + gsize peer_start_line_nr, + const char *filename, + GError **error) +{ + nm_auto_unref_wgpeer NMWireGuardPeer *peer = peer_take; + gs_free_error GError *local = NULL; + + if (!peer) + return TRUE; + + if (!nm_wireguard_peer_is_valid (peer, TRUE, TRUE, &local)) { + nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, + _("Invalid peer starting at %s:%zu: %s"), + filename, + peer_start_line_nr, + local->message); + return FALSE; + } + + if (!*p_peers) + *p_peers = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_wireguard_peer_unref); + g_ptr_array_add (*p_peers, g_steal_pointer (&peer)); + return TRUE; +} + +static gboolean +_line_match (char *line, const char *key, gsize key_len, const char **out_key, char **out_value) +{ + nm_assert (line); + nm_assert (key); + nm_assert (strlen (key) == key_len); + nm_assert (!strchr (key, '=')); + nm_assert (out_key && !*out_key); + nm_assert (out_value && !*out_value); + + /* Note that `wg-quick` (linux.bash) does case-insensitive comparison (shopt -s nocasematch). + * `wg setconf` does case-insensitive comparison too (with strncasecmp, which is locale dependent). + * + * We do a case-insensitive comparison of the key, however in a locale-independent manner. */ + + if (g_ascii_strncasecmp (line, key, key_len) != 0) + return FALSE; + + if (line[key_len] != '=') + return FALSE; + + *out_key = key; + *out_value = &line[key_len + 1]; + return TRUE; +} + +#define line_match(line, key, out_key, out_value) \ + _line_match ((line), ""key"", NM_STRLEN (key), (out_key), (out_value)) + +static gboolean +value_split_word (char **line_remainder, char **out_word) +{ + char *str; + + if ((*line_remainder)[0] == '\0') + return FALSE; + + *out_word = *line_remainder; + + str = strchrnul (*line_remainder, ','); + if (str[0] == ',') { + str[0] = '\0'; + *line_remainder = &str[1]; + } else + *line_remainder = str; + return TRUE; +} + +NMConnection * +nm_vpn_wireguard_import (const char *filename, + GError **error) +{ + nm_auto_clear_secret_ptr NMSecretPtr file_content = NM_SECRET_PTR_INIT (); + char ifname[IFNAMSIZ]; + gs_free char *uuid = NULL; + gboolean ifname_valid = FALSE; + const char *cstr; + char *line_remainder; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection *s_con; + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; + NMSettingWireGuard *s_wg; + gs_free_error GError *local = NULL; + enum { + LINE_CONTEXT_INIT, + LINE_CONTEXT_INTERFACE, + LINE_CONTEXT_PEER, + } line_context; + gsize line_nr; + gsize current_peer_start_line_nr = 0; + nm_auto_unref_wgpeer NMWireGuardPeer *current_peer = NULL; + gs_unref_ptrarray GPtrArray *data_dns_v4 = NULL; + gs_unref_ptrarray GPtrArray *data_dns_v6 = NULL; + gs_unref_ptrarray GPtrArray *data_addr_v4 = NULL; + gs_unref_ptrarray GPtrArray *data_addr_v6 = NULL; + gs_unref_ptrarray GPtrArray *data_peers = NULL; + const char *data_private_key = NULL; + gint64 data_table; + guint data_listen_port = 0; + guint data_fwmark = 0; + guint data_mtu = 0; + int is_v4; + guint i; + + g_return_val_if_fail (filename, NULL); + g_return_val_if_fail (!error || !*error, NULL); + + /* contrary to "wg-quick", we never interpret the filename as "/etc/wireguard/$INTERFACE.conf". + * If the filename has no '/', it is interpreted as relative to the current working directory. + * However, we do require a suitable filename suffix and that the name corresponds to the interface + * name. */ + cstr = strrchr (filename, '/'); + cstr = cstr ? &cstr[1] : filename; + if (NM_STR_HAS_SUFFIX (cstr, ".conf")) { + gsize len = strlen (cstr) - NM_STRLEN (".conf"); + + if (len > 0 && len < sizeof (ifname)) { + memcpy (ifname, cstr, len); + ifname[len] = '\0'; + + if (nm_utils_is_valid_iface_name (ifname, 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\"")); + return FALSE; + } + + if (nm_utils_file_get_contents (-1, + filename, + 10*1024*1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET, + &file_content.str, + &file_content.len, + error) < 0) + return NULL; + + /* We interpret the file like `wg-quick up` and `wg setconf` do. + * + * Of course the WireGuard scripts do something fundamentlly different. They + * perform actions to configure the WireGuard link in kernel, add routes and + * addresses, and call resolvconf. It all happens at the time when the script + * run. + * + * This code here instead generates a NetworkManager connection profile so that + * NetworkManager will apply a similar configuration when later activating the profile. */ + +#define _TABLE_AUTO ((gint64) -1) +#define _TABLE_OFF ((gint64) -2) + + data_table = _TABLE_AUTO; + + line_remainder = file_content.str; + line_context = LINE_CONTEXT_INIT; + line_nr = 0; + while (line_remainder[0] != '\0') { + const char *matched_key = NULL; + char *value = NULL; + char *line; + char ch; + gint64 i64; + + line_nr++; + + line = line_remainder; + line_remainder = strchrnul (line, '\n'); + if (line_remainder[0] != '\0') + (line_remainder++)[0] = '\0'; + + /* Drop all spaces and truncate at first '#'. + * See wg's config_read_line(). + * + * Note that wg-quick doesn't do that. + * + * Neither `wg setconf` nor `wg-quick` does a strict parsing. + * We don't either. Just try to interpret the file (mostly) the same as + * they would. + */ + { + gsize l, n; + + n = 0; + for (l = 0; (ch = line[l]); l++) { + if (g_ascii_isspace (ch)) { + /* wg-setconf strips all whitespace before parsing the content. That means, + * *[I nterface]" will be accepted. We do that too. */ + continue; + } + if (ch == '#') + break; + line[n++] = line[l]; + } + if (n == 0) + continue; + line[n] = '\0'; + } + + if (g_ascii_strcasecmp (line, "[Interface]") == 0) { + if (!_wg_complete_peer (&data_peers, + g_steal_pointer (¤t_peer), + current_peer_start_line_nr, + filename, + error)) + return FALSE; + line_context = LINE_CONTEXT_INTERFACE; + continue; + } + + if (g_ascii_strcasecmp (line, "[Peer]") == 0) { + if (!_wg_complete_peer (&data_peers, + g_steal_pointer (¤t_peer), + current_peer_start_line_nr, + filename, + error)) + return FALSE; + current_peer_start_line_nr = line_nr; + current_peer = nm_wireguard_peer_new (); + line_context = LINE_CONTEXT_PEER; + continue; + } + + if (line_context == LINE_CONTEXT_INTERFACE) { + + if (line_match (line, "Address", &matched_key, &value)) { + char *value_word; + + while (value_split_word (&value, &value_word)) { + GPtrArray **p_data_addr; + NMIPAddr addr_bin; + int addr_family; + int prefix_len; + + if (!nm_utils_parse_inaddr_prefix_bin (AF_UNSPEC, + value_word, + &addr_family, + &addr_bin, + &prefix_len)) + goto fail_invalid_value; + + p_data_addr = (addr_family == AF_INET) + ? &data_addr_v4 + : &data_addr_v6; + + if (!*p_data_addr) + *p_data_addr = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref); + + g_ptr_array_add (*p_data_addr, + nm_ip_address_new_binary (addr_family, + &addr_bin, + prefix_len == -1 + ? ((addr_family == AF_INET) ? 32 : 128) + : prefix_len, + NULL)); + } + continue; + } + + if (line_match (line, "MTU", &matched_key, &value)) { + i64 = _nm_utils_ascii_str_to_int64 (value, 0, 0, G_MAXUINT32, -1); + if (i64 == -1) + goto fail_invalid_value; + + /* wg-quick accepts the "MTU" value, but it also fetches routes to + * autodetect it. NetworkManager won't do that, we can only configure + * an explicit MTU or no autodetection will be performed. */ + data_mtu = i64; + continue; + } + + if (line_match (line, "DNS", &matched_key, &value)) { + 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; + + if (!nm_utils_parse_inaddr_bin (AF_UNSPEC, + value_word, + &addr_family, + &addr_bin)) + goto fail_invalid_value; + + p_data_dns = (addr_family == AF_INET) + ? &data_dns_v4 + : &data_dns_v6; + 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)); + } + continue; + } + + if (line_match (line, "Table", &matched_key, &value)) { + + if (nm_streq (value, "auto")) + data_table = _TABLE_AUTO; + else if (nm_streq (value, "off")) + data_table = _TABLE_OFF; + else { + /* we don't support table names from /etc/iproute2/rt_tables + * But we accept hex like `ip route add` would. */ + i64 = _nm_utils_ascii_str_to_int64 (value, 0, 0, G_MAXINT32, -1); + if (i64 == -1) + goto fail_invalid_value; + data_table = i64; + } + continue; + } + + if ( line_match (line, "PreUp", &matched_key, &value) + || line_match (line, "PreDown", &matched_key, &value) + || line_match (line, "PostUp", &matched_key, &value) + || line_match (line, "PostDown", &matched_key, &value)) { + /* we don't run any scripts. Silently ignore these parameters. */ + continue; + } + + if (line_match (line, "SaveConfig", &matched_key, &value)) { + /* we ignore the setting, but enforce that it's either true or false (like + * wg-quick. */ + if (!NM_IN_STRSET (value, "true", "false")) + goto fail_invalid_value; + continue; + } + + if (line_match (line, "ListenPort", &matched_key, &value)) { + /* we don't use getaddrinfo(), unlike `wg setconf`. Just interpret + * the port as plain decimal number. */ + i64 = _nm_utils_ascii_str_to_int64 (value, 10, 0, 0xFFFF, -1); + if (i64 == -1) + goto fail_invalid_value; + data_listen_port = i64; + continue; + } + + if (line_match (line, "FwMark", &matched_key, &value)) { + if (nm_streq (value, "off")) + data_fwmark = 0; + else { + i64 = _nm_utils_ascii_str_to_int64 (value, 0, 0, G_MAXINT32, -1); + if (i64 == -1) + goto fail_invalid_value; + data_fwmark = i64; + } + continue; + } + + if (line_match (line, "PrivateKey", &matched_key, &value)) { + if (!nm_utils_base64secret_decode (value, NM_WIREGUARD_PUBLIC_KEY_LEN, NULL)) + goto fail_invalid_secret; + data_private_key = value; + continue; + } + + goto fail_invalid_line; + } + + + if (line_context == LINE_CONTEXT_PEER) { + + if (line_match (line, "Endpoint", &matched_key, &value)) { + if (!nm_wireguard_peer_set_endpoint (current_peer, value, FALSE)) + goto fail_invalid_value; + continue; + } + + if (line_match (line, "PublicKey", &matched_key, &value)) { + if (!nm_wireguard_peer_set_public_key (current_peer, value, FALSE)) + goto fail_invalid_value; + continue; + } + + if (line_match (line, "AllowedIPs", &matched_key, &value)) { + char *value_word; + + while (value_split_word (&value, &value_word)) { + if (!nm_wireguard_peer_append_allowed_ip (current_peer, + value_word, + FALSE)) + goto fail_invalid_value; + } + continue; + } + + if (line_match (line, "PersistentKeepalive", &matched_key, &value)) { + if (nm_streq (value, "off")) + i64 = 0; + else { + i64 = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT16, -1); + if (i64 == -1) + goto fail_invalid_value; + } + nm_wireguard_peer_set_persistent_keepalive (current_peer, i64); + continue; + } + + if (line_match (line, "PresharedKey", &matched_key, &value)) { + if (!nm_wireguard_peer_set_preshared_key (current_peer, value, FALSE)) + goto fail_invalid_secret; + nm_wireguard_peer_set_preshared_key_flags (current_peer, NM_SETTING_SECRET_FLAG_NONE); + continue; + } + + goto fail_invalid_line; + } + +fail_invalid_line: + nm_utils_error_set (error, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("unrecognized line at %s:%zu"), + filename, line_nr); + return FALSE; +fail_invalid_value: + nm_utils_error_set (error, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("invalid value for '%s' at %s:%zu"), + matched_key, filename, line_nr); + return FALSE; +fail_invalid_secret: + nm_utils_error_set (error, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("invalid secret '%s' at %s:%zu"), + matched_key, filename, line_nr); + return FALSE; + } + + if (!_wg_complete_peer (&data_peers, + g_steal_pointer (¤t_peer), + current_peer_start_line_nr, + filename, + error)) + return FALSE; + + connection = nm_simple_connection_new (); + s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ()); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + s_ip4 = NM_SETTING_IP_CONFIG (nm_setting_ip4_config_new ()); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + s_ip6 = NM_SETTING_IP_CONFIG (nm_setting_ip6_config_new ()); + nm_connection_add_setting (connection, NM_SETTING (s_ip6)); + s_wg = NM_SETTING_WIREGUARD (nm_setting_wireguard_new ()); + nm_connection_add_setting (connection, NM_SETTING (s_wg)); + + uuid = nm_utils_uuid_generate (); + + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, + ifname, + NM_SETTING_CONNECTION_UUID, + uuid, + NM_SETTING_CONNECTION_TYPE, + NM_SETTING_WIREGUARD_SETTING_NAME, + NM_SETTING_CONNECTION_INTERFACE_NAME, + ifname, + NULL); + + g_object_set (s_wg, + NM_SETTING_WIREGUARD_PRIVATE_KEY, + data_private_key, + NM_SETTING_WIREGUARD_LISTEN_PORT, + data_listen_port, + NM_SETTING_WIREGUARD_FWMARK, + data_fwmark, + NM_SETTING_WIREGUARD_MTU, + data_mtu, + NULL); + + if (data_peers) { + for (i = 0; i < data_peers->len; i++) + nm_setting_wireguard_append_peer (s_wg, data_peers->pdata[i]); + } + + for (is_v4 = 0; is_v4 < 2; is_v4++) { + const char *method_disabled = is_v4 ? NM_SETTING_IP4_CONFIG_METHOD_DISABLED : NM_SETTING_IP6_CONFIG_METHOD_IGNORE; + const char *method_manual = is_v4 ? NM_SETTING_IP4_CONFIG_METHOD_MANUAL : NM_SETTING_IP6_CONFIG_METHOD_MANUAL; + NMSettingIPConfig *s_ip = is_v4 ? s_ip4 : s_ip6; + GPtrArray *data_dns = is_v4 ? data_dns_v4 : data_dns_v6; + GPtrArray *data_addr = is_v4 ? data_addr_v4 : data_addr_v6; + + if (data_dns && !data_addr) { + /* When specifying "DNS", we also require an "Address" for the same address + * family. That is because a NMSettingIPConfig cannot have @method_disabled + * and DNS settings at the same time. + * + * We don't have addresses. Silently ignore the DNS setting. */ + data_dns = NULL; + } + + g_object_set (s_ip, + NM_SETTING_IP_CONFIG_METHOD, + data_addr ? method_manual : method_disabled, + NULL); + + if (data_addr) { + for (i = 0; i < data_addr->len; i++) + nm_setting_ip_config_add_address (s_ip, data_addr->pdata[i]); + } + if (data_dns) { + for (i = 0; i < data_dns->len; i++) + nm_setting_ip_config_add_dns (s_ip, data_dns->pdata[i]); + } + + if (data_table == _TABLE_AUTO) { + /* in the "auto" setting, wg-quick adds peer-routes automatically to the main + * table. NetworkManager will do that too, but there are differences: + * + * - NetworkManager (contrary to wg-quick) does not check whether the peer-route is necessary. + * It will always add a route for each allowed-ips range, even if there is already another + * route that would ensure packets to the endpoint are routed via the WireGuard interface. + * If you don't want that, disable "wireguard.peer-routes", and add the necessary routes + * 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). + */ + } else if (data_table == _TABLE_OFF) { + if (is_v4) { + g_object_set (s_wg, + NM_SETTING_WIREGUARD_PEER_ROUTES, + FALSE, + NULL); + } + } else { + g_object_set (s_ip, + NM_SETTING_IP_CONFIG_ROUTE_TABLE, + (guint) data_table, + NULL); + } + } + + if (!nm_connection_normalize (connection, NULL, NULL, &local)) { + nm_utils_error_set (error, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("Failed to create WireGuard connection: %s"), + local->message); + return FALSE; + } + + return g_steal_pointer (&connection); +} diff --git a/clients/common/nm-vpn-helpers.h b/clients/common/nm-vpn-helpers.h index 4c15faa1..686687ba 100644 --- a/clients/common/nm-vpn-helpers.h +++ b/clients/common/nm-vpn-helpers.h @@ -39,4 +39,7 @@ gboolean nm_vpn_openconnect_authenticate_helper (const char *host, int *status, GError **error); +NMConnection *nm_vpn_wireguard_import (const char *filename, + GError **error); + #endif /* __NM_VPN_HELPERS_H__ */ diff --git a/clients/common/settings-docs.h b/clients/common/settings-docs.h index bc56edae..7b958faa 100644 --- a/clients/common/settings-docs.h +++ b/clients/common/settings-docs.h @@ -24,14 +24,14 @@ #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-none\" (Ad-Hoc WPA-PSK), \"wpa-psk\" (infrastructure WPA-PSK), 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-none\" (Ad-Hoc WPA-PSK), \"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_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\").") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PAIRWISE N_("A list of pairwise 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 \"tkip\" or \"ccmp\".") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PMF N_("Indicates whether Protected Management Frames (802.11w) must be enabled for the connection. One of NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) (use global default value), NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE (1) (disable PMF), NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL (2) (enable PMF if the supplicant and the access point support it) or NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED (3) (enable PMF and fail if not supported). When set to NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) and no global default is set, PMF will be optionally enabled.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PROTO N_("List of strings specifying the allowed WPA protocol versions to use. Each element may be one \"wpa\" (allow WPA) or \"rsn\" (allow WPA2/RSN). If not specified, both WPA and RSN connections are allowed.") -#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PSK N_("Pre-Shared-Key for WPA networks. If the key is 64-characters long, it must contain only hexadecimal characters and is interpreted as a hexadecimal WPA key. Otherwise, the key must be between 8 and 63 ASCII characters (as specified in the 802.11i standard) and is interpreted as a WPA passphrase, and is hashed to derive the actual WPA-PSK used when connecting to the Wi-Fi network.") +#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PSK N_("Pre-Shared-Key for WPA networks. For WPA-PSK, it's either an ASCII passphrase of 8 to 63 characters that is (as specified in the 802.11i standard) hashed to derive the actual key, or the key in form of 64 hexadecimal character. The WPA3-Personal networks use a passphrase of any length for SAE authentication.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS N_("Flags indicating how to handle the \"psk\" property.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS N_("Flags indicating how to handle the \"wep-key0\", \"wep-key1\", \"wep-key2\", and \"wep-key3\" properties.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE N_("Controls the interpretation of WEP keys. Allowed values are NM_WEP_KEY_TYPE_KEY (1), in which case the key is either a 10- or 26-character hexadecimal string, or a 5- or 13-character ASCII password; or NM_WEP_KEY_TYPE_PASSPHRASE (2), in which case the passphrase is provided as a string and will be hashed using the de-facto MD5 method to derive the actual WEP key.") @@ -144,7 +144,7 @@ #define DESCRIBE_DOC_NM_SETTING_CONNECTION_READ_ONLY N_("FALSE if the connection can be modified using the provided settings service's D-Bus interface with the right privileges, or TRUE if the connection is read-only and cannot be modified.") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_SECONDARIES N_("List of connection UUIDs that should be activated when the base connection itself is activated. Currently only VPN connections are supported.") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_SLAVE_TYPE N_("Setting name of the device type of this slave's master connection (eg, \"bond\"), or NULL if this connection is not a slave.") -#define DESCRIBE_DOC_NM_SETTING_CONNECTION_STABLE_ID N_("This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are \"${CONNECTION}\", \"${DEVICE}\", \"${MAC}\", \"${BOOT}\", \"${RANDOM}\". These effectively create unique IDs per-connection, per-device, per-boot, or every time. Note that \"${DEVICE}\" corresponds the the interface name of the device and \"${MAC}\" is the permanent MAC address of the device. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as \"$$\". For example, set it to \"${CONNECTION}-${BOOT}-${DEVICE}\" to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is similar to \"${CONNECTION}\" and uses a unique, fixed ID for the connection.") +#define DESCRIBE_DOC_NM_SETTING_CONNECTION_STABLE_ID N_("This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are \"${CONNECTION}\", \"${DEVICE}\", \"${MAC}\", \"${BOOT}\", \"${RANDOM}\". These effectively create unique IDs per-connection, per-device, per-boot, or every time. Note that \"${DEVICE}\" corresponds to the interface name of the device and \"${MAC}\" is the permanent MAC address of the device. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as \"$$\". For example, set it to \"${CONNECTION}-${BOOT}-${DEVICE}\" to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is similar to \"${CONNECTION}\" and uses a unique, fixed ID for the connection.") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_TIMESTAMP N_("The time, in seconds since the Unix Epoch, that the connection was last _successfully_ fully activated. NetworkManager updates the connection timestamp periodically when the connection is active to ensure that an active connection has the latest timestamp. The property is only meant for reading (changes to this property will not be preserved).") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_TYPE N_("Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, \"802-3-ethernet\" or \"802-11-wireless\" or \"bluetooth\", etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, \"vpn\" or \"bridge\", etc).") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_UUID N_("A universally unique identifier for the connection, for example generated with libuuid. It should be assigned when the connection is created, and never changed as long as the connection still applies to the same network. For example, it should not be changed when the \"id\" property or NMSettingIP4Config changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband network provider, or \"type\" property changes. The UUID must be in the format \"2815492f-7e56-435e-b2e9-246bd7cdc664\" (ie, contains only hexadecimal characters and \"-\").") @@ -169,7 +169,7 @@ #define DESCRIBE_DOC_NM_SETTING_GSM_HOME_ONLY N_("When TRUE, only connections to the home network will be allowed. Connections to roaming networks will not be made.") #define DESCRIBE_DOC_NM_SETTING_GSM_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.") #define DESCRIBE_DOC_NM_SETTING_GSM_NETWORK_ID N_("The Network ID (GSM LAI format, ie MCC-MNC) to force specific network registration. If the Network ID is specified, NetworkManager will attempt to force the device to register only on the specified network. This can be used to ensure that the device does not roam when direct roaming control of the device is not otherwise possible.") -#define DESCRIBE_DOC_NM_SETTING_GSM_NUMBER N_("Number to dial when establishing a PPP data session with the GSM-based mobile broadband network. Many modems do not require PPP for connections to the mobile network and thus this property should be left blank, which allows NetworkManager to select the appropriate settings automatically.") +#define DESCRIBE_DOC_NM_SETTING_GSM_NUMBER N_("Legacy setting that used to help establishing PPP data sessions for GSM-based modems. Deprecated: 1") #define DESCRIBE_DOC_NM_SETTING_GSM_PASSWORD N_("The password used to authenticate with the network, if required. Many providers do not require a password, or accept any password. But if a password is required, it is specified here.") #define DESCRIBE_DOC_NM_SETTING_GSM_PASSWORD_FLAGS N_("Flags indicating how to handle the \"password\" property.") #define DESCRIBE_DOC_NM_SETTING_GSM_PIN N_("If the SIM is locked with a PIN it must be unlocked before any other operations are requested. Specify the PIN here to allow operation of the device.") @@ -204,7 +204,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds.") #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 the default value, which is 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, the one with an active default route will be preferred. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports split-DNS 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 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, the one with an active default route will be preferred. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports split-DNS 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.") @@ -224,7 +224,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds.") #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 the default value, which is 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, the one with an active default route will be preferred. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports split-DNS 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 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, the one with an active default route will be preferred. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports split-DNS 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.") @@ -301,7 +301,7 @@ #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.") #define DESCRIBE_DOC_NM_SETTING_TEAM_CONFIG N_("The JSON configuration for the team network interface. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details.") -#define DESCRIBE_DOC_NM_SETTING_TEAM_LINK_WATCHERS N_("Link watchers configuration for the connection: each link watcher is defined by a dictionary, whose keys depend upon the selected link watcher. Available link watchers are 'ethtool', 'nsna_ping' and 'arp_ping' and it is specified in the dictionary with the key 'name'. Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait'; nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host'; arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', 'validate-incative', 'send-always'. See teamd.conf man for more details.") +#define DESCRIBE_DOC_NM_SETTING_TEAM_LINK_WATCHERS N_("Link watchers configuration for the connection: each link watcher is defined by a dictionary, whose keys depend upon the selected link watcher. Available link watchers are 'ethtool', 'nsna_ping' and 'arp_ping' and it is specified in the dictionary with the key 'name'. Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait'; nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host'; arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', 'validate-inactive', 'send-always'. See teamd.conf man for more details.") #define DESCRIBE_DOC_NM_SETTING_TEAM_MCAST_REJOIN_COUNT N_("Corresponds to the teamd mcast_rejoin.count.") #define DESCRIBE_DOC_NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL N_("Corresponds to the teamd mcast_rejoin.interval.") #define DESCRIBE_DOC_NM_SETTING_TEAM_NOTIFY_PEERS_COUNT N_("Corresponds to the teamd notify_peers.count.") @@ -319,7 +319,7 @@ #define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_CONFIG N_("The JSON configuration for the team port. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details.") #define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_LACP_KEY N_("Corresponds to the teamd ports.PORTIFNAME.lacp_key.") #define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_LACP_PRIO N_("Corresponds to the teamd ports.PORTIFNAME.lacp_prio.") -#define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_LINK_WATCHERS N_("Link watchers configuration for the connection: each link watcher is defined by a dictionary, whose keys depend upon the selected link watcher. Available link watchers are 'ethtool', 'nsna_ping' and 'arp_ping' and it is specified in the dictionary with the key 'name'. Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait'; nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host'; arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', 'validate-incative', 'send-always'. See teamd.conf man for more details.") +#define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_LINK_WATCHERS N_("Link watchers configuration for the connection: each link watcher is defined by a dictionary, whose keys depend upon the selected link watcher. Available link watchers are 'ethtool', 'nsna_ping' and 'arp_ping' and it is specified in the dictionary with the key 'name'. Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait'; nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host'; arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', 'validate-inactive', 'send-always'. See teamd.conf man for more details.") #define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_PRIO N_("Corresponds to the teamd ports.PORTIFNAME.prio.") #define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_QUEUE_ID N_("Corresponds to the teamd ports.PORTIFNAME.queue_id. When set to -1 means the parameter is skipped from the json config.") #define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_STICKY N_("Corresponds to the teamd ports.PORTIFNAME.sticky.") @@ -357,8 +357,19 @@ #define DESCRIBE_DOC_NM_SETTING_VXLAN_SOURCE_PORT_MIN N_("Specifies the minimum UDP source port to communicate to the remote VXLAN tunnel endpoint.") #define DESCRIBE_DOC_NM_SETTING_VXLAN_TOS N_("Specifies the TOS value to use in outgoing packets.") #define DESCRIBE_DOC_NM_SETTING_VXLAN_TTL N_("Specifies the time-to-live value to use in outgoing packets.") +#define DESCRIBE_DOC_NM_SETTING_WIFI_P2P_PEER N_("The P2P device that should be connected to. Currently this is the only way to create or join a group.") +#define DESCRIBE_DOC_NM_SETTING_WIFI_P2P_WFD_IES N_("The Wi-Fi Display (WFD) Information Elements (IEs) to set. Wi-Fi Display requires a protocol specific information element to be set in certain Wi-Fi frames. These can be specified here for the purpose of establishing a connection. This setting is only useful when implementing a Wi-Fi Display client.") +#define DESCRIBE_DOC_NM_SETTING_WIFI_P2P_WPS_METHOD N_("Flags indicating which mode of WPS is to be used. There's little point in changing the default setting as NetworkManager will automatically determine the best method to use.") #define DESCRIBE_DOC_NM_SETTING_WIMAX_MAC_ADDRESS N_("If specified, this connection will only apply to the WiMAX device whose MAC address matches. This property does not change the MAC address of the device (known as MAC spoofing). Deprecated: 1") #define DESCRIBE_DOC_NM_SETTING_WIMAX_NETWORK_NAME N_("Network Service Provider (NSP) name of the WiMAX network this connection should use. Deprecated: 1") +#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_FWMARK N_("The use of fwmark is optional and is by default off. Setting it to 0 disables it. Otherwise it is a 32-bit fwmark for outgoing packets.") +#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_LISTEN_PORT N_("The listen-port. If listen-port is not specified, the port will be chosen randomly when the interface comes up.") +#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple fragments. If zero a default MTU is used. Note that contrary to wg-quick's MTU setting, this does not take into account the current routes at the time of activation.") +#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_PEER_ROUTES N_("Whether to automatically add routes for the AllowedIPs ranges of the peers. If TRUE (the default), NetworkManager will automatically add routes in the routing tables according to ipv4.route-table and ipv6.route-table. If FALSE, no such routes are added automatically. In this case, the user may want to configure static routes in ipv4.routes and ipv6.routes, respectively.") +#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_PRIVATE_KEY N_("The 256 bit private-key in base64 encoding.") +#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS N_("Flags indicating how to handle the \"private-key\" property.") +#define DESCRIBE_DOC_NM_SETTING_WPAN_CHANNEL N_("IEEE 802.15.4 channel. A positive integer or -1, meaning \"do not set, use whatever the device is already set to\".") #define DESCRIBE_DOC_NM_SETTING_WPAN_MAC_ADDRESS N_("If specified, this connection will only apply to the IEEE 802.15.4 (WPAN) MAC layer device whose permanent MAC address matches.") +#define DESCRIBE_DOC_NM_SETTING_WPAN_PAGE N_("IEEE 802.15.4 channel page. A positive integer or -1, meaning \"do not set, use whatever the device is already set to\".") #define DESCRIBE_DOC_NM_SETTING_WPAN_PAN_ID N_("IEEE 802.15.4 Personal Area Network (PAN) identifier.") #define DESCRIBE_DOC_NM_SETTING_WPAN_SHORT_ADDRESS N_("Short IEEE 802.15.4 address to be used within a restricted environment.") diff --git a/clients/common/settings-docs.h.in b/clients/common/settings-docs.h.in index bc56edae..7b958faa 100644 --- a/clients/common/settings-docs.h.in +++ b/clients/common/settings-docs.h.in @@ -24,14 +24,14 @@ #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-none\" (Ad-Hoc WPA-PSK), \"wpa-psk\" (infrastructure WPA-PSK), 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-none\" (Ad-Hoc WPA-PSK), \"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_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\").") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PAIRWISE N_("A list of pairwise 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 \"tkip\" or \"ccmp\".") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PMF N_("Indicates whether Protected Management Frames (802.11w) must be enabled for the connection. One of NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) (use global default value), NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE (1) (disable PMF), NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL (2) (enable PMF if the supplicant and the access point support it) or NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED (3) (enable PMF and fail if not supported). When set to NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) and no global default is set, PMF will be optionally enabled.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PROTO N_("List of strings specifying the allowed WPA protocol versions to use. Each element may be one \"wpa\" (allow WPA) or \"rsn\" (allow WPA2/RSN). If not specified, both WPA and RSN connections are allowed.") -#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PSK N_("Pre-Shared-Key for WPA networks. If the key is 64-characters long, it must contain only hexadecimal characters and is interpreted as a hexadecimal WPA key. Otherwise, the key must be between 8 and 63 ASCII characters (as specified in the 802.11i standard) and is interpreted as a WPA passphrase, and is hashed to derive the actual WPA-PSK used when connecting to the Wi-Fi network.") +#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PSK N_("Pre-Shared-Key for WPA networks. For WPA-PSK, it's either an ASCII passphrase of 8 to 63 characters that is (as specified in the 802.11i standard) hashed to derive the actual key, or the key in form of 64 hexadecimal character. The WPA3-Personal networks use a passphrase of any length for SAE authentication.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS N_("Flags indicating how to handle the \"psk\" property.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS N_("Flags indicating how to handle the \"wep-key0\", \"wep-key1\", \"wep-key2\", and \"wep-key3\" properties.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE N_("Controls the interpretation of WEP keys. Allowed values are NM_WEP_KEY_TYPE_KEY (1), in which case the key is either a 10- or 26-character hexadecimal string, or a 5- or 13-character ASCII password; or NM_WEP_KEY_TYPE_PASSPHRASE (2), in which case the passphrase is provided as a string and will be hashed using the de-facto MD5 method to derive the actual WEP key.") @@ -144,7 +144,7 @@ #define DESCRIBE_DOC_NM_SETTING_CONNECTION_READ_ONLY N_("FALSE if the connection can be modified using the provided settings service's D-Bus interface with the right privileges, or TRUE if the connection is read-only and cannot be modified.") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_SECONDARIES N_("List of connection UUIDs that should be activated when the base connection itself is activated. Currently only VPN connections are supported.") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_SLAVE_TYPE N_("Setting name of the device type of this slave's master connection (eg, \"bond\"), or NULL if this connection is not a slave.") -#define DESCRIBE_DOC_NM_SETTING_CONNECTION_STABLE_ID N_("This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are \"${CONNECTION}\", \"${DEVICE}\", \"${MAC}\", \"${BOOT}\", \"${RANDOM}\". These effectively create unique IDs per-connection, per-device, per-boot, or every time. Note that \"${DEVICE}\" corresponds the the interface name of the device and \"${MAC}\" is the permanent MAC address of the device. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as \"$$\". For example, set it to \"${CONNECTION}-${BOOT}-${DEVICE}\" to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is similar to \"${CONNECTION}\" and uses a unique, fixed ID for the connection.") +#define DESCRIBE_DOC_NM_SETTING_CONNECTION_STABLE_ID N_("This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are \"${CONNECTION}\", \"${DEVICE}\", \"${MAC}\", \"${BOOT}\", \"${RANDOM}\". These effectively create unique IDs per-connection, per-device, per-boot, or every time. Note that \"${DEVICE}\" corresponds to the interface name of the device and \"${MAC}\" is the permanent MAC address of the device. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as \"$$\". For example, set it to \"${CONNECTION}-${BOOT}-${DEVICE}\" to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is similar to \"${CONNECTION}\" and uses a unique, fixed ID for the connection.") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_TIMESTAMP N_("The time, in seconds since the Unix Epoch, that the connection was last _successfully_ fully activated. NetworkManager updates the connection timestamp periodically when the connection is active to ensure that an active connection has the latest timestamp. The property is only meant for reading (changes to this property will not be preserved).") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_TYPE N_("Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, \"802-3-ethernet\" or \"802-11-wireless\" or \"bluetooth\", etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, \"vpn\" or \"bridge\", etc).") #define DESCRIBE_DOC_NM_SETTING_CONNECTION_UUID N_("A universally unique identifier for the connection, for example generated with libuuid. It should be assigned when the connection is created, and never changed as long as the connection still applies to the same network. For example, it should not be changed when the \"id\" property or NMSettingIP4Config changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband network provider, or \"type\" property changes. The UUID must be in the format \"2815492f-7e56-435e-b2e9-246bd7cdc664\" (ie, contains only hexadecimal characters and \"-\").") @@ -169,7 +169,7 @@ #define DESCRIBE_DOC_NM_SETTING_GSM_HOME_ONLY N_("When TRUE, only connections to the home network will be allowed. Connections to roaming networks will not be made.") #define DESCRIBE_DOC_NM_SETTING_GSM_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.") #define DESCRIBE_DOC_NM_SETTING_GSM_NETWORK_ID N_("The Network ID (GSM LAI format, ie MCC-MNC) to force specific network registration. If the Network ID is specified, NetworkManager will attempt to force the device to register only on the specified network. This can be used to ensure that the device does not roam when direct roaming control of the device is not otherwise possible.") -#define DESCRIBE_DOC_NM_SETTING_GSM_NUMBER N_("Number to dial when establishing a PPP data session with the GSM-based mobile broadband network. Many modems do not require PPP for connections to the mobile network and thus this property should be left blank, which allows NetworkManager to select the appropriate settings automatically.") +#define DESCRIBE_DOC_NM_SETTING_GSM_NUMBER N_("Legacy setting that used to help establishing PPP data sessions for GSM-based modems. Deprecated: 1") #define DESCRIBE_DOC_NM_SETTING_GSM_PASSWORD N_("The password used to authenticate with the network, if required. Many providers do not require a password, or accept any password. But if a password is required, it is specified here.") #define DESCRIBE_DOC_NM_SETTING_GSM_PASSWORD_FLAGS N_("Flags indicating how to handle the \"password\" property.") #define DESCRIBE_DOC_NM_SETTING_GSM_PIN N_("If the SIM is locked with a PIN it must be unlocked before any other operations are requested. Specify the PIN here to allow operation of the device.") @@ -204,7 +204,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds.") #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 the default value, which is 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, the one with an active default route will be preferred. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports split-DNS 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 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, the one with an active default route will be preferred. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports split-DNS 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.") @@ -224,7 +224,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds.") #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 the default value, which is 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, the one with an active default route will be preferred. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports split-DNS 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 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, the one with an active default route will be preferred. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports split-DNS 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.") @@ -301,7 +301,7 @@ #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.") #define DESCRIBE_DOC_NM_SETTING_TEAM_CONFIG N_("The JSON configuration for the team network interface. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details.") -#define DESCRIBE_DOC_NM_SETTING_TEAM_LINK_WATCHERS N_("Link watchers configuration for the connection: each link watcher is defined by a dictionary, whose keys depend upon the selected link watcher. Available link watchers are 'ethtool', 'nsna_ping' and 'arp_ping' and it is specified in the dictionary with the key 'name'. Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait'; nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host'; arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', 'validate-incative', 'send-always'. See teamd.conf man for more details.") +#define DESCRIBE_DOC_NM_SETTING_TEAM_LINK_WATCHERS N_("Link watchers configuration for the connection: each link watcher is defined by a dictionary, whose keys depend upon the selected link watcher. Available link watchers are 'ethtool', 'nsna_ping' and 'arp_ping' and it is specified in the dictionary with the key 'name'. Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait'; nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host'; arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', 'validate-inactive', 'send-always'. See teamd.conf man for more details.") #define DESCRIBE_DOC_NM_SETTING_TEAM_MCAST_REJOIN_COUNT N_("Corresponds to the teamd mcast_rejoin.count.") #define DESCRIBE_DOC_NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL N_("Corresponds to the teamd mcast_rejoin.interval.") #define DESCRIBE_DOC_NM_SETTING_TEAM_NOTIFY_PEERS_COUNT N_("Corresponds to the teamd notify_peers.count.") @@ -319,7 +319,7 @@ #define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_CONFIG N_("The JSON configuration for the team port. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details.") #define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_LACP_KEY N_("Corresponds to the teamd ports.PORTIFNAME.lacp_key.") #define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_LACP_PRIO N_("Corresponds to the teamd ports.PORTIFNAME.lacp_prio.") -#define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_LINK_WATCHERS N_("Link watchers configuration for the connection: each link watcher is defined by a dictionary, whose keys depend upon the selected link watcher. Available link watchers are 'ethtool', 'nsna_ping' and 'arp_ping' and it is specified in the dictionary with the key 'name'. Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait'; nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host'; arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', 'validate-incative', 'send-always'. See teamd.conf man for more details.") +#define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_LINK_WATCHERS N_("Link watchers configuration for the connection: each link watcher is defined by a dictionary, whose keys depend upon the selected link watcher. Available link watchers are 'ethtool', 'nsna_ping' and 'arp_ping' and it is specified in the dictionary with the key 'name'. Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait'; nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host'; arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', 'validate-inactive', 'send-always'. See teamd.conf man for more details.") #define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_PRIO N_("Corresponds to the teamd ports.PORTIFNAME.prio.") #define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_QUEUE_ID N_("Corresponds to the teamd ports.PORTIFNAME.queue_id. When set to -1 means the parameter is skipped from the json config.") #define DESCRIBE_DOC_NM_SETTING_TEAM_PORT_STICKY N_("Corresponds to the teamd ports.PORTIFNAME.sticky.") @@ -357,8 +357,19 @@ #define DESCRIBE_DOC_NM_SETTING_VXLAN_SOURCE_PORT_MIN N_("Specifies the minimum UDP source port to communicate to the remote VXLAN tunnel endpoint.") #define DESCRIBE_DOC_NM_SETTING_VXLAN_TOS N_("Specifies the TOS value to use in outgoing packets.") #define DESCRIBE_DOC_NM_SETTING_VXLAN_TTL N_("Specifies the time-to-live value to use in outgoing packets.") +#define DESCRIBE_DOC_NM_SETTING_WIFI_P2P_PEER N_("The P2P device that should be connected to. Currently this is the only way to create or join a group.") +#define DESCRIBE_DOC_NM_SETTING_WIFI_P2P_WFD_IES N_("The Wi-Fi Display (WFD) Information Elements (IEs) to set. Wi-Fi Display requires a protocol specific information element to be set in certain Wi-Fi frames. These can be specified here for the purpose of establishing a connection. This setting is only useful when implementing a Wi-Fi Display client.") +#define DESCRIBE_DOC_NM_SETTING_WIFI_P2P_WPS_METHOD N_("Flags indicating which mode of WPS is to be used. There's little point in changing the default setting as NetworkManager will automatically determine the best method to use.") #define DESCRIBE_DOC_NM_SETTING_WIMAX_MAC_ADDRESS N_("If specified, this connection will only apply to the WiMAX device whose MAC address matches. This property does not change the MAC address of the device (known as MAC spoofing). Deprecated: 1") #define DESCRIBE_DOC_NM_SETTING_WIMAX_NETWORK_NAME N_("Network Service Provider (NSP) name of the WiMAX network this connection should use. Deprecated: 1") +#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_FWMARK N_("The use of fwmark is optional and is by default off. Setting it to 0 disables it. Otherwise it is a 32-bit fwmark for outgoing packets.") +#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_LISTEN_PORT N_("The listen-port. If listen-port is not specified, the port will be chosen randomly when the interface comes up.") +#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple fragments. If zero a default MTU is used. Note that contrary to wg-quick's MTU setting, this does not take into account the current routes at the time of activation.") +#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_PEER_ROUTES N_("Whether to automatically add routes for the AllowedIPs ranges of the peers. If TRUE (the default), NetworkManager will automatically add routes in the routing tables according to ipv4.route-table and ipv6.route-table. If FALSE, no such routes are added automatically. In this case, the user may want to configure static routes in ipv4.routes and ipv6.routes, respectively.") +#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_PRIVATE_KEY N_("The 256 bit private-key in base64 encoding.") +#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS N_("Flags indicating how to handle the \"private-key\" property.") +#define DESCRIBE_DOC_NM_SETTING_WPAN_CHANNEL N_("IEEE 802.15.4 channel. A positive integer or -1, meaning \"do not set, use whatever the device is already set to\".") #define DESCRIBE_DOC_NM_SETTING_WPAN_MAC_ADDRESS N_("If specified, this connection will only apply to the IEEE 802.15.4 (WPAN) MAC layer device whose permanent MAC address matches.") +#define DESCRIBE_DOC_NM_SETTING_WPAN_PAGE N_("IEEE 802.15.4 channel page. A positive integer or -1, meaning \"do not set, use whatever the device is already set to\".") #define DESCRIBE_DOC_NM_SETTING_WPAN_PAN_ID N_("IEEE 802.15.4 Personal Area Network (PAN) identifier.") #define DESCRIBE_DOC_NM_SETTING_WPAN_SHORT_ADDRESS N_("Short IEEE 802.15.4 address to be used within a restricted environment.") diff --git a/clients/common/tests/meson.build b/clients/common/tests/meson.build index cc357cdc..060bab48 100644 --- a/clients/common/tests/meson.build +++ b/clients/common/tests/meson.build @@ -4,7 +4,7 @@ deps = [ libnm_dep, libnmc_dep, libnmc_base_dep, - nm_core_dep + nm_core_dep, ] exe = executable( @@ -19,5 +19,5 @@ exe = executable( test( 'clients/' + test_unit, test_script, - args: test_args + [exe.full_path()] + args: test_args + [exe.full_path()], ) diff --git a/clients/common/tests/test-general.c b/clients/common/tests/test-general.c index 8f96eb26..c39901ba 100644 --- a/clients/common/tests/test-general.c +++ b/clients/common/tests/test-general.c @@ -20,6 +20,7 @@ #include "nm-default.h" #include "nm-meta-setting-access.h" +#include "nm-vpn-helpers.h" #include "nm-utils/nm-test-utils.h" @@ -145,6 +146,96 @@ test_client_meta_check (void) /*****************************************************************************/ +static void +test_client_import_wireguard_test0 (void) +{ + gs_unref_object NMConnection *connection; + NMSettingWireGuard *s_wg; + NMWireGuardPeer *peer; + gs_free_error GError *error = NULL; + + connection = nm_vpn_wireguard_import (NM_BUILD_SRCDIR"/clients/common/tests/wg-test0.conf", + &error); + + g_assert_no_error (error); + + g_assert_cmpstr (nm_connection_get_id (connection), ==, "wg-test0"); + g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "wg-test0"); + g_assert_cmpstr (nm_connection_get_connection_type (connection), ==, NM_SETTING_WIREGUARD_SETTING_NAME); + + s_wg = NM_SETTING_WIREGUARD (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIREGUARD)); + + g_assert_cmpint (nm_setting_wireguard_get_listen_port (s_wg), ==, 51820); + g_assert_cmpstr (nm_setting_wireguard_get_private_key (s_wg), ==, "yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk="); + + g_assert_cmpint (nm_setting_wireguard_get_peers_len (s_wg), ==, 3); + + peer = nm_setting_wireguard_get_peer (s_wg, 0); + g_assert_cmpstr (nm_wireguard_peer_get_public_key (peer), ==, "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg="); + g_assert_cmpstr (nm_wireguard_peer_get_endpoint (peer), ==, "192.95.5.67:1234"); + g_assert_cmpint (nm_wireguard_peer_get_allowed_ips_len (peer), ==, 2); + g_assert_cmpstr (nm_wireguard_peer_get_allowed_ip (peer, 0, NULL), ==, "10.192.122.3/32"); + g_assert_cmpstr (nm_wireguard_peer_get_allowed_ip (peer, 1, NULL), ==, "10.192.124.1/24"); + + peer = nm_setting_wireguard_get_peer (s_wg, 1); + g_assert_cmpstr (nm_wireguard_peer_get_public_key (peer), ==, "TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0="); + g_assert_cmpstr (nm_wireguard_peer_get_endpoint (peer), ==, "[2607:5300:60:6b0::c05f:543]:2468"); + g_assert_cmpint (nm_wireguard_peer_get_allowed_ips_len (peer), ==, 2); + g_assert_cmpstr (nm_wireguard_peer_get_allowed_ip (peer, 0, NULL), ==, "10.192.122.4/32"); + g_assert_cmpstr (nm_wireguard_peer_get_allowed_ip (peer, 1, NULL), ==, "192.168.0.0/16"); + + peer = nm_setting_wireguard_get_peer (s_wg, 2); + g_assert_cmpstr (nm_wireguard_peer_get_public_key (peer), ==, "gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA="); + 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"); +} + +static void +test_client_import_wireguard_test1 (void) +{ + gs_free_error GError *error = NULL; + + nm_vpn_wireguard_import (NM_BUILD_SRCDIR"/clients/common/tests/wg-test1.conf", &error); + g_assert_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT); + g_assert (g_str_has_prefix (error->message, "invalid secret 'PrivateKey'")); + g_assert (g_str_has_suffix (error->message, "wg-test1.conf:2")); +} + +static void +test_client_import_wireguard_test2 (void) +{ + gs_free_error GError *error = NULL; + + nm_vpn_wireguard_import (NM_BUILD_SRCDIR"/clients/common/tests/wg-test2.conf", &error); + + g_assert_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT); + g_assert (g_str_has_prefix (error->message, "unrecognized line at")); + g_assert (g_str_has_suffix (error->message, "wg-test2.conf:5")); +} + +static void +test_client_import_wireguard_test3 (void) +{ + gs_free_error GError *error = NULL; + + nm_vpn_wireguard_import (NM_BUILD_SRCDIR"/clients/common/tests/wg-test3.conf", &error); + g_assert_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT); + g_assert (g_str_has_prefix (error->message, "invalid value for 'ListenPort'")); + g_assert (g_str_has_suffix (error->message, "wg-test3.conf:3")); +} + +static void +test_client_import_wireguard_missing (void) +{ + gs_free_error GError *error = NULL; + + nm_vpn_wireguard_import (NM_BUILD_SRCDIR"/clients/common/tests/wg-missing.conf", &error); + g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT); +} + +/*****************************************************************************/ + NMTST_DEFINE (); int @@ -153,6 +244,11 @@ main (int argc, char **argv) nmtst_init (&argc, &argv, TRUE); g_test_add_func ("/client/meta/check", test_client_meta_check); + g_test_add_func ("/client/import/wireguard/test0", test_client_import_wireguard_test0); + g_test_add_func ("/client/import/wireguard/test1", test_client_import_wireguard_test1); + g_test_add_func ("/client/import/wireguard/test2", test_client_import_wireguard_test2); + g_test_add_func ("/client/import/wireguard/test3", test_client_import_wireguard_test3); + g_test_add_func ("/client/import/wireguard/missing", test_client_import_wireguard_missing); return g_test_run (); } diff --git a/clients/common/tests/wg-test0.conf b/clients/common/tests/wg-test0.conf new file mode 100644 index 00000000..61438c29 --- /dev/null +++ b/clients/common/tests/wg-test0.conf @@ -0,0 +1,18 @@ +[Interface] +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= +ListenPort = 51820 + +[Peer] +PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= +Endpoint = 192.95.5.67:1234 +AllowedIPs = 10.192.122.3/32, 10.192.124.1/24 + +[Peer] +PublicKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0= +Endpoint = [2607:5300:60:6b0::c05f:543]:2468 +AllowedIPs = 10.192.122.4/32, 192.168.0.0/16 + +[Peer] +PublicKey = gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA= +Endpoint = test.wireguard.com:18981 +AllowedIPs = 10.10.10.230/32 diff --git a/clients/common/tests/wg-test1.conf b/clients/common/tests/wg-test1.conf new file mode 100644 index 00000000..ceb267ac --- /dev/null +++ b/clients/common/tests/wg-test1.conf @@ -0,0 +1,3 @@ +[Interface] +PrivateKey = bad +ListenPort = 51820 diff --git a/clients/common/tests/wg-test2.conf b/clients/common/tests/wg-test2.conf new file mode 100644 index 00000000..f691c2af --- /dev/null +++ b/clients/common/tests/wg-test2.conf @@ -0,0 +1,8 @@ +[Interface] +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= +ListenPort = 51820 + +[Beer] +PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= +Endpoint = 192.95.5.67:1234 +AllowedIPs = 10.192.122.3/32, 10.192.124.1/24 diff --git a/clients/common/tests/wg-test3.conf b/clients/common/tests/wg-test3.conf new file mode 100644 index 00000000..9956e400 --- /dev/null +++ b/clients/common/tests/wg-test3.conf @@ -0,0 +1,3 @@ +[Interface] +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= +ListenPort = 666666666 -- cgit 1.3.0-6-gf8a5 From 85563b7fc7ec2cd21e38debb9b28db342e2e8e7c Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Sun, 21 Apr 2019 21:09:51 +0200 Subject: New upstream version 1.18.0 --- clients/common/meson.build | 4 +- clients/common/nm-client-utils.c | 4 + clients/common/nm-client-utils.h | 8 +- clients/common/nm-meta-setting-access.c | 16 + clients/common/nm-meta-setting-access.h | 2 + clients/common/nm-meta-setting-desc.c | 4128 ++++++++++++++----------------- clients/common/nm-meta-setting-desc.h | 83 +- clients/common/nm-secret-agent-simple.c | 49 +- clients/common/nm-vpn-helpers.c | 67 +- clients/common/settings-docs.h | 4 + clients/common/settings-docs.h.in | 4 + clients/common/tests/meson.build | 2 +- 12 files changed, 2049 insertions(+), 2322 deletions(-) (limited to 'clients/common') diff --git a/clients/common/meson.build b/clients/common/meson.build index b4b6bcac..fed0f3bf 100644 --- a/clients/common/meson.build +++ b/clients/common/meson.build @@ -4,7 +4,7 @@ nm_polkit_listener = files('nm-polkit-listener.c') deps = [ libnm_dep, - nm_core_dep, + shared_nm_libnm_core_aux_dep, ] cflags = clients_cflags + [ @@ -55,7 +55,7 @@ libnmc = static_library( sources: files( 'nm-meta-setting-access.c', 'nm-meta-setting-desc.c', - ) + shared_nm_meta_setting_c + shared_nm_ethtool_utils_c + [settings_docs_source], + ) + shared_nm_meta_setting_c + [settings_docs_source], dependencies: deps, c_args: cflags, link_with: libnmc_base, diff --git a/clients/common/nm-client-utils.c b/clients/common/nm-client-utils.c index 1241131a..0a155dae 100644 --- a/clients/common/nm-client-utils.c +++ b/clients/common/nm-client-utils.c @@ -82,6 +82,10 @@ nmc_string_to_uint_base (const char *str, char *end; unsigned long int tmp; + if (!str || !str[0]) + return FALSE; + + /* FIXME: don't use this function, replace by _nm_utils_ascii_str_to_int64() */ errno = 0; tmp = strtoul (str, &end, base); if (errno || *end != '\0' || (range_check && (tmp < min || tmp > max))) { diff --git a/clients/common/nm-client-utils.h b/clients/common/nm-client-utils.h index a5bc05fa..08a39f03 100644 --- a/clients/common/nm-client-utils.h +++ b/clients/common/nm-client-utils.h @@ -23,13 +23,7 @@ #include "nm-meta-setting.h" #include "nm-active-connection.h" #include "nm-device.h" - - -#define nm_auto_unref_ip_address nm_auto (_nm_ip_address_unref) -NM_AUTO_DEFINE_FCN0 (NMIPAddress *, _nm_ip_address_unref, nm_ip_address_unref) - -#define nm_auto_unref_wgpeer nm_auto (_nm_auto_unref_wgpeer) -NM_AUTO_DEFINE_FCN0 (NMWireGuardPeer *, _nm_auto_unref_wgpeer, nm_wireguard_peer_unref) +#include "nm-libnm-core-intern/nm-libnm-core-utils.h" const NMObject **nmc_objects_sort_by_path (const NMObject *const*objs, gssize len); diff --git a/clients/common/nm-meta-setting-access.c b/clients/common/nm-meta-setting-access.c index bd4064de..8399f29d 100644 --- a/clients/common/nm-meta-setting-access.c +++ b/clients/common/nm-meta-setting-access.c @@ -101,6 +101,22 @@ nm_meta_setting_info_editor_get_property_info (const NMMetaSettingInfoEditor *se return NULL; } +gboolean +nm_meta_setting_info_editor_has_secrets (const NMMetaSettingInfoEditor *setting_info) +{ + guint i; + + if (!setting_info) + return FALSE; + + for (i = 0; i < setting_info->properties_num; i++) { + if (setting_info->properties[i]->is_secret) + return TRUE; + } + + return FALSE; +} + const NMMetaPropertyInfo * nm_meta_property_info_find_by_name (const char *setting_name, const char *property_name) { diff --git a/clients/common/nm-meta-setting-access.h b/clients/common/nm-meta-setting-access.h index 9898cc5a..ec1c2ba0 100644 --- a/clients/common/nm-meta-setting-access.h +++ b/clients/common/nm-meta-setting-access.h @@ -39,6 +39,8 @@ const NMMetaPropertyInfo *nm_meta_property_info_find_by_name (const char *settin const NMMetaPropertyInfo *nm_meta_property_info_find_by_setting (NMSetting *setting, const char *property_name); +gboolean nm_meta_setting_info_editor_has_secrets (const NMMetaSettingInfoEditor *setting_info); + /*****************************************************************************/ const NMMetaSettingInfoEditor *const*nm_meta_setting_infos_editor_p (void); diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index 6e35228a..698ded86 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -24,8 +24,10 @@ #include #include -#include "nm-common-macros.h" -#include "nm-utils/nm-enum-utils.h" +#include "nm-libnm-core-intern/nm-common-macros.h" +#include "nm-glib-aux/nm-enum-utils.h" +#include "nm-glib-aux/nm-secret-utils.h" +#include "nm-libnm-core-intern/nm-libnm-core-utils.h" #include "nm-vpn-helpers.h" #include "nm-client-utils.h" @@ -74,6 +76,196 @@ _gtype_property_get_gtype (GType gtype, const char *property_name) /*****************************************************************************/ +static int +_int64_cmp_desc (gconstpointer a, + gconstpointer b, + gpointer user_data) +{ + NM_CMP_DIRECT (*((const gint64 *) b), *((const gint64 *) a)); + return 0; +} + +static gint64 * +_value_str_as_index_list (const char *value, gsize *out_len) +{ + gs_free char *str_clone_free = NULL; + gboolean str_cloned = FALSE; + char *str; + gsize i, j; + gsize n_alloc; + gsize len; + gs_free gint64 *arr = NULL; + + *out_len = 0; + + if (!value) + return NULL; + + str = (char *) value; + n_alloc = 0; + len = 0; + while (TRUE) { + gint64 i64; + const char *s; + gsize good; + + good = strcspn (str, ","NM_ASCII_SPACES); + if (good == 0) { + if (str[0] == '\0') + break; + str++; + continue; + } + if (str[good] == '\0') { + s = str; + str += good; + } else { + if (!str_cloned) { + str_cloned = TRUE; + str = nm_strndup_a (200, str, strlen (str), &str_clone_free); + } + s = str; + str[good] = '\0'; + str += good + 1; + } + + i64 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXINT64, -1); + if (i64 == -1) + return NULL; + + if (len >= n_alloc) { + if (n_alloc > 0) { + n_alloc = n_alloc * 2; + arr = g_realloc (arr, n_alloc * sizeof (gint64)); + } else { + n_alloc = 4; + arr = g_new (gint64, n_alloc); + } + } + arr[len++] = i64; + } + + if (len > 1) { + /* sort the list of indexes descendingly, and drop duplicates. */ + g_qsort_with_data (arr, + len, + sizeof (gint64), + _int64_cmp_desc, + NULL); + j = 1; + for (i = 1; i < len; i++) { + nm_assert (arr[i - 1] >= arr[i]); + if (arr[i - 1] > arr[i]) + arr[j++] = arr[i]; + } + len = j; + } + + *out_len = len; + return g_steal_pointer (&arr); +} + +#define ESCAPED_TOKENS_WITH_SPACES_DELIMTER ' ' +#define ESCAPED_TOKENS_WITH_SPACES_DELIMTERS NM_ASCII_SPACES"," + +#define ESCAPED_TOKENS_DELIMITER ',' +#define ESCAPED_TOKENS_DELIMITERS "," + +typedef enum { + VALUE_STRSPLIT_MODE_OBJLIST, + VALUE_STRSPLIT_MODE_MULTILIST, + VALUE_STRSPLIT_MODE_ESCAPED_TOKENS, + VALUE_STRSPLIT_MODE_ESCAPED_TOKENS_WITH_SPACES, +} ValueStrsplitMode; + +static const char ** +_value_strsplit (const char *value, + ValueStrsplitMode split_mode, + gsize *out_len) +{ + gs_free const char **strv = NULL; + gsize i; + gsize len; + + /* FIXME: some modes should support backslash escaping. + * In particular, to distingish from _value_str_as_index_list(), which + * does not accept '\\'. */ + + /* 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); + break; + case VALUE_STRSPLIT_MODE_MULTILIST: + strv = nm_utils_strsplit_set (value, ESCAPED_TOKENS_WITH_SPACES_DELIMTERS); + 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); + 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); + return g_steal_pointer (&strv); +} + +static gboolean +_value_strsplit_assert_unsplitable (const char *str) +{ +#if NM_MORE_ASSERTS > 5 + gs_free const char **strv_test = NULL; + gsize j, l; + + /* Assert that we cannot split the token and that it + * has no unescaped delimiters. */ + + strv_test = _value_strsplit (str, + VALUE_STRSPLIT_MODE_ESCAPED_TOKENS, + NULL); + nm_assert (NM_PTRARRAY_LEN (strv_test) == 1); + + for (j = 0; str[j] != '\0'; ) { + if (str[j] == '\\') { + j++; + nm_assert (str[j] != '\0'); + } else + nm_assert (!NM_IN_SET (str[j], '\0', ',')); + j++; + } + l = j; + nm_assert ( !g_ascii_isspace (str[l - 1]) + || ( l >= 2 + && str[l - 2] == '\\')); +#endif + + return TRUE; +} + static NMIPAddress * _parse_ip_address (int family, const char *address, GError **error) { @@ -123,20 +315,20 @@ _parse_ip_route (int family, gint64 metric = -1; guint i; gs_free const char **routev = NULL; - gs_free char *str_clean = NULL; + gs_free char *str_clean_free = NULL; + const char *str_clean; gs_free char *dest_clone = NULL; const char *dest; const char *plen; gs_unref_hashtable GHashTable *attrs = NULL; - GHashTable *tmp_attrs; #define ROUTE_SYNTAX _("The valid syntax is: 'ip[/prefix] [next-hop] [metric] [attribute=val]... [,ip[/prefix] ...]'") nm_assert (NM_IN_SET (family, AF_INET, AF_INET6)); nm_assert (str); nm_assert (!error || !*error); - str_clean = g_strstrip (g_strdup (str)); - routev = nm_utils_strsplit_set (str_clean, " \t", FALSE); + str_clean = nm_strstrip_avoid_copy_a (300, str, &str_clean_free); + routev = nm_utils_strsplit_set (str_clean, " \t"); if (!routev) { g_set_error (error, 1, 0, "'%s' is not valid. %s", @@ -182,6 +374,7 @@ _parse_ip_route (int family, GHashTableIter iter; char *iter_key; GVariant *iter_value; + gs_unref_hashtable GHashTable *tmp_attrs = NULL; tmp_attrs = nm_utils_parse_variant_attributes (routev[i], ' ', '=', FALSE, nm_ip_route_get_variant_attribute_spec(), @@ -207,13 +400,11 @@ _parse_ip_route (int family, if (!nm_ip_route_attribute_validate (iter_key, iter_value, family, NULL, error)) { g_prefix_error (error, "%s: ", iter_key); - g_hash_table_unref (tmp_attrs); return NULL; } g_hash_table_insert (attrs, iter_key, iter_value); g_hash_table_iter_steal (&iter); } - g_hash_table_unref (tmp_attrs); } else { g_set_error (error, 1, 0, "%s", ROUTE_SYNTAX); return NULL; @@ -298,7 +489,8 @@ _parse_team_link_watcher (const char *str, GError **error) { gs_free const char **watcherv = NULL; - gs_free char *str_clean = NULL; + gs_free char *str_clean_free = NULL; + const char *str_clean; guint i; gs_free const char *name = NULL; int val1 = 0, val2 = 0, val3 = 3, val4 = -1; @@ -309,8 +501,8 @@ _parse_team_link_watcher (const char *str, nm_assert (str); nm_assert (!error || !*error); - str_clean = g_strstrip (g_strdup (str)); - watcherv = nm_utils_strsplit_set (str_clean, " \t", FALSE); + str_clean = nm_strstrip_avoid_copy_a (300, str, &str_clean_free); + watcherv = nm_utils_strsplit_set (str_clean, " \t"); if (!watcherv) { g_set_error (error, 1, 0, "'%s' is not valid", str); return NULL; @@ -319,7 +511,7 @@ _parse_team_link_watcher (const char *str, for (i = 0; watcherv[i]; i++) { gs_free const char **pair = NULL; - pair = nm_utils_strsplit_set (watcherv[i], "=", FALSE); + pair = nm_utils_strsplit_set (watcherv[i], "="); if (!pair) { g_set_error (error, 1, 0, "'%s' is not valid: %s", watcherv[i], "properties should be specified as 'key=value'"); @@ -397,62 +589,6 @@ _parse_team_link_watcher (const char *str, #define MAX_SKB_PRIO G_MAXUINT32 #define MAX_8021P_PRIO 7 /* Max 802.1p priority */ -/* - * Parse VLAN priority mappings from the following format: 2:1,3:4,7:3 - * and verify if the priority numbers are valid - * - * Return: string array with split maps, or NULL on error - * Caller is responsible for freeing the array. - */ -static char ** -_parse_vlan_priority_maps (const char *priority_map, - NMVlanPriorityMap map_type, - GError **error) -{ - char **mapping = NULL, **iter; - unsigned long from, to, from_max, to_max; - - g_return_val_if_fail (priority_map != NULL, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - if (map_type == NM_VLAN_INGRESS_MAP) { - from_max = MAX_8021P_PRIO; - to_max = MAX_SKB_PRIO; - } else { - from_max = MAX_SKB_PRIO; - to_max = MAX_8021P_PRIO; - } - - mapping = g_strsplit (priority_map, ",", 0); - for (iter = mapping; iter && *iter; iter++) { - char *left, *right; - - left = g_strstrip (*iter); - right = strchr (left, ':'); - if (!right) { - g_set_error (error, 1, 0, _("invalid priority map '%s'"), *iter); - g_strfreev (mapping); - return NULL; - } - *right++ = '\0'; - - if (!nmc_string_to_uint (left, TRUE, 0, from_max, &from)) { - g_set_error (error, 1, 0, _("priority '%s' is not valid (<0-%ld>)"), - left, from_max); - g_strfreev (mapping); - return NULL; - } - if (!nmc_string_to_uint (right, TRUE, 0, to_max, &to)) { - g_set_error (error, 1, 0, _("priority '%s' is not valid (<0-%ld>)"), - right, to_max); - g_strfreev (mapping); - return NULL; - } - *(right-1) = ':'; /* Put back ':' */ - } - return mapping; -} - /* * nmc_proxy_check_script: * @script: file name with PAC script, or raw PAC Script data @@ -646,10 +782,10 @@ _env_warn_fcn (const NMMetaEnvironment *environment, const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, NMSetting *setting, NMMetaAccessorGetType get_type, NMMetaAccessorGetFlags get_flags, NMMetaAccessorGetOutFlags *out_flags, gboolean *out_is_default, gpointer *out_to_free #define ARGS_SET_FCN \ - const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, NMSetting *setting, const char *value, GError **error + const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, NMSetting *setting, char modifier, const char *value, GError **error #define ARGS_REMOVE_FCN \ - const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, NMSetting *setting, const char *value, guint32 idx, GError **error + const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, NMSetting *setting, const char *value, GError **error #define ARGS_COMPLETE_FCN \ const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, const NMMetaOperationContext *operation_context, const char *text, char ***out_to_free @@ -660,6 +796,46 @@ _env_warn_fcn (const NMMetaEnvironment *environment, #define ARGS_SETTING_INIT_FCN \ const NMMetaSettingInfoEditor *setting_info, NMSetting *setting, NMMetaAccessorSettingInitType init_type +static gboolean +_SET_FCN_DO_RESET_DEFAULT (const NMMetaPropertyInfo *property_info, char modifier, const char *value) +{ + nm_assert (property_info); + nm_assert (!property_info->property_type->set_supports_remove); + nm_assert (NM_IN_SET (modifier, '\0', '+')); + nm_assert (value || modifier == '\0'); + + return value == NULL; +} + +static gboolean +_SET_FCN_DO_RESET_DEFAULT_WITH_SUPPORTS_REMOVE (const NMMetaPropertyInfo *property_info, char modifier, const char *value) +{ + nm_assert (property_info); + nm_assert (property_info->property_type->set_supports_remove); + nm_assert (NM_IN_SET (modifier, '\0', '+', '-')); + nm_assert (value || modifier == '\0'); + + return value == NULL; +} + +static gboolean +_SET_FCN_DO_SET_ALL (char modifier, const char *value) +{ + nm_assert (NM_IN_SET (modifier, '\0', '+', '-')); + nm_assert (value); + + return modifier == '\0'; +} + +static gboolean +_SET_FCN_DO_REMOVE (char modifier, const char *value) +{ + nm_assert (NM_IN_SET (modifier, '\0', '+', '-')); + nm_assert (value); + + return modifier == '-'; +} + #define RETURN_UNSUPPORTED_GET_TYPE() \ G_STMT_START { \ if (!NM_IN_SET (get_type, \ @@ -677,7 +853,7 @@ _env_warn_fcn (const NMMetaEnvironment *environment, } G_STMT_END static gboolean -property_is_default (NMSetting *setting, const char *prop_name) +_gobject_property_is_default (NMSetting *setting, const char *prop_name) { nm_auto_unset_gvalue GValue v = G_VALUE_INIT; GParamSpec *pspec; @@ -703,32 +879,30 @@ property_is_default (NMSetting *setting, const char *prop_name) return g_param_value_defaults (pspec, &v); } -static gconstpointer -_get_fcn_nmc_with_default (ARGS_GET_FCN) +static gboolean +_gobject_property_reset (NMSetting *setting, + const char *prop_name, + gboolean reset_default) { - const char *s; - char *s_full; - GValue val = G_VALUE_INIT; - - RETURN_UNSUPPORTED_GET_TYPE (); - NM_SET_OUT (out_is_default, property_is_default (setting, property_info->property_name)); + nm_auto_unset_gvalue GValue v = G_VALUE_INIT; + GParamSpec *pspec; - if (property_info->property_typ_data->subtype.get_with_default.fcn (setting)) { - if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) - return _("(default)"); - return ""; - } + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), + prop_name); + if (!G_IS_PARAM_SPEC (pspec)) + g_return_val_if_reached (FALSE); - g_value_init (&val, G_TYPE_STRING); - g_object_get_property (G_OBJECT (setting), property_info->property_name, &val); - s = g_value_get_string (&val); - if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) - s_full = s ? g_strdup_printf ("\"%s\"", s) : g_strdup (""); - else - s_full = g_strdup (s && *s ? s : " "); - g_value_unset (&val); + g_value_init (&v, pspec->value_type); + if (reset_default) + g_param_value_defaults (pspec, &v); + g_object_set_property (G_OBJECT (setting), prop_name, &v); + return TRUE; +} - RETURN_STR_TO_FREE (s_full); +static gboolean +_gobject_property_reset_default (NMSetting *setting, const char *prop_name) +{ + return _gobject_property_reset (setting, prop_name, TRUE); } static gconstpointer @@ -738,13 +912,20 @@ _get_fcn_gobject_impl (const NMMetaPropertyInfo *property_info, gboolean *out_is_default, gpointer *out_to_free) { - char *s; - const char *s_c; + const char *cstr; GType gtype_prop; nm_auto_unset_gvalue GValue val = G_VALUE_INIT; RETURN_UNSUPPORTED_GET_TYPE (); - NM_SET_OUT (out_is_default, property_is_default (setting, property_info->property_name)); + NM_SET_OUT (out_is_default, _gobject_property_is_default (setting, property_info->property_name)); + + if ( property_info->property_typ_data + && property_info->property_typ_data->is_default_fcn + && property_info->property_typ_data->is_default_fcn (setting)) { + if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) + return _("(default)"); + return ""; + } gtype_prop = _gobject_property_get_gtype (G_OBJECT (setting), property_info->property_name); @@ -755,15 +936,35 @@ _get_fcn_gobject_impl (const NMMetaPropertyInfo *property_info, g_object_get_property (G_OBJECT (setting), property_info->property_name, &val); b = g_value_get_boolean (&val); if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) - s_c = b ? _("yes") : _("no"); + cstr = b ? _("yes") : _("no"); else - s_c = b ? "yes" : "no"; - return s_c; + cstr = b ? "yes" : "no"; + return cstr; } else { + char *str; + + /* Note that we register certain transform functions in nmc_value_transforms_register(). + * This makes G_TYPE_STRV working. + * + * FIXME: that is particularly ugly because it's non-obvious which code relies + * on nmc_value_transforms_register(). Also, nmc_value_transforms_register() is + * in clients/cli, while we are here in clients/common. */ g_value_init (&val, G_TYPE_STRING); g_object_get_property (G_OBJECT (setting), property_info->property_name, &val); - s = g_value_dup_string (&val); - RETURN_STR_TO_FREE (s); + cstr = g_value_get_string (&val); + + if ( property_info->property_typ_data + && property_info->property_typ_data->is_default_fcn) { + if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) { + str = cstr + ? g_strdup_printf ("\"%s\"", cstr) + : g_strdup (""); + } else + str = g_strdup (cstr && cstr[0] ? cstr : " "); + } else + str = cstr ? g_strdup (cstr) : NULL; + + RETURN_STR_TO_FREE (str); } } @@ -842,10 +1043,9 @@ _get_fcn_gobject_int (ARGS_GET_FCN) for (; value_infos->nick; value_infos++) { if ( ( is_uint64 && value_infos->value.u64 == v.u64) || (!is_uint64 && value_infos->value.i64 == v.i64)) { - char *old_str = return_str; + gs_free char *old_str = return_str; return_str = g_strdup_printf ("%s (%s)", old_str, value_infos->nick); - g_free (old_str); break; } } @@ -1033,6 +1233,9 @@ _set_fcn_gobject_string (ARGS_SET_FCN) { gs_free char *to_free = NULL; + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) + return _gobject_property_reset_default (setting, property_info->property_name); + if (property_info->property_typ_data) { if (property_info->property_typ_data->subtype.gobject_string.validate_fcn) { value = property_info->property_typ_data->subtype.gobject_string.validate_fcn (value, &to_free, error); @@ -1055,6 +1258,9 @@ _set_fcn_gobject_bool (ARGS_SET_FCN) { gboolean val_bool; + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) + return _gobject_property_reset_default (setting, property_info->property_name); + if (!nmc_string_to_bool (value, &val_bool, error)) return FALSE; @@ -1076,6 +1282,9 @@ _set_fcn_gobject_int (ARGS_SET_FCN) guint base = 10; const NMMetaUtilsIntValueInfo *value_infos; + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) + return _gobject_property_reset_default (setting, property_info->property_name); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), property_info->property_name); if (!G_IS_PARAM_SPEC (pspec)) g_return_val_if_reached (FALSE); @@ -1085,14 +1294,10 @@ _set_fcn_gobject_int (ARGS_SET_FCN) if (property_info->property_typ_data) { if ( value && (value_infos = property_info->property_typ_data->subtype.gobject_int.value_infos)) { - gs_free char *vv_stripped = NULL; - const char *vv = nm_str_skip_leading_spaces (value); - - if (vv[0] && g_ascii_isspace (vv[strlen (vv) - 1])) { - vv_stripped = g_strstrip (g_strdup (vv)); - vv = vv_stripped; - } + gs_free char *vv_free = NULL; + const char *vv; + vv = nm_strstrip_avoid_copy_a (300, value, &vv_free); for (; value_infos->nick; value_infos++) { if (nm_streq (value_infos->nick, vv)) { v = value_infos->value; @@ -1216,7 +1421,10 @@ _set_fcn_gobject_mtu (ARGS_SET_FCN) const GParamSpec *pspec; gint64 v; - if (nm_streq0 (value, "auto")) + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) + return _gobject_property_reset_default (setting, property_info->property_name); + + if (nm_streq (value, "auto")) value = "0"; pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), @@ -1254,6 +1462,9 @@ _set_fcn_gobject_mac (ARGS_SET_FCN) NMMetaPropertyTypeMacMode mode; gboolean valid; + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) + return _gobject_property_reset_default (setting, property_info->property_name); + if (property_info->property_typ_data) mode = property_info->property_typ_data->subtype.mac.mode; else @@ -1289,6 +1500,9 @@ _set_fcn_gobject_enum (ARGS_SET_FCN) gboolean is_flags; int v; + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) + return _gobject_property_reset_default (setting, property_info->property_name); + if (property_info->property_typ_data) { if (property_info->property_typ_data->subtype.gobject_enum.get_gtype) { gtype = property_info->property_typ_data->subtype.gobject_enum.get_gtype (); @@ -1558,25 +1772,6 @@ vlan_flags_to_string (guint32 flags, NMMetaAccessorGetType get_type) return g_string_free (flag_str, FALSE); } -static char * -vlan_priorities_to_string (NMSettingVlan *s_vlan, NMVlanPriorityMap map) -{ - GString *priorities; - int i; - - priorities = g_string_new (NULL); - for (i = 0; i < nm_setting_vlan_get_num_priorities (s_vlan, map); i++) { - guint32 from, to; - - if (nm_setting_vlan_get_priority (s_vlan, map, i, &from, &to)) - g_string_append_printf (priorities, "%d:%d,", from, to); - } - if (priorities->len) - g_string_truncate (priorities, priorities->len-1); /* chop off trailing ',' */ - - return g_string_free (priorities, FALSE); -} - static char * secret_flags_to_string (guint32 flags, NMMetaAccessorGetType get_type) { @@ -1619,166 +1814,204 @@ vpn_data_item (const char *key, const char *value, gpointer user_data) g_string_append_printf (ret_str, "%s = %s", key, value); } -#define DEFINE_SETTER_STR_LIST_MULTI(def_func, s_macro, set_func) \ - static gboolean \ - def_func (NMSetting *setting, \ - const char *prop, \ - const char *value, \ - const char **valid_strv, \ - GError **error) \ - { \ - gs_free const char **strv = NULL; \ - gsize i; \ - const char *item; \ - nm_assert (!error || !*error); \ - strv = nm_utils_strsplit_set (value, " \t,", FALSE); \ - if (strv) { \ - for (i = 0; strv[i]; i++) { \ - if (!(item = nmc_string_is_valid (strv[i], valid_strv, error))) { \ - return FALSE; \ - } \ - set_func (s_macro (setting), item); \ - } \ - } \ - return TRUE; \ +static const char * +_multilist_do_validate (const NMMetaPropertyInfo *property_info, + NMSetting *setting, + const char *item, + GError **error) +{ + if (property_info->property_typ_data->values_static) { + nm_assert (!property_info->property_typ_data->subtype.multilist.validate_fcn); + return nmc_string_is_valid (item, + (const char **) property_info->property_typ_data->values_static, + error); + } + if (property_info->property_typ_data->subtype.multilist.validate_fcn) { + return property_info->property_typ_data->subtype.multilist.validate_fcn (item, + error); + } + if (property_info->property_typ_data->subtype.multilist.validate2_fcn) { + return property_info->property_typ_data->subtype.multilist.validate2_fcn (setting, + item, + error); } -#define DEFINE_SETTER_OPTIONS(def_func, s_macro, s_type, add_func, valid_func1, valid_func2) \ - static gboolean \ - def_func (ARGS_SET_FCN) \ - { \ - gs_free const char **strv = NULL; \ - const char **iter; \ - const char **(*valid_func1_p) (s_type *) = valid_func1; \ - const char * (*valid_func2_p) (const char *, const char *, GError **) = valid_func2; \ - const char *opt_name, *opt_val; \ - \ - nm_assert (!error || !*error); \ - \ - strv = nm_utils_strsplit_set (value, ",", FALSE); \ - for (iter = strv; iter && *iter; iter++) { \ - gs_free char *left_clone = g_strstrip (g_strdup (*iter)); \ - char *left = left_clone; \ - char *right = strchr (left, '='); \ - if (!right) { \ - g_set_error (error, 1, 0, _("'%s' is not valid; use