From e94abbc4658e9e6af93f8bad65ecf0b1bf19521e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 21 Oct 2022 14:50:27 +0200 Subject: [PATCH 01/17] libnm: rename internal to/from dbus functions --- src/libnm-core-impl/nm-setting-ip-config.c | 8 ++--- src/libnm-core-impl/nm-setting-ip4-config.c | 40 +++++++++++---------- src/libnm-core-impl/nm-setting-ip6-config.c | 32 ++++++++--------- src/libnm-core-impl/nm-setting-private.h | 9 +++-- src/libnm-core-impl/nm-setting-tc-config.c | 25 ++++++------- src/libnm-core-impl/nm-setting-vlan.c | 8 ++--- src/libnm-core-impl/nm-setting-wired.c | 12 ++++--- src/libnm-core-impl/nm-setting-wireguard.c | 8 ++--- src/libnm-core-impl/nm-setting-wireless.c | 16 +++++---- src/libnm-core-impl/nm-setting.c | 7 ++-- src/libnm-core-impl/nm-utils.c | 15 ++++---- 11 files changed, 96 insertions(+), 84 deletions(-) diff --git a/src/libnm-core-impl/nm-setting-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c index 84e6247773..78e8ece67e 100644 --- a/src/libnm-core-impl/nm-setting-ip-config.c +++ b/src/libnm-core-impl/nm-setting-ip-config.c @@ -5012,7 +5012,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 +5043,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; @@ -5883,9 +5883,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, diff --git a/src/libnm-core-impl/nm-setting-ip4-config.c b/src/libnm-core-impl/nm-setting-ip4-config.c index 27f500557a..2d454085c5 100644 --- a/src/libnm-core-impl/nm-setting-ip4-config.c +++ b/src/libnm-core-impl/nm-setting-ip4-config.c @@ -402,7 +402,7 @@ ip4_dns_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_GPROP_FCN_ARGS _nm_nil) } 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,7 +413,7 @@ 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; @@ -454,7 +454,7 @@ ip4_addresses_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) } 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; @@ -493,7 +493,7 @@ ip4_address_labels_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } 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,7 +505,7 @@ 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; @@ -524,7 +524,7 @@ ip4_address_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) } 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,7 +533,7 @@ 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; @@ -551,7 +551,7 @@ ip4_routes_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) } 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,7 +563,7 @@ 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; @@ -1002,15 +1002,17 @@ 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, )); _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--- * property: address-data @@ -1025,9 +1027,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 +1139,9 @@ 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, )); /* ---dbus--- * property: route-data @@ -1158,9 +1160,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..82f5ff9687 100644 --- a/src/libnm-core-impl/nm-setting-ip6-config.c +++ b/src/libnm-core-impl/nm-setting-ip6-config.c @@ -403,7 +403,7 @@ ip6_dns_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_GPROP_FCN_ARGS _nm_nil) } 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,7 +414,7 @@ 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; @@ -438,7 +438,7 @@ ip6_addresses_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) } 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,7 +450,7 @@ 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; @@ -467,7 +467,7 @@ ip6_address_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) } 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,7 +476,7 @@ 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; @@ -492,7 +492,7 @@ ip6_routes_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) } 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,7 +504,7 @@ 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; @@ -1012,9 +1012,9 @@ 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, )); /* ---dbus--- * property: address-data @@ -1029,9 +1029,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 +1130,9 @@ 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, )); /* ---dbus--- * property: route-data @@ -1151,9 +1151,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..d89d0c3642 100644 --- a/src/libnm-core-impl/nm-setting-private.h +++ b/src/libnm-core-impl/nm-setting-private.h @@ -1064,11 +1064,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-vlan.c b/src/libnm-core-impl/nm-setting-vlan.c index 288945271b..ab24d33547 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)); diff --git a/src/libnm-core-impl/nm-setting-wired.c b/src/libnm-core-impl/nm-setting-wired.c index 3e08369f85..3a8a965831 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--- * 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..2dead8c540 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--- * property: assigned-mac-address @@ -1830,7 +1832,7 @@ 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, + .to_dbus_fcn = security_to_dbus, .compare_fcn = _nm_setting_property_compare_fcn_ignore, )); /** diff --git a/src/libnm-core-impl/nm-setting.c b/src/libnm-core-impl/nm-setting.c index 4c786ea18b..46ed9ebb79 100644 --- a/src/libnm-core-impl/nm-setting.c +++ b/src/libnm-core-impl/nm-setting.c @@ -3504,7 +3504,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 +3524,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.c b/src/libnm-core-impl/nm-utils.c index 8db96b6d30..77eecea441 100644 --- a/src/libnm-core-impl/nm-utils.c +++ b/src/libnm-core-impl/nm-utils.c @@ -3980,7 +3980,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 +3991,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 +4022,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 +4059,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 +4081,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, ); /*****************************************************************************/ From bb9a9b8ee10b5b29b3165d1cfb75d1eba3613412 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 24 Oct 2022 11:16:42 +0200 Subject: [PATCH 02/17] libnm: add extra arguments to _nm_properties_override_dbus() --- src/libnm-core-impl/nm-setting-private.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libnm-core-impl/nm-setting-private.h b/src/libnm-core-impl/nm-setting-private.h index d89d0c3642..d38e889222 100644 --- a/src/libnm-core-impl/nm-setting-private.h +++ b/src/libnm-core-impl/nm-setting-private.h @@ -504,10 +504,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__)) /*****************************************************************************/ From 0fd7691b096a11d375e68c5b2dc9508ef3877595 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 24 Oct 2022 10:59:53 +0200 Subject: [PATCH 03/17] libnm: add NMSettInfoProperty.{,dbus_}deprecated flag to mark deprecated properties --- src/libnm-core-intern/nm-core-internal.h | 31 ++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/libnm-core-intern/nm-core-internal.h b/src/libnm-core-intern/nm-core-internal.h index a288dc43ce..563811305c 100644 --- a/src/libnm-core-intern/nm-core-internal.h +++ b/src/libnm-core-intern/nm-core-internal.h @@ -826,6 +826,37 @@ struct _NMSettInfoProperty { * Set this flag to force always converting the property even if the value * is the default. */ bool to_dbus_including_default : 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 { From 05d0b81130228a25b186911fe2a575a09f22dcb3 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 24 Oct 2022 11:01:15 +0200 Subject: [PATCH 04/17] libnm: mark deprecated D-Bus properties in meta data This has no effect (yet), but we will generate documentation from this information. Also, it's just self-documenting code. --- src/libnm-core-impl/nm-setting-8021x.c | 6 ++++-- src/libnm-core-impl/nm-setting-bond.c | 3 ++- src/libnm-core-impl/nm-setting-bridge.c | 6 ++++-- src/libnm-core-impl/nm-setting-gsm.c | 9 ++++++--- src/libnm-core-impl/nm-setting-ip4-config.c | 10 ++++++---- src/libnm-core-impl/nm-setting-ip6-config.c | 6 ++++-- src/libnm-core-impl/nm-setting-team.c | 3 ++- src/libnm-core-impl/nm-setting-vlan.c | 3 ++- src/libnm-core-impl/nm-setting-wimax.c | 6 ++++-- src/libnm-core-impl/nm-setting-wired.c | 10 +++++----- src/libnm-core-impl/nm-setting-wireless.c | 16 +++++++++------- 11 files changed, 48 insertions(+), 30 deletions(-) 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-ip4-config.c b/src/libnm-core-impl/nm-setting-ip4-config.c index 2d454085c5..a207e2d7ef 100644 --- a/src/libnm-core-impl/nm-setting-ip4-config.c +++ b/src/libnm-core-impl/nm-setting-ip4-config.c @@ -1004,15 +1004,16 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aau"), .to_dbus_fcn = ip4_addresses_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_addresses, - .from_dbus_fcn = ip4_addresses_from_dbus, )); + .from_dbus_fcn = ip4_addresses_from_dbus, ), + .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_to_dbus, .compare_fcn = _nm_setting_property_compare_fcn_ignore, - /* from_dbus() is handled by ip4_addresses_from_dbus(). */ - )); + /* from_dbus() is handled by ip4_addresses_from_dbus(). */), + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: address-data @@ -1141,7 +1142,8 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aau"), .to_dbus_fcn = ip4_routes_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_routes, - .from_dbus_fcn = ip4_routes_from_dbus, )); + .from_dbus_fcn = ip4_routes_from_dbus, ), + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: route-data diff --git a/src/libnm-core-impl/nm-setting-ip6-config.c b/src/libnm-core-impl/nm-setting-ip6-config.c index 82f5ff9687..53486d0f7f 100644 --- a/src/libnm-core-impl/nm-setting-ip6-config.c +++ b/src/libnm-core-impl/nm-setting-ip6-config.c @@ -1014,7 +1014,8 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("a(ayuay)"), .to_dbus_fcn = ip6_addresses_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_addresses, - .from_dbus_fcn = ip6_addresses_from_dbus, )); + .from_dbus_fcn = ip6_addresses_from_dbus, ), + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: address-data @@ -1132,7 +1133,8 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("a(ayuayu)"), .to_dbus_fcn = ip6_routes_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_routes, - .from_dbus_fcn = ip6_routes_from_dbus, )); + .from_dbus_fcn = ip6_routes_from_dbus, ), + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: route-data 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 ab24d33547..20f455f579 100644 --- a/src/libnm-core-impl/nm-setting-vlan.c +++ b/src/libnm-core-impl/nm-setting-vlan.c @@ -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 3a8a965831..45e8b50624 100644 --- a/src/libnm-core-impl/nm-setting-wired.c +++ b/src/libnm-core-impl/nm-setting-wired.c @@ -1387,11 +1387,11 @@ nm_setting_wired_class_init(NMSettingWiredClass *klass) 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_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, )); + .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-wireless.c b/src/libnm-core-impl/nm-setting-wireless.c index 2dead8c540..604cf94ce2 100644 --- a/src/libnm-core-impl/nm-setting-wireless.c +++ b/src/libnm-core-impl/nm-setting-wireless.c @@ -1569,11 +1569,11 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass) 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_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, )); + .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 @@ -1811,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--- @@ -1833,7 +1834,8 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass) "security", NM_SETT_INFO_PROPERT_TYPE_DBUS(G_VARIANT_TYPE_STRING, .to_dbus_fcn = security_to_dbus, - .compare_fcn = _nm_setting_property_compare_fcn_ignore, )); + .compare_fcn = _nm_setting_property_compare_fcn_ignore, ), + .dbus_deprecated = TRUE, ); /** * NMSettingWireless:wake-on-wlan: From b1ec664869cfc9a8c300f709433638199e9383ed Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 21 Oct 2022 14:55:15 +0200 Subject: [PATCH 05/17] libnm: cleanup from/to dbus callbacks in ip[46]-config --- src/libnm-core-impl/nm-setting-ip4-config.c | 64 ++++++++++----------- src/libnm-core-impl/nm-setting-ip6-config.c | 15 ++--- 2 files changed, 35 insertions(+), 44 deletions(-) diff --git a/src/libnm-core-impl/nm-setting-ip4-config.c b/src/libnm-core-impl/nm-setting-ip4-config.c index a207e2d7ef..a8c3aea75f 100644 --- a/src/libnm-core-impl/nm-setting-ip4-config.c +++ b/src/libnm-core-impl/nm-setting-ip4-config.c @@ -415,10 +415,11 @@ ip4_addresses_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) static gboolean 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 +433,15 @@ ip4_addresses_from_dbus(_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,8 +449,6 @@ ip4_addresses_from_dbus(_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; } @@ -458,38 +457,38 @@ 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 * @@ -507,7 +506,7 @@ ip4_address_data_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) static gboolean 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,7 +518,6 @@ ip4_address_data_from_dbus(_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; } @@ -535,7 +533,7 @@ ip4_routes_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) static gboolean 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,7 +544,6 @@ ip4_routes_from_dbus(_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; } @@ -565,7 +562,7 @@ ip4_route_data_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) static gboolean 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 +574,6 @@ ip4_route_data_from_dbus(_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; } diff --git a/src/libnm-core-impl/nm-setting-ip6-config.c b/src/libnm-core-impl/nm-setting-ip6-config.c index 53486d0f7f..02bc85c295 100644 --- a/src/libnm-core-impl/nm-setting-ip6-config.c +++ b/src/libnm-core-impl/nm-setting-ip6-config.c @@ -416,8 +416,8 @@ ip6_addresses_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) static gboolean 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,8 +432,6 @@ ip6_addresses_from_dbus(_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; } @@ -452,7 +450,7 @@ ip6_address_data_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) static gboolean 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,7 +460,6 @@ ip6_address_data_from_dbus(_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; } @@ -478,7 +475,7 @@ ip6_routes_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) static gboolean 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,7 +484,6 @@ ip6_routes_from_dbus(_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; } @@ -506,7 +502,7 @@ ip6_route_data_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) static gboolean 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 +512,6 @@ ip6_route_data_from_dbus(_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; } From c8392018ca19ae88997af2fb8a64a9eb762da394 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 24 Oct 2022 13:22:40 +0200 Subject: [PATCH 06/17] libnm: refactor to-dbus on the client skipping to serialize legacy properties We have 4 legacy properties ("ipv[46].addresses", "ipv[46].routes") that got replaced by newer variants ("ipv[46].address-data", "ipv[46].route-data"). When the client side of libnm (_nm_utils_is_manager_process) serializes those properties, it must only serialize the newer version. That is so that the forward/backward compatibility works as intended. Previously, there was the NM_SETTING_PARAM_LEGACY GObject property flag. That was fine, but not very clear. For one, the legacy part of those properties is only about D-Bus. In particular, they are not deprecated in libnm, keyfile, or nmcli. Thus the name wasn't very clear. Also, in the meantime we have more elaborate property meta data, that goes beyond the meta data of the GObject property. Move NM_SETTING_PARAM_LEGACY to NMSettInfoProperty.to_dbus_only_in_manager_process. I think, this is a better name. It's also right at ``` _nm_properties_override_gobj( 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_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_routes, .from_dbus_fcn = ip6_routes_from_dbus, ), .to_dbus_only_in_manager_process = TRUE, .dbus_deprecated = TRUE, ); ``` that is, directly at the place where we describe how the D-Bus property behaves. --- src/libnm-core-impl/nm-setting-ip-config.c | 17 ++++++++--------- src/libnm-core-impl/nm-setting-ip4-config.c | 6 ++++-- src/libnm-core-impl/nm-setting-ip6-config.c | 6 ++++-- src/libnm-core-impl/nm-setting-private.h | 5 +++-- src/libnm-core-impl/nm-setting.c | 7 +++---- src/libnm-core-intern/nm-core-internal.h | 7 +++++++ 6 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/libnm-core-impl/nm-setting-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c index 78e8ece67e..7d21551853 100644 --- a/src/libnm-core-impl/nm-setting-ip-config.c +++ b/src/libnm-core-impl/nm-setting-ip-config.c @@ -6291,12 +6291,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 +6315,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 +6329,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 a8c3aea75f..80b6d0ea5c 100644 --- a/src/libnm-core-impl/nm-setting-ip4-config.c +++ b/src/libnm-core-impl/nm-setting-ip4-config.c @@ -1001,7 +1001,8 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) .to_dbus_fcn = ip4_addresses_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_addresses, .from_dbus_fcn = ip4_addresses_from_dbus, ), - .dbus_deprecated = TRUE, ); + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE, ); _nm_properties_override_dbus( properties_override, "address-labels", @@ -1139,7 +1140,8 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) .to_dbus_fcn = ip4_routes_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_routes, .from_dbus_fcn = ip4_routes_from_dbus, ), - .dbus_deprecated = TRUE, ); + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: route-data diff --git a/src/libnm-core-impl/nm-setting-ip6-config.c b/src/libnm-core-impl/nm-setting-ip6-config.c index 02bc85c295..16e96895f6 100644 --- a/src/libnm-core-impl/nm-setting-ip6-config.c +++ b/src/libnm-core-impl/nm-setting-ip6-config.c @@ -1010,7 +1010,8 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) .to_dbus_fcn = ip6_addresses_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_addresses, .from_dbus_fcn = ip6_addresses_from_dbus, ), - .dbus_deprecated = TRUE, ); + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: address-data @@ -1129,7 +1130,8 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) .to_dbus_fcn = ip6_routes_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_routes, .from_dbus_fcn = ip6_routes_from_dbus, ), - .dbus_deprecated = TRUE, ); + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: route-data diff --git a/src/libnm-core-impl/nm-setting-private.h b/src/libnm-core-impl/nm-setting-private.h index d38e889222..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 diff --git a/src/libnm-core-impl/nm-setting.c b/src/libnm-core-impl/nm-setting.c index 46ed9ebb79..30fdcc0400 100644 --- a/src/libnm-core-impl/nm-setting.c +++ b/src/libnm-core-impl/nm-setting.c @@ -1737,12 +1737,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; diff --git a/src/libnm-core-intern/nm-core-internal.h b/src/libnm-core-intern/nm-core-internal.h index 563811305c..21c994f033 100644 --- a/src/libnm-core-intern/nm-core-internal.h +++ b/src/libnm-core-intern/nm-core-internal.h @@ -827,6 +827,13 @@ struct _NMSettInfoProperty { * 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, From 3297b079b26d0ce9223f0b45d7bf9a34e0e332c4 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 21 Oct 2022 17:03:54 +0200 Subject: [PATCH 07/17] libnm: rework _nm_setting_use_legacy_property() to minimize dictionary lookups The previous could would first check whether the new property is not set. In almost all cases, the new property is actually set. We can get away with fewer lookups, by checking for the expected things first. --- src/libnm-core-impl/nm-setting.c | 68 ++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 11 deletions(-) diff --git a/src/libnm-core-impl/nm-setting.c b/src/libnm-core-impl/nm-setting.c index 30fdcc0400..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; } /*****************************************************************************/ From 63eaf168d1b8a8cbac4fbeb1d6806cebccbabdb2 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 21 Oct 2022 14:50:32 +0200 Subject: [PATCH 08/17] libnm: add "dns-data" replacement for "ipv[46].dns" properties on D-Bus On D-Bus, the properties "ipv[46].dns" are of type "au" and "aay", respectively. Btw, in particular "au" is bad, because we put there a big-endian number. There is no D-Bus type to represent big endian numbers, so "u" is bad because it can cause endianess problem when trying to remote the D-Bus communication to another host (without explicitly understanding which "u" properties need to swap for endinness). Anyway. The plain addresses are not enough. We soon will also support the DNS-over-TLS server name, or maybe a DoT port number. The previous property was not extensible, so deprecate it and replace it by "dns-data". This one is just a list of strings. That is unlike "address-data" or "route-data", which do a similar thing but are "a{sv}" dictionaries. Here a string is supposed to be sufficient also for the future. Also, because in nmcli and keyfile will will simply have a string format for representing the extra data, not a structure (unlike for routes or addresses). --- src/libnm-core-impl/nm-setting-ip-config.c | 56 +++++++++++++++++++-- src/libnm-core-impl/nm-setting-ip4-config.c | 25 ++++++--- src/libnm-core-impl/nm-setting-ip6-config.c | 25 ++++++--- 3 files changed, 85 insertions(+), 21 deletions(-) diff --git a/src/libnm-core-impl/nm-setting-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c index 7d21551853..7db55c2da1 100644 --- a/src/libnm-core-impl/nm-setting-ip-config.c +++ b/src/libnm-core-impl/nm-setting-ip-config.c @@ -5829,6 +5829,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) { @@ -5915,6 +5944,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], @@ -6156,11 +6200,13 @@ nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass) * * Array of IP addresses of DNS servers. **/ - 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: diff --git a/src/libnm-core-impl/nm-setting-ip4-config.c b/src/libnm-core-impl/nm-setting-ip4-config.c index 80b6d0ea5c..3649df3f90 100644 --- a/src/libnm-core-impl/nm-setting-ip4-config.c +++ b/src/libnm-core-impl/nm-setting-ip4-config.c @@ -395,10 +395,19 @@ ip4_dns_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) return _nm_utils_ip4_dns_to_variant((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 * @@ -964,11 +973,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 diff --git a/src/libnm-core-impl/nm-setting-ip6-config.c b/src/libnm-core-impl/nm-setting-ip6-config.c index 16e96895f6..6a08552c7e 100644 --- a/src/libnm-core-impl/nm-setting-ip6-config.c +++ b/src/libnm-core-impl/nm-setting-ip6-config.c @@ -396,10 +396,19 @@ ip6_dns_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) return _nm_utils_ip6_dns_to_variant((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 * @@ -973,11 +982,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 From d8ea008372fb90309b1f65de810d3742948e9ede Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 17 Oct 2022 10:30:50 +0200 Subject: [PATCH 09/17] wifi/iwd: merge ip[46]_config_to_iwd_config() It is almost always wrong, to split IPv4 and IPv6 behaviors at a high level. Most of the code does something very similar. Combine the two functions. and let them handle the difference closer to where it is. --- src/core/devices/wifi/nm-wifi-utils.c | 164 +++++++++++--------------- 1 file changed, 69 insertions(+), 95 deletions(-) diff --git a/src/core/devices/wifi/nm-wifi-utils.c b/src/core/devices/wifi/nm-wifi-utils.c index 185f8c3da4..b82c9c8385 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,16 @@ 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)); + if (strbuf.len > 0) + nm_str_buf_append_c(&strbuf, ' '); + nm_str_buf_append(&strbuf, nm_setting_ip_config_get_dns(s_ip, i)); } /* 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 +1589,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 +1731,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)) From 053d0a0768be6c67711d5c39154e38a6545e1e8e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 17 Oct 2022 11:04:58 +0200 Subject: [PATCH 10/17] libnm: fix inconsistencies and assertions of "ipv[46].dns" handing - nm_setting_ip_config_add_dns() and nm_setting_ip_config_remove_dns_by_value() used to assert that the provided input is valid. That is not documented and highly problematic. Our parsing code for keyfile, ifcfg-rh and GVariant rightly just call add. Likewise, nmcli. We cannot reasonably expect them to pre-validate the input. Why would we anyway? This is wrong in particular because we usually want the user to be able to construct invalid settings. That is often necessary, because whether a value is valid depends on other values. So in general, we can only validate when all properties are set. We have nm_connection_verify() for that, and asserting/validating during add is very wrong. Note that "add" still filters out duplicates, which may be an inconsistency, but well. Also, the user could set any bogus value via the NM_SETTING_IP_CONFIG_DNS property. Those should be allowed to be removed, and the same values should be allowed to be added via the add method. - add() does a normalization, presumably so that the values look nice. Do the same normalization also when using the NM_SETTING_IP_CONFIG_DNS property setter. - previously, the setter could also set unnormalized values. As nm_setting_ip_config_remove_dns_by_value() looked for the normalized value, you couldn't remove such values anymore. That is fixed now, by letting the property setter do the same normalization. - don't allocate a GPtrArray unless we need it. No need for the extra allocation. - in the property setter, first set the new value before destroying the previous GPtrArray. It might not be possible, but it's not clear to me whether the strv argument from the GValue is always deep-copied or whether it could contain strings to the DNS property itself. --- src/libnm-core-impl/nm-setting-ip-config.c | 138 +++++++++++--------- src/libnm-core-impl/nm-setting-ip4-config.c | 1 - src/libnm-core-impl/nm-setting-ip6-config.c | 1 - src/libnm-core-impl/tests/test-general.c | 6 +- 4 files changed, 80 insertions(+), 66 deletions(-) diff --git a/src/libnm-core-impl/nm-setting-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c index 7db55c2da1..e2bcebf2d5 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,34 @@ 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; + const int addr_family = NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting); + NMIPAddr dns_bin; + char dns_canonical[NM_INET_ADDRSTRLEN]; + + nm_assert(NM_IS_SETTING_IP_CONFIG(setting)); + nm_assert(dns); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + if (valid_ip(addr_family, dns, &dns_bin, NULL)) + dns = nm_inet_ntop(addr_family, &dns_bin, dns_canonical); + + if (nm_strv_ptrarray_contains(priv->dns, dns)) + return FALSE; + + nm_strv_ptrarray_add_string_dup(nm_strv_ptrarray_ensure(&priv->dns), dns); + return TRUE; +} + /** * nm_setting_ip_config_add_dns: * @setting: the #NMSettingIPConfig @@ -4046,36 +4069,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 +4102,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,6 +4117,8 @@ 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) @@ -4117,30 +4127,25 @@ nm_setting_ip_config_remove_dns_by_value(NMSettingIPConfig *setting, const char 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); + addr_family = NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting); - 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; - } - } - return FALSE; + if (valid_ip(addr_family, dns, &dns_bin, NULL)) + dns = nm_inet_ntop(addr_family, &dns_bin, dns_canonical); + + idx = nm_strv_ptrarray_find_first(priv->dns, dns); + if (idx < 0) + return FALSE; + + g_ptr_array_remove_index(nm_strv_ptrarray_ensure(&priv->dns), idx); + _notify(setting, PROP_DNS); + return TRUE; } /** @@ -4158,7 +4163,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); } @@ -5433,20 +5438,22 @@ 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_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; + } } } @@ -6068,9 +6075,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)); @@ -6122,7 +6137,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); @@ -6140,7 +6154,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); diff --git a/src/libnm-core-impl/nm-setting-ip4-config.c b/src/libnm-core-impl/nm-setting-ip4-config.c index 3649df3f90..230425347d 100644 --- a/src/libnm-core-impl/nm-setting-ip4-config.c +++ b/src/libnm-core-impl/nm-setting-ip4-config.c @@ -388,7 +388,6 @@ 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; diff --git a/src/libnm-core-impl/nm-setting-ip6-config.c b/src/libnm-core-impl/nm-setting-ip6-config.c index 6a08552c7e..a3f4d0c9dc 100644 --- a/src/libnm-core-impl/nm-setting-ip6-config.c +++ b/src/libnm-core-impl/nm-setting-ip6-config.c @@ -389,7 +389,6 @@ 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; diff --git a/src/libnm-core-impl/tests/test-general.c b/src/libnm-core-impl/tests/test-general.c index a45ead3b9f..d38a26471a 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(); From a20aae326fc8c230c7ac1504dd8270be2aff2f36 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 20 Oct 2022 12:14:07 +0200 Subject: [PATCH 11/17] nmcli: drop validation of DNS name in nmcli Now, nm_setting_ip_config_add_dns() no longer asserts that the name is a valid DNS nameserver. Instead, that is handled by nm_connection_verify(). Also, the DNS property is going to be extended to support specifying the SNI server name for DNS over TLS. The validation would need to be extended. Instead, drop the validation from nmcli. nmcli often needs to understand what is happening. But in this case, it doesn't need to know (or validate) the exact text. Don't duplicate the validation and let libnm (or the daemon) reject invalid settings. --- src/libnmc-setting/nm-meta-setting-desc.c | 19 ------------------- 1 file changed, 19 deletions(-) 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, ), ), From 6f9090538f39ad48321a17e8acbd03ae9fd0c938 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 17 Oct 2022 09:28:04 +0200 Subject: [PATCH 12/17] dns: accept DoT SNI server name in "ipv[46].dns" settings --- src/core/devices/wifi/nm-wifi-utils.c | 12 +- src/core/nm-l3-config-data.c | 6 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 40 ++-- .../tests/network-scripts/ifcfg-netmask-1 | 3 + .../network-scripts/ifcfg-netmask-1.cexpected | 3 + .../ifcfg-test-wired-static-routes | 2 +- .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 15 +- .../nm-libnm-core-utils.c | 110 +++++++++++ .../nm-libnm-core-utils.h | 29 +++ src/libnm-core-impl/nm-keyfile.c | 13 +- src/libnm-core-impl/nm-setting-ip-config.c | 50 +++-- src/libnm-core-impl/nm-utils.c | 13 +- src/libnm-core-impl/tests/test-general.c | 176 ++++++++++++++++++ src/libnmc-setting/settings-docs.h.in | 4 +- .../generate-docs-nm-settings-nmcli.xml.in | 4 +- 15 files changed, 425 insertions(+), 55 deletions(-) diff --git a/src/core/devices/wifi/nm-wifi-utils.c b/src/core/devices/wifi/nm-wifi-utils.c index b82c9c8385..759fb0cc01 100644 --- a/src/core/devices/wifi/nm-wifi-utils.c +++ b/src/core/devices/wifi/nm-wifi-utils.c @@ -1578,9 +1578,19 @@ ip_config_to_iwd_config(int addr_family, GKeyFile *file, NMSettingIPConfig *s_ip if (num) { nm_str_buf_reset(&strbuf); for (i = 0; i < num; 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_setting_ip_config_get_dns(s_ip, i)); + 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 diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 2d4389323f..7e3d1d931b 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -2844,12 +2844,16 @@ _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 *server_name; 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)) + + if (!nm_utils_dnsname_parse_assert(addr_family, s, NULL, &ip, &server_name)) continue; + + /* TODO: handle server_name. */ nm_l3_config_data_add_nameserver(self, addr_family, &ip); } 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/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-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c index e2bcebf2d5..218a5a745d 100644 --- a/src/libnm-core-impl/nm-setting-ip-config.c +++ b/src/libnm-core-impl/nm-setting-ip-config.c @@ -4041,22 +4041,23 @@ static gboolean _ip_config_add_dns(NMSettingIPConfig *setting, const char *dns) { NMSettingIPConfigPrivate *priv; - const int addr_family = NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting); - NMIPAddr dns_bin; - char dns_canonical[NM_INET_ADDRSTRLEN]; + 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); - if (valid_ip(addr_family, dns, &dns_bin, NULL)) - dns = nm_inet_ntop(addr_family, &dns_bin, dns_canonical); + 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, dns)) + if (nm_strv_ptrarray_contains(priv->dns, s)) return FALSE; - nm_strv_ptrarray_add_string_dup(nm_strv_ptrarray_ensure(&priv->dns), dns); + nm_strv_ptrarray_add_string_take(nm_strv_ptrarray_ensure(&priv->dns), + g_steal_pointer(&s_free) ?: g_strdup(s)); return TRUE; } @@ -4124,9 +4125,6 @@ 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]; gssize idx; g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); @@ -4134,16 +4132,23 @@ nm_setting_ip_config_remove_dns_by_value(NMSettingIPConfig *setting, const char priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - addr_family = NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting); - - if (valid_ip(addr_family, dns, &dns_bin, NULL)) - dns = 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; + + 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); + } + if (idx < 0) return FALSE; - g_ptr_array_remove_index(nm_strv_ptrarray_ensure(&priv->dns), idx); + g_ptr_array_remove_index(priv->dns, idx); _notify(setting, PROP_DNS); return TRUE; } @@ -5442,12 +5447,16 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) 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)) { + 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, - _("%d. DNS server address is invalid"), - (int) (i + 1)); + _("%u. DNS server address is invalid"), + (i + 1u)); g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), @@ -6213,6 +6222,9 @@ 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. **/ obj_properties[PROP_DNS] = g_param_spec_boxed(NM_SETTING_IP_CONFIG_DNS, diff --git a/src/libnm-core-impl/nm-utils.c b/src/libnm-core-impl/nm-utils.c index 77eecea441..adcd1d258b 100644 --- a/src/libnm-core-impl/nm-utils.c +++ b/src/libnm-core-impl/nm-utils.c @@ -1317,8 +1317,12 @@ _nm_utils_ip4_dns_to_variant(const char *const *dns, gssize len) for (i = 0; i < l; i++) { in_addr_t ip; - if (inet_pton(AF_INET, dns[i], &ip) == 1) - g_variant_builder_add(&builder, "u", ip); + /* We can only represent the IP address on the legacy property "ipv4.dns". + * Expose what we can. */ + if (!nm_utils_dnsname_parse(AF_INET, dns[i], NULL, &ip, NULL)) + continue; + + g_variant_builder_add(&builder, "u", ip); } return g_variant_builder_end(&builder); @@ -1639,8 +1643,11 @@ _nm_utils_ip6_dns_to_variant(const char *const *dns, gssize len) for (i = 0; i < l; i++) { struct in6_addr ip; - if (inet_pton(AF_INET6, dns[i], &ip) != 1) + /* We can only represent the IP address on the legacy property "ipv6.dns". + * Expose what we can. */ + if (!nm_utils_dnsname_parse(AF_INET6, dns[i], NULL, &ip, NULL)) continue; + g_variant_builder_add(&builder, "@ay", nm_g_variant_new_ay_in6addr(&ip)); } return g_variant_builder_end(&builder); diff --git a/src/libnm-core-impl/tests/test-general.c b/src/libnm-core-impl/tests/test-general.c index d38a26471a..9317451daf 100644 --- a/src/libnm-core-impl/tests/test-general.c +++ b/src/libnm-core-impl/tests/test-general.c @@ -11165,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 @@ -11511,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/libnmc-setting/settings-docs.h.in b/src/libnmc-setting/settings-docs.h.in index cf87f38c15..3ee4aab51b 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.") #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.") #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..1a26b86a94 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." /> + 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." /> Date: Mon, 17 Oct 2022 12:07:54 +0200 Subject: [PATCH 13/17] core: extend NML3ConfigData:nameserver to track DNS as string The DNS name can now also contain the DoT server name. It's not longer a binary IP address only. Extend NML3ConfigData to account for that. To track the additional data, use the string representation. The alternative to have a separate type that contains the parsed information would be cumbersome too. --- src/core/devices/nm-device.c | 10 +- src/core/devices/wifi/nm-device-iwd.c | 2 +- src/core/devices/wwan/nm-modem-broadband.c | 4 +- src/core/devices/wwan/nm-modem-ofono.c | 2 +- src/core/dhcp/nm-dhcp-nettools.c | 2 +- src/core/dhcp/nm-dhcp-systemd.c | 2 +- src/core/dhcp/nm-dhcp-utils.c | 4 +- src/core/dhcp/tests/test-dhcp-utils.c | 7 +- src/core/dns/nm-dns-dnsmasq.c | 24 ++--- src/core/dns/nm-dns-manager.c | 72 +++++++------- src/core/dns/nm-dns-systemd-resolved.c | 26 ++--- src/core/dnsmasq/nm-dnsmasq-manager.c | 10 +- src/core/ndisc/nm-ndisc.c | 36 ++++--- src/core/nm-dispatcher.c | 16 +-- src/core/nm-ip-config.c | 110 ++++++++++++--------- src/core/nm-l3-config-data.c | 107 ++++++++++---------- src/core/nm-l3-config-data.h | 12 ++- src/core/ppp/nm-ppp-manager.c | 2 +- src/core/vpn/nm-vpn-connection.c | 4 +- 19 files changed, 248 insertions(+), 204 deletions(-) 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/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..6caa637652 100644 --- a/src/core/dns/nm-dns-systemd-resolved.c +++ b/src/core/dns/nm-dns-systemd-resolved.c @@ -343,13 +343,13 @@ update_add_ip_config(NMDnsSystemdResolved *self, GVariantBuilder *domains, const NMDnsConfigIPData *ip_data) { - gsize addr_size; - guint n; - guint i; - gboolean is_routing; - const char *domain; - gboolean has_config = FALSE; - gconstpointer nameservers; + 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,14 +361,16 @@ 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++) { + NMIPAddr a; + + if (!nm_utils_dnsname_parse_assert(ip_data->addr_family, strarr[i], NULL, &a, NULL)) + continue; + 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_add_value(dns, nm_g_variant_new_ay((gconstpointer) &a, addr_size)); g_variant_builder_close(dns); has_config = TRUE; } 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 7e3d1d931b..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,19 +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 *server_name; - const char *s; - NMIPAddr ip; - - s = nm_setting_ip_config_get_dns(s_ip, i); - - if (!nm_utils_dnsname_parse_assert(addr_family, s, NULL, &ip, &server_name)) - continue; - - /* TODO: handle server_name. */ - 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++) { @@ -3210,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/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); From ba3394273400691553570baed9a4a3ee33faf017 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 17 Oct 2022 21:23:51 +0200 Subject: [PATCH 14/17] dns/resolved: cleanup detection of supported API in "nm-dns-systemd-resolved.c" - rename the "has_" variables to have the same name as the API that they check. - do an if-else-if for checking the operation when detecting support. This just feels nicer. No strong reasons. --- src/core/dns/nm-dns-systemd-resolved.c | 54 +++++++++++++------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/src/core/dns/nm-dns-systemd-resolved.c b/src/core/dns/nm-dns-systemd-resolved.c index 6caa637652..b8a8785605 100644 --- a/src/core/dns/nm-dns-systemd-resolved.c +++ b/src/core/dns/nm-dns-systemd-resolved.c @@ -94,8 +94,8 @@ typedef struct { * 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; + NMTernary has_set_link_default_route : 3; + NMTernary has_set_link_dns_over_tls : 3; } NMDnsSystemdResolvedPrivate; struct _NMDnsSystemdResolved { @@ -290,30 +290,32 @@ 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"); + } } 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"); + } } goto out_dec_pending; } @@ -633,9 +635,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 @@ -800,8 +802,8 @@ 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; } send_updates(self); @@ -1160,8 +1162,8 @@ 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; c_list_init(&priv->request_queue_lst_head); c_list_init(&priv->handle_lst_head); From d5be1c706ed4f0943b6cf36d142e28e1c0216f6c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 17 Oct 2022 21:06:49 +0200 Subject: [PATCH 15/17] dns/resolved: set DoT server name (SNI) in systemd-resolved Unfortunately, for this we require SetLinkDNSEx() API from v246. That adds extra complexity. If the configuration contains no server name, we continue using SetLinkDNS(). Otherwise, at first we try using SetLinkDNSEx(). We will notice if that method is unsupported, reconfigure with SetLinkDNS(), and set a flag to not try that again. --- src/core/dns/nm-dns-systemd-resolved.c | 139 ++++++++++++++---- src/libnm-core-impl/nm-setting-ip-config.c | 3 +- src/libnmc-setting/settings-docs.h.in | 4 +- .../generate-docs-nm-settings-nmcli.xml.in | 4 +- 4 files changed, 116 insertions(+), 34 deletions(-) diff --git a/src/core/dns/nm-dns-systemd-resolved.c b/src/core/dns/nm-dns-systemd-resolved.c index b8a8785605..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 - */ + + /* 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; @@ -300,6 +303,11 @@ call_done(GObject *source, GAsyncResult *r, gpointer user_data) 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; @@ -316,6 +324,21 @@ call_done(GObject *source, GAsyncResult *r, gpointer user_data) 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; } @@ -337,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; - const char *const *strarr; + 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); @@ -365,29 +396,50 @@ update_add_ip_config(NMDnsSystemdResolved *self, strarr = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &n); for (i = 0; i < n; i++) { - NMIPAddr a; + const char *server_name; + NMIPAddr a; - if (!nm_utils_dnsname_parse_assert(ip_data->addr_family, strarr[i], NULL, &a, NULL)) + if (!nm_utils_dnsname_parse_assert(ip_data->addr_family, strarr[i], NULL, &a, &server_name)) continue; - 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); + 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; @@ -410,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; @@ -421,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); @@ -434,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) @@ -452,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"; @@ -517,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, @@ -804,6 +883,7 @@ name_owner_changed(NMDnsSystemdResolved *self, const char *owner) } else { 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); @@ -1164,6 +1244,7 @@ nm_dns_systemd_resolved_init(NMDnsSystemdResolved *self) 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/libnm-core-impl/nm-setting-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c index 218a5a745d..4c4d09bd59 100644 --- a/src/libnm-core-impl/nm-setting-ip-config.c +++ b/src/libnm-core-impl/nm-setting-ip-config.c @@ -6224,7 +6224,8 @@ nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass) * 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. + * "#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, diff --git a/src/libnmc-setting/settings-docs.h.in b/src/libnmc-setting/settings-docs.h.in index 3ee4aab51b..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. For DoT (DNS over TLS), the SNI server name can be specified by appending \"#example.com\" to the IP address of the DNS server.") +#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. For DoT (DNS over TLS), the SNI server name can be specified by appending \"#example.com\" to the IP address of the DNS server.") +#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 1a26b86a94..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." /> Date: Mon, 24 Oct 2022 18:36:29 +0200 Subject: [PATCH 16/17] libnm: unify IPv4/IPv6 forms of DNS to GVariant helper --- src/libnm-core-impl/nm-setting-ip4-config.c | 2 +- src/libnm-core-impl/nm-setting-ip6-config.c | 2 +- src/libnm-core-impl/nm-utils-private.h | 3 +- src/libnm-core-impl/nm-utils.c | 78 ++++++++------------- 4 files changed, 31 insertions(+), 54 deletions(-) diff --git a/src/libnm-core-impl/nm-setting-ip4-config.c b/src/libnm-core-impl/nm-setting-ip4-config.c index 230425347d..ccc3760e06 100644 --- a/src/libnm-core-impl/nm-setting-ip4-config.c +++ b/src/libnm-core-impl/nm-setting-ip4-config.c @@ -391,7 +391,7 @@ ip4_dns_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) 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 gboolean diff --git a/src/libnm-core-impl/nm-setting-ip6-config.c b/src/libnm-core-impl/nm-setting-ip6-config.c index a3f4d0c9dc..a87cfb0a28 100644 --- a/src/libnm-core-impl/nm-setting-ip6-config.c +++ b/src/libnm-core-impl/nm-setting-ip6-config.c @@ -392,7 +392,7 @@ ip6_dns_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) 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 gboolean 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 adcd1d258b..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,17 +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; - /* We can only represent the IP address on the legacy property "ipv4.dns". + /* We can only represent the IP address on the legacy property "ipv[46].dns". * Expose what we can. */ - if (!nm_utils_dnsname_parse(AF_INET, dns[i], NULL, &ip, NULL)) + if (!nm_utils_dnsname_parse(addr_family, dns[i], NULL, &ip, NULL)) continue; - g_variant_builder_add(&builder, "u", ip); + 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); @@ -1610,49 +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; - - /* We can only represent the IP address on the legacy property "ipv6.dns". - * Expose what we can. */ - if (!nm_utils_dnsname_parse(AF_INET6, dns[i], NULL, &ip, NULL)) - 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' From 3970489219ed957a98be1a92fda8c1fab42076bf Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 27 Oct 2022 09:15:20 +0200 Subject: [PATCH 17/17] NEWS: update --- NEWS | 2 ++ 1 file changed, 2 insertions(+) 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