From e74c568b07b50b97873fb4ee1d776dedefbd54d6 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Fri, 1 Oct 2021 23:05:04 +0200 Subject: New upstream version 1.32.12 --- src/core/nm-l3-config-data.c | 342 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 290 insertions(+), 52 deletions(-) (limited to 'src/core/nm-l3-config-data.c') diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 5f9af7ac..f2ec040b 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -8,11 +8,12 @@ #include #include -#include "nm-glib-aux/nm-enum-utils.h" -#include "nm-core-internal.h" -#include "platform/nm-platform.h" -#include "nm-platform/nm-platform-utils.h" -#include "platform/nmp-object.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-glib-aux/nm-enum-utils.h" +#include "libnm-glib-aux/nm-ref-string.h" +#include "libnm-platform/nm-platform-utils.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nmp-object.h" #include "NetworkManagerUtils.h" /*****************************************************************************/ @@ -52,7 +53,9 @@ struct _NML3ConfigData { GArray *wins; GArray *nis_servers; - char *nis_domain; + NMRefString *nis_domain; + NMRefString *proxy_pac_url; + NMRefString *proxy_pac_script; union { struct { @@ -130,6 +133,10 @@ struct _NML3ConfigData { NMTernary metered : 3; + NMTernary proxy_browser_only : 3; + + NMProxyConfigMethod proxy_method : 4; + NMSettingIP6ConfigPrivacy ip6_privacy : 4; bool is_sealed : 1; @@ -251,7 +258,7 @@ _garray_inaddr_get(GArray *arr, guint *out_len) } static gconstpointer -_garray_inaddr_at(GArray *arr, guint idx, gboolean IS_IPv4) +_garray_inaddr_at(GArray *arr, gboolean IS_IPv4, guint idx) { nm_assert(arr); nm_assert(idx < arr->len); @@ -507,7 +514,7 @@ nm_l3_config_data_log(const NML3ConfigData *self, _nm_utils_inet4_ntop(g_array_index(self->nis_servers, in_addr_t, i), sbuf_addr)); } if (self->nis_domain) - _L("nis-domain: %s", self->nis_domain); + _L("nis-domain: %s", self->nis_domain->str); } if (self->dhcp_lease_x[IS_IPv4]) { @@ -556,10 +563,20 @@ nm_l3_config_data_log(const NML3ConfigData *self, NULL))); } - if (self->metered != NM_TERNARY_DEFAULT) { + if (self->metered != NM_TERNARY_DEFAULT) _L("metered: %s", self->metered ? "yes" : "no"); - } + if (self->proxy_browser_only != NM_TERNARY_DEFAULT) + _L("proxy-browser-only: %s", self->proxy_browser_only ? "yes" : "no"); + + if (self->proxy_method != NM_PROXY_CONFIG_METHOD_UNKNOWN) + _L("proxy-method: %s", self->proxy_method == NM_PROXY_CONFIG_METHOD_AUTO ? "auto" : "none"); + + if (self->proxy_pac_url) + _L("proxy-pac-url: %s", self->proxy_pac_url->str); + + if (self->proxy_pac_script) + _L("proxy-pac-script: %s", self->proxy_pac_script->str); #undef _L } @@ -642,6 +659,8 @@ nm_l3_config_data_new(NMDedupMultiIndex *multi_idx, int ifindex) .llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT, .flags = NM_L3_CONFIG_DAT_FLAGS_NONE, .metered = NM_TERNARY_DEFAULT, + .proxy_browser_only = NM_TERNARY_DEFAULT, + .proxy_method = NM_PROXY_CONFIG_METHOD_UNKNOWN, .route_table_sync_4 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE, .route_table_sync_6 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE, .source = NM_IP_CONFIG_SOURCE_UNKNOWN, @@ -742,7 +761,9 @@ nm_l3_config_data_unref(const NML3ConfigData *self) nm_dedup_multi_index_unref(mutable->multi_idx); - g_free(mutable->nis_domain); + nm_ref_string_unref(mutable->nis_domain); + nm_ref_string_unref(mutable->proxy_pac_url); + nm_ref_string_unref(mutable->proxy_pac_script); nm_g_slice_free(mutable); } @@ -796,8 +817,8 @@ nm_l3_config_data_lookup_route(const NML3ConfigData * self, int addr_family, const NMPlatformIPRoute *needle) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); - NMPObject obj_stack; + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMPObject obj_stack; nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); nm_assert_addr_family(addr_family); @@ -895,7 +916,7 @@ nmtst_l3_config_data_get_obj_at(const NML3ConfigData *self, NMPObjectType obj_ty gboolean nm_l3_config_data_has_routes_with_type_local(const NML3ConfigData *self, int addr_family) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); NML3ConfigData * self_mutable; NMDedupMultiIter iter; const NMPObject *obj; @@ -1178,7 +1199,7 @@ _l3_config_best_default_route_find_better(const NMPObject *obj_cur, const NMPObj return c < 0 ? obj_cur : obj_cmp; /* as last resort, compare pointers. */ - if (((uintptr_t)((void *) (obj_cmp))) < ((uintptr_t)((void *) (obj_cur)))) + if (((uintptr_t) ((void *) (obj_cmp))) < ((uintptr_t) ((void *) (obj_cur)))) return obj_cmp; } } @@ -1230,7 +1251,7 @@ nm_l3_config_data_add_route_full(NML3ConfigData * self, const NMPObject ** out_obj_new, gboolean * out_changed_best_default_route) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); nm_auto_nmpobj const NMPObject *obj_old = NULL; const NMPObject * obj_new_2; gboolean changed = FALSE; @@ -1364,6 +1385,14 @@ nm_l3_config_data_add_wins(NML3ConfigData *self, in_addr_t wins) return _garray_inaddr_add(&self->wins, AF_INET, &wins); } +const in_addr_t * +nm_l3_config_data_get_nis_servers(const NML3ConfigData *self, guint *out_len) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return _garray_inaddr_get(self->nis_servers, out_len); +} + gboolean nm_l3_config_data_add_nis_server(NML3ConfigData *self, in_addr_t nis_server) { @@ -1372,18 +1401,26 @@ nm_l3_config_data_add_nis_server(NML3ConfigData *self, in_addr_t nis_server) return _garray_inaddr_add(&self->nis_servers, AF_INET, &nis_server); } +const char * +nm_l3_config_data_get_nis_domain(const NML3ConfigData *self) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return nm_ref_string_get_str(self->nis_domain); +} + gboolean nm_l3_config_data_set_nis_domain(NML3ConfigData *self, const char *nis_domain) { nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); - return nm_utils_strdup_reset(&self->nis_domain, nis_domain); + return nm_ref_string_reset_str(&self->nis_domain, nis_domain); } const char *const * nm_l3_config_data_get_domains(const NML3ConfigData *self, int addr_family, guint *out_len) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); nm_assert_addr_family(addr_family); nm_assert(out_len); @@ -1452,10 +1489,57 @@ nm_l3_config_data_add_dns_option(NML3ConfigData *self, int addr_family, const ch return TRUE; } +const char *const * +nm_l3_config_data_get_dns_options(const NML3ConfigData *self, int addr_family, guint *out_len) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + nm_assert_addr_family(addr_family); + nm_assert(out_len); + + return nm_strv_ptrarray_get_unsafe(self->dns_options_x[NM_IS_IPv4(addr_family)], out_len); +} + +gboolean +nm_l3_config_data_get_dns_priority(const NML3ConfigData *self, int addr_family, int *out_prio) +{ + switch (addr_family) { + case AF_UNSPEC: + if (NM_FLAGS_ANY(self->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY_4)) { + if (NM_FLAGS_ANY(self->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY_6)) { + NM_SET_OUT(out_prio, MIN(self->dns_priority_4, self->dns_priority_6)); + return TRUE; + } + NM_SET_OUT(out_prio, self->dns_priority_4); + return TRUE; + } + if (NM_FLAGS_ANY(self->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY_6)) { + NM_SET_OUT(out_prio, self->dns_priority_6); + return TRUE; + } + break; + case AF_INET: + if (NM_FLAGS_ANY(self->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY_4)) { + NM_SET_OUT(out_prio, self->dns_priority_4); + return TRUE; + } + break; + case AF_INET6: + if (NM_FLAGS_ANY(self->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY_6)) { + NM_SET_OUT(out_prio, self->dns_priority_6); + return TRUE; + } + break; + default: + nm_assert_not_reached(); + } + NM_SET_OUT(out_prio, 0); + return FALSE; +} + gboolean nm_l3_config_data_set_dns_priority(NML3ConfigData *self, int addr_family, int dns_priority) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); const NML3ConfigDatFlags has_dns_priority_flag = NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY(IS_IPv4); @@ -1471,6 +1555,14 @@ nm_l3_config_data_set_dns_priority(NML3ConfigData *self, int addr_family, int dn return TRUE; } +NMSettingConnectionMdns +nm_l3_config_data_get_mdns(const NML3ConfigData *self) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return self->mdns; +} + gboolean nm_l3_config_data_set_mdns(NML3ConfigData *self, NMSettingConnectionMdns mdns) { @@ -1483,6 +1575,14 @@ nm_l3_config_data_set_mdns(NML3ConfigData *self, NMSettingConnectionMdns mdns) return TRUE; } +NMSettingConnectionLlmnr +nm_l3_config_data_get_llmnr(const NML3ConfigData *self) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return self->llmnr; +} + gboolean nm_l3_config_data_set_llmnr(NML3ConfigData *self, NMSettingConnectionLlmnr llmnr) { @@ -1509,7 +1609,7 @@ nm_l3_config_data_set_route_table_sync(NML3ConfigData * self, int addr_family, NMIPRouteTableSyncMode route_table_sync) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); nm_assert_addr_family(addr_family); @@ -1533,7 +1633,7 @@ gboolean nm_l3_config_data_set_metered(NML3ConfigData *self, NMTernary metered) { nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); - nm_assert(NM_IN_SET(metered, NM_TERNARY_DEFAULT, NM_TERNARY_FALSE, NM_TERNARY_TRUE)); + nm_assert_is_ternary(metered); if (self->metered == metered) return FALSE; @@ -1619,6 +1719,83 @@ nm_l3_config_data_set_ip6_privacy(NML3ConfigData *self, NMSettingIP6ConfigPrivac return TRUE; } +NMProxyConfigMethod +nm_l3_config_data_get_proxy_method(const NML3ConfigData *self) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return self->proxy_method; +} + +gboolean +nm_l3_config_data_set_proxy_method(NML3ConfigData *self, NMProxyConfigMethod value) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(NM_IN_SET(value, + NM_PROXY_CONFIG_METHOD_UNKNOWN, + NM_PROXY_CONFIG_METHOD_NONE, + NM_PROXY_CONFIG_METHOD_AUTO)); + + if (self->proxy_method == value) + return FALSE; + + self->proxy_method = value; + return TRUE; +} + +NMTernary +nm_l3_config_data_get_proxy_browser_only(const NML3ConfigData *self) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return self->proxy_browser_only; +} + +gboolean +nm_l3_config_data_set_proxy_browser_only(NML3ConfigData *self, NMTernary value) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert_is_ternary(value); + + if (value == self->proxy_browser_only) + return FALSE; + + self->proxy_browser_only = value; + return TRUE; +} + +const char * +nm_l3_config_data_get_proxy_pac_url(const NML3ConfigData *self) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return nm_ref_string_get_str(self->proxy_pac_url); +} + +gboolean +nm_l3_config_data_set_proxy_pac_url(NML3ConfigData *self, const char *value) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + + return nm_ref_string_reset_str(&self->proxy_pac_url, value); +} + +const char * +nm_l3_config_data_get_proxy_pac_script(const NML3ConfigData *self) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return nm_ref_string_get_str(self->proxy_pac_script); +} + +gboolean +nm_l3_config_data_set_proxy_pac_script(NML3ConfigData *self, const char *value) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + + return nm_ref_string_reset_str(&self->proxy_pac_script, value); +} + gboolean nm_l3_config_data_get_ndisc_hop_limit(const NML3ConfigData *self, int *out_val) { @@ -1780,13 +1957,16 @@ _dedup_multi_index_cmp(const NML3ConfigData *a, const NML3ConfigData *b, NMPObje } int -nm_l3_config_data_cmp(const NML3ConfigData *a, const NML3ConfigData *b) +nm_l3_config_data_cmp_full(const NML3ConfigData *a, + const NML3ConfigData *b, + NML3ConfigCmpFlags cmp_flags) { int IS_IPv4; NM_CMP_SELF(a, b); - NM_CMP_DIRECT(a->ifindex, b->ifindex); + if (!NM_FLAGS_HAS(cmp_flags, NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX)) + NM_CMP_DIRECT(a->ifindex, b->ifindex); NM_CMP_DIRECT(a->flags, b->flags); @@ -1823,12 +2003,16 @@ nm_l3_config_data_cmp(const NML3ConfigData *a, const NML3ConfigData *b) NM_CMP_RETURN(_garray_inaddr_cmp(a->wins, b->wins, AF_INET)); NM_CMP_RETURN(_garray_inaddr_cmp(a->nis_servers, b->nis_servers, AF_INET)); - NM_CMP_FIELD_STR0(a, b, nis_domain); + NM_CMP_DIRECT_REF_STRING(a->nis_domain, b->nis_domain); NM_CMP_DIRECT(a->mdns, b->mdns); NM_CMP_DIRECT(a->llmnr, b->llmnr); NM_CMP_DIRECT(a->mtu, b->mtu); NM_CMP_DIRECT(a->ip6_mtu, b->ip6_mtu); NM_CMP_DIRECT_UNSAFE(a->metered, b->metered); + NM_CMP_DIRECT_UNSAFE(a->proxy_browser_only, b->proxy_browser_only); + NM_CMP_DIRECT_UNSAFE(a->proxy_method, b->proxy_method); + NM_CMP_DIRECT_REF_STRING(a->proxy_pac_url, b->proxy_pac_url); + NM_CMP_DIRECT_REF_STRING(a->proxy_pac_script, b->proxy_pac_script); NM_CMP_DIRECT_UNSAFE(a->ip6_privacy, b->ip6_privacy); NM_CMP_DIRECT_UNSAFE(a->ndisc_hop_limit_set, b->ndisc_hop_limit_set); @@ -1863,7 +2047,7 @@ _data_get_direct_route_for_host(const NML3ConfigData *self, gconstpointer host, guint32 route_table) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); const NMPObject * best_route_obj = NULL; const NMPlatformIPXRoute *best_route = NULL; const NMPObject * item_obj; @@ -1998,7 +2182,7 @@ nm_l3_config_data_add_dependent_routes(NML3ConfigData *self, guint32 route_metric, gboolean is_vrf) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); gs_unref_ptrarray GPtrArray *extra_onlink_routes = NULL; const NMPObject * my_addr_obj; const NMPObject * my_route_obj; @@ -2209,7 +2393,7 @@ _init_from_connection_ip(NML3ConfigData *self, guint32 route_table, guint32 route_metric) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); NMSettingIPConfig *s_ip; guint naddresses; guint nroutes; @@ -2388,11 +2572,28 @@ nm_l3_config_data_new_from_connection(NMDedupMultiIndex *multi_idx, guint32 route_metric_6) { NML3ConfigData *self; + NMSettingProxy *s_proxy; self = nm_l3_config_data_new(multi_idx, ifindex); _init_from_connection_ip(self, AF_INET, connection, route_table_4, route_metric_4); _init_from_connection_ip(self, AF_INET6, connection, route_table_6, route_metric_6); + + s_proxy = _nm_connection_get_setting(connection, NM_TYPE_SETTING_PROXY); + if (s_proxy) { + switch (nm_setting_proxy_get_method(s_proxy)) { + case NM_SETTING_PROXY_METHOD_NONE: + self->proxy_method = NM_PROXY_CONFIG_METHOD_NONE; + break; + case NM_SETTING_PROXY_METHOD_AUTO: + self->proxy_method = NM_PROXY_CONFIG_METHOD_AUTO; + self->proxy_pac_url = nm_ref_string_new(nm_setting_proxy_get_pac_url(s_proxy)); + self->proxy_pac_script = nm_ref_string_new(nm_setting_proxy_get_pac_script(s_proxy)); + break; + } + self->proxy_browser_only = (!!nm_setting_proxy_get_browser_only(s_proxy)); + } + return self; } @@ -2433,7 +2634,7 @@ _init_from_platform(NML3ConfigData * self, NMPlatform * platform, NMSettingIP6ConfigPrivacy ipv6_privacy_rfc4941) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); const NMDedupMultiHeadEntry *head_entry; const NMPObject * plobj = NULL; NMDedupMultiIter iter; @@ -2534,6 +2735,9 @@ nm_l3_config_data_merge(NML3ConfigData * self, nm_assert(default_route_table_x[1] != 0); nm_assert(default_route_metric_x[0] != 0); /* IPv6 route metric cannot be zero. */ + nm_assert(!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_CLONE) + || nm_utils_is_power_of_two(merge_flags)); + for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { const int addr_family = IS_IPv4 ? AF_INET : AF_INET6; const NML3ConfigDatFlags has_dns_priority_flag = @@ -2588,28 +2792,31 @@ nm_l3_config_data_merge(NML3ConfigData * self, } \ G_STMT_END - if (r_src->table_any) { - _ensure_r(); - r.rx.table_any = FALSE; - r.rx.table_coerced = default_route_table_x[IS_IPv4]; - } - - if (r_src->metric_any) { - _ensure_r(); - r.rx.metric_any = FALSE; - r.rx.metric = nm_add_clamped_u32(r.rx.metric, default_route_metric_x[IS_IPv4]); - } + if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_CLONE)) { + if (r_src->table_any) { + _ensure_r(); + r.rx.table_any = FALSE; + r.rx.table_coerced = default_route_table_x[IS_IPv4]; + } - if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r_src)) { - if (NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES) - && !NM_FLAGS_HAS(src->flags, - NM_L3_CONFIG_DAT_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES)) - continue; - if (default_route_penalty_x && default_route_penalty_x[IS_IPv4] > 0) { + if (r_src->metric_any) { _ensure_r(); + r.rx.metric_any = FALSE; r.rx.metric = - nm_utils_ip_route_metric_penalize(r.rx.metric, - default_route_penalty_x[IS_IPv4]); + nm_add_clamped_u32(r.rx.metric, default_route_metric_x[IS_IPv4]); + } + + if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r_src)) { + if (NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES) + && !NM_FLAGS_HAS(src->flags, + NM_L3_CONFIG_DAT_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES)) + continue; + if (default_route_penalty_x && default_route_penalty_x[IS_IPv4] > 0) { + _ensure_r(); + r.rx.metric = + nm_utils_ip_route_metric_penalize(r.rx.metric, + default_route_penalty_x[IS_IPv4]); + } } } @@ -2653,8 +2860,8 @@ nm_l3_config_data_merge(NML3ConfigData * self, _garray_inaddr_merge(&self->wins, src->wins, AF_INET); _garray_inaddr_merge(&self->nis_servers, src->nis_servers, AF_INET); - if (!self->nis_domain && src->nis_domain) - self->nis_domain = g_strdup(src->nis_domain); + if (!self->nis_domain) + self->nis_domain = nm_ref_string_ref(src->nis_domain); } if (self->mdns == NM_SETTING_CONNECTION_MDNS_DEFAULT) @@ -2665,6 +2872,18 @@ nm_l3_config_data_merge(NML3ConfigData * self, self->metered = NM_MAX((NMTernary) self->metered, (NMTernary) src->metered); + if (self->proxy_method == NM_PROXY_CONFIG_METHOD_UNKNOWN) + self->proxy_method = src->proxy_method; + + if (self->proxy_browser_only == NM_TERNARY_DEFAULT) + self->proxy_browser_only = src->proxy_browser_only; + + if (!self->proxy_pac_url) + self->proxy_pac_url = nm_ref_string_ref(src->proxy_pac_url); + + if (!self->proxy_pac_script) + self->proxy_pac_script = nm_ref_string_ref(src->proxy_pac_script); + if (self->ip6_privacy == NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN) self->ip6_privacy = src->ip6_privacy; @@ -2689,8 +2908,16 @@ nm_l3_config_data_merge(NML3ConfigData * self, if (self->ip6_mtu == 0u) self->ip6_mtu = src->ip6_mtu; - /* self->source does not get merged. */ - /* self->dhcp_lease_x does not get merged. */ + if (NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_CLONE)) { + _nm_unused nm_auto_unref_dhcplease NMDhcpLease *dhcp_lease_6 = + g_steal_pointer(&self->dhcp_lease_x[0]); + _nm_unused nm_auto_unref_dhcplease NMDhcpLease *dhcp_lease_4 = + g_steal_pointer(&self->dhcp_lease_x[1]); + + self->source = src->source; + self->dhcp_lease_x[0] = nm_dhcp_lease_ref(self->dhcp_lease_x[0]); + self->dhcp_lease_x[1] = nm_dhcp_lease_ref(self->dhcp_lease_x[1]); + } } NML3ConfigData * @@ -2707,6 +2934,17 @@ nm_l3_config_data_new_clone(const NML3ConfigData *src, int ifindex) ifindex = src->ifindex; self = nm_l3_config_data_new(src->multi_idx, ifindex); - nm_l3_config_data_merge(self, src, NM_L3_CONFIG_MERGE_FLAGS_NONE, NULL, NULL, NULL, NULL, NULL); + nm_l3_config_data_merge(self, + src, + NM_L3_CONFIG_MERGE_FLAGS_CLONE, + NULL, + NULL, + NULL, + NULL, + NULL); + + nm_assert(nm_l3_config_data_cmp_full(src, self, NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX) == 0); + nm_assert(nm_l3_config_data_get_ifindex(self) == ifindex); + return self; } -- cgit 1.3.0-6-gf8a5 From 88c227d90a6b7b388c5c85d72802a0ca8f05ed5c Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Thu, 13 Jan 2022 22:30:39 +0100 Subject: New upstream version 1.34.0 --- src/core/nm-l3-config-data.c | 701 ++++++++++++++++++++++++++----------------- 1 file changed, 428 insertions(+), 273 deletions(-) (limited to 'src/core/nm-l3-config-data.c') diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index f2ec040b..033c8942 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -131,6 +131,14 @@ struct _NML3ConfigData { guint32 ndisc_reachable_time_msec_val; guint32 ndisc_retrans_timer_msec_val; + union { + struct { + NMOptionBool never_default_6; + NMOptionBool never_default_4; + }; + NMOptionBool never_default_x[2]; + }; + NMTernary metered : 3; NMTernary proxy_browser_only : 3; @@ -323,7 +331,7 @@ _strv_ptrarray_merge(GPtrArray **p_dst, const GPtrArray *src) const char *s = src->pdata[i]; if (dst_initial_len > 0 - && nm_utils_strv_find_first((char **) ((*p_dst)->pdata), dst_initial_len, s) >= 0) + && nm_strv_find_first((const char *const *) ((*p_dst)->pdata), dst_initial_len, s) >= 0) continue; g_ptr_array_add(*p_dst, g_strdup(s)); @@ -439,27 +447,23 @@ nm_l3_config_data_log(const NML3ConfigData *self, const char *s_prefix = "ndisc: "; if (self->ndisc_hop_limit_set) { - nm_utils_strbuf_append(&p, - &l, - "%shop-limit=%d", - s_prefix, - self->ndisc_hop_limit_val); + nm_strbuf_append(&p, &l, "%shop-limit=%d", s_prefix, self->ndisc_hop_limit_val); s_prefix = ", "; } if (self->ndisc_reachable_time_msec_set) { - nm_utils_strbuf_append(&p, - &l, - "%sreachable-time-msec=%u", - s_prefix, - self->ndisc_reachable_time_msec_val); + nm_strbuf_append(&p, + &l, + "%sreachable-time-msec=%u", + s_prefix, + self->ndisc_reachable_time_msec_val); s_prefix = ", "; } if (self->ndisc_retrans_timer_msec_set) { - nm_utils_strbuf_append(&p, - &l, - "%sretrans-timer-msec=%u", - s_prefix, - self->ndisc_retrans_timer_msec_val); + nm_strbuf_append(&p, + &l, + "%sretrans-timer-msec=%u", + s_prefix, + self->ndisc_retrans_timer_msec_val); s_prefix = ", "; } _L("%s", sbuf); @@ -541,6 +545,9 @@ nm_l3_config_data_log(const NML3ConfigData *self, options[i].value_str); } } + + if (self->never_default_x[IS_IPv4] != NM_OPTION_BOOL_DEFAULT) + _L("never-default: %s", self->never_default_x[IS_IPv4] ? "yes" : "no"); } if (self->mdns != NM_SETTING_CONNECTION_MDNS_DEFAULT) { @@ -643,12 +650,14 @@ _idx_type_init(DedupMultiIdxType *idx_type, NMPObjectType obj_type) } NML3ConfigData * -nm_l3_config_data_new(NMDedupMultiIndex *multi_idx, int ifindex) +nm_l3_config_data_new(NMDedupMultiIndex *multi_idx, int ifindex, NMIPConfigSource source) { NML3ConfigData *self; nm_assert(multi_idx); nm_assert(ifindex > 0); + nm_assert(source == NM_IP_CONFIG_SOURCE_UNKNOWN + || (source >= NM_IP_CONFIG_SOURCE_KERNEL && source <= NM_IP_CONFIG_SOURCE_USER)); self = g_slice_new(NML3ConfigData); *self = (NML3ConfigData){ @@ -663,7 +672,9 @@ nm_l3_config_data_new(NMDedupMultiIndex *multi_idx, int ifindex) .proxy_method = NM_PROXY_CONFIG_METHOD_UNKNOWN, .route_table_sync_4 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE, .route_table_sync_6 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE, - .source = NM_IP_CONFIG_SOURCE_UNKNOWN, + .never_default_6 = NM_OPTION_BOOL_DEFAULT, + .never_default_4 = NM_OPTION_BOOL_DEFAULT, + .source = source, .ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, .ndisc_hop_limit_set = FALSE, .ndisc_reachable_time_msec_set = FALSE, @@ -691,17 +702,21 @@ nm_l3_config_data_ref(const NML3ConfigData *self) const NML3ConfigData * nm_l3_config_data_ref_and_seal(const NML3ConfigData *self) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); - ((NML3ConfigData *) self)->is_sealed = TRUE; - ((NML3ConfigData *) self)->ref_count++; + if (self) { + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + ((NML3ConfigData *) self)->is_sealed = TRUE; + ((NML3ConfigData *) self)->ref_count++; + } return self; } const NML3ConfigData * nm_l3_config_data_seal(const NML3ConfigData *self) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); - ((NML3ConfigData *) self)->is_sealed = TRUE; + if (self) { + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + ((NML3ConfigData *) self)->is_sealed = TRUE; + } return self; } @@ -871,6 +886,26 @@ nm_l3_config_data_lookup_obj(const NML3ConfigData *self, const NMPObject *obj) return nm_dedup_multi_index_lookup_obj(self->multi_idx, idx, obj); } +const NMPlatformIP4Address * +nm_l3_config_data_lookup_address_4(const NML3ConfigData *self, + in_addr_t addr, + guint8 plen, + in_addr_t peer_addr) +{ + const NMDedupMultiEntry *head; + NMPObject obj_stack; + + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + nmp_object_stackinit_id_ip4_address(&obj_stack, self->ifindex, addr, plen, peer_addr); + + head = nm_l3_config_data_lookup_obj(self, &obj_stack); + if (!head) + return NULL; + + return NMP_OBJECT_CAST_IP4_ADDRESS(head->obj); +} + const NMPlatformIP6Address * nm_l3_config_data_lookup_address_6(const NML3ConfigData *self, const struct in6_addr *addr) { @@ -879,7 +914,7 @@ nm_l3_config_data_lookup_address_6(const NML3ConfigData *self, const struct in6_ nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); - /* this works only, because the primary key for a Ipv6 address is the + /* this works only, because the primary key for a IPv6 address is the * ifindex and the "struct in6_addr". */ nmp_object_stackinit_id_ip6_address(&obj_stack, self->ifindex, addr); @@ -1104,6 +1139,14 @@ _l3_config_data_add_obj(NMDedupMultiIndex * multi_idx, obj_new_stackinit.ip_address.addr_source = obj_old->ip_address.addr_source; modified = TRUE; } + + /* OR assume_config_once flag */ + if (obj_new->ip_address.a_assume_config_once + && !obj_old->ip_address.a_assume_config_once) { + obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new); + obj_new_stackinit.ip_address.a_assume_config_once = TRUE; + modified = TRUE; + } break; case NMP_OBJECT_TYPE_IP4_ROUTE: case NMP_OBJECT_TYPE_IP6_ROUTE: @@ -1113,6 +1156,14 @@ _l3_config_data_add_obj(NMDedupMultiIndex * multi_idx, obj_new_stackinit.ip_route.rt_source = obj_old->ip_route.rt_source; modified = TRUE; } + + /* OR assume_config_once flag */ + if (obj_new->ip_route.r_assume_config_once + && !obj_old->ip_route.r_assume_config_once) { + obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new); + obj_new_stackinit.ip_route.r_assume_config_once = TRUE; + modified = TRUE; + } break; default: nm_assert_not_reached(); @@ -1168,11 +1219,11 @@ _l3_config_best_default_route_find_better(const NMPObject *obj_cur, const NMPObj NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)) || NMP_OBJECT_GET_TYPE(obj_cur) == NMP_OBJECT_GET_TYPE(obj_cmp)); - nm_assert(!obj_cur || nmp_object_ip_route_is_best_defaut_route(obj_cur)); + nm_assert(!obj_cur || nmp_object_ip_route_is_best_default_route(obj_cur)); /* assumes that @obj_cur is already the best default route (or NULL). It checks whether * @obj_cmp is also a default route and returns the best of both. */ - if (obj_cmp && nmp_object_ip_route_is_best_defaut_route(obj_cmp)) { + if (obj_cmp && nmp_object_ip_route_is_best_default_route(obj_cmp)) { guint32 metric_cur, metric_cmp; if (!obj_cur) @@ -1297,9 +1348,16 @@ const NMPObject * nm_l3_config_data_get_best_default_route(const NML3ConfigData *self, int addr_family) { nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); - nm_assert_addr_family(addr_family); - return self->best_default_route_x[NM_IS_IPv4(addr_family)]; + switch (addr_family) { + case AF_INET: + return self->best_default_route_4; + case AF_INET6: + return self->best_default_route_6; + case AF_UNSPEC: + return self->best_default_route_4 ?: self->best_default_route_6; + } + return nm_assert_unreachable_val(NULL); } /*****************************************************************************/ @@ -1336,10 +1394,15 @@ _check_and_add_domain(GPtrArray **p_arr, const char *domain) gconstpointer nm_l3_config_data_get_nameservers(const NML3ConfigData *self, int addr_family, guint *out_len) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + nm_assert(!self || _NM_IS_L3_CONFIG_DATA(self, TRUE)); nm_assert_addr_family(addr_family); nm_assert(out_len); + if (!self) { + *out_len = 0; + return NULL; + } + return _garray_inaddr_get(self->nameservers_x[NM_IS_IPv4(addr_family)], out_len); } @@ -1372,7 +1435,13 @@ nm_l3_config_data_clear_nameservers(NML3ConfigData *self, int addr_family) const in_addr_t * nm_l3_config_data_get_wins(const NML3ConfigData *self, guint *out_len) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + nm_assert(!self || _NM_IS_L3_CONFIG_DATA(self, TRUE)); + nm_assert(out_len); + + if (!self) { + *out_len = 0; + return NULL; + } return _garray_inaddr_get(self->wins, out_len); } @@ -1420,10 +1489,15 @@ nm_l3_config_data_set_nis_domain(NML3ConfigData *self, const char *nis_domain) const char *const * nm_l3_config_data_get_domains(const NML3ConfigData *self, int addr_family, guint *out_len) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + nm_assert(!self || _NM_IS_L3_CONFIG_DATA(self, TRUE)); nm_assert_addr_family(addr_family); nm_assert(out_len); + if (!self) { + *out_len = 0; + return NULL; + } + return nm_strv_ptrarray_get_unsafe(self->domains_x[NM_IS_IPv4(addr_family)], out_len); } @@ -1439,10 +1513,15 @@ nm_l3_config_data_add_domain(NML3ConfigData *self, int addr_family, const char * const char *const * nm_l3_config_data_get_searches(const NML3ConfigData *self, int addr_family, guint *out_len) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + nm_assert(!self || _NM_IS_L3_CONFIG_DATA(self, TRUE)); nm_assert_addr_family(addr_family); nm_assert(out_len); + if (!self) { + *out_len = 0; + return NULL; + } + return nm_strv_ptrarray_get_unsafe(self->searches_x[NM_IS_IPv4(addr_family)], out_len); } @@ -1492,10 +1571,15 @@ nm_l3_config_data_add_dns_option(NML3ConfigData *self, int addr_family, const ch const char *const * nm_l3_config_data_get_dns_options(const NML3ConfigData *self, int addr_family, guint *out_len) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + nm_assert(!self || _NM_IS_L3_CONFIG_DATA(self, TRUE)); nm_assert_addr_family(addr_family); nm_assert(out_len); + if (!self) { + *out_len = 0; + return NULL; + } + return nm_strv_ptrarray_get_unsafe(self->dns_options_x[NM_IS_IPv4(addr_family)], out_len); } @@ -1621,6 +1705,29 @@ nm_l3_config_data_set_route_table_sync(NML3ConfigData * self, return TRUE; } +NMTernary +nm_l3_config_data_get_never_default(const NML3ConfigData *self, int addr_family) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return NM_TERNARY_FROM_OPTION_BOOL(self->never_default_x[NM_IS_IPv4(addr_family)]); +} + +gboolean +nm_l3_config_data_set_never_default(NML3ConfigData *self, int addr_family, NMTernary never_default) +{ + const int IS_IPv4 = NM_IS_IPv4(addr_family); + const NMOptionBool v = NM_TERNARY_TO_OPTION_BOOL(never_default); + + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + + if (self->never_default_x[IS_IPv4] == v) + return FALSE; + + self->never_default_x[IS_IPv4] = v; + return TRUE; +} + NMTernary nm_l3_config_data_get_metered(const NML3ConfigData *self) { @@ -1682,22 +1789,13 @@ nm_l3_config_data_set_ip6_mtu(NML3ConfigData *self, guint32 ip6_mtu) return TRUE; } -gboolean -nm_l3_config_data_set_source(NML3ConfigData *self, NMIPConfigSource source) -{ - nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); - - if (self->source == source) - return FALSE; - - self->source = source; - return TRUE; -} - NMSettingIP6ConfigPrivacy nm_l3_config_data_get_ip6_privacy(const NML3ConfigData *self) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(!self || _NM_IS_L3_CONFIG_DATA(self, TRUE)); + + if (!self) + return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; return self->ip6_privacy; } @@ -1799,7 +1897,7 @@ nm_l3_config_data_set_proxy_pac_script(NML3ConfigData *self, const char *value) gboolean nm_l3_config_data_get_ndisc_hop_limit(const NML3ConfigData *self, int *out_val) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); if (!self->ndisc_hop_limit_set) { NM_SET_OUT(out_val, 0); @@ -1822,7 +1920,7 @@ nm_l3_config_data_set_ndisc_hop_limit(NML3ConfigData *self, int val) gboolean nm_l3_config_data_get_ndisc_reachable_time_msec(const NML3ConfigData *self, guint32 *out_val) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); if (!self->ndisc_reachable_time_msec_set) { NM_SET_OUT(out_val, 0); @@ -1845,7 +1943,7 @@ nm_l3_config_data_set_ndisc_reachable_time_msec(NML3ConfigData *self, guint32 va gboolean nm_l3_config_data_get_ndisc_retrans_timer_msec(const NML3ConfigData *self, guint32 *out_val) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); if (!self->ndisc_retrans_timer_msec_set) { NM_SET_OUT(out_val, 0); @@ -1922,14 +2020,26 @@ nm_l3_config_data_set_dhcp_lease_from_options(NML3ConfigData *self, /*****************************************************************************/ static int -_dedup_multi_index_cmp(const NML3ConfigData *a, const NML3ConfigData *b, NMPObjectType obj_type) +_dedup_multi_index_cmp(const NML3ConfigData *a, + const NML3ConfigData *b, + NMPObjectType obj_type, + gboolean ignore_ifindex) { const NMDedupMultiHeadEntry *h_a = nm_l3_config_data_lookup_objs(a, obj_type); const NMDedupMultiHeadEntry *h_b = nm_l3_config_data_lookup_objs(b, obj_type); NMDedupMultiIter iter_a; NMDedupMultiIter iter_b; + /* We handle ignore_index via NMP_OBJECT_CMP_FLAGS_IGNORE_IFINDEX flag, which is + * only implemented for certain types. */ + nm_assert(NM_IN_SET(obj_type, + NMP_OBJECT_TYPE_IP4_ADDRESS, + NMP_OBJECT_TYPE_IP6_ADDRESS, + NMP_OBJECT_TYPE_IP4_ROUTE, + NMP_OBJECT_TYPE_IP6_ROUTE)); + NM_CMP_SELF(h_a, h_b); + NM_CMP_DIRECT(h_a->len, h_b->len); nm_assert(h_a->len > 0); @@ -1952,7 +2062,10 @@ _dedup_multi_index_cmp(const NML3ConfigData *a, const NML3ConfigData *b, NMPObje have_b = nm_platform_dedup_multi_iter_next_obj(&iter_b, &obj_b, obj_type); nm_assert(have_b); - NM_CMP_RETURN(nmp_object_cmp(obj_a, obj_b)); + NM_CMP_RETURN(nmp_object_cmp_full(obj_a, + obj_b, + ignore_ifindex ? NMP_OBJECT_CMP_FLAGS_IGNORE_IFINDEX + : NMP_OBJECT_CMP_FLAGS_NONE)); } } @@ -1961,25 +2074,30 @@ nm_l3_config_data_cmp_full(const NML3ConfigData *a, const NML3ConfigData *b, NML3ConfigCmpFlags cmp_flags) { - int IS_IPv4; + int IS_IPv4; + gboolean ignore_ifindex; NM_CMP_SELF(a, b); - if (!NM_FLAGS_HAS(cmp_flags, NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX)) + ignore_ifindex = NM_FLAGS_HAS(cmp_flags, NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX); + + if (!ignore_ifindex) NM_CMP_DIRECT(a->ifindex, b->ifindex); NM_CMP_DIRECT(a->flags, b->flags); - NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP4_ADDRESS)); - NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP6_ADDRESS)); - NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP4_ROUTE)); - NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP6_ROUTE)); + NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP4_ADDRESS, ignore_ifindex)); + NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP6_ADDRESS, ignore_ifindex)); + NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP4_ROUTE, ignore_ifindex)); + NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP6_ROUTE, ignore_ifindex)); for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { const int addr_family = IS_IPv4 ? AF_INET : AF_INET6; - NM_CMP_RETURN( - nmp_object_cmp(a->best_default_route_x[IS_IPv4], b->best_default_route_x[IS_IPv4])); + NM_CMP_RETURN(nmp_object_cmp_full(a->best_default_route_x[IS_IPv4], + b->best_default_route_x[IS_IPv4], + ignore_ifindex ? NMP_OBJECT_CMP_FLAGS_IGNORE_IFINDEX + : NMP_OBJECT_CMP_FLAGS_NONE)); NM_CMP_RETURN( _garray_inaddr_cmp(a->nameservers_x[IS_IPv4], b->nameservers_x[IS_IPv4], addr_family)); @@ -1999,6 +2117,7 @@ nm_l3_config_data_cmp_full(const NML3ConfigData *a, NM_CMP_DIRECT(a->dns_priority_x[IS_IPv4], b->dns_priority_x[IS_IPv4]); NM_CMP_DIRECT(a->route_table_sync_x[IS_IPv4], b->route_table_sync_x[IS_IPv4]); + NM_CMP_DIRECT(a->never_default_x[IS_IPv4], b->never_default_x[IS_IPv4]); } NM_CMP_RETURN(_garray_inaddr_cmp(a->wins, b->wins, AF_INET)); @@ -2066,8 +2185,8 @@ _data_get_direct_route_for_host(const NML3ConfigData *self, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { const NMPlatformIPXRoute *item = NMP_OBJECT_CAST_IPX_ROUTE(item_obj); - if (nm_ip_addr_is_null(addr_family, - nm_platform_ip_route_get_gateway(addr_family, &item->rx))) + if (!nm_ip_addr_is_null(addr_family, + nm_platform_ip_route_get_gateway(addr_family, &item->rx))) continue; if (best_route && best_route->rx.plen > item->rx.plen) @@ -2114,7 +2233,7 @@ nm_l3_config_data_get_blacklisted_ip4_routes(const NML3ConfigData *self, gboolea const NMPObject * my_addr_obj; NMDedupMultiIter iter; - nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); /* For IPv6 slaac, we explicitly add the device-routes (onlink). * As we don't do that for IPv4 and manual IPv6 addresses. Add them here @@ -2125,9 +2244,6 @@ nm_l3_config_data_get_blacklisted_ip4_routes(const NML3ConfigData *self, gboolea in_addr_t network_4; NMPlatformIPXRoute rx; - if (my_addr->external) - continue; - nm_assert(my_addr->plen <= 32); if (my_addr->plen == 0) continue; @@ -2176,120 +2292,137 @@ nm_l3_config_data_get_blacklisted_ip4_routes(const NML3ConfigData *self, gboolea /*****************************************************************************/ void -nm_l3_config_data_add_dependent_routes(NML3ConfigData *self, - int addr_family, - guint32 route_table, - guint32 route_metric, - gboolean is_vrf) +nm_l3_config_data_add_dependent_onlink_routes(NML3ConfigData *self, int addr_family) { - const int IS_IPv4 = NM_IS_IPv4(addr_family); gs_unref_ptrarray GPtrArray *extra_onlink_routes = NULL; - const NMPObject * my_addr_obj; - const NMPObject * my_route_obj; - NMPlatformIPXRoute rx; + const NMPObject * obj_src; NMDedupMultiIter iter; - in_addr_t network_4 = 0; + int IS_IPv4; guint i; + if (addr_family == AF_UNSPEC) { + nm_l3_config_data_add_dependent_onlink_routes(self, AF_INET); + nm_l3_config_data_add_dependent_onlink_routes(self, AF_INET6); + return; + } + + IS_IPv4 = NM_IS_IPv4(addr_family); + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); - nm_assert_addr_family(addr_family); /* For IPv6 slaac, we explicitly add the device-routes (onlink). * As we don't do that for IPv4 and manual IPv6 addresses. Add them here * as dependent routes. */ - if (!IS_IPv4) { - /* Pre-generate multicast route */ - rx.r6 = (NMPlatformIP6Route){ - .ifindex = self->ifindex, - .network.s6_addr[0] = 0xffu, - .plen = 8, - .table_coerced = nm_platform_route_table_coerce(RT_TABLE_LOCAL), - .type_coerced = nm_platform_route_type_coerce(RTN_UNICAST), - .metric = 256, - }; - nm_l3_config_data_add_route(self, addr_family, NULL, &rx.rx); - } + nm_l3_config_data_iter_obj_for_each (&iter, self, &obj_src, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { + const NMPlatformIPXRoute *route_src = NMP_OBJECT_CAST_IPX_ROUTE(obj_src); + NMPObject * new_route; + NMPlatformIPXRoute * new_r; + const NMIPAddr * p_gateway; - nm_l3_config_data_iter_obj_for_each (&iter, - self, - &my_addr_obj, - NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) { - const NMPlatformIPXAddress *const my_addr = NMP_OBJECT_CAST_IPX_ADDRESS(my_addr_obj); + p_gateway = nm_platform_ip_route_get_gateway(addr_family, &route_src->rx); + + if (nm_ip_addr_is_null(addr_family, p_gateway)) + continue; - if (my_addr->ax.external) + if (_data_get_direct_route_for_host( + self, + addr_family, + p_gateway, + nm_platform_route_table_uncoerce(route_src->rx.table_coerced, TRUE))) continue; + new_route = nmp_object_clone(obj_src, FALSE); + new_r = NMP_OBJECT_CAST_IPX_ROUTE(new_route); if (IS_IPv4) { - nm_assert(my_addr->a4.plen <= 32); - if (my_addr->a4.plen == 0) - continue; + new_r->r4.network = route_src->r4.gateway; + new_r->r4.plen = 32; + new_r->r4.gateway = 0; + } else { + new_r->r6.network = route_src->r6.gateway; + new_r->r6.plen = 128; + new_r->r6.gateway = in6addr_any; } - if (IS_IPv4) { - rx.r4 = (NMPlatformIP4Route){ - .ifindex = self->ifindex, - .rt_source = NM_IP_CONFIG_SOURCE_KERNEL, - .network = my_addr->a4.address, - .plen = 32, - .pref_src = my_addr->a4.address, - .type_coerced = nm_platform_route_type_coerce(RTN_LOCAL), - .scope_inv = nm_platform_route_scope_inv(RT_SCOPE_HOST), - .table_coerced = - nm_platform_route_table_coerce(is_vrf ? route_table : RT_TABLE_LOCAL), - }; - } else { - rx.r6 = (NMPlatformIP6Route){ - .ifindex = self->ifindex, - .network = my_addr->a6.address, - .plen = 128, - .type_coerced = nm_platform_route_type_coerce(RTN_LOCAL), - .metric = 0, - .table_coerced = - nm_platform_route_table_coerce(is_vrf ? route_table : RT_TABLE_LOCAL), - }; + /* we cannot add the route right away, because that invalidates the iteration. */ + if (!extra_onlink_routes) + extra_onlink_routes = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); + g_ptr_array_add(extra_onlink_routes, new_route); + } + if (extra_onlink_routes) { + for (i = 0; i < extra_onlink_routes->len; i++) { + nm_l3_config_data_add_route_full(self, + addr_family, + extra_onlink_routes->pdata[i], + NULL, + NM_L3_CONFIG_ADD_FLAGS_EXCLUSIVE, + NULL, + NULL); } - nm_l3_config_data_add_route(self, addr_family, NULL, &rx.rx); + } +} - if (my_addr->ax.plen == 0) +void +nm_l3_config_data_add_dependent_device_routes(NML3ConfigData * self, + int addr_family, + guint32 route_table, + guint32 route_metric, + const NML3ConfigData *source) +{ + const int IS_IPv4 = NM_IS_IPv4(addr_family); + const NMPObject * obj_src; + NMPlatformIPXRoute rx; + NMDedupMultiIter iter; + + nm_assert_addr_family(addr_family); + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(_NM_IS_L3_CONFIG_DATA(source, TRUE)); + nm_assert(self != source); + + /* For IPv6 slaac, we explicitly add the device-routes (onlink) and track them + * as regular routes in NML3ConfigData. + * + * For IPv4 and for manual IPv6 addresses we don't do that. Instead, add those + * routes automatically afterwards. + * + * As route-table/metric is associated with the source l3cd, we need to process + * all source l3cds separately. */ + + nm_l3_config_data_iter_obj_for_each (&iter, + source, + &obj_src, + NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) { + const NMPlatformIPXAddress *const addr_src = NMP_OBJECT_CAST_IPX_ADDRESS(obj_src); + const NMPlatformIPXAddress * addr_dst; + + addr_dst = NMP_OBJECT_CAST_IPX_ADDRESS( + nm_dedup_multi_entry_get_obj(nm_l3_config_data_lookup_obj(self, obj_src))); + if (!addr_dst) continue; if (IS_IPv4) { - network_4 = - nm_utils_ip4_address_clear_host_address(my_addr->a4.peer_address, my_addr->a4.plen); + NMPlatformIPXRoute r_stack; + const NMPlatformIPRoute *r; - if (nm_utils_ip4_address_is_zeronet(network_4)) { - /* Kernel doesn't add device-routes for destinations that - * start with 0.x.y.z. Skip them. */ + if (addr_dst->a4.a_acd_not_ready) continue; - } - if (my_addr->a4.plen == 32 && my_addr->a4.address == my_addr->a4.peer_address) { - /* Kernel doesn't add device-routes for /32 addresses unless - * they have a peer. */ - continue; - } + r = (NMPlatformIPRoute *) nm_platform_ip4_address_generate_device_route(&addr_src->a4, + self->ifindex, + route_table, + route_metric, + &r_stack.r4); + if (r) + nm_l3_config_data_add_route(self, addr_family, NULL, r); } else { - if (NM_FLAGS_HAS(my_addr->a6.n_ifa_flags, IFA_F_NOPREFIXROUTE)) + const gboolean has_peer = !IN6_IS_ADDR_UNSPECIFIED(&addr_src->a6.peer_address); + int routes_i; + + if (addr_src->ax.plen == 0) continue; - } - if (IS_IPv4) { - rx.r4 = (NMPlatformIP4Route){ - .ifindex = self->ifindex, - .rt_source = NM_IP_CONFIG_SOURCE_KERNEL, - .network = network_4, - .plen = my_addr->a4.plen, - .pref_src = my_addr->a4.address, - .table_coerced = nm_platform_route_table_coerce(route_table), - .metric = route_metric, - .scope_inv = nm_platform_route_scope_inv(NM_RT_SCOPE_LINK), - }; - nm_platform_ip_route_normalize(addr_family, &rx.rx); - nm_l3_config_data_add_route(self, addr_family, NULL, &rx.rx); - } else { - const gboolean has_peer = !IN6_IS_ADDR_UNSPECIFIED(&my_addr->a6.peer_address); - int routes_i; + if (NM_FLAGS_HAS(addr_src->a6.n_ifa_flags, IFA_F_NOPREFIXROUTE)) + continue; /* If we have an IPv6 peer, we add two /128 routes * (unless, both addresses are identical). */ @@ -2299,20 +2432,20 @@ nm_l3_config_data_add_dependent_routes(NML3ConfigData *self, guint8 plen; if (routes_i == 1 && has_peer - && IN6_ARE_ADDR_EQUAL(&my_addr->a6.address, &my_addr->a6.peer_address)) + && IN6_ARE_ADDR_EQUAL(&addr_src->a6.address, &addr_src->a6.peer_address)) break; if (has_peer) { if (routes_i == 0) - a6 = &my_addr->a6.address; + a6 = &addr_src->a6.address; else - a6 = &my_addr->a6.peer_address; + a6 = &addr_src->a6.peer_address; plen = 128; } else { a6 = nm_utils_ip6_address_clear_host_address(&a6_stack, - &my_addr->a6.address, - my_addr->a6.plen); - plen = my_addr->a6.plen; + &addr_src->a6.address, + addr_src->a6.plen); + plen = addr_src->a6.plen; } rx.r6 = (NMPlatformIP6Route){ @@ -2328,73 +2461,16 @@ nm_l3_config_data_add_dependent_routes(NML3ConfigData *self, } } } - - nm_l3_config_data_iter_obj_for_each (&iter, - self, - &my_route_obj, - NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { - const NMPlatformIPXRoute *my_route = NMP_OBJECT_CAST_IPX_ROUTE(my_route_obj); - NMPObject * new_route; - NMPlatformIPXRoute * new_r; - const NMIPAddr * p_gateway; - - if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(my_route) - || NM_IS_IP_CONFIG_SOURCE_RTPROT(my_route->rx.rt_source)) - continue; - - p_gateway = nm_platform_ip_route_get_gateway(addr_family, &my_route->rx); - - if (nm_ip_addr_is_null(addr_family, p_gateway)) - continue; - - if (_data_get_direct_route_for_host( - self, - addr_family, - p_gateway, - nm_platform_route_table_uncoerce(my_route->rx.table_coerced, TRUE))) - continue; - - new_route = nmp_object_clone(my_route_obj, FALSE); - new_r = NMP_OBJECT_CAST_IPX_ROUTE(new_route); - if (IS_IPv4) { - new_r->r4.network = my_route->r4.gateway; - new_r->r4.plen = 32; - new_r->r4.gateway = 0; - } else { - new_r->r6.network = my_route->r6.gateway; - new_r->r6.plen = 128; - new_r->r6.gateway = in6addr_any; - } - - /* we cannot add the route right away, because that invalidates the iteration. */ - if (!extra_onlink_routes) - extra_onlink_routes = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); - g_ptr_array_add(extra_onlink_routes, new_route); - } - if (extra_onlink_routes) { - for (i = 0; i < extra_onlink_routes->len; i++) { - nm_l3_config_data_add_route_full(self, - addr_family, - extra_onlink_routes->pdata[i], - NULL, - NM_L3_CONFIG_ADD_FLAGS_EXCLUSIVE, - NULL, - NULL); - } - } } /*****************************************************************************/ static void -_init_from_connection_ip(NML3ConfigData *self, - int addr_family, - NMConnection * connection, - guint32 route_table, - guint32 route_metric) +_init_from_connection_ip(NML3ConfigData *self, int addr_family, NMConnection *connection) { const int IS_IPv4 = NM_IS_IPv4(addr_family); NMSettingIPConfig *s_ip; + gboolean never_default; guint naddresses; guint nroutes; guint nnameservers; @@ -2415,25 +2491,28 @@ _init_from_connection_ip(NML3ConfigData *self, if (!s_ip) return; - if (!nm_setting_ip_config_get_never_default(s_ip) - && (gateway_str = nm_setting_ip_config_get_gateway(s_ip)) + never_default = nm_setting_ip_config_get_never_default(s_ip); + + nm_l3_config_data_set_never_default(self, addr_family, !!never_default); + + if (!never_default && (gateway_str = nm_setting_ip_config_get_gateway(s_ip)) && inet_pton(addr_family, gateway_str, &gateway_bin) == 1 && !nm_ip_addr_is_null(addr_family, &gateway_bin)) { NMPlatformIPXRoute r; if (IS_IPv4) { r.r4 = (NMPlatformIP4Route){ - .rt_source = NM_IP_CONFIG_SOURCE_USER, - .gateway = gateway_bin.addr4, - .table_coerced = nm_platform_route_table_coerce(route_table), - .metric = route_metric, + .rt_source = NM_IP_CONFIG_SOURCE_USER, + .gateway = gateway_bin.addr4, + .table_any = TRUE, + .metric_any = TRUE, }; } else { r.r6 = (NMPlatformIP6Route){ - .rt_source = NM_IP_CONFIG_SOURCE_USER, - .gateway = gateway_bin.addr6, - .table_coerced = nm_platform_route_table_coerce(route_table), - .metric = route_metric, + .rt_source = NM_IP_CONFIG_SOURCE_USER, + .gateway = gateway_bin.addr6, + .table_any = TRUE, + .metric_any = TRUE, }; } @@ -2488,6 +2567,7 @@ _init_from_connection_ip(NML3ConfigData *self, NMIPAddr next_hop_bin; gint64 metric64; guint32 metric; + gboolean metric_any; guint plen; nm_assert(nm_ip_route_get_family(s_route) == addr_family); @@ -2496,11 +2576,14 @@ _init_from_connection_ip(NML3ConfigData *self, nm_ip_route_get_next_hop_binary(s_route, &next_hop_bin); metric64 = nm_ip_route_get_metric(s_route); - if (metric64 < 0) - metric = route_metric; - else - metric = metric64; - metric = nm_utils_ip_route_metric_normalize(addr_family, metric); + if (metric64 < 0) { + metric_any = TRUE; + metric = 0; + } else { + metric_any = FALSE; + metric = metric64; + metric = nm_utils_ip_route_metric_normalize(addr_family, metric); + } plen = nm_ip_route_get_prefix(s_route); @@ -2508,25 +2591,27 @@ _init_from_connection_ip(NML3ConfigData *self, if (IS_IPv4) { r.r4 = (NMPlatformIP4Route){ - .network = network_bin.addr4, - .plen = nm_ip_route_get_prefix(s_route), - .gateway = next_hop_bin.addr4, - .metric = metric, - .rt_source = NM_IP_CONFIG_SOURCE_USER, + .network = network_bin.addr4, + .plen = nm_ip_route_get_prefix(s_route), + .gateway = next_hop_bin.addr4, + .metric_any = metric_any, + .metric = metric, + .rt_source = NM_IP_CONFIG_SOURCE_USER, }; nm_assert(r.r4.plen <= 32); } else { r.r6 = (NMPlatformIP6Route){ - .network = network_bin.addr6, - .plen = nm_ip_route_get_prefix(s_route), - .gateway = next_hop_bin.addr6, - .metric = metric, - .rt_source = NM_IP_CONFIG_SOURCE_USER, + .network = network_bin.addr6, + .plen = nm_ip_route_get_prefix(s_route), + .gateway = next_hop_bin.addr6, + .metric_any = metric_any, + .metric = metric, + .rt_source = NM_IP_CONFIG_SOURCE_USER, }; nm_assert(r.r6.plen <= 128); } - nm_utils_ip_route_attribute_to_platform(addr_family, s_route, &r.rx, route_table); + nm_utils_ip_route_attribute_to_platform(addr_family, s_route, &r.rx, -1); nm_l3_config_data_add_route(self, addr_family, NULL, &r.rx); } @@ -2550,34 +2635,36 @@ _init_from_connection_ip(NML3ConfigData *self, } idx = 0; - while ((idx = nm_setting_ip_config_next_valid_dns_option(s_ip, i)) >= 0) { + while ((idx = nm_setting_ip_config_next_valid_dns_option(s_ip, idx)) >= 0) { nm_l3_config_data_add_dns_option(self, addr_family, - nm_setting_ip_config_get_dns_option(s_ip, i)); + nm_setting_ip_config_get_dns_option(s_ip, idx)); idx++; } nm_l3_config_data_set_dns_priority(self, addr_family, nm_setting_ip_config_get_dns_priority(s_ip)); + + if (!IS_IPv4) { + nm_l3_config_data_set_ip6_privacy( + self, + nm_setting_ip6_config_get_ip6_privacy(NM_SETTING_IP6_CONFIG(s_ip))); + } } NML3ConfigData * nm_l3_config_data_new_from_connection(NMDedupMultiIndex *multi_idx, int ifindex, - NMConnection * connection, - guint32 route_table_4, - guint32 route_table_6, - guint32 route_metric_4, - guint32 route_metric_6) + NMConnection * connection) { NML3ConfigData *self; NMSettingProxy *s_proxy; - self = nm_l3_config_data_new(multi_idx, ifindex); + self = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_USER); - _init_from_connection_ip(self, AF_INET, connection, route_table_4, route_metric_4); - _init_from_connection_ip(self, AF_INET6, connection, route_table_6, route_metric_6); + _init_from_connection_ip(self, AF_INET, connection); + _init_from_connection_ip(self, AF_INET6, connection); s_proxy = _nm_connection_get_setting(connection, NM_TYPE_SETTING_PROXY); if (s_proxy) { @@ -2693,7 +2780,7 @@ nm_l3_config_data_new_from_platform(NMDedupMultiIndex * multi_idx, if (nm_platform_link_get_master(platform, ifindex) > 0) return NULL; - self = nm_l3_config_data_new(multi_idx, ifindex); + self = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_KERNEL); _init_from_platform(self, AF_INET, platform, ipv6_privacy_rfc4941); _init_from_platform(self, AF_INET6, platform, ipv6_privacy_rfc4941); @@ -2710,13 +2797,16 @@ nm_l3_config_data_merge(NML3ConfigData * self, const guint32 * default_route_table_x /* length 2, for IS_IPv4 */, const guint32 * default_route_metric_x /* length 2, for IS_IPv4 */, const guint32 * default_route_penalty_x /* length 2, for IS_IPv4 */, - NML3ConfigMergeHookAddObj hook_add_addr, + const int * default_dns_priority_x /* length 2, for IS_IPv4 */, + NML3ConfigMergeHookAddObj hook_add_obj, gpointer hook_user_data) { static const guint32 x_default_route_table_x[2] = {RT_TABLE_MAIN, RT_TABLE_MAIN}; static const guint32 x_default_route_metric_x[2] = {NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6, NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4}; static const guint32 x_default_route_penalty_x[2] = {0, 0}; + static const int x_default_dns_priority_x[2] = {NM_DNS_PRIORITY_DEFAULT_NORMAL, + NM_DNS_PRIORITY_DEFAULT_NORMAL}; NMDedupMultiIter iter; const NMPObject * obj; int IS_IPv4; @@ -2730,6 +2820,8 @@ nm_l3_config_data_merge(NML3ConfigData * self, default_route_metric_x = x_default_route_metric_x; if (!default_route_penalty_x) default_route_penalty_x = x_default_route_penalty_x; + if (!default_dns_priority_x) + default_dns_priority_x = x_default_dns_priority_x; nm_assert(default_route_table_x[0] != 0); nm_assert(default_route_table_x[1] != 0); @@ -2747,51 +2839,100 @@ nm_l3_config_data_merge(NML3ConfigData * self, src, &obj, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) { - NMPlatformIPXAddress addr_stack; - const NMPlatformIPAddress *addr = NULL; - NMTernary ip4acd_not_ready = NM_TERNARY_DEFAULT; + const NMPlatformIPAddress *a_src = NMP_OBJECT_CAST_IP_ADDRESS(obj); + NMPlatformIPXAddress a; + NML3ConfigMergeHookResult hook_result = { + .ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT, + .assume_config_once = NM_OPTION_BOOL_DEFAULT, + }; + +#define _ensure_a() \ + G_STMT_START \ + { \ + if (a_src != &a.ax) { \ + if (IS_IPv4) \ + a.a4 = *NMP_OBJECT_CAST_IP4_ADDRESS(obj); \ + else \ + a.a6 = *NMP_OBJECT_CAST_IP6_ADDRESS(obj); \ + a_src = &a.ax; \ + } \ + } \ + G_STMT_END - if (hook_add_addr && !hook_add_addr(src, obj, &ip4acd_not_ready, hook_user_data)) + if (hook_add_obj && !hook_add_obj(src, obj, &hook_result, hook_user_data)) continue; - if (IS_IPv4 && ip4acd_not_ready != NM_TERNARY_DEFAULT - && (!!ip4acd_not_ready) != NMP_OBJECT_CAST_IP4_ADDRESS(obj)->ip4acd_not_ready) { - addr_stack.a4 = *NMP_OBJECT_CAST_IP4_ADDRESS(obj); - addr_stack.a4.ip4acd_not_ready = (!!ip4acd_not_ready); - addr = &addr_stack.ax; - } else - nm_assert(IS_IPv4 || ip4acd_not_ready == NM_TERNARY_DEFAULT); + nm_assert(IS_IPv4 || hook_result.ip4acd_not_ready == NM_OPTION_BOOL_DEFAULT); + + if (a_src->ifindex != self->ifindex) { + _ensure_a(); + a.ax.ifindex = self->ifindex; + } + + if (hook_result.ip4acd_not_ready != NM_OPTION_BOOL_DEFAULT && IS_IPv4 + && (!!hook_result.ip4acd_not_ready) + != ((const NMPlatformIP4Address *) a_src)->a_acd_not_ready) { + _ensure_a(); + a.a4.a_acd_not_ready = (!!hook_result.ip4acd_not_ready); + } + + if (hook_result.assume_config_once != NM_OPTION_BOOL_DEFAULT + && (!!hook_result.assume_config_once) != a_src->a_assume_config_once) { + _ensure_a(); + a.ax.a_assume_config_once = (!!hook_result.assume_config_once); + } nm_l3_config_data_add_address_full(self, addr_family, - addr ? NULL : obj, - addr, + a_src == &a.ax ? NULL : obj, + a_src == &a.ax ? a_src : NULL, NM_L3_CONFIG_ADD_FLAGS_EXCLUSIVE, NULL); } +#undef _ensure_a + if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES)) { nm_l3_config_data_iter_obj_for_each (&iter, src, &obj, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { - const NMPlatformIPRoute *r_src = NMP_OBJECT_CAST_IP_ROUTE(obj); - NMPlatformIPXRoute r; + const NMPlatformIPRoute * r_src = NMP_OBJECT_CAST_IP_ROUTE(obj); + NMPlatformIPXRoute r; + NML3ConfigMergeHookResult hook_result = { + .ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT, + .assume_config_once = NM_OPTION_BOOL_DEFAULT, + }; #define _ensure_r() \ G_STMT_START \ { \ if (r_src != &r.rx) { \ - r_src = &r.rx; \ if (IS_IPv4) \ r.r4 = *NMP_OBJECT_CAST_IP4_ROUTE(obj); \ else \ r.r6 = *NMP_OBJECT_CAST_IP6_ROUTE(obj); \ - r.rx.ifindex = self->ifindex; \ + r_src = &r.rx; \ } \ } \ G_STMT_END + if (hook_add_obj && !hook_add_obj(src, obj, &hook_result, hook_user_data)) + continue; + + nm_assert(hook_result.ip4acd_not_ready == NM_OPTION_BOOL_DEFAULT); + + if (r_src->ifindex != self->ifindex) { + _ensure_r(); + r.rx.ifindex = self->ifindex; + } + + if (hook_result.assume_config_once != NM_OPTION_BOOL_DEFAULT + && (!!hook_result.assume_config_once) != r_src->r_assume_config_once) { + _ensure_r(); + r.rx.r_assume_config_once = (!!hook_result.assume_config_once); + } + if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_CLONE)) { if (r_src->table_any) { _ensure_r(); @@ -2848,12 +2989,20 @@ nm_l3_config_data_merge(NML3ConfigData * self, if (!NM_FLAGS_ANY(self->flags, has_dns_priority_flag) && NM_FLAGS_ANY(src->flags, has_dns_priority_flag)) { - self->dns_priority_x[IS_IPv4] = src->dns_priority_x[IS_IPv4]; + int p = src->dns_priority_x[IS_IPv4]; + + if (p == 0 && !NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_CLONE)) + p = default_dns_priority_x[IS_IPv4]; + + self->dns_priority_x[IS_IPv4] = p; self->flags |= has_dns_priority_flag; } if (self->route_table_sync_x[IS_IPv4] == NM_IP_ROUTE_TABLE_SYNC_MODE_NONE) self->route_table_sync_x[IS_IPv4] = src->route_table_sync_x[IS_IPv4]; + + if (self->never_default_x[IS_IPv4] == NM_OPTION_BOOL_DEFAULT) + self->never_default_x[IS_IPv4] = src->never_default_x[IS_IPv4]; } if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DNS)) { @@ -2933,7 +3082,7 @@ nm_l3_config_data_new_clone(const NML3ConfigData *src, int ifindex) if (ifindex <= 0) ifindex = src->ifindex; - self = nm_l3_config_data_new(src->multi_idx, ifindex); + self = nm_l3_config_data_new(src->multi_idx, ifindex, src->source); nm_l3_config_data_merge(self, src, NM_L3_CONFIG_MERGE_FLAGS_CLONE, @@ -2941,9 +3090,15 @@ nm_l3_config_data_new_clone(const NML3ConfigData *src, int ifindex) NULL, NULL, NULL, + NULL, NULL); - nm_assert(nm_l3_config_data_cmp_full(src, self, NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX) == 0); + nm_assert(nm_l3_config_data_cmp_full(src, + self, + src->ifindex != ifindex + ? NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX + : NM_L3_CONFIG_CMP_FLAGS_NONE) + == 0); nm_assert(nm_l3_config_data_get_ifindex(self) == ifindex); return self; -- cgit 1.3.0-6-gf8a5