diff --git a/NEWS b/NEWS index 4bd63ab496..b4737fe8a9 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,8 @@ USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE! with "balance-xor" mode and "vlan-srcmac" xmit_hash_policy. In this mode, NetworkManager configures nftables to prevent loops in the switch. +* dns: support specifying DNS-over-TLS server name (SNI) for static + name servers. Only works with systemd-resolved plugin. ============================================= NetworkManager-1.40 diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index a8624754a4..aefffc529e 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -10780,14 +10780,14 @@ nm_device_copy_ip6_dns_config(NMDevice *self, NMDevice *from_device) l3cd_src = priv_src->l3cds[L3_CONFIG_DATA_TYPE_AC_6].d; } if (l3cd_src) { - const char *const *strvarr; - const struct in6_addr *addrs; - guint n; - guint i; + const char *const *strvarr; + const char *const *addrs; + guint n; + guint i; addrs = nm_l3_config_data_get_nameservers(l3cd_src, AF_INET6, &n); for (i = 0; i < n; i++) - nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &addrs[i]); + nm_l3_config_data_add_nameserver(l3cd, AF_INET6, addrs[i]); strvarr = nm_l3_config_data_get_searches(l3cd_src, AF_INET6, &n); for (i = 0; i < n; i++) diff --git a/src/core/devices/wifi/nm-device-iwd.c b/src/core/devices/wifi/nm-device-iwd.c index a304fc7178..e03227cd03 100644 --- a/src/core/devices/wifi/nm-device-iwd.c +++ b/src/core/devices/wifi/nm-device-iwd.c @@ -3735,7 +3735,7 @@ nm_device_iwd_parse_netconfig(NMDeviceIwd *self, int addr_family, GVariantIter * if (inet_pton(addr_family, str_value, &dns_bin) != 1) goto param_error; - nm_l3_config_data_add_nameserver(l3cd, addr_family, &dns_bin); + nm_l3_config_data_add_nameserver_detail(l3cd, addr_family, &dns_bin, NULL); nm_l3_config_data_set_dns_priority(l3cd, addr_family, NM_DNS_PRIORITY_DEFAULT_NORMAL); } } diff --git a/src/core/devices/wifi/nm-wifi-utils.c b/src/core/devices/wifi/nm-wifi-utils.c index 185f8c3da4..759fb0cc01 100644 --- a/src/core/devices/wifi/nm-wifi-utils.c +++ b/src/core/devices/wifi/nm-wifi-utils.c @@ -11,6 +11,7 @@ #include #include +#include "libnm-glib-aux/nm-str-buf.h" #include "nm-utils.h" #include "libnm-core-intern/nm-core-internal.h" #include "libnm-core-aux-intern/nm-libnm-core-utils.h" @@ -1549,10 +1550,16 @@ eap_setting_to_iwd_config(GKeyFile *file, NMSetting8021x *s_8021x, GError **erro } static gboolean -ip4_config_to_iwd_config(GKeyFile *file, NMSettingIPConfig *s_ip, GError **error) +ip_config_to_iwd_config(int addr_family, GKeyFile *file, NMSettingIPConfig *s_ip, GError **error) { - guint num; - struct in_addr ip; + const int IS_IPv4 = NM_IS_IPv4(addr_family); + nm_auto_str_buf NMStrBuf strbuf = NM_STR_BUF_INIT_A(NM_UTILS_GET_NEXT_REALLOC_SIZE_488, FALSE); + NMIPAddress *addr; + guint num; + guint i; + char buf[NM_INET_ADDRSTRLEN + 10]; + const char *kf_group = IS_IPv4 ? "IPv4" : "IPv6"; + const char *gw; /* These settings are not acutally used unless global * [General].EnableNetworkConfiguration is true, which we don't support. @@ -1564,15 +1571,26 @@ ip4_config_to_iwd_config(GKeyFile *file, NMSettingIPConfig *s_ip, GError **error if (!s_ip) return TRUE; + nm_assert(NM_IS_IPv4(addr_family) ? NM_IS_SETTING_IP4_CONFIG(s_ip) + : NM_IS_SETTING_IP6_CONFIG(s_ip)); + num = nm_setting_ip_config_get_num_dns(s_ip); if (num) { - nm_auto_free_gstring GString *s = g_string_sized_new(128); - guint i; - + nm_str_buf_reset(&strbuf); for (i = 0; i < num; i++) { - if (s->len) - g_string_append_c(s, ' '); - g_string_append(s, nm_setting_ip_config_get_dns(s_ip, i)); + char sbuf[NM_INET_ADDRSTRLEN]; + NMIPAddr a; + + if (!nm_utils_dnsname_parse_assert(addr_family, + nm_setting_ip_config_get_dns(s_ip, i), + NULL, + &a, + NULL)) + continue; + + if (strbuf.len > 0) + nm_str_buf_append_c(&strbuf, ' '); + nm_str_buf_append(&strbuf, nm_inet_ntop(addr_family, &a, sbuf)); } /* It doesn't matter whether we add the DNS under [IPv4] or [IPv6] * except that with method=auto the list will override the @@ -1581,97 +1599,61 @@ ip4_config_to_iwd_config(GKeyFile *file, NMSettingIPConfig *s_ip, GError **error * Note ignore-auto-dns=false isn't supported, this list always * overrides the DHCP DNSes. */ - g_key_file_set_string(file, "IPv4", "DNS", s->str); + g_key_file_set_string(file, kf_group, "DNS", nm_str_buf_get_str(&strbuf)); } - if (!nm_streq0(nm_setting_ip_config_get_method(s_ip), NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) - return TRUE; + if (!IS_IPv4) { + if (!NM_IN_STRSET(nm_setting_ip_config_get_method(s_ip), + NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP6_CONFIG_METHOD_DHCP, + NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) + return TRUE; + g_key_file_set_boolean(file, kf_group, "Enabled", TRUE); + } num = nm_setting_ip_config_get_num_addresses(s_ip); - if (num) { - NMIPAddress *addr = nm_setting_ip_config_get_address(s_ip, 0); - guint prefix = nm_ip_address_get_prefix(addr); - in_addr_t netmask = nm_ip4_addr_netmask_from_prefix(prefix); - char buf[INET_ADDRSTRLEN]; - - nm_ip_address_get_address_binary(addr, &ip); - g_key_file_set_string(file, "IPv4", "Address", nm_ip_address_get_address(addr)); - g_key_file_set_string(file, "IPv4", "Netmask", nm_inet4_ntop(netmask, buf)); - } else { - inet_pton(AF_INET, "10.42.0.100", &ip); - g_key_file_set_string(file, "IPv4", "Address", "10.42.0.100"); - } - - if (nm_setting_ip_config_get_gateway(s_ip)) { - g_key_file_set_string(file, "IPv4", "Gateway", nm_setting_ip_config_get_gateway(s_ip)); - } else { - uint32_t val; - char buf[INET_ADDRSTRLEN]; - - /* IWD won't enable static IP unless both Address and Gateway are - * set so generate a gateway address if not known. - */ - val = (ntohl(ip.s_addr) & 0xfffffff0) + 1; - if (val == ntohl(ip.s_addr)) - val += 1; - g_key_file_set_string(file, "IPv4", "Gateway", nm_inet4_ntop(htonl(val), buf)); - } - - return TRUE; -} - -static gboolean -ip6_config_to_iwd_config(GKeyFile *file, NMSettingIPConfig *s_ip, GError **error) -{ - guint num; - NMIPAddress *addr; - char buf[INET6_ADDRSTRLEN + 10]; - - if (!s_ip) + if (num == 0) return TRUE; - num = nm_setting_ip_config_get_num_dns(s_ip); - if (num) { - nm_auto_free_gstring GString *s = g_string_sized_new(128); - guint i; - - for (i = 0; i < num; i++) { - if (s->len) - g_string_append_c(s, ' '); - g_string_append(s, nm_setting_ip_config_get_dns(s_ip, i)); - } - g_key_file_set_string(file, "IPv6", "DNS", s->str); - } - - if (!NM_IN_STRSET(nm_setting_ip_config_get_method(s_ip), - NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NM_SETTING_IP6_CONFIG_METHOD_DHCP, - NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) - return TRUE; - - g_key_file_set_boolean(file, "IPv6", "Enabled", TRUE); - - if (!nm_streq0(nm_setting_ip_config_get_method(s_ip), NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) - return TRUE; - - if (!nm_setting_ip_config_get_num_addresses(s_ip)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - "IP address required for IPv6 manual config"); - return FALSE; - } - addr = nm_setting_ip_config_get_address(s_ip, 0); - g_key_file_set_string(file, - "IPv6", - "Address", - nm_sprintf_buf(buf, - "%s/%u", - nm_ip_address_get_address(addr), - nm_ip_address_get_prefix(addr))); - if (nm_setting_ip_config_get_gateway(s_ip)) - g_key_file_set_string(file, "IPv6", "Gateway", nm_setting_ip_config_get_gateway(s_ip)); + gw = nm_setting_ip_config_get_gateway(s_ip); + + if (IS_IPv4) { + in_addr_t ip; + + nm_ip_address_get_address_binary(addr, &ip); + + g_key_file_set_string(file, kf_group, "Address", nm_ip_address_get_address(addr)); + g_key_file_set_string( + file, + kf_group, + "Netmask", + nm_inet4_ntop(nm_ip4_addr_netmask_from_prefix(nm_ip_address_get_prefix(addr)), buf)); + + if (!gw) { + guint32 val; + + /* IWD won't enable static IP unless both Address and Gateway are + * set so generate a gateway address if not known. + */ + val = (ntohl(ip) & 0xfffffff0) + 1; + if (val == ntohl(ip)) + val += 1; + gw = nm_inet4_ntop(htonl(val), buf); + } + g_key_file_set_string(file, kf_group, "Gateway", gw); + } else { + g_key_file_set_string(file, + kf_group, + "Address", + nm_sprintf_buf(buf, + "%s/%u", + nm_ip_address_get_address(addr), + nm_ip_address_get_prefix(addr))); + if (gw) + g_key_file_set_string(file, kf_group, "Gateway", gw); + } + return TRUE; } @@ -1759,13 +1741,15 @@ nm_wifi_utils_connection_to_iwd_config(NMConnection *connection, else if (cloned_mac_addr && nm_utils_hwaddr_valid(cloned_mac_addr, ETH_ALEN)) g_key_file_set_string(file, "Settings", "AddressOverride", cloned_mac_addr); - if (!ip4_config_to_iwd_config( + if (!ip_config_to_iwd_config( + AF_INET, file, NM_SETTING_IP_CONFIG(nm_connection_get_setting_ip4_config(connection)), error)) return NULL; - if (!ip6_config_to_iwd_config( + if (!ip_config_to_iwd_config( + AF_INET6, file, NM_SETTING_IP_CONFIG(nm_connection_get_setting_ip6_config(connection)), error)) diff --git a/src/core/devices/wwan/nm-modem-broadband.c b/src/core/devices/wwan/nm-modem-broadband.c index d550283a3e..556df83198 100644 --- a/src/core/devices/wwan/nm-modem-broadband.c +++ b/src/core/devices/wwan/nm-modem-broadband.c @@ -1058,7 +1058,7 @@ stage3_ip_config_start(NMModem *modem, int addr_family, NMModemIPMethod ip_metho dns = mm_bearer_ip_config_get_dns(self->_priv.ipv4_config); for (i = 0; dns && dns[i]; i++) { if (nm_inet_parse_bin(AF_INET, dns[i], NULL, &address_network) && address_network > 0) { - nm_l3_config_data_add_nameserver(l3cd, AF_INET, &address_network); + nm_l3_config_data_add_nameserver_detail(l3cd, AF_INET, &address_network, NULL); _LOGI(" DNS %s", dns[i]); } } @@ -1173,7 +1173,7 @@ stage3_ip_config_start(NMModem *modem, int addr_family, NMModemIPMethod ip_metho struct in6_addr addr; if (inet_pton(AF_INET6, dns[i], &addr)) { - nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &addr); + nm_l3_config_data_add_nameserver_detail(l3cd, AF_INET6, &addr, NULL); _LOGI(" DNS %s", dns[i]); } } diff --git a/src/core/devices/wwan/nm-modem-ofono.c b/src/core/devices/wwan/nm-modem-ofono.c index 4a5ed6613f..d2f3f38b82 100644 --- a/src/core/devices/wwan/nm-modem-ofono.c +++ b/src/core/devices/wwan/nm-modem-ofono.c @@ -846,7 +846,7 @@ handle_settings(GVariant *v_dict, gpointer user_data) } any_good = TRUE; _LOGI("DNS: %s", *array); - nm_l3_config_data_add_nameserver(priv->l3cd_4, AF_INET, &address_network); + nm_l3_config_data_add_nameserver_detail(priv->l3cd_4, AF_INET, &address_network, NULL); } if (!any_good) { _LOGW("Settings: 'DomainNameServers': none specified"); diff --git a/src/core/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c index f4f783a395..19ac52c8be 100644 --- a/src/core/dhcp/nm-dhcp-nettools.c +++ b/src/core/dhcp/nm-dhcp-nettools.c @@ -353,7 +353,7 @@ lease_parse_address_list(NDhcp4ClientLease *lease, nm_inet4_ntop(addr, addr_str)); continue; } - nm_l3_config_data_add_nameserver(l3cd, AF_INET, &addr); + nm_l3_config_data_add_nameserver_detail(l3cd, AF_INET, &addr, NULL); break; case NM_DHCP_OPTION_DHCP4_NIS_SERVERS: nm_l3_config_data_add_nis_server(l3cd, addr); diff --git a/src/core/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c index d406339a09..c142199791 100644 --- a/src/core/dhcp/nm-dhcp-systemd.c +++ b/src/core/dhcp/nm-dhcp-systemd.c @@ -135,7 +135,7 @@ lease_to_ip6_config(NMDhcpSystemd *self, sd_dhcp6_lease *lease, gint32 ts, GErro for (i = 0; i < num; i++) { nm_inet6_ntop(&dns[i], addr_str); g_string_append(nm_gstring_add_space_delimiter(str), addr_str); - nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &dns[i]); + nm_l3_config_data_add_nameserver_detail(l3cd, AF_INET6, &dns[i], NULL); } nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_DNS_SERVERS, str->str); } diff --git a/src/core/dhcp/nm-dhcp-utils.c b/src/core/dhcp/nm-dhcp-utils.c index 6a389dbef4..b9a787488e 100644 --- a/src/core/dhcp/nm-dhcp-utils.c +++ b/src/core/dhcp/nm-dhcp-utils.c @@ -499,7 +499,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx, for (s = dns; dns && *s; s++) { if (inet_pton(AF_INET, *s, &tmp_addr) > 0) { if (tmp_addr) { - nm_l3_config_data_add_nameserver(l3cd, AF_INET, &tmp_addr); + nm_l3_config_data_add_nameserver_detail(l3cd, AF_INET, &tmp_addr, NULL); _LOG2I(LOGD_DHCP4, iface, " nameserver '%s'", *s); } } else @@ -704,7 +704,7 @@ nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx, for (s = dns; dns && *s; s++) { if (inet_pton(AF_INET6, *s, &tmp_addr) > 0) { if (!IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) { - nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &tmp_addr); + nm_l3_config_data_add_nameserver_detail(l3cd, AF_INET6, &tmp_addr, NULL); _LOG2I(LOGD_DHCP6, iface, " nameserver '%s'", *s); } } else diff --git a/src/core/dhcp/tests/test-dhcp-utils.c b/src/core/dhcp/tests/test-dhcp-utils.c index 7597f51611..285943132a 100644 --- a/src/core/dhcp/tests/test-dhcp-utils.c +++ b/src/core/dhcp/tests/test-dhcp-utils.c @@ -88,7 +88,6 @@ test_generic_options(void) const char *expected_route2_dest = "100.99.88.56"; const char *expected_route2_gw = "10.1.1.1"; const char *const *strarr; - const in_addr_t *ia_arr; guint u; options = fill_table(generic_options, NULL); @@ -115,10 +114,10 @@ test_generic_options(void) g_assert_cmpstr(strarr[0], ==, expected_search1); g_assert_cmpstr(strarr[1], ==, expected_search2); - ia_arr = nm_l3_config_data_get_nameservers(l3cd, AF_INET, &u); + strarr = nm_l3_config_data_get_nameservers(l3cd, AF_INET, &u); g_assert_cmpint(u, ==, 2); - nmtst_assert_ip4_address(ia_arr[0], expected_dns1); - nmtst_assert_ip4_address(ia_arr[1], expected_dns2); + g_assert_cmpstr(strarr[0], ==, expected_dns1); + g_assert_cmpstr(strarr[1], ==, expected_dns2); g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3); diff --git a/src/core/dns/nm-dns-dnsmasq.c b/src/core/dns/nm-dns-dnsmasq.c index 495208b19e..8ae1bb961b 100644 --- a/src/core/dns/nm-dns-dnsmasq.c +++ b/src/core/dns/nm-dns-dnsmasq.c @@ -868,22 +868,24 @@ add_global_config(NMDnsDnsmasq *self, static void add_ip_config(NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsConfigIPData *ip_data) { - const char *iface; - const char *domain; - char ip_addr_to_string_buf[IP_ADDR_TO_STRING_BUFLEN]; - gconstpointer nameservers; - guint num; - guint i; - guint j; + const char *iface; + const char *domain; + char ip_addr_to_string_buf[IP_ADDR_TO_STRING_BUFLEN]; + const char *const *strarr; + guint num; + guint i; + guint j; iface = nm_platform_link_get_name(NM_PLATFORM_GET, ip_data->data->ifindex); - nameservers = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num); + strarr = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num); for (i = 0; i < num; i++) { - gconstpointer addr; + NMIPAddr a; - addr = nm_ip_addr_from_packed_array(ip_data->addr_family, nameservers, i); - ip_addr_to_string(ip_data->addr_family, addr, iface, ip_addr_to_string_buf); + if (!nm_utils_dnsname_parse_assert(ip_data->addr_family, strarr[i], NULL, &a, NULL)) + continue; + + ip_addr_to_string(ip_data->addr_family, &a, iface, ip_addr_to_string_buf); if (!ip_data->domains.has_default_route_explicit && ip_data->domains.has_default_route) add_dnsmasq_nameserver(self, servers, ip_addr_to_string_buf, NULL); diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index f39d0c0c1b..ea02d4f7c8 100644 --- a/src/core/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -557,24 +557,24 @@ merge_one_l3cd(NMResolvConfData *rc, int addr_family, int ifindex, const NML3Con guint num_nameservers; guint num; guint i; - gconstpointer nameservers; - const char *const *strv; + const char *const *strarr; nm_assert(ifindex == nm_l3_config_data_get_ifindex(l3cd)); - nameservers = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num_nameservers); + strarr = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num_nameservers); for (i = 0; i < num_nameservers; i++) { - const NMIPAddr *addr; + NMIPAddr a; - addr = nm_ip_addr_from_packed_array(addr_family, nameservers, i); + if (!nm_utils_dnsname_parse_assert(addr_family, strarr[i], NULL, &a, NULL)) + continue; if (addr_family == AF_INET) - nm_inet_ntop(addr_family, addr, buf); - else if (IN6_IS_ADDR_V4MAPPED(addr)) - nm_inet4_ntop(addr->addr6.s6_addr32[3], buf); + nm_inet_ntop(addr_family, &a, buf); + else if (IN6_IS_ADDR_V4MAPPED(&a)) + nm_inet4_ntop(a.addr6.s6_addr32[3], buf); else { - nm_inet6_ntop(&addr->addr6, buf); - if (IN6_IS_ADDR_LINKLOCAL(addr)) { + nm_inet6_ntop(&a.addr6, buf); + if (IN6_IS_ADDR_LINKLOCAL(&a)) { const char *ifname; ifname = nm_platform_link_get_name(NM_PLATFORM_GET, ifindex); @@ -591,9 +591,9 @@ merge_one_l3cd(NMResolvConfData *rc, int addr_family, int ifindex, const NML3Con add_dns_domains(rc->searches, addr_family, l3cd, FALSE, TRUE); has_trust_ad = FALSE; - strv = nm_l3_config_data_get_dns_options(l3cd, addr_family, &num); + strarr = nm_l3_config_data_get_dns_options(l3cd, addr_family, &num); for (i = 0; i < num; i++) { - const char *option = strv[i]; + const char *option = strarr[i]; if (nm_streq(option, NM_SETTING_DNS_OPTION_TRUST_AD)) { has_trust_ad = TRUE; @@ -1258,19 +1258,21 @@ merge_global_dns_config(NMResolvConfData *rc, NMGlobalDnsConfig *global_conf) static const char * get_nameserver_list(int addr_family, const NML3ConfigData *l3cd, NMStrBuf *tmp_strbuf) { - char buf[NM_INET_ADDRSTRLEN]; - guint num; - guint i; - gconstpointer nameservers; + char buf[NM_INET_ADDRSTRLEN]; + guint num; + guint i; + const char *const *strarr; nm_str_buf_reset(tmp_strbuf); - nameservers = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num); + strarr = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num); for (i = 0; i < num; i++) { - const NMIPAddr *addr; + NMIPAddr a; - addr = nm_ip_addr_from_packed_array(addr_family, nameservers, i); - nm_inet_ntop(addr_family, addr->addr_ptr, buf); + if (!nm_utils_dnsname_parse_assert(addr_family, strarr[i], NULL, &a, NULL)) + continue; + + nm_inet_ntop(addr_family, &a, buf); if (i > 0) nm_str_buf_append_c(tmp_strbuf, ' '); nm_str_buf_append(tmp_strbuf, buf); @@ -2628,17 +2630,17 @@ _get_config_variant(NMDnsManager *self) head = _mgr_get_ip_data_lst_head(self); c_list_for_each_entry (ip_data, head, ip_data_lst) { - GVariantBuilder entry_builder; - GVariantBuilder strv_builder; - guint num; - guint num_domains; - guint num_searches; - guint i; - char buf[NM_INET_ADDRSTRLEN]; - const char *ifname; - gconstpointer nameservers; + GVariantBuilder entry_builder; + GVariantBuilder strv_builder; + guint num; + guint num_domains; + guint num_searches; + guint i; + char buf[NM_INET_ADDRSTRLEN]; + const char *ifname; + const char *const *strarr; - nameservers = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num); + strarr = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num); if (num == 0) continue; @@ -2646,12 +2648,12 @@ _get_config_variant(NMDnsManager *self) g_variant_builder_init(&strv_builder, G_VARIANT_TYPE("as")); for (i = 0; i < num; i++) { - const NMIPAddr *addr; + NMIPAddr a; - addr = nm_ip_addr_from_packed_array(ip_data->addr_family, nameservers, i); - g_variant_builder_add(&strv_builder, - "s", - nm_inet_ntop(ip_data->addr_family, addr, buf)); + if (!nm_utils_dnsname_parse_assert(ip_data->addr_family, strarr[i], NULL, &a, NULL)) + continue; + + g_variant_builder_add(&strv_builder, "s", nm_inet_ntop(ip_data->addr_family, &a, buf)); } g_variant_builder_add(&entry_builder, "{sv}", diff --git a/src/core/dns/nm-dns-systemd-resolved.c b/src/core/dns/nm-dns-systemd-resolved.c index 06e524302d..96e2794c6a 100644 --- a/src/core/dns/nm-dns-systemd-resolved.c +++ b/src/core/dns/nm-dns-systemd-resolved.c @@ -36,6 +36,7 @@ /* define a variable, so that we can compare the operation with pointer equality. */ static const char *const DBUS_OP_SET_LINK_DEFAULT_ROUTE = "SetLinkDefaultRoute"; static const char *const DBUS_OP_SET_LINK_DNS_OVER_TLS = "SetLinkDNSOverTLS"; +static const char *const DBUS_OP_SET_LINK_DNS_EX = "SetLinkDNSEx"; /*****************************************************************************/ @@ -90,12 +91,11 @@ typedef struct { bool dbus_initied : 1; bool send_updates_waiting : 1; bool update_pending : 1; - /* These two variables ensure that the log is not spammed with - * API (not) supported messages. - * They can be removed when no distro uses systemd-resolved < v240 anymore - */ - NMTernary has_link_default_route : 3; - NMTernary has_link_dns_over_tls : 3; + + /* Detect support for the respective D-Bus API. */ + NMTernary has_set_link_default_route : 3; + NMTernary has_set_link_dns_over_tls : 3; + NMTernary has_set_link_dns_ex : 3; } NMDnsSystemdResolvedPrivate; struct _NMDnsSystemdResolved { @@ -148,6 +148,8 @@ static void _resolve_complete_error(NMDnsSystemdResolvedResolveHandle *handle, G static void _resolve_start(NMDnsSystemdResolved *self, NMDnsSystemdResolvedResolveHandle *handle); +static void send_updates(NMDnsSystemdResolved *self); + /*****************************************************************************/ static gboolean @@ -276,6 +278,7 @@ call_done(GObject *source, GAsyncResult *r, gpointer user_data) NMLogLevel log_level; const char *operation; int ifindex; + gboolean reconfigure = FALSE; request_item = user_data; self = request_item->self; @@ -290,30 +293,52 @@ call_done(GObject *source, GAsyncResult *r, gpointer user_data) goto out_dec_pending; if (v) { - if (operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE - && priv->has_link_default_route == NM_TERNARY_DEFAULT) { - priv->has_link_default_route = NM_TERNARY_TRUE; - _LOGD("systemd-resolved support for SetLinkDefaultRoute(): API supported"); - } - if (operation == DBUS_OP_SET_LINK_DNS_OVER_TLS - && priv->has_link_dns_over_tls == NM_TERNARY_DEFAULT) { - priv->has_link_dns_over_tls = NM_TERNARY_TRUE; - _LOGD("systemd-resolved support for SetLinkDNSOverTLS(): API supported"); + if (operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE) { + if (priv->has_set_link_default_route == NM_TERNARY_DEFAULT) { + priv->has_set_link_default_route = NM_TERNARY_TRUE; + _LOGD("systemd-resolved support for SetLinkDefaultRoute(): API supported"); + } + } else if (operation == DBUS_OP_SET_LINK_DNS_OVER_TLS) { + if (priv->has_set_link_dns_over_tls == NM_TERNARY_DEFAULT) { + priv->has_set_link_dns_over_tls = NM_TERNARY_TRUE; + _LOGD("systemd-resolved support for SetLinkDNSOverTLS(): API supported"); + } + } else if (operation == DBUS_OP_SET_LINK_DNS_EX) { + if (priv->has_set_link_dns_ex == NM_TERNARY_DEFAULT) { + priv->has_set_link_dns_ex = NM_TERNARY_TRUE; + _LOGD("systemd-resolved support for SetLinkDNSEx(): API supported"); + } } priv->send_updates_warn_ratelimited = FALSE; goto out_dec_pending; } if (nm_g_error_matches(error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) { - if (priv->has_link_default_route == NM_TERNARY_DEFAULT - && operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE) { - priv->has_link_default_route = NM_TERNARY_FALSE; - _LOGD("systemd-resolved support for SetLinkDefaultRoute(): API not supported"); - } - if (priv->has_link_dns_over_tls == NM_TERNARY_DEFAULT - && operation == DBUS_OP_SET_LINK_DNS_OVER_TLS) { - priv->has_link_dns_over_tls = NM_TERNARY_FALSE; - _LOGD("systemd-resolved support for SetLinkDNSOverTLS(): API not supported"); + if (operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE) { + if (priv->has_set_link_default_route == NM_TERNARY_DEFAULT) { + priv->has_set_link_default_route = NM_TERNARY_FALSE; + _LOGD("systemd-resolved support for SetLinkDefaultRoute(): API not supported"); + } + } else if (operation == DBUS_OP_SET_LINK_DNS_OVER_TLS) { + if (priv->has_set_link_dns_over_tls == NM_TERNARY_DEFAULT) { + priv->has_set_link_dns_over_tls = NM_TERNARY_FALSE; + _LOGD("systemd-resolved support for SetLinkDNSOverTLS(): API not supported"); + } + } else if (operation == DBUS_OP_SET_LINK_DNS_EX) { + if (priv->has_set_link_dns_ex == NM_TERNARY_DEFAULT) { + priv->has_set_link_dns_ex = NM_TERNARY_FALSE; + _LOGD("systemd-resolved support for SetLinkDNSEx(): API not supported"); + + _LOGW("systemd-resolved does not support SetLinkDNSEx API (v246). " + "Cannot set DoT server name (SNI)"); + + /* We need to reconfigure with the SetLinkDNS fallback. + * + * In the other cases above, there is no need to reconfigure anything. + * We won't retry SetLinkDefaultRoute/SetLinkDNSOverTLS anymore, but there + * is nothing else we can do about that. */ + reconfigure = TRUE; + } } goto out_dec_pending; } @@ -335,21 +360,29 @@ out_dec_pending: * we must wrap up fast, and not hang an undefined amount time. */ g_object_unref(self); } + + if (reconfigure) { + priv->send_updates_waiting = TRUE; + send_updates(self); + } } static gboolean update_add_ip_config(NMDnsSystemdResolved *self, + const NMDnsConfigIPData *ip_data, GVariantBuilder *dns, + GVariantBuilder *dns_ex, GVariantBuilder *domains, - const NMDnsConfigIPData *ip_data) + gboolean *out_require_dns_ex) { - gsize addr_size; - guint n; - guint i; - gboolean is_routing; - const char *domain; - gboolean has_config = FALSE; - gconstpointer nameservers; + NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); + gsize addr_size; + guint n; + guint i; + gboolean is_routing; + const char *domain; + gboolean has_config = FALSE; + const char *const *strarr; addr_size = nm_utils_addr_family_to_size(ip_data->addr_family); @@ -361,29 +394,52 @@ update_add_ip_config(NMDnsSystemdResolved *self, return FALSE; } - nameservers = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &n); + strarr = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &n); for (i = 0; i < n; i++) { - g_variant_builder_open(dns, G_VARIANT_TYPE("(iay)")); - g_variant_builder_add(dns, "i", ip_data->addr_family); - g_variant_builder_add_value( - dns, - nm_g_variant_new_ay(nm_ip_addr_from_packed_array(ip_data->addr_family, nameservers, i), - addr_size)); - g_variant_builder_close(dns); + const char *server_name; + NMIPAddr a; + + if (!nm_utils_dnsname_parse_assert(ip_data->addr_family, strarr[i], NULL, &a, &server_name)) + continue; + + if (server_name) { + NM_SET_OUT(out_require_dns_ex, TRUE); + if (priv->has_set_link_dns_ex == FALSE) { + /* The caller won't care about this result anymore. We can skip setting it. */ + dns = NULL; + } + } + + if (dns_ex) { + g_variant_builder_open(dns_ex, G_VARIANT_TYPE("(iayqs)")); + g_variant_builder_add(dns_ex, "i", ip_data->addr_family); + g_variant_builder_add_value(dns_ex, nm_g_variant_new_ay((gconstpointer) &a, addr_size)); + g_variant_builder_add(dns_ex, "q", 0); + g_variant_builder_add(dns_ex, "s", server_name ?: ""); + g_variant_builder_close(dns_ex); + } + if (dns) { + g_variant_builder_open(dns, G_VARIANT_TYPE("(iay)")); + g_variant_builder_add(dns, "i", ip_data->addr_family); + g_variant_builder_add_value(dns, nm_g_variant_new_ay((gconstpointer) &a, addr_size)); + g_variant_builder_close(dns); + } has_config = TRUE; } - if (!ip_data->domains.has_default_route_explicit - && ip_data->domains.has_default_route_exclusive) { - g_variant_builder_add(domains, "(sb)", ".", TRUE); - has_config = TRUE; - } - if (ip_data->domains.search) { - for (i = 0; ip_data->domains.search[i]; i++) { - domain = nm_utils_parse_dns_domain(ip_data->domains.search[i], &is_routing); - g_variant_builder_add(domains, "(sb)", domain[0] ? domain : ".", is_routing); + if (!has_config || domains) { + if (!ip_data->domains.has_default_route_explicit + && ip_data->domains.has_default_route_exclusive) { + g_variant_builder_add(domains, "(sb)", ".", TRUE); has_config = TRUE; } + if (ip_data->domains.search) { + for (i = 0; ip_data->domains.search[i]; i++) { + domain = nm_utils_parse_dns_domain(ip_data->domains.search[i], &is_routing); + g_variant_builder_add(domains, "(sb)", domain[0] ? domain : ".", is_routing); + has_config = TRUE; + } + } } return has_config; @@ -406,7 +462,9 @@ free_pending_updates(NMDnsSystemdResolved *self) static gboolean prepare_one_interface(NMDnsSystemdResolved *self, const InterfaceConfig *ic) { + NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); GVariantBuilder dns; + GVariantBuilder dns_ex; GVariantBuilder domains; NMSettingConnectionMdns mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; NMSettingConnectionLlmnr llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; @@ -417,6 +475,7 @@ prepare_one_interface(NMDnsSystemdResolved *self, const InterfaceConfig *ic) gboolean has_config = FALSE; gboolean has_default_route = FALSE; guint i; + gboolean require_dns_ex = FALSE; g_variant_builder_init(&dns, G_VARIANT_TYPE("(ia(iay))")); g_variant_builder_add(&dns, "i", ic->ifindex); @@ -430,7 +489,7 @@ prepare_one_interface(NMDnsSystemdResolved *self, const InterfaceConfig *ic) for (i = 0; i < ic->ip_data_list->len; i++) { const NMDnsConfigIPData *ip_data = ic->ip_data_list->pdata[i]; - if (update_add_ip_config(self, &dns, &domains, ip_data)) + if (update_add_ip_config(self, ip_data, &dns, NULL, &domains, &require_dns_ex)) has_config = TRUE; if (ip_data->domains.has_default_route) @@ -448,6 +507,23 @@ prepare_one_interface(NMDnsSystemdResolved *self, const InterfaceConfig *ic) g_variant_builder_close(&dns); g_variant_builder_close(&domains); + if (!require_dns_ex) { + /* No need to use the new API. SetLinkDNS() is sufficient. */ + } else if (!priv->has_set_link_dns_ex) { + /* API to set server name is not supported. Nothing we can do. */ + require_dns_ex = FALSE; + } else { + g_variant_builder_init(&dns_ex, G_VARIANT_TYPE("(ia(iayqs))")); + g_variant_builder_add(&dns_ex, "i", ic->ifindex); + g_variant_builder_open(&dns_ex, G_VARIANT_TYPE("a(iayqs)")); + for (i = 0; i < ic->ip_data_list->len; i++) { + const NMDnsConfigIPData *ip_data = ic->ip_data_list->pdata[i]; + + update_add_ip_config(self, ip_data, NULL, &dns_ex, NULL, NULL); + } + g_variant_builder_close(&dns_ex); + } + switch (mdns) { case NM_SETTING_CONNECTION_MDNS_NO: mdns_arg = "no"; @@ -513,7 +589,14 @@ prepare_one_interface(NMDnsSystemdResolved *self, const InterfaceConfig *ic) "SetLinkLLMNR", ic->ifindex, g_variant_new("(is)", ic->ifindex, llmnr_arg ?: "")); - _request_item_append(self, "SetLinkDNS", ic->ifindex, g_variant_builder_end(&dns)); + if (require_dns_ex) { + _request_item_append(self, + DBUS_OP_SET_LINK_DNS_EX, + ic->ifindex, + g_variant_builder_end(&dns_ex)); + g_variant_builder_clear(&dns); + } else + _request_item_append(self, "SetLinkDNS", ic->ifindex, g_variant_builder_end(&dns)); _request_item_append(self, DBUS_OP_SET_LINK_DNS_OVER_TLS, ic->ifindex, @@ -631,9 +714,9 @@ send_updates(NMDnsSystemdResolved *self) gs_free char *ss = NULL; if ((request_item->operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE - && priv->has_link_default_route == NM_TERNARY_FALSE) + && priv->has_set_link_default_route == NM_TERNARY_FALSE) || (request_item->operation == DBUS_OP_SET_LINK_DNS_OVER_TLS - && priv->has_link_dns_over_tls == NM_TERNARY_FALSE)) { + && priv->has_set_link_dns_over_tls == NM_TERNARY_FALSE)) { /* The "SetLinkDefaultRoute" API is only supported since v240. * The "SetLinkDNSOverTLS" API is only supported since v239. * We detected whether they are supported, and skip the calls. There @@ -798,8 +881,9 @@ name_owner_changed(NMDnsSystemdResolved *self, const char *owner) priv->try_start_blocked = FALSE; priv->send_updates_waiting = TRUE; } else { - priv->has_link_default_route = NM_TERNARY_DEFAULT; - priv->has_link_dns_over_tls = NM_TERNARY_DEFAULT; + priv->has_set_link_default_route = NM_TERNARY_DEFAULT; + priv->has_set_link_dns_over_tls = NM_TERNARY_DEFAULT; + priv->has_set_link_dns_ex = NM_TERNARY_DEFAULT; } send_updates(self); @@ -1158,8 +1242,9 @@ nm_dns_systemd_resolved_init(NMDnsSystemdResolved *self) { NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); - priv->has_link_default_route = NM_TERNARY_DEFAULT; - priv->has_link_dns_over_tls = NM_TERNARY_DEFAULT; + priv->has_set_link_default_route = NM_TERNARY_DEFAULT; + priv->has_set_link_dns_over_tls = NM_TERNARY_DEFAULT; + priv->has_set_link_dns_ex = NM_TERNARY_DEFAULT; c_list_init(&priv->request_queue_lst_head); c_list_init(&priv->handle_lst_head); diff --git a/src/core/dnsmasq/nm-dnsmasq-manager.c b/src/core/dnsmasq/nm-dnsmasq-manager.c index 2cdfb29643..d245d5d3c6 100644 --- a/src/core/dnsmasq/nm-dnsmasq-manager.c +++ b/src/core/dnsmasq/nm-dnsmasq-manager.c @@ -104,7 +104,6 @@ create_dm_cmd_line(const char *iface, gs_free char *error_desc = NULL; const char *dm_binary; const NMPlatformIP4Address *listen_address; - const in_addr_t *ipv4arr; const char *const *strarr; guint n; guint i; @@ -163,13 +162,18 @@ create_dm_cmd_line(const char *iface, nm_strv_ptrarray_add_string_concat(cmd, "--dhcp-option=option:router,", listen_address_s); } - ipv4arr = nm_l3_config_data_get_nameservers(l3cd, AF_INET, &n); + strarr = nm_l3_config_data_get_nameservers(l3cd, AF_INET, &n); if (n > 0) { nm_gstring_prepare(&s); g_string_append(s, "--dhcp-option=option:dns-server"); for (i = 0; i < n; i++) { + in_addr_t a; + + if (!nm_utils_dnsname_parse_assert(AF_INET, strarr[i], NULL, &a, NULL)) + continue; + g_string_append_c(s, ','); - g_string_append(s, nm_inet4_ntop(ipv4arr[i], sbuf_addr)); + g_string_append(s, nm_inet4_ntop(a, sbuf_addr)); } nm_strv_ptrarray_take_gstring(cmd, &s); } diff --git a/src/core/ndisc/nm-ndisc.c b/src/core/ndisc/nm-ndisc.c index b7617e1f96..8aa7b6e3ac 100644 --- a/src/core/ndisc/nm-ndisc.c +++ b/src/core/ndisc/nm-ndisc.c @@ -13,6 +13,7 @@ #include "libnm-platform/nm-platform-utils.h" #include "libnm-platform/nm-platform.h" #include "libnm-platform/nmp-netns.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nm-l3-config-data.h" #include "nm-l3cfg.h" #include "nm-ndisc-private.h" @@ -186,8 +187,12 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex *multi_idx, } } - for (i = 0; i < rdata->dns_servers_n; i++) - nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &rdata->dns_servers[i].address); + for (i = 0; i < rdata->dns_servers_n; i++) { + nm_l3_config_data_add_nameserver_detail(l3cd, + AF_INET6, + &rdata->dns_servers[i].address, + NULL); + } for (i = 0; i < rdata->dns_domains_n; i++) nm_l3_config_data_add_search(l3cd, AF_INET6, rdata->dns_domains[i].domain); @@ -989,14 +994,13 @@ announce_router_solicited(NMNDisc *ndisc) void nm_ndisc_set_config(NMNDisc *ndisc, const NML3ConfigData *l3cd) { - gboolean changed = FALSE; - const struct in6_addr *in6arr; - const char *const *strvarr; - NMDedupMultiIter iter; - const NMPObject *obj; - guint len; - guint i; - gint32 fake_now = NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000; + gboolean changed = FALSE; + const char *const *strvarr; + NMDedupMultiIter iter; + const NMPObject *obj; + guint len; + guint i; + gint32 fake_now = NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000; nm_assert(NM_IS_NDISC(ndisc)); nm_assert(nm_ndisc_get_node_type(ndisc) == NM_NDISC_NODE_TYPE_ROUTER); @@ -1035,15 +1039,19 @@ nm_ndisc_set_config(NMNDisc *ndisc, const NML3ConfigData *l3cd) changed = TRUE; } - in6arr = NULL; - len = 0; + strvarr = NULL; + len = 0; if (l3cd) - in6arr = nm_l3_config_data_get_nameservers(l3cd, AF_INET6, &len); + strvarr = nm_l3_config_data_get_nameservers(l3cd, AF_INET6, &len); for (i = 0; i < len; i++) { + struct in6_addr a; NMNDiscDNSServer n; + if (!nm_utils_dnsname_parse_assert(AF_INET6, strvarr[i], NULL, &a, NULL)) + continue; + n = (NMNDiscDNSServer){ - .address = in6arr[i], + .address = a, .expiry_msec = _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, NM_NDISC_ROUTER_LIFETIME), }; diff --git a/src/core/nm-dispatcher.c b/src/core/nm-dispatcher.c index d3529ee4de..1617dc3667 100644 --- a/src/core/nm-dispatcher.c +++ b/src/core/nm-dispatcher.c @@ -179,7 +179,6 @@ dump_ip_to_props(const NML3ConfigData *l3cd, int addr_family, GVariantBuilder *b const NMPObject *default_route; const char *const *strarr; const in_addr_t *ip4arr; - gconstpointer iparr; if (IS_IPv4) g_variant_builder_init(&int_builder, G_VARIANT_TYPE("aau")); @@ -223,14 +222,17 @@ dump_ip_to_props(const NML3ConfigData *l3cd, int addr_family, GVariantBuilder *b g_variant_builder_init(&int_builder, G_VARIANT_TYPE("au")); else g_variant_builder_init(&int_builder, G_VARIANT_TYPE("aay")); - iparr = nm_l3_config_data_get_nameservers(l3cd, addr_family, &n); + strarr = nm_l3_config_data_get_nameservers(l3cd, addr_family, &n); for (i = 0; i < n; i++) { + NMIPAddr a; + + if (!nm_utils_dnsname_parse_assert(addr_family, strarr[i], NULL, &a, NULL)) + continue; + if (IS_IPv4) - g_variant_builder_add(&int_builder, "u", ((const in_addr_t *) iparr)[i]); - else { - var1 = nm_g_variant_new_ay_in6addr(&(((const struct in6_addr *) iparr)[i])); - g_variant_builder_add(&int_builder, "@ay", var1); - } + g_variant_builder_add(&int_builder, "u", &a); + else + g_variant_builder_add(&int_builder, "@ay", nm_g_variant_new_ay_in6addr(&a.addr6)); } g_variant_builder_add(builder, "{sv}", "nameservers", g_variant_builder_end(&int_builder)); diff --git a/src/core/nm-ip-config.c b/src/core/nm-ip-config.c index 12f4fadff0..a87e4c3f17 100644 --- a/src/core/nm-ip-config.c +++ b/src/core/nm-ip-config.c @@ -10,6 +10,7 @@ #include +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nm-l3cfg.h" #include "NetworkManagerUtils.h" @@ -336,6 +337,7 @@ get_property_ip4(GObject *object, guint prop_id, GValue *value, GParamSpec *pspe char addr_str[NM_INET_ADDRSTRLEN]; GVariantBuilder builder; const in_addr_t *addrs; + const char *const *strarr; guint len; guint i; @@ -347,28 +349,37 @@ get_property_ip4(GObject *object, guint prop_id, GValue *value, GParamSpec *pspe g_value_set_variant(value, priv->v_routes); break; case PROP_IP4_NAMESERVERS: - addrs = nm_l3_config_data_get_nameservers(priv->l3cd, AF_INET, &len); - g_value_set_variant(value, - (len == 0) ? nm_g_variant_singleton_au() - : nm_g_variant_new_au(addrs, len)); - break; case PROP_IP4_NAMESERVER_DATA: - addrs = nm_l3_config_data_get_nameservers(priv->l3cd, AF_INET, &len); - if (len == 0) - g_value_set_variant(value, nm_g_variant_singleton_aaLsvI()); - else { - g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); + strarr = nm_l3_config_data_get_nameservers(priv->l3cd, AF_INET, &len); + if (len == 0) { + g_value_set_variant(value, + (prop_id == PROP_IP4_NAMESERVERS) + ? nm_g_variant_singleton_au() + : nm_g_variant_singleton_aaLsvI()); + } else { + if (prop_id == PROP_IP4_NAMESERVERS) + g_variant_builder_init(&builder, G_VARIANT_TYPE("au")); + else + g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); for (i = 0; i < len; i++) { - GVariantBuilder nested_builder; + in_addr_t a; - nm_inet4_ntop(addrs[i], addr_str); + if (!nm_utils_dnsname_parse_assert(AF_INET, strarr[i], NULL, &a, NULL)) + continue; - g_variant_builder_init(&nested_builder, G_VARIANT_TYPE("a{sv}")); - g_variant_builder_add(&nested_builder, - "{sv}", - "address", - g_variant_new_string(addr_str)); - g_variant_builder_add(&builder, "a{sv}", &nested_builder); + if (prop_id == PROP_IP4_NAMESERVERS) + g_variant_builder_add(&builder, "u", &a); + else { + GVariantBuilder nested_builder; + + nm_inet4_ntop(a, addr_str); + g_variant_builder_init(&nested_builder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&nested_builder, + "{sv}", + "address", + g_variant_new_string(addr_str)); + g_variant_builder_add(&builder, "a{sv}", &nested_builder); + } } g_value_take_variant(value, g_variant_builder_end(&builder)); @@ -503,7 +514,7 @@ nm_ip_config_dns_hash(const NML3ConfigData *l3cd, GChecksum *sum, int addr_famil { guint i; int val; - const char *const *nameservers; + const char *const *strarr; const in_addr_t *wins; const char *const *domains; const char *const *searches; @@ -517,12 +528,9 @@ nm_ip_config_dns_hash(const NML3ConfigData *l3cd, GChecksum *sum, int addr_famil g_return_if_fail(l3cd); g_return_if_fail(sum); - nameservers = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num_nameservers); - for (i = 0; i < num_nameservers; i++) { - g_checksum_update(sum, - nm_ip_addr_from_packed_array(addr_family, nameservers, i), - nm_utils_addr_family_to_size(addr_family)); - } + strarr = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num_nameservers); + for (i = 0; i < num_nameservers; i++) + g_checksum_update(sum, (gpointer) strarr[i], strlen(strarr[i])); if (addr_family == AF_INET) { wins = nm_l3_config_data_get_wins(l3cd, &num_wins); @@ -630,12 +638,12 @@ static const NMDBusInterfaceInfoExtended interface_info_ip6_config = { static void get_property_ip6(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMIPConfig *self = NM_IP_CONFIG(object); - NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self); - GVariantBuilder builder; - guint len; - guint i; - const struct in6_addr *addrs; + NMIPConfig *self = NM_IP_CONFIG(object); + NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self); + GVariantBuilder builder; + guint len; + guint i; + const char *const *strarr; switch (prop_id) { case PROP_IP6_ADDRESSES: @@ -645,13 +653,19 @@ get_property_ip6(GObject *object, guint prop_id, GValue *value, GParamSpec *pspe g_value_set_variant(value, priv->v_routes); break; case PROP_IP6_NAMESERVERS: - addrs = nm_l3_config_data_get_nameservers(priv->l3cd, AF_INET6, &len); + strarr = nm_l3_config_data_get_nameservers(priv->l3cd, AF_INET6, &len); if (len == 0) g_value_set_variant(value, nm_g_variant_singleton_aay()); else { g_variant_builder_init(&builder, G_VARIANT_TYPE("aay")); - for (i = 0; i < len; i++) - g_variant_builder_add(&builder, "@ay", nm_g_variant_new_ay_in6addr(&addrs[i])); + for (i = 0; i < len; i++) { + struct in6_addr a; + + if (!nm_utils_dnsname_parse_assert(AF_INET6, strarr[i], NULL, &a, NULL)) + continue; + + g_variant_builder_add(&builder, "@ay", nm_g_variant_new_ay_in6addr(&a)); + } g_value_take_variant(value, g_variant_builder_end(&builder)); } break; @@ -736,8 +750,8 @@ _handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd) nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL; GParamSpec *changed_params[8]; guint n_changed_params = 0; - const char *const *strv; - const char *const *strv_old; + const char *const *strarr; + const char *const *strarr_old; gconstpointer addrs; gconstpointer addrs_old; guint len; @@ -748,9 +762,9 @@ _handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd) l3cd_old = g_steal_pointer(&priv->l3cd); priv->l3cd = nm_l3_config_data_ref(l3cd); - addrs_old = nm_l3_config_data_get_nameservers(l3cd_old, addr_family, &len_old); - addrs = nm_l3_config_data_get_nameservers(priv->l3cd, addr_family, &len); - if (!nm_memeq_n(addrs_old, len_old, addrs, len, nm_utils_addr_family_to_size(addr_family))) { + strarr_old = nm_l3_config_data_get_nameservers(l3cd_old, addr_family, &len_old); + strarr = nm_l3_config_data_get_nameservers(priv->l3cd, addr_family, &len); + if (!nm_strv_equal_n(strarr_old, len_old, strarr, len)) { if (IS_IPv4) { changed_params[n_changed_params++] = obj_properties_ip4[PROP_IP4_NAMESERVER_DATA]; changed_params[n_changed_params++] = obj_properties_ip4[PROP_IP4_NAMESERVERS]; @@ -758,14 +772,14 @@ _handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd) changed_params[n_changed_params++] = obj_properties_ip6[PROP_IP6_NAMESERVERS]; } - strv_old = nm_l3_config_data_get_domains(l3cd_old, addr_family, &len_old); - strv = nm_l3_config_data_get_domains(priv->l3cd, addr_family, &len); - if (!nm_strv_equal_n(strv, len, strv_old, len_old)) + strarr_old = nm_l3_config_data_get_domains(l3cd_old, addr_family, &len_old); + strarr = nm_l3_config_data_get_domains(priv->l3cd, addr_family, &len); + if (!nm_strv_equal_n(strarr, len, strarr_old, len_old)) changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_DOMAINS]; - strv_old = nm_l3_config_data_get_searches(l3cd_old, addr_family, &len_old); - strv = nm_l3_config_data_get_searches(priv->l3cd, addr_family, &len); - if (!nm_strv_equal_n(strv, len, strv_old, len_old)) + strarr_old = nm_l3_config_data_get_searches(l3cd_old, addr_family, &len_old); + strarr = nm_l3_config_data_get_searches(priv->l3cd, addr_family, &len); + if (!nm_strv_equal_n(strarr, len, strarr_old, len_old)) changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_SEARCHES]; v_i_old = nm_l3_config_data_get_dns_priority_or_default(l3cd_old, addr_family); @@ -773,9 +787,9 @@ _handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd) if (v_i != v_i_old) changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_DNS_PRIORITY]; - strv_old = nm_l3_config_data_get_dns_options(l3cd_old, addr_family, &len); - strv = nm_l3_config_data_get_dns_options(priv->l3cd, addr_family, &len); - if (!nm_strv_equal_n(strv, len, strv_old, len_old)) + strarr_old = nm_l3_config_data_get_dns_options(l3cd_old, addr_family, &len); + strarr = nm_l3_config_data_get_dns_options(priv->l3cd, addr_family, &len); + if (!nm_strv_equal_n(strarr, len, strarr_old, len_old)) changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_DNS_OPTIONS]; if (IS_IPv4) { diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 2d4389323f..53896839f7 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -67,10 +67,10 @@ struct _NML3ConfigData { union { struct { - GArray *nameservers_6; - GArray *nameservers_4; + GPtrArray *nameservers_6; + GPtrArray *nameservers_4; }; - GArray *nameservers_x[2]; + GPtrArray *nameservers_x[2]; }; union { @@ -269,17 +269,6 @@ _garray_inaddr_get(GArray *arr, guint *out_len) return arr->data; } -static gconstpointer -_garray_inaddr_at(GArray *arr, gboolean IS_IPv4, guint idx) -{ - nm_assert(arr); - nm_assert(idx < arr->len); - - if (IS_IPv4) - return &nm_g_array_index(arr, in_addr_t, idx); - return &nm_g_array_index(arr, struct in6_addr, idx); -} - static gboolean _garray_inaddr_add(GArray **p_arr, int addr_family, gconstpointer addr) { @@ -480,13 +469,11 @@ nm_l3_config_data_log(const NML3ConfigData *self, self->dns_priority_x[IS_IPv4]); } - for (i = 0; i < nm_g_array_len(self->nameservers_x[IS_IPv4]); i++) { + for (i = 0; i < nm_g_ptr_array_len(self->nameservers_x[IS_IPv4]); i++) { _L("nameserver%c[%u]: %s", nm_utils_addr_family_to_char(addr_family), i, - nm_inet_ntop(addr_family, - _garray_inaddr_at(self->nameservers_x[IS_IPv4], IS_IPv4, i), - sbuf_addr)); + (char *) self->nameservers_x[IS_IPv4]->pdata[i]); } for (i = 0; i < nm_g_ptr_array_len(self->domains_x[IS_IPv4]); i++) { @@ -792,8 +779,8 @@ nm_l3_config_data_unref(const NML3ConfigData *self) nm_clear_pointer(&mutable->dhcp_lease_4, nm_dhcp_lease_unref); nm_clear_pointer(&mutable->dhcp_lease_6, nm_dhcp_lease_unref); - nm_clear_pointer(&mutable->nameservers_4, g_array_unref); - nm_clear_pointer(&mutable->nameservers_6, g_array_unref); + nm_clear_pointer(&mutable->nameservers_4, g_ptr_array_unref); + nm_clear_pointer(&mutable->nameservers_6, g_ptr_array_unref); nm_clear_pointer(&mutable->domains_4, g_ptr_array_unref); nm_clear_pointer(&mutable->domains_6, g_ptr_array_unref); @@ -1421,7 +1408,7 @@ _check_and_add_domain(GPtrArray **p_arr, const char *domain) return TRUE; } -gconstpointer +const char *const * nm_l3_config_data_get_nameservers(const NML3ConfigData *self, int addr_family, guint *out_len) { nm_assert(!self || _NM_IS_L3_CONFIG_DATA(self, TRUE)); @@ -1433,33 +1420,68 @@ nm_l3_config_data_get_nameservers(const NML3ConfigData *self, int addr_family, g return NULL; } - return _garray_inaddr_get(self->nameservers_x[NM_IS_IPv4(addr_family)], out_len); + return nm_strv_ptrarray_get_unsafe(self->nameservers_x[NM_IS_IPv4(addr_family)], out_len); } gboolean -nm_l3_config_data_add_nameserver(NML3ConfigData *self, - int addr_family, - gconstpointer /* (const NMIPAddr *) */ nameserver) +nm_l3_config_data_add_nameserver(NML3ConfigData *self, int addr_family, const char *nameserver) { + GPtrArray **p_arr; + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); nm_assert_addr_family(addr_family); nm_assert(nameserver); - return _garray_inaddr_add(&self->nameservers_x[NM_IS_IPv4(addr_family)], - addr_family, - nameserver); + if (NM_MORE_ASSERTS > 5) { + gs_free char *s_free = NULL; + + nm_assert( + nm_streq0(nm_utils_dnsname_normalize(addr_family, nameserver, &s_free), nameserver)); + } + + p_arr = &self->nameservers_x[NM_IS_IPv4(addr_family)]; + + if (nm_strv_ptrarray_contains(*p_arr, nameserver)) + return FALSE; + + nm_strv_ptrarray_add_string_dup(nm_strv_ptrarray_ensure(p_arr), nameserver); + return TRUE; +} + +gboolean +nm_l3_config_data_add_nameserver_detail(NML3ConfigData *self, + int addr_family, + gconstpointer addr_bin, + const char *server_name) +{ + gs_free char *s_free = NULL; + char *s; + gsize l; + + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert_addr_family(addr_family); + nm_assert(addr_bin); + + l = (NM_INET_ADDRSTRLEN + 2u) + (server_name ? strlen(server_name) : 0u); + + s = nm_malloc_maybe_a(300, l, &s_free); + + if (!nm_utils_dnsname_construct(addr_family, addr_bin, server_name, s, l)) + nm_assert_not_reached(); + + return nm_l3_config_data_add_nameserver(self, addr_family, s); } gboolean nm_l3_config_data_clear_nameservers(NML3ConfigData *self, int addr_family) { - gs_unref_array GArray *old = NULL; + gs_unref_ptrarray GPtrArray *old = NULL; nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); nm_assert_addr_family(addr_family); old = g_steal_pointer(&self->nameservers_x[NM_IS_IPv4(addr_family)]); - return (nm_g_array_len(old) > 0); + return (nm_g_ptr_array_len(old) > 0); } const in_addr_t * @@ -2272,7 +2294,6 @@ nm_l3_config_data_cmp_full(const NML3ConfigData *a, } for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { - const int addr_family = IS_IPv4 ? AF_INET : AF_INET6; const NMPObject *def_route_a = a->best_default_route_x[IS_IPv4]; const NMPObject *def_route_b = b->best_default_route_x[IS_IPv4]; @@ -2311,9 +2332,8 @@ nm_l3_config_data_cmp_full(const NML3ConfigData *a, if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_DNS)) { const NML3ConfigDatFlags FLAG = NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY(IS_IPv4); - NM_CMP_RETURN(_garray_inaddr_cmp(a->nameservers_x[IS_IPv4], - b->nameservers_x[IS_IPv4], - addr_family)); + NM_CMP_RETURN( + nm_strv_ptrarray_cmp(a->nameservers_x[IS_IPv4], b->nameservers_x[IS_IPv4])); NM_CMP_RETURN(nm_strv_ptrarray_cmp(a->domains_x[IS_IPv4], b->domains_x[IS_IPv4])); NM_CMP_RETURN(nm_strv_ptrarray_cmp(a->searches_x[IS_IPv4], b->searches_x[IS_IPv4])); NM_CMP_RETURN( @@ -2843,15 +2863,8 @@ _init_from_connection_ip(NML3ConfigData *self, int addr_family, NMConnection *co } nnameservers = nm_setting_ip_config_get_num_dns(s_ip); - for (i = 0; i < nnameservers; i++) { - const char *s; - NMIPAddr ip; - - s = nm_setting_ip_config_get_dns(s_ip, i); - if (!nm_inet_parse_bin(addr_family, s, NULL, &ip)) - continue; - nm_l3_config_data_add_nameserver(self, addr_family, &ip); - } + for (i = 0; i < nnameservers; i++) + nm_l3_config_data_add_nameserver(self, addr_family, nm_setting_ip_config_get_dns(s_ip, i)); nsearches = nm_setting_ip_config_get_num_dns_searches(s_ip); for (i = 0; i < nsearches; i++) { @@ -3206,9 +3219,7 @@ nm_l3_config_data_merge(NML3ConfigData *self, } if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DNS)) - _garray_inaddr_merge(&self->nameservers_x[IS_IPv4], - src->nameservers_x[IS_IPv4], - addr_family); + _strv_ptrarray_merge(&self->nameservers_x[IS_IPv4], src->nameservers_x[IS_IPv4]); if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DNS)) _strv_ptrarray_merge(&self->domains_x[IS_IPv4], src->domains_x[IS_IPv4]); diff --git a/src/core/nm-l3-config-data.h b/src/core/nm-l3-config-data.h index ca42d4a104..1a181e5cc1 100644 --- a/src/core/nm-l3-config-data.h +++ b/src/core/nm-l3-config-data.h @@ -495,12 +495,16 @@ const in_addr_t *nm_l3_config_data_get_wins(const NML3ConfigData *self, guint *o gboolean nm_l3_config_data_add_wins(NML3ConfigData *self, in_addr_t wins); -gconstpointer +const char *const * nm_l3_config_data_get_nameservers(const NML3ConfigData *self, int addr_family, guint *out_len); -gboolean nm_l3_config_data_add_nameserver(NML3ConfigData *self, - int addr_family, - gconstpointer /* (const NMIPAddr *) */ nameserver); +gboolean +nm_l3_config_data_add_nameserver(NML3ConfigData *self, int addr_family, const char *nameserver); + +gboolean nm_l3_config_data_add_nameserver_detail(NML3ConfigData *self, + int addr_family, + gconstpointer addr_bin, + const char *server_name); gboolean nm_l3_config_data_clear_nameservers(NML3ConfigData *self, int addr_family); diff --git a/src/core/ppp/nm-ppp-manager.c b/src/core/ppp/nm-ppp-manager.c index 003a9806a0..c77e5a1dee 100644 --- a/src/core/ppp/nm-ppp-manager.c +++ b/src/core/ppp/nm-ppp-manager.c @@ -582,7 +582,7 @@ impl_ppp_manager_set_ip4_config(NMDBusObject *obj, if (g_variant_lookup(config_dict, NM_PPP_IP4_CONFIG_DNS, "au", &iter)) { while (g_variant_iter_next(iter, "u", &u32)) - nm_l3_config_data_add_nameserver(l3cd, AF_INET, &u32); + nm_l3_config_data_add_nameserver_detail(l3cd, AF_INET, &u32, NULL); g_variant_iter_free(iter); } diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index 96f5969728..0680b23e71 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -2047,7 +2047,9 @@ make_ip4_setting(shvarFile *ifcfg, * Pick up just IPv4 addresses (IPv6 addresses are taken by make_ip6_setting()) */ for (i = 1; i < 10000; i++) { - char tag[256]; + int af; + NMIPAddr ip; + char tag[256]; numbered_tag(tag, "DNS", i); nm_clear_g_free(&value); @@ -2055,18 +2057,18 @@ make_ip4_setting(shvarFile *ifcfg, if (!v) break; - if (nm_inet_is_valid(AF_INET, v)) { - if (!nm_setting_ip_config_add_dns(s_ip4, v)) - PARSE_WARNING("duplicate DNS server %s", tag); - } else if (nm_inet_is_valid(AF_INET6, v)) { - /* Ignore IPv6 addresses */ - } else { + if (!nm_utils_dnsname_parse(AF_UNSPEC, v, &af, &ip, NULL)) { g_set_error(error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid DNS server address '%s'", v); return NULL; + } else if (af == AF_INET) { + if (!nm_setting_ip_config_add_dns(s_ip4, v)) + PARSE_WARNING("duplicate DNS server %s", tag); + } else { + /* Ignore IPv6 addresses */ } } @@ -2586,7 +2588,9 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea * Pick up just IPv6 addresses (IPv4 addresses are taken by make_ip4_setting()) */ for (i = 1; i < 10000; i++) { - char tag[256]; + int af; + NMIPAddr ip; + char tag[256]; numbered_tag(tag, "DNS", i); nm_clear_g_free(&value); @@ -2594,16 +2598,7 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea if (!v) break; - if (nm_inet_is_valid(AF_INET6, v)) { - if (is_disabled) { - PARSE_WARNING("ignore DNS server addresses with method disabled/ignore"); - break; - } - if (!nm_setting_ip_config_add_dns(s_ip6, v)) - PARSE_WARNING("duplicate DNS server %s", tag); - } else if (nm_inet_is_valid(AF_INET, v)) { - /* Ignore IPv4 addresses */ - } else { + if (!nm_utils_dnsname_parse(AF_UNSPEC, v, &af, &ip, NULL)) { if (is_disabled) continue; g_set_error(error, @@ -2612,6 +2607,15 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea "Invalid DNS server address '%s'", v); return NULL; + } else if (af == AF_INET6) { + if (is_disabled) { + PARSE_WARNING("ignore DNS server addresses with method disabled/ignore"); + break; + } + if (!nm_setting_ip_config_add_dns(s_ip6, v)) + PARSE_WARNING("duplicate DNS server %s", tag); + } else { + /* Ignore IPv4 addresses */ } } diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1 index ecb36c3792..5e40362e9f 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1 @@ -1,4 +1,7 @@ DNS1="192.0.2.1" +DNS2="192.0.2.2#adfs.afddsaf" +DNS3="1::2" +DNS4="1::3#dfdf.er" IPADDR="102.0.2.2" GATEWAY="192.0.2.1" NETMASK="255.254.0.0" diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected index 87493ac2b3..d0eeeb9911 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected @@ -1,4 +1,7 @@ DNS1=192.0.2.1 +DNS2=192.0.2.2#adfs.afddsaf +DNS3=1::2 +DNS4=1::3#dfdf.er IPADDR=102.0.2.2 GATEWAY=192.0.2.1 NETMASK=255.254.0.0 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes index 7faf49bdae..fac9a5a28c 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes @@ -9,7 +9,7 @@ IPV6INIT=no MTU=1492 NM_CONTROLLED=yes DNS1=4.2.2.1 -DNS2=4.2.2.2 +DNS2=4.2.2.2#dns.name IPADDR=192.168.1.5 NETMASK=255.255.255.0 GATEWAY=192.168.1.1 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 653a52133a..aba9b922dc 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -461,6 +461,7 @@ test_read_netmask_1(void) gs_free char *content = NULL; NMSettingConnection *s_con; NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; NMIPAddress *ip4_addr; const char *FILENAME = TEST_IFCFG_DIR "/ifcfg-netmask-1"; @@ -470,12 +471,20 @@ test_read_netmask_1(void) g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System netmask-1"); s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); - g_assert_cmpuint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 1); + g_assert_cmpuint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 2); + g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 0), ==, "192.0.2.1"); + g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 1), ==, "192.0.2.2#adfs.afddsaf"); + ip4_addr = nm_setting_ip_config_get_address(s_ip4, 0); g_assert(ip4_addr); g_assert_cmpstr(nm_ip_address_get_address(ip4_addr), ==, "102.0.2.2"); g_assert_cmpint(nm_ip_address_get_prefix(ip4_addr), ==, 15); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); + g_assert_cmpuint(nm_setting_ip_config_get_num_dns(s_ip6), ==, 2); + g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip6, 0), ==, "1::2"); + g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip6, 1), ==, "1::3#dfdf.er"); + nmtst_assert_connection_verifies_without_normalization(connection); content = nmtst_file_get_contents(FILENAME); @@ -1390,6 +1399,10 @@ test_read_wired_static_routes(void) g_assert_cmpint(nm_ip_route_get_prefix(ip4_route), ==, 32); nmtst_assert_route_attribute_string(ip4_route, NM_IP_ROUTE_ATTRIBUTE_TYPE, "local"); nmtst_assert_route_attribute_byte(ip4_route, NM_IP_ROUTE_ATTRIBUTE_SCOPE, 254); + + g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 2); + g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 0), ==, "4.2.2.1"); + g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 1), ==, "4.2.2.2#dns.name"); } static void diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c index cdf77a7185..b538c4c473 100644 --- a/src/core/vpn/nm-vpn-connection.c +++ b/src/core/vpn/nm-vpn-connection.c @@ -2011,14 +2011,14 @@ _dbus_signal_ip_config_cb(NMVpnConnection *self, int addr_family, GVariant *dict if (IS_IPv4) { if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_DNS, "au", &var_iter)) { while (g_variant_iter_next(var_iter, "u", &u32)) - nm_l3_config_data_add_nameserver(l3cd, addr_family, &u32); + nm_l3_config_data_add_nameserver_detail(l3cd, addr_family, &u32, NULL); g_variant_iter_free(var_iter); } } else { if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP6_CONFIG_DNS, "aay", &var_iter)) { while (g_variant_iter_next(var_iter, "@ay", &v)) { if (nm_ip_addr_set_from_variant(AF_INET6, &v_addr, v, NULL)) - nm_l3_config_data_add_nameserver(l3cd, addr_family, &v_addr); + nm_l3_config_data_add_nameserver_detail(l3cd, addr_family, &v_addr, NULL); g_variant_unref(v); } g_variant_iter_free(var_iter); diff --git a/src/libnm-core-aux-intern/nm-libnm-core-utils.c b/src/libnm-core-aux-intern/nm-libnm-core-utils.c index b76ff0fa3d..0e464fba42 100644 --- a/src/libnm-core-aux-intern/nm-libnm-core-utils.c +++ b/src/libnm-core-aux-intern/nm-libnm-core-utils.c @@ -520,3 +520,113 @@ nm_mptcp_flags_normalize(NMMptcpFlags flags) return flags; } + +/*****************************************************************************/ + +gboolean +nm_utils_dnsname_parse(int addr_family, + const char *dns, + int *out_addr_family, + gpointer /* (NMIPAddr **) */ out_addr, + const char **out_servername) +{ + gs_free char *dns_heap = NULL; + const char *s; + NMIPAddr addr; + + nm_assert_addr_family_or_unspec(addr_family); + nm_assert(!out_addr || out_addr_family || NM_IN_SET(addr_family, AF_INET, AF_INET6)); + + if (!dns) + return FALSE; + + s = strchr(dns, '#'); + + if (s) { + dns = nm_strndup_a(200, dns, s - dns, &dns_heap); + s++; + } + + if (s && s[0] == '\0') { + /* "ADDR#" empty DoT SNI name is not allowed. */ + return FALSE; + } + + if (!nm_inet_parse_bin(addr_family, dns, &addr_family, out_addr ? &addr : NULL)) + return FALSE; + + NM_SET_OUT(out_addr_family, addr_family); + if (out_addr) + nm_ip_addr_set(addr_family, out_addr, &addr); + NM_SET_OUT(out_servername, s); + return TRUE; +} + +const char * +nm_utils_dnsname_construct(int addr_family, + gconstpointer /* (const NMIPAddr *) */ addr, + const char *server_name, + char *result, + gsize result_len) +{ + char sbuf[NM_INET_ADDRSTRLEN]; + gsize l; + int d; + + nm_assert_addr_family(addr_family); + nm_assert(addr); + nm_assert(!server_name || !nm_str_is_empty(server_name)); + + nm_inet_ntop(addr_family, addr, sbuf); + + if (!server_name) { + l = g_strlcpy(result, sbuf, result_len); + } else { + d = g_snprintf(result, result_len, "%s#%s", sbuf, server_name); + nm_assert(d >= 0); + l = (gsize) d; + } + + return l < result_len ? result : NULL; +} + +const char * +nm_utils_dnsname_normalize(int addr_family, const char *dns, char **out_free) +{ + char sbuf[NM_INET_ADDRSTRLEN]; + const char *server_name; + char *s; + NMIPAddr a; + gsize l; + + nm_assert_addr_family_or_unspec(addr_family); + nm_assert(dns); + nm_assert(out_free && !*out_free); + + if (!nm_utils_dnsname_parse(addr_family, dns, &addr_family, &a, &server_name)) + return NULL; + + nm_inet_ntop(addr_family, &a, sbuf); + + l = strlen(sbuf); + + /* In the vast majority of cases, the name is in fact normalized. Check + * whether it is, and don't duplicate the string. */ + if (strncmp(dns, sbuf, l) == 0) { + if (server_name) { + if (dns[l] == '#' && nm_streq(&dns[l + 1], server_name)) + return dns; + } else { + if (dns[l] == '\0') + return dns; + } + } + + if (!server_name) + s = g_strdup(sbuf); + else + s = g_strconcat(sbuf, "#", server_name, NULL); + + *out_free = s; + return s; +} diff --git a/src/libnm-core-aux-intern/nm-libnm-core-utils.h b/src/libnm-core-aux-intern/nm-libnm-core-utils.h index 0208bfdb24..63e8be4ec1 100644 --- a/src/libnm-core-aux-intern/nm-libnm-core-utils.h +++ b/src/libnm-core-aux-intern/nm-libnm-core-utils.h @@ -279,4 +279,33 @@ gpointer _nm_connection_new_setting(NMConnection *connection, GType gtype); NMMptcpFlags nm_mptcp_flags_normalize(NMMptcpFlags flags); +/*****************************************************************************/ + +gboolean nm_utils_dnsname_parse(int addr_family, + const char *dns, + int *out_addr_family, + gpointer /* (NMIPAddr **) */ out_addr, + const char **out_servername); + +#define nm_utils_dnsname_parse_assert(addr_family, dns, out_addr_family, out_addr, out_servername) \ + ({ \ + gboolean _good; \ + \ + _good = nm_utils_dnsname_parse((addr_family), \ + (dns), \ + (out_addr_family), \ + (out_addr), \ + (out_servername)); \ + nm_assert(_good); \ + _good; \ + }) + +const char *nm_utils_dnsname_construct(int addr_family, + gconstpointer /* (const NMIPAddr *) */ addr, + const char *server_name, + char *result, + gsize result_len); + +const char *nm_utils_dnsname_normalize(int addr_family, const char *dns, char **out_free); + #endif /* __NM_LIBNM_SHARED_UTILS_H__ */ diff --git a/src/libnm-core-impl/nm-keyfile.c b/src/libnm-core-impl/nm-keyfile.c index ae6d892c28..a41974dd02 100644 --- a/src/libnm-core-impl/nm-keyfile.c +++ b/src/libnm-core-impl/nm-keyfile.c @@ -1102,7 +1102,9 @@ ip_dns_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) { int addr_family; gs_strfreev char **list = NULL; - gsize i, n, length; + gsize length; + gsize n; + gsize i; nm_assert(NM_IS_SETTING_IP4_CONFIG(setting) || NM_IS_SETTING_IP6_CONFIG(setting)); @@ -1115,13 +1117,10 @@ ip_dns_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) if (length == 0) return; - addr_family = NM_IS_SETTING_IP4_CONFIG(setting) ? AF_INET : AF_INET6; + addr_family = NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting); - n = 0; - for (i = 0; i < length; i++) { - NMIPAddr addr; - - if (inet_pton(addr_family, list[i], &addr) <= 0) { + for (i = 0, n = 0; i < length; i++) { + if (!nm_utils_dnsname_parse(addr_family, list[i], NULL, NULL, NULL)) { if (!read_handle_warn(info, key, key, diff --git a/src/libnm-core-impl/nm-setting-8021x.c b/src/libnm-core-impl/nm-setting-8021x.c index be1ee41c56..9eccd95d41 100644 --- a/src/libnm-core-impl/nm-setting-8021x.c +++ b/src/libnm-core-impl/nm-setting-8021x.c @@ -3384,7 +3384,8 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass) PROP_SUBJECT_MATCH, NM_SETTING_PARAM_NONE, NMSetting8021xPrivate, - subject_match); + subject_match, + .is_deprecated = TRUE, ); /** * NMSetting8021x:altsubject-matches: @@ -3797,7 +3798,8 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass) PROP_PHASE2_SUBJECT_MATCH, NM_SETTING_PARAM_NONE, NMSetting8021xPrivate, - phase2_subject_match); + phase2_subject_match, + .is_deprecated = TRUE, ); /** * NMSetting8021x:phase2-altsubject-matches: diff --git a/src/libnm-core-impl/nm-setting-bond.c b/src/libnm-core-impl/nm-setting-bond.c index b03cc455a7..99bcc8faea 100644 --- a/src/libnm-core-impl/nm-setting-bond.c +++ b/src/libnm-core-impl/nm-setting-bond.c @@ -1313,7 +1313,8 @@ nm_setting_bond_class_init(NMSettingBondClass *klass) */ _nm_properties_override_dbus(properties_override, "interface-name", - &nm_sett_info_propert_type_deprecated_interface_name); + &nm_sett_info_propert_type_deprecated_interface_name, + .dbus_deprecated = TRUE, ); g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/libnm-core-impl/nm-setting-bridge.c b/src/libnm-core-impl/nm-setting-bridge.c index 19048287b7..0ec6e71ea8 100644 --- a/src/libnm-core-impl/nm-setting-bridge.c +++ b/src/libnm-core-impl/nm-setting-bridge.c @@ -1454,7 +1454,8 @@ nm_setting_bridge_class_init(NMSettingBridgeClass *klass) NM_SETTING_PARAM_INFERRABLE, NMSettingBridge, _priv.mac_address, - .direct_set_string_mac_address_len = ETH_ALEN); + .direct_set_string_mac_address_len = ETH_ALEN, + .is_deprecated = TRUE, ); /** * NMSettingBridge:stp: @@ -1748,7 +1749,8 @@ nm_setting_bridge_class_init(NMSettingBridgeClass *klass) */ _nm_properties_override_dbus(properties_override, "interface-name", - &nm_sett_info_propert_type_deprecated_interface_name); + &nm_sett_info_propert_type_deprecated_interface_name, + .dbus_deprecated = TRUE, ); /** * NMSettingBridge:group-address: diff --git a/src/libnm-core-impl/nm-setting-gsm.c b/src/libnm-core-impl/nm-setting-gsm.c index cd7d9b8061..3fe5dfa11a 100644 --- a/src/libnm-core-impl/nm-setting-gsm.c +++ b/src/libnm-core-impl/nm-setting-gsm.c @@ -545,7 +545,8 @@ nm_setting_gsm_class_init(NMSettingGsmClass *klass) PROP_NUMBER, NM_SETTING_PARAM_NONE, NMSettingGsmPrivate, - number); + number, + .is_deprecated = TRUE, ); /** * NMSettingGsm:username: @@ -744,10 +745,12 @@ nm_setting_gsm_class_init(NMSettingGsmClass *klass) /* Ignore incoming deprecated properties */ _nm_properties_override_dbus(properties_override, "allowed-bands", - &nm_sett_info_propert_type_deprecated_ignore_u); + &nm_sett_info_propert_type_deprecated_ignore_u, + .dbus_deprecated = TRUE, ); _nm_properties_override_dbus(properties_override, "network-type", - &nm_sett_info_propert_type_deprecated_ignore_i); + &nm_sett_info_propert_type_deprecated_ignore_i, + .dbus_deprecated = TRUE, ); g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/libnm-core-impl/nm-setting-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c index 84e6247773..4c4d09bd59 100644 --- a/src/libnm-core-impl/nm-setting-ip-config.c +++ b/src/libnm-core-impl/nm-setting-ip-config.c @@ -4014,7 +4014,7 @@ nm_setting_ip_config_get_num_dns(NMSettingIPConfig *setting) { g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns->len; + return nm_g_ptr_array_len(NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns); } /** @@ -4032,11 +4032,35 @@ nm_setting_ip_config_get_dns(NMSettingIPConfig *setting, int idx) g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_val_if_fail(idx >= 0 && idx < priv->dns->len, NULL); + g_return_val_if_fail(idx >= 0 && ((guint) idx) < nm_g_ptr_array_len(priv->dns), NULL); return priv->dns->pdata[idx]; } +static gboolean +_ip_config_add_dns(NMSettingIPConfig *setting, const char *dns) +{ + NMSettingIPConfigPrivate *priv; + gs_free char *s_free = NULL; + const char *s; + + nm_assert(NM_IS_SETTING_IP_CONFIG(setting)); + nm_assert(dns); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + s = nm_utils_dnsname_normalize(NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting), dns, &s_free); + if (!s) + s = dns; + + if (nm_strv_ptrarray_contains(priv->dns, s)) + return FALSE; + + nm_strv_ptrarray_add_string_take(nm_strv_ptrarray_ensure(&priv->dns), + g_steal_pointer(&s_free) ?: g_strdup(s)); + return TRUE; +} + /** * nm_setting_ip_config_add_dns: * @setting: the #NMSettingIPConfig @@ -4046,36 +4070,20 @@ nm_setting_ip_config_get_dns(NMSettingIPConfig *setting, int idx) * * Returns: %TRUE if the DNS server was added; %FALSE if the server was already * known + * + * Before 1.42, setting @dns to an invalid string was treated as user-error. + * Now, also invalid DNS values can be set, but will be rejected later during + * nm_connection_verify(). **/ gboolean nm_setting_ip_config_add_dns(NMSettingIPConfig *setting, const char *dns) { - NMSettingIPConfigPrivate *priv; - int addr_family; - NMIPAddr dns_bin; - char dns_canonical[NM_INET_ADDRSTRLEN]; - guint i; - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + g_return_val_if_fail(dns, FALSE); - addr_family = NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting); + if (!_ip_config_add_dns(setting, dns)) + return FALSE; - if (!valid_ip(addr_family, dns, &dns_bin, NULL)) { - g_return_val_if_fail(dns != NULL, FALSE); - g_return_val_if_fail(nm_inet_is_valid(addr_family, dns), FALSE); - nm_assert_not_reached(); - } - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - nm_inet_ntop(addr_family, &dns_bin, dns_canonical); - - for (i = 0; i < priv->dns->len; i++) { - if (nm_streq(dns_canonical, priv->dns->pdata[i])) - return FALSE; - } - - g_ptr_array_add(priv->dns, g_strdup(dns_canonical)); _notify(setting, PROP_DNS); return TRUE; } @@ -4095,7 +4103,8 @@ nm_setting_ip_config_remove_dns(NMSettingIPConfig *setting, int idx) g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(idx >= 0 && idx < priv->dns->len); + + g_return_if_fail(idx >= 0 && ((guint) idx) < nm_g_ptr_array_len(priv->dns)); g_ptr_array_remove_index(priv->dns, idx); _notify(setting, PROP_DNS); @@ -4109,38 +4118,39 @@ nm_setting_ip_config_remove_dns(NMSettingIPConfig *setting, int idx) * Removes the DNS server @dns. * * Returns: %TRUE if the DNS server was found and removed; %FALSE if it was not. + * + * Before 1.42, setting @dns to an invalid string was treated as user-error. **/ gboolean nm_setting_ip_config_remove_dns_by_value(NMSettingIPConfig *setting, const char *dns) { NMSettingIPConfigPrivate *priv; - int addr_family; - NMIPAddr dns_bin; - char dns_canonical[NM_INET_ADDRSTRLEN]; - guint i; + gssize idx; g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - - addr_family = NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting); - - if (!valid_ip(addr_family, dns, &dns_bin, NULL)) { - g_return_val_if_fail(dns != NULL, FALSE); - g_return_val_if_fail(nm_inet_is_valid(addr_family, dns), FALSE); - nm_assert_not_reached(); - } + g_return_val_if_fail(dns, FALSE); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - nm_inet_ntop(addr_family, &dns_bin, dns_canonical); + /* "priv->dns" can only contain normalized or invalid values. Expect that + * "dns" is normalized already, so lookup first for that string. Only + * if that fails, fallback to normalize "dns". */ + idx = nm_strv_ptrarray_find_first(priv->dns, dns); + if (idx < 0) { + gs_free char *s_free = NULL; + const char *s; - for (i = 0; i < priv->dns->len; i++) { - if (nm_streq(dns_canonical, priv->dns->pdata[i])) { - g_ptr_array_remove_index(priv->dns, i); - _notify(setting, PROP_DNS); - return TRUE; - } + s = nm_utils_dnsname_normalize(NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting), dns, &s_free); + if (s && !nm_streq(dns, s)) + idx = nm_strv_ptrarray_find_first(priv->dns, dns); } - return FALSE; + + if (idx < 0) + return FALSE; + + g_ptr_array_remove_index(priv->dns, idx); + _notify(setting, PROP_DNS); + return TRUE; } /** @@ -4158,7 +4168,7 @@ nm_setting_ip_config_clear_dns(NMSettingIPConfig *setting) priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - if (priv->dns->len != 0) { + if (nm_g_ptr_array_len(priv->dns) != 0) { g_ptr_array_set_size(priv->dns, 0); _notify(setting, PROP_DNS); } @@ -5012,7 +5022,7 @@ nm_setting_ip_config_clear_routing_rules(NMSettingIPConfig *setting) } static GVariant * -_routing_rules_dbus_only_synth(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +routing_rules_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { NMSettingIPConfig *self = NM_SETTING_IP_CONFIG(setting); NMSettingIPConfigPrivate *priv; @@ -5043,7 +5053,7 @@ _routing_rules_dbus_only_synth(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -_routing_rules_dbus_only_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +routing_rules_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { GVariantIter iter_rules; GVariant *rule_var; @@ -5433,20 +5443,26 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) } /* Validate DNS */ - for (i = 0; i < priv->dns->len; i++) { - const char *dns = priv->dns->pdata[i]; + if (priv->dns) { + for (i = 0; i < priv->dns->len; i++) { + const char *dns = priv->dns->pdata[i]; - if (!nm_inet_is_valid(NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting), dns)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%d. DNS server address is invalid"), - (int) (i + 1)); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DNS); - return FALSE; + if (!nm_utils_dnsname_parse(NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting), + dns, + NULL, + NULL, + NULL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("%u. DNS server address is invalid"), + (i + 1u)); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_DNS); + return FALSE; + } } } @@ -5829,6 +5845,35 @@ _nm_setting_property_from_dbus_fcn_direct_ip_config_gateway( error); } +static GVariant * +dns_data_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +{ + GPtrArray *arr; + + if (!_nm_connection_serialize_non_secret(flags)) + return NULL; + + arr = _nm_setting_ip_config_get_dns_array(NM_SETTING_IP_CONFIG(setting)); + if (nm_g_ptr_array_len(arr) == 0) + return NULL; + return g_variant_new_strv((const char *const *) arr->pdata, arr->len); +} + +static gboolean +dns_data_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +{ + gs_free const char **strv = NULL; + + if (_nm_setting_use_legacy_property(setting, connection_dict, "dns", "dns-data")) { + *out_is_modified = FALSE; + return TRUE; + } + + strv = g_variant_get_strv(value, NULL); + g_object_set(setting, NM_SETTING_IP_CONFIG_DNS, strv, NULL); + return TRUE; +} + GArray * _nm_sett_info_property_override_create_array_ip_config(int addr_family) { @@ -5883,9 +5928,9 @@ _nm_sett_info_property_override_create_array_ip_config(int addr_family) properties_override, NM_SETTING_IP_CONFIG_ROUTING_RULES, NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = _routing_rules_dbus_only_synth, + .to_dbus_fcn = routing_rules_to_dbus, .compare_fcn = compare_fcn_routing_rules, - .from_dbus_fcn = _routing_rules_dbus_only_set, )); + .from_dbus_fcn = routing_rules_from_dbus, )); _nm_properties_override_gobj( properties_override, @@ -5915,6 +5960,21 @@ _nm_sett_info_property_override_create_array_ip_config(int addr_family) .direct_offset = NM_STRUCT_OFFSET_ENSURE_TYPE(bool, NMSettingIPConfigPrivate, ignore_auto_dns)); + /* ---dbus--- + * property: dns-data + * format: array of strings + * description: Array of DNS name servers. This replaces the deprecated + * "dns" property. Each name server can also contain a DoT server name. + * ---end--- + */ + _nm_properties_override_dbus( + properties_override, + "dns-data", + NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("as"), + .to_dbus_fcn = dns_data_to_dbus, + .compare_fcn = _nm_setting_property_compare_fcn_ignore, + .from_dbus_fcn = dns_data_from_dbus, )); + _nm_properties_override_gobj( properties_override, obj_properties[PROP_DNS_PRIORITY], @@ -6024,9 +6084,17 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps switch (prop_id) { case PROP_DNS: - g_ptr_array_unref(priv->dns); - priv->dns = nm_strv_to_ptrarray(g_value_get_boxed(value)); + { + gs_unref_ptrarray GPtrArray *dns_old = NULL; + + dns_old = g_steal_pointer(&priv->dns); + strv = g_value_get_boxed(value); + if (strv) { + for (i = 0; strv[i]; i++) + _ip_config_add_dns(setting, strv[i]); + } break; + } case PROP_DNS_SEARCH: g_ptr_array_unref(priv->dns_search); priv->dns_search = nm_strv_to_ptrarray(g_value_get_boxed(value)); @@ -6078,7 +6146,6 @@ _nm_setting_ip_config_private_init(gpointer self, NMSettingIPConfigPrivate *priv { nm_assert(NM_IS_SETTING_IP_CONFIG(self)); - priv->dns = g_ptr_array_new_with_free_func(g_free); priv->dns_search = g_ptr_array_new_with_free_func(g_free); priv->addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); priv->routes = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_route_unref); @@ -6096,7 +6163,7 @@ finalize(GObject *object) NMSettingIPConfig *self = NM_SETTING_IP_CONFIG(object); NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(self); - g_ptr_array_unref(priv->dns); + nm_g_ptr_array_unref(priv->dns); g_ptr_array_unref(priv->dns_search); nm_g_ptr_array_unref(priv->dns_options); g_ptr_array_unref(priv->addresses); @@ -6155,12 +6222,18 @@ nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass) * NMSettingIPConfig:dns: * * Array of IP addresses of DNS servers. + * + * For DoT (DNS over TLS), the SNI server name can be specified by appending + * "#example.com" to the IP address of the DNS server. This currently only has + * effect when using systemd-resolved. **/ - obj_properties[PROP_DNS] = g_param_spec_boxed(NM_SETTING_IP_CONFIG_DNS, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DNS] = + g_param_spec_boxed(NM_SETTING_IP_CONFIG_DNS, + "", + "", + G_TYPE_STRV, + /* On D-Bus, "dns" is deprecated for "dns-data". */ + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); /** * NMSettingIPConfig:dns-search: @@ -6291,12 +6364,9 @@ nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass) "", "", G_TYPE_PTR_ARRAY, - /* "addresses" is a legacy D-Bus property, because the - * "addresses" GObject property normally gets set from - * the "address-data" D-Bus property... - */ - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | NM_SETTING_PARAM_LEGACY - | G_PARAM_STATIC_STRINGS); + /* On D-Bus, "addresses" is deprecated for "address-data". */ + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | NM_SETTING_PARAM_UNUSED1 | G_PARAM_STATIC_STRINGS); /** * NMSettingIPConfig:gateway: @@ -6318,6 +6388,8 @@ nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass) "", "", NULL, + /* On D-Bus, the legacy property "addresses" contains the gateway. + * This was replaced by "address-data" and "gateway". */ G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** @@ -6330,9 +6402,9 @@ nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass) "", "", G_TYPE_PTR_ARRAY, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | - /* See :addresses above Re: LEGACY */ - NM_SETTING_PARAM_LEGACY | G_PARAM_STATIC_STRINGS); + /* On D-Bus, "routes" is deprecated for "route-data". */ + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | NM_SETTING_PARAM_UNUSED1 | G_PARAM_STATIC_STRINGS); /** * NMSettingIPConfig:route-metric: diff --git a/src/libnm-core-impl/nm-setting-ip4-config.c b/src/libnm-core-impl/nm-setting-ip4-config.c index 27f500557a..ccc3760e06 100644 --- a/src/libnm-core-impl/nm-setting-ip4-config.c +++ b/src/libnm-core-impl/nm-setting-ip4-config.c @@ -388,21 +388,29 @@ ip4_dns_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) GPtrArray *dns; dns = _nm_setting_ip_config_get_dns_array(NM_SETTING_IP_CONFIG(setting)); - if (nm_g_ptr_array_len(dns) == 0) return NULL; - return _nm_utils_ip4_dns_to_variant((const char *const *) dns->pdata, dns->len); + return nm_utils_dns_to_variant(AF_INET, (const char *const *) dns->pdata, dns->len); } -static void -ip4_dns_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_GPROP_FCN_ARGS _nm_nil) +static gboolean +ip4_dns_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - g_value_take_boxed(to, nm_utils_ip4_dns_from_variant(from)); + gs_strfreev char **strv = NULL; + + if (!_nm_setting_use_legacy_property(setting, connection_dict, "dns", "dns-data")) { + *out_is_modified = FALSE; + return TRUE; + } + + strv = nm_utils_ip4_dns_from_variant(value); + g_object_set(setting, NM_SETTING_IP_CONFIG_DNS, strv, NULL); + return TRUE; } static GVariant * -ip4_addresses_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip4_addresses_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *addrs = NULL; const char *gateway; @@ -413,12 +421,13 @@ ip4_addresses_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip4_addresses_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip4_addresses_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *addrs; - GVariant *s_ip4; - char **labels, *gateway = NULL; - int i; + gs_unref_ptrarray GPtrArray *addrs = NULL; + gs_unref_variant GVariant *s_ip4 = NULL; + gs_free const char **labels = NULL; + gs_free char *gateway = NULL; + guint i; /* FIXME: properly handle errors */ @@ -432,15 +441,15 @@ ip4_addresses_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) s_ip4 = g_variant_lookup_value(connection_dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING); - if (g_variant_lookup(s_ip4, "address-labels", "^as", &labels)) { - for (i = 0; i < addrs->len && labels[i]; i++) - if (*labels[i]) + if (g_variant_lookup(s_ip4, "address-labels", "^a&s", &labels)) { + for (i = 0; i < addrs->len && labels[i]; i++) { + if (*labels[i]) { nm_ip_address_set_attribute(addrs->pdata[i], NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string(labels[i])); - g_strfreev(labels); + } + } } - g_variant_unref(s_ip4); g_object_set(setting, NM_SETTING_IP_CONFIG_ADDRESSES, @@ -448,52 +457,50 @@ ip4_addresses_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) NM_SETTING_IP_CONFIG_GATEWAY, gateway, NULL); - g_ptr_array_unref(addrs); - g_free(gateway); return TRUE; } static GVariant * -ip4_address_labels_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip4_address_labels_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG(setting); gboolean have_labels = FALSE; - GPtrArray *labels; - GVariant *ret; - int num_addrs, i; + gs_free GVariant **labels_free = NULL; + GVariant *s_empty; + GVariant **labels; + guint num_addrs; + guint i; if (!_nm_connection_serialize_non_secret(flags)) return NULL; num_addrs = nm_setting_ip_config_get_num_addresses(s_ip); + if (num_addrs == 0) + return NULL; + + labels = nm_malloc_maybe_a(500, sizeof(gpointer) * num_addrs, &labels_free); + + s_empty = nm_g_variant_singleton_s_empty(); + for (i = 0; i < num_addrs; i++) { NMIPAddress *addr = nm_setting_ip_config_get_address(s_ip, i); GVariant *label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); if (label) { have_labels = TRUE; - break; - } + labels[i] = label; + } else + labels[i] = s_empty; } + if (!have_labels) return NULL; - labels = g_ptr_array_sized_new(num_addrs); - for (i = 0; i < num_addrs; i++) { - NMIPAddress *addr = nm_setting_ip_config_get_address(s_ip, i); - GVariant *label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - - g_ptr_array_add(labels, (char *) (label ? g_variant_get_string(label, NULL) : "")); - } - - ret = g_variant_new_strv((const char *const *) labels->pdata, labels->len); - g_ptr_array_unref(labels); - - return ret; + return g_variant_new_array(G_VARIANT_TYPE_STRING, labels, num_addrs); } static GVariant * -ip4_address_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip4_address_data_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *addrs = NULL; @@ -505,9 +512,9 @@ ip4_address_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip4_address_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip4_address_data_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *addrs; + gs_unref_ptrarray GPtrArray *addrs = NULL; /* FIXME: properly handle errors */ @@ -519,12 +526,11 @@ ip4_address_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) addrs = nm_utils_ip_addresses_from_variant(value, AF_INET); g_object_set(setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL); - g_ptr_array_unref(addrs); return TRUE; } static GVariant * -ip4_routes_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip4_routes_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *routes = NULL; @@ -533,9 +539,9 @@ ip4_routes_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip4_routes_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip4_routes_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *routes; + gs_unref_ptrarray GPtrArray *routes = NULL; /* FIXME: properly handle errors */ @@ -546,12 +552,11 @@ ip4_routes_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) routes = nm_utils_ip4_routes_from_variant(value); g_object_set(setting, property_info->name, routes, NULL); - g_ptr_array_unref(routes); return TRUE; } static GVariant * -ip4_route_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip4_route_data_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *routes = NULL; @@ -563,9 +568,9 @@ ip4_route_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip4_route_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip4_route_data_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *routes; + gs_unref_ptrarray GPtrArray *routes = NULL; /* FIXME: properly handle errors */ @@ -577,7 +582,6 @@ ip4_route_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) routes = nm_utils_ip_routes_from_variant(value, AF_INET); g_object_set(setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL); - g_ptr_array_unref(routes); return TRUE; } @@ -968,11 +972,11 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) properties_override, g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_DNS), NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("au"), - .compare_fcn = _nm_setting_property_compare_fcn_default, - .to_dbus_fcn = ip4_dns_to_dbus, - .typdata_from_dbus.gprop_fcn = ip4_dns_from_dbus, - .from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop, - .from_dbus_is_full = TRUE), ); + .compare_fcn = _nm_setting_property_compare_fcn_default, + .to_dbus_fcn = ip4_dns_to_dbus, + .from_dbus_fcn = ip4_dns_from_dbus, ), + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: addresses @@ -1002,15 +1006,19 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) properties_override, g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ADDRESSES), NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aau"), - .to_dbus_fcn = ip4_addresses_get, + .to_dbus_fcn = ip4_addresses_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_addresses, - .from_dbus_fcn = ip4_addresses_set, )); + .from_dbus_fcn = ip4_addresses_from_dbus, ), + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE, ); _nm_properties_override_dbus( properties_override, "address-labels", NM_SETT_INFO_PROPERT_TYPE_DBUS(G_VARIANT_TYPE_STRING_ARRAY, - .to_dbus_fcn = ip4_address_labels_get, - .compare_fcn = _nm_setting_property_compare_fcn_ignore, )); + .to_dbus_fcn = ip4_address_labels_to_dbus, + .compare_fcn = _nm_setting_property_compare_fcn_ignore, + /* from_dbus() is handled by ip4_addresses_from_dbus(). */), + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: address-data @@ -1025,9 +1033,9 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) properties_override, "address-data", NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = ip4_address_data_get, + .to_dbus_fcn = ip4_address_data_to_dbus, .compare_fcn = _nm_setting_property_compare_fcn_ignore, - .from_dbus_fcn = ip4_address_data_set, )); + .from_dbus_fcn = ip4_address_data_from_dbus, )); /* ---dbus--- * property: routes @@ -1137,9 +1145,11 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) properties_override, g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ROUTES), NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aau"), - .to_dbus_fcn = ip4_routes_get, + .to_dbus_fcn = ip4_routes_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_routes, - .from_dbus_fcn = ip4_routes_set, )); + .from_dbus_fcn = ip4_routes_from_dbus, ), + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: route-data @@ -1158,9 +1168,9 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) properties_override, "route-data", NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = ip4_route_data_get, + .to_dbus_fcn = ip4_route_data_to_dbus, .compare_fcn = _nm_setting_property_compare_fcn_ignore, - .from_dbus_fcn = ip4_route_data_set, )); + .from_dbus_fcn = ip4_route_data_from_dbus, )); /* ---nmcli--- * property: routing-rules diff --git a/src/libnm-core-impl/nm-setting-ip6-config.c b/src/libnm-core-impl/nm-setting-ip6-config.c index e91d9ec4bf..a87cfb0a28 100644 --- a/src/libnm-core-impl/nm-setting-ip6-config.c +++ b/src/libnm-core-impl/nm-setting-ip6-config.c @@ -389,21 +389,29 @@ ip6_dns_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) GPtrArray *dns; dns = _nm_setting_ip_config_get_dns_array(NM_SETTING_IP_CONFIG(setting)); - if (nm_g_ptr_array_len(dns) == 0) return NULL; - return _nm_utils_ip6_dns_to_variant((const char *const *) dns->pdata, dns->len); + return nm_utils_dns_to_variant(AF_INET6, (const char *const *) dns->pdata, dns->len); } -static void -ip6_dns_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_GPROP_FCN_ARGS _nm_nil) +static gboolean +ip6_dns_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - g_value_take_boxed(to, nm_utils_ip6_dns_from_variant(from)); + gs_strfreev char **strv = NULL; + + if (!_nm_setting_use_legacy_property(setting, connection_dict, "dns", "dns-data")) { + *out_is_modified = FALSE; + return TRUE; + } + + strv = nm_utils_ip6_dns_from_variant(value); + g_object_set(setting, NM_SETTING_IP_CONFIG_DNS, strv, NULL); + return TRUE; } static GVariant * -ip6_addresses_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip6_addresses_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *addrs = NULL; const char *gateway; @@ -414,10 +422,10 @@ ip6_addresses_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip6_addresses_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip6_addresses_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *addrs; - char *gateway = NULL; + gs_unref_ptrarray GPtrArray *addrs = NULL; + gs_free char *gateway = NULL; if (!_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "address-data")) { *out_is_modified = FALSE; @@ -432,13 +440,11 @@ ip6_addresses_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) NM_SETTING_IP_CONFIG_GATEWAY, gateway, NULL); - g_ptr_array_unref(addrs); - g_free(gateway); return TRUE; } static GVariant * -ip6_address_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip6_address_data_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *addrs = NULL; @@ -450,9 +456,9 @@ ip6_address_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip6_address_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip6_address_data_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *addrs; + gs_unref_ptrarray GPtrArray *addrs = NULL; /* Ignore 'address-data' if we're going to process 'addresses' */ if (_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "address-data")) { @@ -462,12 +468,11 @@ ip6_address_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) addrs = nm_utils_ip_addresses_from_variant(value, AF_INET6); g_object_set(setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL); - g_ptr_array_unref(addrs); return TRUE; } static GVariant * -ip6_routes_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip6_routes_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *routes = NULL; @@ -476,9 +481,9 @@ ip6_routes_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip6_routes_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip6_routes_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *routes; + gs_unref_ptrarray GPtrArray *routes = NULL; if (!_nm_setting_use_legacy_property(setting, connection_dict, "routes", "route-data")) { *out_is_modified = FALSE; @@ -487,12 +492,11 @@ ip6_routes_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) routes = nm_utils_ip6_routes_from_variant(value); g_object_set(setting, property_info->name, routes, NULL); - g_ptr_array_unref(routes); return TRUE; } static GVariant * -ip6_route_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip6_route_data_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *routes = NULL; @@ -504,9 +508,9 @@ ip6_route_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip6_route_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip6_route_data_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *routes; + gs_unref_ptrarray GPtrArray *routes = NULL; /* Ignore 'route-data' if we're going to process 'routes' */ if (_nm_setting_use_legacy_property(setting, connection_dict, "routes", "route-data")) { @@ -516,7 +520,6 @@ ip6_route_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) routes = nm_utils_ip_routes_from_variant(value, AF_INET6); g_object_set(setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL); - g_ptr_array_unref(routes); return TRUE; } @@ -978,11 +981,11 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) properties_override, g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_DNS), NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aay"), - .compare_fcn = _nm_setting_property_compare_fcn_default, - .to_dbus_fcn = ip6_dns_to_dbus, - .typdata_from_dbus.gprop_fcn = ip6_dns_from_dbus, - .from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop, - .from_dbus_is_full = TRUE)); + .compare_fcn = _nm_setting_property_compare_fcn_default, + .to_dbus_fcn = ip6_dns_to_dbus, + .from_dbus_fcn = ip6_dns_from_dbus, ), + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE); /* ---dbus--- * property: addresses @@ -1012,9 +1015,11 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) properties_override, g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ADDRESSES), NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("a(ayuay)"), - .to_dbus_fcn = ip6_addresses_get, + .to_dbus_fcn = ip6_addresses_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_addresses, - .from_dbus_fcn = ip6_addresses_set, )); + .from_dbus_fcn = ip6_addresses_from_dbus, ), + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: address-data @@ -1029,9 +1034,9 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) properties_override, "address-data", NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = ip6_address_data_get, + .to_dbus_fcn = ip6_address_data_to_dbus, .compare_fcn = _nm_setting_property_compare_fcn_ignore, - .from_dbus_fcn = ip6_address_data_set, )); + .from_dbus_fcn = ip6_address_data_from_dbus, )); /* ---dbus--- * property: routes @@ -1130,9 +1135,11 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) properties_override, g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ROUTES), NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("a(ayuayu)"), - .to_dbus_fcn = ip6_routes_get, + .to_dbus_fcn = ip6_routes_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_routes, - .from_dbus_fcn = ip6_routes_set, )); + .from_dbus_fcn = ip6_routes_from_dbus, ), + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: route-data @@ -1151,9 +1158,9 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) properties_override, "route-data", NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = ip6_route_data_get, + .to_dbus_fcn = ip6_route_data_to_dbus, .compare_fcn = _nm_setting_property_compare_fcn_ignore, - .from_dbus_fcn = ip6_route_data_set, )); + .from_dbus_fcn = ip6_route_data_from_dbus, )); /* ---nmcli--- * property: routing-rules diff --git a/src/libnm-core-impl/nm-setting-private.h b/src/libnm-core-impl/nm-setting-private.h index 0b8b9cb640..8c674053c7 100644 --- a/src/libnm-core-impl/nm-setting-private.h +++ b/src/libnm-core-impl/nm-setting-private.h @@ -318,8 +318,9 @@ typedef struct { */ #define NM_SETTING_PARAM_INFERRABLE (1 << (4 + G_PARAM_USER_SHIFT)) -/* This is a legacy property, which clients should not send to the daemon. */ -#define NM_SETTING_PARAM_LEGACY (1 << (5 + G_PARAM_USER_SHIFT)) +/* This flag has no meaning (anymore). It's only kept, because we used it + * on some older versions of libnm. */ +#define NM_SETTING_PARAM_UNUSED1 (1 << (5 + G_PARAM_USER_SHIFT)) /* When a connection is active and gets modified, usually the change * to the settings-connection does not propagate automatically to the @@ -504,10 +505,14 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p .property_type = (p_property_type), \ __VA_ARGS__)) -#define _nm_properties_override_dbus(properties_override, p_name, p_property_type) \ - _nm_properties_override( \ - (properties_override), \ - NM_SETT_INFO_PROPERTY(.name = ("" p_name ""), .property_type = (p_property_type), )) +#define _nm_properties_override_dbus(properties_override, \ + p_name, \ + p_property_type, \ + ... /* extra NMSettInfoProperty fields */) \ + _nm_properties_override((properties_override), \ + NM_SETT_INFO_PROPERTY(.name = ("" p_name ""), \ + .property_type = (p_property_type), \ + __VA_ARGS__)) /*****************************************************************************/ @@ -1064,11 +1069,14 @@ NMTernary _nm_setting_ip_config_compare_fcn_addresses(_NM_SETT_INFO_PROP_COMPARE NMTernary _nm_setting_ip_config_compare_fcn_routes(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm_nil); -gboolean _nm_utils_hwaddr_cloned_not_set(_NM_SETT_INFO_PROP_MISSING_FROM_DBUS_FCN_ARGS _nm_nil); +gboolean _nm_sett_info_prop_missing_from_dbus_fcn_cloned_mac_address( + _NM_SETT_INFO_PROP_MISSING_FROM_DBUS_FCN_ARGS _nm_nil); -GVariant *_nm_utils_hwaddr_cloned_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil); +GVariant * +_nm_sett_info_prop_to_dbus_fcn_cloned_mac_address(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil); -gboolean _nm_utils_hwaddr_cloned_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil); +gboolean +_nm_sett_info_prop_from_dbus_fcn_cloned_mac_address(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil); /*****************************************************************************/ diff --git a/src/libnm-core-impl/nm-setting-tc-config.c b/src/libnm-core-impl/nm-setting-tc-config.c index ab7f2533c4..651e837a2d 100644 --- a/src/libnm-core-impl/nm-setting-tc-config.c +++ b/src/libnm-core-impl/nm-setting-tc-config.c @@ -1475,7 +1475,7 @@ next: } static GVariant * -tc_qdiscs_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +qdiscs_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *qdiscs = NULL; @@ -1484,7 +1484,7 @@ tc_qdiscs_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -tc_qdiscs_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +qdiscs_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *qdiscs = NULL; @@ -1661,7 +1661,7 @@ next: } static GVariant * -tc_tfilters_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +tfilters_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *tfilters = NULL; @@ -1670,7 +1670,7 @@ tc_tfilters_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -tc_tfilters_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +tfilters_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *tfilters = NULL; @@ -2083,12 +2083,13 @@ nm_setting_tc_config_class_init(NMSettingTCConfigClass *klass) G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_QDISCS], - NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = tc_qdiscs_get, - .compare_fcn = compare_fcn_qdiscs, - .from_dbus_fcn = tc_qdiscs_set, )); + _nm_properties_override_gobj( + properties_override, + obj_properties[PROP_QDISCS], + NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), + .to_dbus_fcn = qdiscs_to_dbus, + .compare_fcn = compare_fcn_qdiscs, + .from_dbus_fcn = qdiscs_from_dbus, )); /** * NMSettingTCConfig:tfilters: (type GPtrArray(NMTCTfilter)) @@ -2225,9 +2226,9 @@ nm_setting_tc_config_class_init(NMSettingTCConfigClass *klass) properties_override, obj_properties[PROP_TFILTERS], NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = tc_tfilters_get, + .to_dbus_fcn = tfilters_to_dbus, .compare_fcn = compare_fcn_tfilter, - .from_dbus_fcn = tc_tfilters_set, )); + .from_dbus_fcn = tfilters_from_dbus, )); g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/libnm-core-impl/nm-setting-team.c b/src/libnm-core-impl/nm-setting-team.c index 3eeeb2c335..9478ab98d7 100644 --- a/src/libnm-core-impl/nm-setting-team.c +++ b/src/libnm-core-impl/nm-setting-team.c @@ -1829,7 +1829,8 @@ nm_setting_team_class_init(NMSettingTeamClass *klass) */ _nm_properties_override_dbus(properties_override, "interface-name", - &nm_sett_info_propert_type_deprecated_interface_name); + &nm_sett_info_propert_type_deprecated_interface_name, + .dbus_deprecated = TRUE); g_object_class_install_properties(object_class, G_N_ELEMENTS(obj_properties), obj_properties); diff --git a/src/libnm-core-impl/nm-setting-vlan.c b/src/libnm-core-impl/nm-setting-vlan.c index 288945271b..20f455f579 100644 --- a/src/libnm-core-impl/nm-setting-vlan.c +++ b/src/libnm-core-impl/nm-setting-vlan.c @@ -678,13 +678,13 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) } static GVariant * -_override_flags_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +vlan_flags_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { return g_variant_new_uint32(nm_setting_vlan_get_flags((NMSettingVlan *) setting)); } static gboolean -_override_flags_not_set(_NM_SETT_INFO_PROP_MISSING_FROM_DBUS_FCN_ARGS _nm_nil) +vlan_flags_missing_from_dbus(_NM_SETT_INFO_PROP_MISSING_FROM_DBUS_FCN_ARGS _nm_nil) { /* we changed the default value for FLAGS. When an older client * doesn't serialize the property, we assume it is the old default. */ @@ -909,9 +909,9 @@ nm_setting_vlan_class_init(NMSettingVlanClass *klass) properties_override, obj_properties[PROP_FLAGS], NM_SETT_INFO_PROPERT_TYPE_DBUS(G_VARIANT_TYPE_UINT32, - .to_dbus_fcn = _override_flags_get, + .to_dbus_fcn = vlan_flags_to_dbus, .compare_fcn = _nm_setting_property_compare_fcn_default, - .missing_from_dbus_fcn = _override_flags_not_set, + .missing_from_dbus_fcn = vlan_flags_missing_from_dbus, .from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop, .from_dbus_is_full = TRUE)); @@ -976,7 +976,8 @@ nm_setting_vlan_class_init(NMSettingVlanClass *klass) */ _nm_properties_override_dbus(properties_override, "interface-name", - &nm_sett_info_propert_type_deprecated_interface_name); + &nm_sett_info_propert_type_deprecated_interface_name, + .dbus_deprecated = TRUE, ); g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/libnm-core-impl/nm-setting-wimax.c b/src/libnm-core-impl/nm-setting-wimax.c index 1e2b51c340..c33ad3eaa8 100644 --- a/src/libnm-core-impl/nm-setting-wimax.c +++ b/src/libnm-core-impl/nm-setting-wimax.c @@ -178,7 +178,8 @@ nm_setting_wimax_class_init(NMSettingWimaxClass *klass) PROP_NETWORK_NAME, NM_SETTING_PARAM_NONE, NMSettingWimaxPrivate, - network_name); + network_name, + .is_deprecated = TRUE, ); /** * NMSettingWimax:mac-address: @@ -196,7 +197,8 @@ nm_setting_wimax_class_init(NMSettingWimaxClass *klass) NM_SETTING_PARAM_NONE, NMSettingWimaxPrivate, mac_address, - .direct_set_string_mac_address_len = ETH_ALEN); + .direct_set_string_mac_address_len = ETH_ALEN, + .is_deprecated = TRUE, ); g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/libnm-core-impl/nm-setting-wired.c b/src/libnm-core-impl/nm-setting-wired.c index 3e08369f85..45e8b50624 100644 --- a/src/libnm-core-impl/nm-setting-wired.c +++ b/src/libnm-core-impl/nm-setting-wired.c @@ -1385,11 +1385,13 @@ nm_setting_wired_class_init(NMSettingWiredClass *klass) _nm_properties_override_gobj( properties_override, obj_properties[PROP_CLONED_MAC_ADDRESS], - NM_SETT_INFO_PROPERT_TYPE_DBUS(G_VARIANT_TYPE_BYTESTRING, - .compare_fcn = compare_fcn_cloned_mac_address, - .to_dbus_fcn = _nm_utils_hwaddr_cloned_get, - .from_dbus_fcn = _nm_utils_hwaddr_cloned_set, - .missing_from_dbus_fcn = _nm_utils_hwaddr_cloned_not_set, )); + NM_SETT_INFO_PROPERT_TYPE_DBUS( + G_VARIANT_TYPE_BYTESTRING, + .compare_fcn = compare_fcn_cloned_mac_address, + .to_dbus_fcn = _nm_sett_info_prop_to_dbus_fcn_cloned_mac_address, + .from_dbus_fcn = _nm_sett_info_prop_from_dbus_fcn_cloned_mac_address, + .missing_from_dbus_fcn = _nm_sett_info_prop_missing_from_dbus_fcn_cloned_mac_address, ), + .dbus_deprecated = TRUE); /* ---dbus--- * property: assigned-mac-address diff --git a/src/libnm-core-impl/nm-setting-wireguard.c b/src/libnm-core-impl/nm-setting-wireguard.c index 82ae994031..8e3d002fed 100644 --- a/src/libnm-core-impl/nm-setting-wireguard.c +++ b/src/libnm-core-impl/nm-setting-wireguard.c @@ -1460,7 +1460,7 @@ nm_setting_wireguard_clear_peers(NMSettingWireGuard *self) /*****************************************************************************/ static GVariant * -_peers_dbus_only_synth(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +peers_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { NMSettingWireGuard *self = NM_SETTING_WIREGUARD(setting); NMSettingWireGuardPrivate *priv; @@ -1558,7 +1558,7 @@ _peers_dbus_only_synth(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -_peers_dbus_only_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +peers_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { GVariantIter iter_peers; GVariant *peer_var; @@ -2526,9 +2526,9 @@ nm_setting_wireguard_class_init(NMSettingWireGuardClass *klass) properties_override, NM_SETTING_WIREGUARD_PEERS, NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = _peers_dbus_only_synth, + .to_dbus_fcn = peers_to_dbus, .compare_fcn = compare_fcn_peers, - .from_dbus_fcn = _peers_dbus_only_set, )); + .from_dbus_fcn = peers_from_dbus, )); g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/libnm-core-impl/nm-setting-wireless.c b/src/libnm-core-impl/nm-setting-wireless.c index 6d27ba8400..604cf94ce2 100644 --- a/src/libnm-core-impl/nm-setting-wireless.c +++ b/src/libnm-core-impl/nm-setting-wireless.c @@ -1123,7 +1123,7 @@ compare_fcn_seen_bssids(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm_nil) /*****************************************************************************/ static GVariant * -nm_setting_wireless_get_security(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +security_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { if (!_nm_connection_serialize_non_secret(flags)) return NULL; @@ -1567,11 +1567,13 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass) _nm_properties_override_gobj( properties_override, obj_properties[PROP_CLONED_MAC_ADDRESS], - NM_SETT_INFO_PROPERT_TYPE_DBUS(G_VARIANT_TYPE_BYTESTRING, - .compare_fcn = compare_fcn_cloned_mac_address, - .to_dbus_fcn = _nm_utils_hwaddr_cloned_get, - .from_dbus_fcn = _nm_utils_hwaddr_cloned_set, - .missing_from_dbus_fcn = _nm_utils_hwaddr_cloned_not_set, )); + NM_SETT_INFO_PROPERT_TYPE_DBUS( + G_VARIANT_TYPE_BYTESTRING, + .compare_fcn = compare_fcn_cloned_mac_address, + .to_dbus_fcn = _nm_sett_info_prop_to_dbus_fcn_cloned_mac_address, + .from_dbus_fcn = _nm_sett_info_prop_from_dbus_fcn_cloned_mac_address, + .missing_from_dbus_fcn = _nm_sett_info_prop_missing_from_dbus_fcn_cloned_mac_address, ), + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: assigned-mac-address @@ -1809,7 +1811,8 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass) NM_SETTING_MAC_RANDOMIZATION_DEFAULT, NM_SETTING_PARAM_NONE, NMSettingWirelessPrivate, - mac_address_randomization); + mac_address_randomization, + .is_deprecated = TRUE, ); /* Compatibility for deprecated property */ /* ---ifcfg-rh--- @@ -1830,8 +1833,9 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass) properties_override, "security", NM_SETT_INFO_PROPERT_TYPE_DBUS(G_VARIANT_TYPE_STRING, - .to_dbus_fcn = nm_setting_wireless_get_security, - .compare_fcn = _nm_setting_property_compare_fcn_ignore, )); + .to_dbus_fcn = security_to_dbus, + .compare_fcn = _nm_setting_property_compare_fcn_ignore, ), + .dbus_deprecated = TRUE, ); /** * NMSettingWireless:wake-on-wlan: diff --git a/src/libnm-core-impl/nm-setting.c b/src/libnm-core-impl/nm-setting.c index 4c786ea18b..ebb3cb5e71 100644 --- a/src/libnm-core-impl/nm-setting.c +++ b/src/libnm-core-impl/nm-setting.c @@ -589,7 +589,48 @@ _nm_setting_use_legacy_property(NMSetting *setting, const char *new_property) { gs_unref_variant GVariant *setting_dict = NULL; - gs_unref_variant GVariant *value = NULL; + gs_unref_variant GVariant *val_leg = NULL; + gs_unref_variant GVariant *val_new = NULL; + + /* We want to be both forward and backward compatible (both the client or the daemon + * can be newer). + * + * For the most part, we achieve that by ignoring unknown properties (to be forward + * compatible). That of course has the downside, that we don't do strong validation + * of the input. + * + * In some cases, we deprecated a D-Bus property for another one (e.g. the legacy property + * "ipv4.routes" became the new property "ipv4.route-data"). In that case, the to/from D-Bus + * methods behave differently on the client and the daemon. + * + * The daemon will serialize both the legacy property and the new property to D-Bus. + * The client, will prefer the newer property (if it exists) when deserializing from D-Bus. + * + * Usually that scheme would fully suffice to support forward and backward compatibility. + * However, there is a problem. An old client (unaware of the new property) might get + * the profile, modify the old property, and send the entire profile back to the daemon. + * In this case, the old client does not know that the new property conflicts with the + * old property. The client also might try to preserve any unknown properties and send + * them back to the daemon. If the daemon now would prefer the new property, it would be wrong. + * + * The solution to this is that the daemon -- when both old and new property is set -- + * will prefer the old property. This is what _nm_setting_use_legacy_property() checks + * for. Consequently, a new client will not serialize both the old and the new property. + * This is done via "to_dbus_only_in_manager_process" flag. + * + * The downside of this scheme is that: + * + * - to/from D-Bus just got more complicated and behaves differently on the client + * and the daemon. + * - backward compatibility does not work with a newer client vs. and older daemon. + * This is the major downside. It's only not that severe, because we only deprecate + * properties seldom and only on major versions. Major version updates happen not + * often and they user might reboot (restart the daemon). + * + * The benefit is that the case with an older client and a newer daemon works, even + * if the client fetches a (new) profile, modifies only parts that it understands, + * and sends back the complete profile (including the new, unmodified properties). + */ if (!connection_dict) { /* we also allow the caller to provide no connection_dict. @@ -611,19 +652,24 @@ _nm_setting_use_legacy_property(NMSetting *setting, g_return_val_if_fail(setting_dict != NULL, FALSE); - /* If the new property isn't set, we have to use the legacy property. */ - value = g_variant_lookup_value(setting_dict, new_property, NULL); - if (!value) - return TRUE; - nm_clear_pointer(&value, g_variant_unref); + if (!_nm_utils_is_manager_process) { + /* The client will prefer the new property, unless it does not exist and + * the legacy property exists. */ + val_new = g_variant_lookup_value(setting_dict, new_property, NULL); + if (!val_new) { + val_leg = g_variant_lookup_value(setting_dict, legacy_property, NULL); + if (val_leg) + return TRUE; + } - /* Otherwise, clients always prefer new properties sent from the daemon. */ - if (!_nm_utils_is_manager_process) return FALSE; + } - /* The daemon prefers the legacy property if it exists. */ - value = g_variant_lookup_value(setting_dict, legacy_property, NULL); - return !!value; + /* The daemon prefers the old property (if it exists). */ + val_leg = g_variant_lookup_value(setting_dict, legacy_property, NULL); + if (val_leg) + return TRUE; + return FALSE; } /*****************************************************************************/ @@ -1737,12 +1783,11 @@ property_to_dbus(const NMSettInfoSetting *sett_info, || NM_FLAGS_HAS(property_info->param_spec->flags, G_PARAM_WRITABLE) || property_info->property_type == &nm_sett_info_propert_type_setting_name); + if (property_info->to_dbus_only_in_manager_process && !_nm_utils_is_manager_process) + return NULL; + if (property_info->param_spec && !ignore_flags && !NM_FLAGS_HAS(property_info->param_spec->flags, NM_SETTING_PARAM_TO_DBUS_IGNORE_FLAGS)) { - if (NM_FLAGS_HAS(property_info->param_spec->flags, NM_SETTING_PARAM_LEGACY) - && !_nm_utils_is_manager_process) - return NULL; - if (NM_FLAGS_HAS(property_info->param_spec->flags, NM_SETTING_PARAM_SECRET)) { NMSettingSecretFlags f = NM_SETTING_SECRET_FLAG_NONE; @@ -3504,7 +3549,7 @@ nm_setting_to_string(NMSetting *setting) } static GVariant * -_nm_setting_get_deprecated_virtual_interface_name(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +depreated_interface_name_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { NMSettingConnection *s_con; @@ -3524,8 +3569,9 @@ _nm_setting_get_deprecated_virtual_interface_name(_NM_SETT_INFO_PROP_TO_DBUS_FCN const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_interface_name = NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(G_VARIANT_TYPE_STRING, .compare_fcn = _nm_setting_property_compare_fcn_ignore, - .to_dbus_fcn = - _nm_setting_get_deprecated_virtual_interface_name, ); + .to_dbus_fcn = depreated_interface_name_to_dbus, + /* from_dbus_fcn() is handled by the connection.interface-name setter. + * See nm_setting_connection_no_interface_name(). */ ); const NMSettInfoPropertType nm_sett_info_propert_type_setting_name = NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(G_VARIANT_TYPE_STRING, diff --git a/src/libnm-core-impl/nm-utils-private.h b/src/libnm-core-impl/nm-utils-private.h index 1a6f29ef9b..a89a466983 100644 --- a/src/libnm-core-impl/nm-utils-private.h +++ b/src/libnm-core-impl/nm-utils-private.h @@ -64,8 +64,7 @@ GVariant *_nm_team_settings_property_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS void _nm_team_settings_property_from_dbus_link_watchers( _NM_SETT_INFO_PROP_FROM_DBUS_GPROP_FCN_ARGS _nm_nil); -GVariant *_nm_utils_ip4_dns_to_variant(const char *const *dns, gssize len); -GVariant *_nm_utils_ip6_dns_to_variant(const char *const *dns, gssize len); +GVariant *nm_utils_dns_to_variant(int addr_family, const char *const *dns, gssize len); const char *const *nmtst_system_encodings_for_lang(const char *lang); const char *const *nmtst_system_encodings_get_default(void); diff --git a/src/libnm-core-impl/nm-utils.c b/src/libnm-core-impl/nm-utils.c index 8db96b6d30..6550dc38d3 100644 --- a/src/libnm-core-impl/nm-utils.c +++ b/src/libnm-core-impl/nm-utils.c @@ -1297,12 +1297,30 @@ nm_utils_wpa_psk_valid(const char *psk) GVariant * nm_utils_ip4_dns_to_variant(char **dns) { - return _nm_utils_ip4_dns_to_variant(NM_CAST_STRV_CC(dns), -1); + return nm_utils_dns_to_variant(AF_INET, NM_CAST_STRV_CC(dns), -1); +} + +/** + * nm_utils_ip6_dns_to_variant: + * @dns: (type utf8): an array of IP address strings + * + * Utility function to convert an array of IP address strings int a #GVariant of + * type 'aay' representing an array of IPv6 addresses. + * + * If a string cannot be parsed, it will be silently ignored. + * + * Returns: (transfer none): a new floating #GVariant representing @dns. + **/ +GVariant * +nm_utils_ip6_dns_to_variant(char **dns) +{ + return nm_utils_dns_to_variant(AF_INET6, NM_CAST_STRV_CC(dns), -1); } GVariant * -_nm_utils_ip4_dns_to_variant(const char *const *dns, gssize len) +nm_utils_dns_to_variant(int addr_family, const char *const *dns, gssize len) { + const int IS_IPv4 = NM_IS_IPv4(addr_family); GVariantBuilder builder; gsize l; gsize i; @@ -1312,13 +1330,20 @@ _nm_utils_ip4_dns_to_variant(const char *const *dns, gssize len) else l = len; - g_variant_builder_init(&builder, G_VARIANT_TYPE("au")); + g_variant_builder_init(&builder, IS_IPv4 ? G_VARIANT_TYPE("au") : G_VARIANT_TYPE("aay")); for (i = 0; i < l; i++) { - in_addr_t ip; + NMIPAddr ip; - if (inet_pton(AF_INET, dns[i], &ip) == 1) + /* We can only represent the IP address on the legacy property "ipv[46].dns". + * Expose what we can. */ + if (!nm_utils_dnsname_parse(addr_family, dns[i], NULL, &ip, NULL)) + continue; + + if (IS_IPv4) g_variant_builder_add(&builder, "u", ip); + else + g_variant_builder_add(&builder, "@ay", nm_g_variant_new_ay_in6addr(&ip.addr6)); } return g_variant_builder_end(&builder); @@ -1606,46 +1631,6 @@ nm_utils_ip4_get_default_prefix(guint32 ip) return nm_ip4_addr_get_default_prefix(ip); } -/** - * nm_utils_ip6_dns_to_variant: - * @dns: (type utf8): an array of IP address strings - * - * Utility function to convert an array of IP address strings int a #GVariant of - * type 'aay' representing an array of IPv6 addresses. - * - * If a string cannot be parsed, it will be silently ignored. - * - * Returns: (transfer none): a new floating #GVariant representing @dns. - **/ -GVariant * -nm_utils_ip6_dns_to_variant(char **dns) -{ - return _nm_utils_ip6_dns_to_variant(NM_CAST_STRV_CC(dns), -1); -} - -GVariant * -_nm_utils_ip6_dns_to_variant(const char *const *dns, gssize len) -{ - GVariantBuilder builder; - gsize i; - gsize l; - - if (len < 0) - l = NM_PTRARRAY_LEN(dns); - else - l = len; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("aay")); - for (i = 0; i < l; i++) { - struct in6_addr ip; - - if (inet_pton(AF_INET6, dns[i], &ip) != 1) - continue; - g_variant_builder_add(&builder, "@ay", nm_g_variant_new_ay_in6addr(&ip)); - } - return g_variant_builder_end(&builder); -} - /** * nm_utils_ip6_dns_from_variant: * @value: a #GVariant of type 'aay' @@ -3980,7 +3965,7 @@ nm_utils_hwaddr_to_dbus(const char *str) } GVariant * -_nm_utils_hwaddr_cloned_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +_nm_sett_info_prop_to_dbus_fcn_cloned_mac_address(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_free char *addr = NULL; @@ -3991,7 +3976,7 @@ _nm_utils_hwaddr_cloned_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } gboolean -_nm_utils_hwaddr_cloned_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +_nm_sett_info_prop_from_dbus_fcn_cloned_mac_address(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { gsize length; const guint8 *array; @@ -4022,14 +4007,15 @@ _nm_utils_hwaddr_cloned_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) } gboolean -_nm_utils_hwaddr_cloned_not_set(_NM_SETT_INFO_PROP_MISSING_FROM_DBUS_FCN_ARGS _nm_nil) +_nm_sett_info_prop_missing_from_dbus_fcn_cloned_mac_address( + _NM_SETT_INFO_PROP_MISSING_FROM_DBUS_FCN_ARGS _nm_nil) { nm_assert(nm_streq0(property, "cloned-mac-address")); return TRUE; } static GVariant * -_nm_utils_hwaddr_cloned_data_synth(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +assigned_mac_address_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_free char *addr = NULL; @@ -4058,7 +4044,7 @@ _nm_utils_hwaddr_cloned_data_synth(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -_nm_utils_hwaddr_cloned_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +assigned_mac_address_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { nm_assert(nm_streq0(property_info->name, "assigned-mac-address")); @@ -4080,8 +4066,8 @@ _nm_utils_hwaddr_cloned_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) const NMSettInfoPropertType nm_sett_info_propert_type_assigned_mac_address = NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(G_VARIANT_TYPE_STRING, .compare_fcn = _nm_setting_property_compare_fcn_ignore, - .to_dbus_fcn = _nm_utils_hwaddr_cloned_data_synth, - .from_dbus_fcn = _nm_utils_hwaddr_cloned_data_set, ); + .to_dbus_fcn = assigned_mac_address_to_dbus, + .from_dbus_fcn = assigned_mac_address_from_dbus, ); /*****************************************************************************/ diff --git a/src/libnm-core-impl/tests/test-general.c b/src/libnm-core-impl/tests/test-general.c index a45ead3b9f..9317451daf 100644 --- a/src/libnm-core-impl/tests/test-general.c +++ b/src/libnm-core-impl/tests/test-general.c @@ -5247,7 +5247,8 @@ test_setting_ip4_changed_signal(void) ASSERT_CHANGED(nm_setting_ip_config_add_dns(s_ip4, "11.22.0.0")); ASSERT_CHANGED(nm_setting_ip_config_remove_dns(s_ip4, 0)); - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns->len)); + NMTST_EXPECT_LIBNM_CRITICAL( + NMTST_G_RETURN_MSG(idx >= 0 && ((guint) idx) < nm_g_ptr_array_len(priv->dns))); ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns(s_ip4, 1)); g_test_assert_expected_messages(); @@ -5323,7 +5324,8 @@ test_setting_ip6_changed_signal(void) ASSERT_CHANGED(nm_setting_ip_config_add_dns(s_ip6, "1:2:3::4:5:6")); ASSERT_CHANGED(nm_setting_ip_config_remove_dns(s_ip6, 0)); - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns->len)); + NMTST_EXPECT_LIBNM_CRITICAL( + NMTST_G_RETURN_MSG(idx >= 0 && ((guint) idx) < nm_g_ptr_array_len(priv->dns))); ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns(s_ip6, 1)); g_test_assert_expected_messages(); @@ -11163,6 +11165,181 @@ test_connection_path(void) /*****************************************************************************/ +static void +_t_dnsname_1(const char *str, const char *exp_addr, const char *exp_server_name) +{ + int addr_family; + NMIPAddr exp_addr_bin; + gboolean addr_family_request; + gboolean r; + int detect_addr_family; + NMIPAddr detect_addr; + const char *detect_server_name; + int *p_detect_addr_family = &detect_addr_family; + NMIPAddr *p_detect_addr = &detect_addr; + const char **p_detect_server_name = &detect_server_name; + char str_construct_buf[100]; + char str_construct_buf2[100]; + const char *str_construct; + const char *str_construct2; + gsize l; + const char *str_normalized; + gs_free char *str_normalized_alloc = NULL; + + g_assert(str); + g_assert(exp_addr); + + r = nm_inet_parse_bin(AF_UNSPEC, exp_addr, &addr_family, &exp_addr_bin); + g_assert(r); + g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); + + addr_family_request = nmtst_get_rand_bool(); + if (nmtst_get_rand_bool()) + p_detect_addr = NULL; + if ((addr_family_request || !p_detect_addr) && nmtst_get_rand_bool()) + p_detect_addr_family = NULL; + if (nmtst_get_rand_bool()) + p_detect_server_name = NULL; + + r = nm_utils_dnsname_parse(addr_family_request ? addr_family : AF_UNSPEC, + str, + p_detect_addr_family, + p_detect_addr, + p_detect_server_name); + g_assert(r); + + if (p_detect_addr_family) + g_assert_cmpint(addr_family, ==, detect_addr_family); + if (p_detect_addr) + g_assert_cmpstr(nmtst_inet_to_string(addr_family, &detect_addr), ==, exp_addr); + if (p_detect_server_name) + g_assert_cmpstr(detect_server_name, ==, exp_server_name); + + r = nm_utils_dnsname_parse(addr_family == AF_INET ? AF_INET6 : AF_INET, + str, + p_detect_addr_family, + p_detect_addr, + p_detect_server_name); + g_assert(!r); + + /* Construct the expected value. */ + str_construct = nm_utils_dnsname_construct(addr_family, + &exp_addr_bin, + exp_server_name, + str_construct_buf, + sizeof(str_construct_buf)); + g_assert(str_construct); + g_assert(str_construct == str_construct_buf); + g_assert(strlen(str_construct) < sizeof(str_construct_buf)); + + /* Check that a too short buffer causes truncation. */ + l = nmtst_get_rand_uint32() % (strlen(str_construct) + 10); + str_construct2 = nm_utils_dnsname_construct(addr_family, + &exp_addr_bin, + exp_server_name, + str_construct_buf2, + l); + if (str_construct2) { + g_assert(str_construct2 == str_construct_buf2); + g_assert_cmpstr(str_construct2, ==, str_construct); + g_assert(l > strlen(str_construct)); + } else + g_assert(l <= strlen(str_construct)); + + if (!nm_streq(str_construct, str)) { + _t_dnsname_1(str_construct, exp_addr, exp_server_name); + } + + str_normalized = nm_utils_dnsname_normalize(nmtst_get_rand_bool() ? addr_family : AF_UNSPEC, + str, + &str_normalized_alloc); + g_assert(str_normalized); + if (str_normalized_alloc) { + g_assert(str_normalized == str_normalized_alloc); + g_assert_cmpstr(str_normalized, !=, str); + } else { + g_assert(str == str_normalized); + } + g_assert_cmpstr(str_normalized, ==, str_construct); + + nm_clear_g_free(&str_normalized_alloc); + str_normalized = nm_utils_dnsname_normalize(addr_family == AF_INET ? AF_INET6 : AF_INET, + str, + &str_normalized_alloc); + g_assert(!str_normalized); + g_assert(!str_normalized_alloc); +} + +static void +_t_dnsname_0(const char *str) +{ + gboolean addr_family_request; + int detect_addr_family; + NMIPAddr detect_addr; + const char *detect_server_name; + int *p_detect_addr_family = &detect_addr_family; + NMIPAddr *p_detect_addr = &detect_addr; + const char **p_detect_server_name = &detect_server_name; + const char *str_normalized; + gs_free char *str_normalized_alloc = NULL; + gboolean r; + + g_assert(str); + + addr_family_request = nmtst_get_rand_bool(); + if (nmtst_get_rand_bool()) + p_detect_addr = NULL; + if ((addr_family_request || !p_detect_addr) && nmtst_get_rand_bool()) + p_detect_addr_family = NULL; + if (nmtst_get_rand_bool()) + p_detect_server_name = NULL; + + r = nm_utils_dnsname_parse(addr_family_request ? nmtst_rand_select(AF_INET, AF_INET6) + : AF_UNSPEC, + str, + p_detect_addr_family, + p_detect_addr, + p_detect_server_name); + g_assert(!r); + + str_normalized = nm_utils_dnsname_normalize(nmtst_rand_select(AF_UNSPEC, AF_INET, AF_INET6), + str, + &str_normalized_alloc); + g_assert(!str_normalized); + g_assert(!str_normalized_alloc); +} + +static void +test_dnsname(void) +{ + _t_dnsname_1("1.2.3.4", "1.2.3.4", NULL); + _t_dnsname_1("1.2.3.4#foo", "1.2.3.4", "foo"); + _t_dnsname_1("1::#x", "1::", "x"); + _t_dnsname_1("1::0#x", "1::", "x"); + _t_dnsname_1("192.168.0.1", "192.168.0.1", NULL); + _t_dnsname_1("192.168.0.1#test.com", "192.168.0.1", "test.com"); + _t_dnsname_1("fe80::18", "fe80::18", NULL); + _t_dnsname_1("fe80::18#hoge.com", "fe80::18", "hoge.com"); + + _t_dnsname_0("1.2.3.4#"); + _t_dnsname_0("1::0#"); + _t_dnsname_0("192.168.0.1:53"); + _t_dnsname_0("192.168.0.1:53#example.com"); + _t_dnsname_0("fe80::18%19"); + _t_dnsname_0("fe80::18%lo"); + _t_dnsname_0("[fe80::18]:53"); + _t_dnsname_0("[fe80::18]:53%19"); + _t_dnsname_0("[fe80::18]:53%lo"); + _t_dnsname_0("fe80::18%19#hoge.com"); + _t_dnsname_0("[fe80::18]:53#hoge.com"); + _t_dnsname_0("[fe80::18]:53%19"); + _t_dnsname_0("[fe80::18]:53%19#hoge.com"); + _t_dnsname_0("[fe80::18]:53%lo"); + _t_dnsname_0("[fe80::18]:53%lo#hoge.com"); +} + +/*****************************************************************************/ + NMTST_DEFINE(); int @@ -11509,6 +11686,7 @@ main(int argc, char **argv) g_test_add_func("/core/general/test_system_encodings", test_system_encodings); g_test_add_func("/core/general/test_direct_string_is_refstr", test_direct_string_is_refstr); g_test_add_func("/core/general/test_connection_path", test_connection_path); + g_test_add_func("/core/general/test_dnsname", test_dnsname); return g_test_run(); } diff --git a/src/libnm-core-intern/nm-core-internal.h b/src/libnm-core-intern/nm-core-internal.h index a288dc43ce..21c994f033 100644 --- a/src/libnm-core-intern/nm-core-internal.h +++ b/src/libnm-core-intern/nm-core-internal.h @@ -826,6 +826,44 @@ struct _NMSettInfoProperty { * Set this flag to force always converting the property even if the value * is the default. */ bool to_dbus_including_default : 1; + + /* This indicates, that the property is deprecated (on D-Bus) for another property. + * See also _nm_setting_use_legacy_property() how that works. + * + * The to_dbus_fcn() will be skipped for such properties, if _nm_utils_is_manager_process + * is FALSE. */ + bool to_dbus_only_in_manager_process : 1; + + /* Whether the property is deprecated. + * + * Note that we have various representations of profiles, e.g. on D-Bus, keyfile, + * nmcli, libnm/NMSetting. Usually a property (in the general sense) is named and + * applies similarly to all those. But not always, for example, on D-Bus we + * have the field "ethernet.assigned-mac-address", but that exists nowhere + * as a property in the other parts (the real property is called + * "ethernet.cloned-mac-address"). + * + * This flag indicates whether a property is deprecated. Here "property" means + * no specific representation. When a property is deprecated this way, it will + * also indirectly apply to setting the property on D-Bus, keyfile, nmcli, etc. + * It means the general concept of this thing is no longer useful/recommended. + */ + bool is_deprecated : 1; + + /* Whether the property is deprecated in the D-Bus API. + * + * This has no real effect (for now). It is only self-documenting code that + * this property is discouraged on D-Bus. We might honor this when generating + * documentation, or we might use it to find properties that are deprecated. + * + * Note what this means. For example, "802-1x.phase2-subject-match" is deprecated + * as a property altogether, but that does not mean it's deprecated specifically on + * D-Bus. + * "ethernet.cloned-mac-address" is deprecated on D-Bus in favor of + * "ethernet.assigned-mac-address", but the property clone-mac-address itself + * is not deprecated. This flag is about the deprecation of the D-Bus representation + * of a property. */ + bool dbus_deprecated : 1; }; typedef struct { diff --git a/src/libnmc-setting/nm-meta-setting-desc.c b/src/libnmc-setting/nm-meta-setting-desc.c index 888a0e6962..c4e5e7de03 100644 --- a/src/libnmc-setting/nm-meta-setting-desc.c +++ b/src/libnmc-setting/nm-meta-setting-desc.c @@ -3449,23 +3449,6 @@ _set_fcn_ip_config_method(ARGS_SET_FCN) return TRUE; } -static const char * -_multilist_validate2_fcn_ip_config_dns(NMSetting *setting, const char *value, GError **error) -{ - int addr_family = nm_setting_ip_config_get_addr_family(NM_SETTING_IP_CONFIG(setting)); - - if (!nm_inet_parse_str(addr_family, value, NULL)) { - nm_utils_error_set(error, - NM_UTILS_ERROR_INVALID_ARGUMENT, - _("invalid IPv%c address '%s'"), - nm_utils_addr_family_to_char(addr_family), - value); - return NULL; - } - - return value; -} - static gboolean _multilist_add_fcn_ip_config_dns_options(NMSetting *setting, const char *item) { @@ -6040,7 +6023,6 @@ static const NMMetaPropertyInfo *const property_infos_IP4_CONFIG[] = { .add_fcn = MULTILIST_ADD_FCN (NMSettingIPConfig, nm_setting_ip_config_add_dns), .remove_by_idx_fcn_s = MULTILIST_REMOVE_BY_IDX_FCN_S (NMSettingIPConfig, nm_setting_ip_config_remove_dns), .remove_by_value_fcn = MULTILIST_REMOVE_BY_VALUE_FCN (NMSettingIPConfig, nm_setting_ip_config_remove_dns_by_value), - .validate2_fcn = _multilist_validate2_fcn_ip_config_dns, .strsplit_plain = TRUE, ), ), @@ -6293,7 +6275,6 @@ static const NMMetaPropertyInfo *const property_infos_IP6_CONFIG[] = { .add_fcn = MULTILIST_ADD_FCN (NMSettingIPConfig, nm_setting_ip_config_add_dns), .remove_by_idx_fcn_s = MULTILIST_REMOVE_BY_IDX_FCN_S (NMSettingIPConfig, nm_setting_ip_config_remove_dns), .remove_by_value_fcn = MULTILIST_REMOVE_BY_VALUE_FCN (NMSettingIPConfig, nm_setting_ip_config_remove_dns_by_value), - .validate2_fcn = _multilist_validate2_fcn_ip_config_dns, .strsplit_plain = TRUE, ), ), diff --git a/src/libnmc-setting/settings-docs.h.in b/src/libnmc-setting/settings-docs.h.in index cf87f38c15..b9fb1234fd 100644 --- a/src/libnmc-setting/settings-docs.h.in +++ b/src/libnmc-setting/settings-docs.h.in @@ -167,7 +167,7 @@ #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.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER N_("The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server. Since 1.28") -#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS N_("Array of IP addresses of DNS servers.") +#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS N_("Array of IP addresses of DNS servers. For DoT (DNS over TLS), the SNI server name can be specified by appending \"#example.com\" to the IP address of the DNS server. This currently only has effect when using systemd-resolved.") #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. The currently supported options are \"attempts\", \"debug\", \"edns0\", \"inet6\", \"ip6-bytestring\", \"ip6-dotint\", \"ndots\", \"no-check-names\", \"no-ip6-dotint\", \"no-reload\", \"no-tld-query\", \"rotate\", \"single-request\", \"single-request-reopen\", \"timeout\", \"trust-ad\", \"use-vc\". The \"trust-ad\" setting is only honored if the profile contributes name servers to resolv.conf, and if all contributing profiles have \"trust-ad\" enabled. When using a caching DNS plugin (dnsmasq or systemd-resolved in NetworkManager.conf) then \"edns0\" and \"trust-ad\" are automatically added.") #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 numerical value is better (higher priority). Negative values have the special effect of excluding other configurations with a greater numerical priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. To avoid all DNS leaks, set the priority of the profile that should be used to the most negative value of all active connections profiles. Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. 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. Note that commonly the resolver tries name servers in /etc/resolv.conf in the order listed, proceeding with the next server in the list on failure. See for example the \"rotate\" option of the dns-options setting. If there are any negative DNS priorities, then only name servers from the devices with that lowest priority will be considered. When using a DNS resolver that supports Conditional Forwarding or Split DNS (with dns=dnsmasq or dns=systemd-resolved settings), each connection is used to query domains in its search list. The search domains determine which name servers to ask, and the DNS priority is used to prioritize name servers based on the domain. 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 best priority (lowest numerical value) wins. If a sub domain is configured on another interface it will be accepted regardless the priority, unless parent domain on the other interface has a negative priority, which causes the sub domain to be shadowed. With Split DNS one can avoid undesired DNS leaks by properly configuring DNS priorities and the search domains, so that only name servers of the desired interface are configured.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_SEARCH N_("List 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. When using a DNS plugin that supports Conditional Forwarding or Split DNS, then the search domains specify which name servers to query. This makes the behavior different from running with plain /etc/resolv.conf. For more information see also the dns-priority setting. When set on a profile that also enabled DHCP, the DNS search list received automatically (option 119 for DHCPv4 and option 24 for DHCPv6) gets merged with the manual list. This can be prevented by setting \"ignore-auto-dns\". Note that if no DNS searches are configured, the fallback will be derived from the domain from DHCP (option 15).") @@ -193,7 +193,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_REJECT_SERVERS N_("Array of servers from which DHCP offers must be rejected. This property is useful to avoid getting a lease from misconfigured or rogue servers. For DHCPv4, each element must be an IPv4 address, optionally followed by a slash and a prefix length (e.g. \"192.168.122.0/24\"). This property is currently not implemented for DHCPv6.") #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. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity.") -#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS N_("Array of IP addresses of DNS servers.") +#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS N_("Array of IP addresses of DNS servers. For DoT (DNS over TLS), the SNI server name can be specified by appending \"#example.com\" to the IP address of the DNS server. This currently only has effect when using systemd-resolved.") #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. The currently supported options are \"attempts\", \"debug\", \"edns0\", \"inet6\", \"ip6-bytestring\", \"ip6-dotint\", \"ndots\", \"no-check-names\", \"no-ip6-dotint\", \"no-reload\", \"no-tld-query\", \"rotate\", \"single-request\", \"single-request-reopen\", \"timeout\", \"trust-ad\", \"use-vc\". The \"trust-ad\" setting is only honored if the profile contributes name servers to resolv.conf, and if all contributing profiles have \"trust-ad\" enabled. When using a caching DNS plugin (dnsmasq or systemd-resolved in NetworkManager.conf) then \"edns0\" and \"trust-ad\" are automatically added.") #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 numerical value is better (higher priority). Negative values have the special effect of excluding other configurations with a greater numerical priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. To avoid all DNS leaks, set the priority of the profile that should be used to the most negative value of all active connections profiles. Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. 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. Note that commonly the resolver tries name servers in /etc/resolv.conf in the order listed, proceeding with the next server in the list on failure. See for example the \"rotate\" option of the dns-options setting. If there are any negative DNS priorities, then only name servers from the devices with that lowest priority will be considered. When using a DNS resolver that supports Conditional Forwarding or Split DNS (with dns=dnsmasq or dns=systemd-resolved settings), each connection is used to query domains in its search list. The search domains determine which name servers to ask, and the DNS priority is used to prioritize name servers based on the domain. 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 best priority (lowest numerical value) wins. If a sub domain is configured on another interface it will be accepted regardless the priority, unless parent domain on the other interface has a negative priority, which causes the sub domain to be shadowed. With Split DNS one can avoid undesired DNS leaks by properly configuring DNS priorities and the search domains, so that only name servers of the desired interface are configured.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_SEARCH N_("List 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. When using a DNS plugin that supports Conditional Forwarding or Split DNS, then the search domains specify which name servers to query. This makes the behavior different from running with plain /etc/resolv.conf. For more information see also the dns-priority setting. When set on a profile that also enabled DHCP, the DNS search list received automatically (option 119 for DHCPv4 and option 24 for DHCPv6) gets merged with the manual list. This can be prevented by setting \"ignore-auto-dns\". Note that if no DNS searches are configured, the fallback will be derived from the domain from DHCP (option 15).") diff --git a/src/nmcli/generate-docs-nm-settings-nmcli.xml.in b/src/nmcli/generate-docs-nm-settings-nmcli.xml.in index 464d53b9ab..8600e7a5f4 100644 --- a/src/nmcli/generate-docs-nm-settings-nmcli.xml.in +++ b/src/nmcli/generate-docs-nm-settings-nmcli.xml.in @@ -652,7 +652,7 @@ + description="Array of IP addresses of DNS servers. For DoT (DNS over TLS), the SNI server name can be specified by appending "#example.com" to the IP address of the DNS server. This currently only has effect when using systemd-resolved." /> + description="Array of IP addresses of DNS servers. For DoT (DNS over TLS), the SNI server name can be specified by appending "#example.com" to the IP address of the DNS server. This currently only has effect when using systemd-resolved." />