summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-09-20 12:46:06 +0200
committerThomas Haller <thaller@redhat.com>2022-09-23 11:43:36 +0200
commitc43fe3d33d1e3aa028b437e3e81ab03b571b477f (patch)
tree6695728331c806f17b127380c84261c712c6520c /src
parent4366dc6582316ba713a1b1db373b64a6052f5ba8 (diff)
downloadNetworkManager-c43fe3d33d1e3aa028b437e3e81ab03b571b477f.tar.gz
platform: move NMPlatformIP[46]Address to "nmp-plobj.c"
Later, we should move all such objects. And we should rename the API to have a unique prefix, like "NMPPlObjIP[4]Address". This is just a first step that introduces more inconsistencies than it solves. It will get better afterwards.
Diffstat (limited to 'src')
-rw-r--r--src/libnm-platform/nm-platform.c657
-rw-r--r--src/libnm-platform/nm-platform.h296
-rw-r--r--src/libnm-platform/nmp-base.c60
-rw-r--r--src/libnm-platform/nmp-base.h23
-rw-r--r--src/libnm-platform/nmp-plobj.c628
-rw-r--r--src/libnm-platform/nmp-plobj.h272
6 files changed, 989 insertions, 947 deletions
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index 16c9c3abd5..95507a8ca5 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -3314,28 +3314,6 @@ nm_platform_wpan_set_channel(NMPlatform *self, int ifindex, guint8 page, guint8
_ifindex ? nm_sprintf_buf((arr), " dev %d", ifindex) : nm_str_truncate((arr)); \
})
-#define TO_STRING_IFA_FLAGS_BUF_SIZE 256
-
-static const char *
-_to_string_ifa_flags(guint32 ifa_flags, char *buf, gsize size)
-{
-#define S_FLAGS_PREFIX " flags "
- nm_assert(buf && size >= TO_STRING_IFA_FLAGS_BUF_SIZE && size > NM_STRLEN(S_FLAGS_PREFIX));
-
- if (!ifa_flags)
- buf[0] = '\0';
- else {
- nm_platform_addr_flags2str(ifa_flags,
- &buf[NM_STRLEN(S_FLAGS_PREFIX)],
- size - NM_STRLEN(S_FLAGS_PREFIX));
- if (buf[NM_STRLEN(S_FLAGS_PREFIX)] == '\0')
- buf[0] = '\0';
- else
- memcpy(buf, S_FLAGS_PREFIX, NM_STRLEN(S_FLAGS_PREFIX));
- }
- return buf;
-}
-
/*****************************************************************************/
gboolean
@@ -3541,72 +3519,6 @@ nm_platform_lookup_clone(NMPlatform *self,
user_data);
}
-void
-nm_platform_ip4_address_set_addr(NMPlatformIP4Address *addr, in_addr_t address, guint8 plen)
-{
- nm_assert(plen <= 32);
-
- addr->address = address;
- addr->peer_address = address;
- addr->plen = plen;
-}
-
-const struct in6_addr *
-nm_platform_ip6_address_get_peer(const NMPlatformIP6Address *addr)
-{
- if (IN6_IS_ADDR_UNSPECIFIED(&addr->peer_address)
- || IN6_ARE_ADDR_EQUAL(&addr->peer_address, &addr->address))
- return &addr->address;
- return &addr->peer_address;
-}
-
-gboolean
-nm_platform_ip_address_match(int addr_family,
- const NMPlatformIPAddress *address,
- NMPlatformMatchFlags match_flag)
-{
- nm_assert(!NM_FLAGS_ANY(
- match_flag,
- ~(NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY)));
- nm_assert(NM_FLAGS_ANY(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY));
- nm_assert(NM_FLAGS_ANY(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY));
-
- if (addr_family == AF_INET) {
- if (nm_ip4_addr_is_link_local(((NMPlatformIP4Address *) address)->address)) {
- if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL))
- return FALSE;
- } else {
- if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL))
- return FALSE;
- }
- } else {
- if (IN6_IS_ADDR_LINKLOCAL(address->address_ptr)) {
- if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL))
- return FALSE;
- } else {
- if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL))
- return FALSE;
- }
- }
-
- if (NM_FLAGS_HAS(address->n_ifa_flags, IFA_F_DADFAILED)) {
- if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED))
- return FALSE;
- } else if (NM_FLAGS_HAS(address->n_ifa_flags, IFA_F_TENTATIVE)
- && !NM_FLAGS_HAS(address->n_ifa_flags, IFA_F_OPTIMISTIC)) {
- if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE))
- return FALSE;
- } else if (NM_FLAGS_HAS(address->n_ifa_flags, IFA_F_DEPRECATED)) {
- if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_DEPRECATED))
- return FALSE;
- } else {
- if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL))
- return FALSE;
- }
-
- return TRUE;
-}
-
gboolean
nm_platform_ip4_address_add(NMPlatform *self,
int ifindex,
@@ -5820,37 +5732,6 @@ nm_platform_vlan_qos_mapping_to_string(const char *name,
return buf;
}
-static const char *
-_lifetime_to_string(guint32 timestamp, guint32 lifetime, gint32 now, char *buf, size_t buf_size)
-{
- if (lifetime == NM_PLATFORM_LIFETIME_PERMANENT)
- return "forever";
-
- g_snprintf(buf,
- buf_size,
- "%usec",
- nmp_utils_lifetime_rebase_relative_time_on_now(timestamp, lifetime, now));
- return buf;
-}
-
-static const char *
-_lifetime_summary_to_string(gint32 now,
- guint32 timestamp,
- guint32 preferred,
- guint32 lifetime,
- char *buf,
- size_t buf_size)
-{
- g_snprintf(buf,
- buf_size,
- " lifetime %d-%u[%u,%u]",
- (signed) now,
- (unsigned) timestamp,
- (unsigned) preferred,
- (unsigned) lifetime);
- return buf;
-}
-
/**
* nm_platform_link_to_string:
* @route: pointer to NMPlatformLink address structure
@@ -6691,244 +6572,6 @@ nm_platform_lnk_wireguard_to_string(const NMPlatformLnkWireGuard *lnk, char *buf
return buf;
}
-/**
- * nm_platform_ip4_address_to_string:
- * @route: pointer to NMPlatformIP4Address address structure
- * @buf: (allow-none): an optional buffer. If %NULL, a static buffer is used.
- * @len: the size of the @buf. If @buf is %NULL, this argument is ignored.
- *
- * A method for converting an address struct into a string representation.
- *
- * Example output: ""
- *
- * Returns: a string representation of the address.
- */
-const char *
-nm_platform_ip4_address_to_string(const NMPlatformIP4Address *address, char *buf, gsize len)
-{
- char s_flags[TO_STRING_IFA_FLAGS_BUF_SIZE];
- char s_address[INET_ADDRSTRLEN];
- char s_peer[INET_ADDRSTRLEN];
- char str_dev[30];
- char str_label[32];
- char str_lft[30];
- char str_pref[30];
- char str_time[50];
- char s_source[50];
- char *str_peer = NULL;
- const char *str_lft_p, *str_pref_p, *str_time_p;
- gint32 now = nm_utils_get_monotonic_timestamp_sec();
- in_addr_t broadcast_address;
- char str_broadcast[INET_ADDRSTRLEN];
-
- if (!nm_utils_to_string_buffer_init_null(address, &buf, &len))
- return buf;
-
- inet_ntop(AF_INET, &address->address, s_address, sizeof(s_address));
-
- if (address->peer_address != address->address) {
- inet_ntop(AF_INET, &address->peer_address, s_peer, sizeof(s_peer));
- str_peer = g_strconcat(" ptp ", s_peer, NULL);
- }
-
- if (*address->label)
- g_snprintf(str_label, sizeof(str_label), " label %s", address->label);
- else
- str_label[0] = 0;
-
- str_lft_p = _lifetime_to_string(address->timestamp,
- address->lifetime ?: NM_PLATFORM_LIFETIME_PERMANENT,
- now,
- str_lft,
- sizeof(str_lft)),
- str_pref_p =
- (address->lifetime == address->preferred)
- ? str_lft_p
- : (_lifetime_to_string(address->timestamp,
- address->lifetime ? MIN(address->preferred, address->lifetime)
- : NM_PLATFORM_LIFETIME_PERMANENT,
- now,
- str_pref,
- sizeof(str_pref)));
- str_time_p = _lifetime_summary_to_string(now,
- address->timestamp,
- address->preferred,
- address->lifetime,
- str_time,
- sizeof(str_time));
-
- broadcast_address = nm_platform_ip4_broadcast_address_from_addr(address);
-
- g_snprintf(
- buf,
- len,
- "%s/%d"
- "%s%s" /* broadcast */
- " lft %s"
- " pref %s"
- "%s" /* time */
- "%s" /* peer */
- "%s" /* dev */
- "%s" /* flags */
- "%s" /* label */
- " src %s"
- "%s" /* a_acd_not_ready */
- "%s" /* a_force_commit */
- "",
- s_address,
- address->plen,
- broadcast_address != 0u || address->use_ip4_broadcast_address
- ? (address->use_ip4_broadcast_address ? " brd " : " brd* ")
- : "",
- broadcast_address != 0u || address->use_ip4_broadcast_address
- ? nm_inet4_ntop(broadcast_address, str_broadcast)
- : "",
- str_lft_p,
- str_pref_p,
- str_time_p,
- str_peer ?: "",
- _to_string_dev(str_dev, address->ifindex),
- _to_string_ifa_flags(address->n_ifa_flags, s_flags, sizeof(s_flags)),
- str_label,
- nmp_utils_ip_config_source_to_string(address->addr_source, s_source, sizeof(s_source)),
- address->a_acd_not_ready ? " ip4acd-not-ready" : "",
- address->a_force_commit ? " force-commit" : "");
- g_free(str_peer);
- return buf;
-}
-
-NM_UTILS_FLAGS2STR_DEFINE(nm_platform_link_flags2str,
- unsigned,
- NM_UTILS_FLAGS2STR(IFF_LOOPBACK, "loopback"),
- NM_UTILS_FLAGS2STR(IFF_BROADCAST, "broadcast"),
- NM_UTILS_FLAGS2STR(IFF_POINTOPOINT, "pointopoint"),
- NM_UTILS_FLAGS2STR(IFF_MULTICAST, "multicast"),
- NM_UTILS_FLAGS2STR(IFF_NOARP, "noarp"),
- NM_UTILS_FLAGS2STR(IFF_ALLMULTI, "allmulti"),
- NM_UTILS_FLAGS2STR(IFF_PROMISC, "promisc"),
- NM_UTILS_FLAGS2STR(IFF_MASTER, "master"),
- NM_UTILS_FLAGS2STR(IFF_SLAVE, "slave"),
- NM_UTILS_FLAGS2STR(IFF_DEBUG, "debug"),
- NM_UTILS_FLAGS2STR(IFF_DYNAMIC, "dynamic"),
- NM_UTILS_FLAGS2STR(IFF_AUTOMEDIA, "automedia"),
- NM_UTILS_FLAGS2STR(IFF_PORTSEL, "portsel"),
- NM_UTILS_FLAGS2STR(IFF_NOTRAILERS, "notrailers"),
- NM_UTILS_FLAGS2STR(IFF_UP, "up"),
- NM_UTILS_FLAGS2STR(IFF_RUNNING, "running"),
- NM_UTILS_FLAGS2STR(IFF_LOWER_UP, "lowerup"),
- NM_UTILS_FLAGS2STR(IFF_DORMANT, "dormant"),
- NM_UTILS_FLAGS2STR(IFF_ECHO, "echo"), );
-
-NM_UTILS_ENUM2STR_DEFINE(nm_platform_link_inet6_addrgenmode2str,
- guint8,
- NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_NONE, "none"),
- NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_EUI64, "eui64"),
- NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY, "stable-privacy"),
- NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_RANDOM, "random"), );
-
-G_STATIC_ASSERT(IFA_F_SECONDARY == IFA_F_TEMPORARY);
-
-NM_UTILS_FLAGS2STR_DEFINE(nm_platform_addr_flags2str,
- unsigned,
- NM_UTILS_FLAGS2STR(IFA_F_SECONDARY, "secondary"),
- NM_UTILS_FLAGS2STR(IFA_F_NODAD, "nodad"),
- NM_UTILS_FLAGS2STR(IFA_F_OPTIMISTIC, "optimistic"),
- NM_UTILS_FLAGS2STR(IFA_F_DADFAILED, "dadfailed"),
- NM_UTILS_FLAGS2STR(IFA_F_HOMEADDRESS, "homeaddress"),
- NM_UTILS_FLAGS2STR(IFA_F_DEPRECATED, "deprecated"),
- NM_UTILS_FLAGS2STR(IFA_F_TENTATIVE, "tentative"),
- NM_UTILS_FLAGS2STR(IFA_F_PERMANENT, "permanent"),
- NM_UTILS_FLAGS2STR(IFA_F_MANAGETEMPADDR, "mngtmpaddr"),
- NM_UTILS_FLAGS2STR(IFA_F_NOPREFIXROUTE, "noprefixroute"),
- NM_UTILS_FLAGS2STR(IFA_F_MCAUTOJOIN, "mcautojoin"),
- NM_UTILS_FLAGS2STR(IFA_F_STABLE_PRIVACY, "stable-privacy"), );
-
-NM_UTILS_ENUM2STR_DEFINE(nm_platform_route_scope2str,
- int,
- NM_UTILS_ENUM2STR(RT_SCOPE_NOWHERE, "nowhere"),
- NM_UTILS_ENUM2STR(RT_SCOPE_HOST, "host"),
- NM_UTILS_ENUM2STR(RT_SCOPE_LINK, "link"),
- NM_UTILS_ENUM2STR(RT_SCOPE_SITE, "site"),
- NM_UTILS_ENUM2STR(RT_SCOPE_UNIVERSE, "global"), );
-
-/**
- * nm_platform_ip6_address_to_string:
- * @route: pointer to NMPlatformIP6Address address structure
- * @buf: (allow-none): an optional buffer. If %NULL, a static buffer is used.
- * @len: the size of the @buf. If @buf is %NULL, this argument is ignored.
- *
- * A method for converting an address struct into a string representation.
- *
- * Example output: "2001:db8:0:f101::1/64 lft 4294967295 pref 4294967295 time 16922666 on dev em1"
- *
- * Returns: a string representation of the address.
- */
-const char *
-nm_platform_ip6_address_to_string(const NMPlatformIP6Address *address, char *buf, gsize len)
-{
- char s_flags[TO_STRING_IFA_FLAGS_BUF_SIZE];
- char s_address[INET6_ADDRSTRLEN];
- char s_peer[INET6_ADDRSTRLEN];
- char str_lft[30];
- char str_pref[30];
- char str_time[50];
- char s_source[50];
- char str_dev[30];
- char *str_peer = NULL;
- const char *str_lft_p, *str_pref_p, *str_time_p;
- gint32 now = nm_utils_get_monotonic_timestamp_sec();
-
- if (!nm_utils_to_string_buffer_init_null(address, &buf, &len))
- return buf;
-
- inet_ntop(AF_INET6, &address->address, s_address, sizeof(s_address));
-
- if (!IN6_IS_ADDR_UNSPECIFIED(&address->peer_address)) {
- inet_ntop(AF_INET6, &address->peer_address, s_peer, sizeof(s_peer));
- str_peer = g_strconcat(" ptp ", s_peer, NULL);
- }
-
- str_lft_p = _lifetime_to_string(address->timestamp,
- address->lifetime ?: NM_PLATFORM_LIFETIME_PERMANENT,
- now,
- str_lft,
- sizeof(str_lft)),
- str_pref_p =
- (address->lifetime == address->preferred)
- ? str_lft_p
- : (_lifetime_to_string(address->timestamp,
- address->lifetime ? MIN(address->preferred, address->lifetime)
- : NM_PLATFORM_LIFETIME_PERMANENT,
- now,
- str_pref,
- sizeof(str_pref)));
- str_time_p = _lifetime_summary_to_string(now,
- address->timestamp,
- address->preferred,
- address->lifetime,
- str_time,
- sizeof(str_time));
-
- g_snprintf(
- buf,
- len,
- "%s/%d lft %s pref %s%s%s%s%s src %s"
- "%s" /* a_force_commit */
- "",
- s_address,
- address->plen,
- str_lft_p,
- str_pref_p,
- str_time_p,
- str_peer ?: "",
- _to_string_dev(str_dev, address->ifindex),
- _to_string_ifa_flags(address->n_ifa_flags, s_flags, sizeof(s_flags)),
- nmp_utils_ip_config_source_to_string(address->addr_source, s_source, sizeof(s_source)),
- address->a_force_commit ? " force-commit" : "");
- g_free(str_peer);
- return buf;
-}
-
static NM_UTILS_FLAGS2STR_DEFINE(_rtm_flags_to_string,
unsigned,
NM_UTILS_FLAGS2STR(RTNH_F_DEAD, "dead"),
@@ -8434,275 +8077,6 @@ nm_platform_lnk_wireguard_cmp(const NMPlatformLnkWireGuard *a, const NMPlatformL
return 0;
}
-static int
-_address_pretty_sort_get_prio_4(in_addr_t addr)
-{
- if (nm_ip4_addr_is_link_local(addr))
- return 0;
- return 1;
-}
-
-int
-nm_platform_ip4_address_pretty_sort_cmp(const NMPlatformIP4Address *a1,
- const NMPlatformIP4Address *a2)
-{
- in_addr_t n1;
- in_addr_t n2;
-
- nm_assert(a1);
- nm_assert(a2);
-
- /* Sort by address type. For example link local will
- * be sorted *after* a global address. */
- NM_CMP_DIRECT(_address_pretty_sort_get_prio_4(a2->address),
- _address_pretty_sort_get_prio_4(a1->address));
-
- /* Sort the addresses based on their source. */
- NM_CMP_DIRECT(a2->addr_source, a1->addr_source);
-
- NM_CMP_DIRECT((a2->label[0] == '\0'), (a1->label[0] == '\0'));
-
- /* Finally, sort addresses lexically. We compare only the
- * network part so that the order of addresses in the same
- * subnet (and thus also the primary/secondary role) is
- * preserved.
- */
- n1 = nm_ip4_addr_clear_host_address(a1->address, a1->plen);
- n2 = nm_ip4_addr_clear_host_address(a2->address, a2->plen);
- NM_CMP_DIRECT_MEMCMP(&n1, &n2, sizeof(guint32));
- return 0;
-}
-
-static int
-_address_pretty_sort_get_prio_6(const struct in6_addr *addr)
-{
- if (IN6_IS_ADDR_V4MAPPED(addr))
- return 0;
- if (IN6_IS_ADDR_V4COMPAT(addr))
- return 1;
- if (IN6_IS_ADDR_UNSPECIFIED(addr))
- return 2;
- if (IN6_IS_ADDR_LOOPBACK(addr))
- return 3;
- if (IN6_IS_ADDR_LINKLOCAL(addr))
- return 4;
- if (IN6_IS_ADDR_SITELOCAL(addr))
- return 5;
- return 6;
-}
-
-static int
-_address_cmp_expiry(const NMPlatformIPAddress *a, const NMPlatformIPAddress *b)
-{
- guint32 lifetime_a;
- guint32 lifetime_b;
- guint32 preferred_a;
- guint32 preferred_b;
- gint32 now = 0;
-
- lifetime_a =
- nmp_utils_lifetime_get(a->timestamp, a->lifetime, a->preferred, &now, &preferred_a);
- lifetime_b =
- nmp_utils_lifetime_get(b->timestamp, b->lifetime, b->preferred, &now, &preferred_b);
-
- NM_CMP_DIRECT(lifetime_a, lifetime_b);
- NM_CMP_DIRECT(preferred_a, preferred_b);
- return 0;
-}
-
-int
-nm_platform_ip6_address_pretty_sort_cmp(const NMPlatformIP6Address *a1,
- const NMPlatformIP6Address *a2,
- gboolean prefer_temp)
-{
- gboolean ipv6_privacy1;
- gboolean ipv6_privacy2;
-
- nm_assert(a1);
- nm_assert(a2);
-
- /* tentative addresses are always sorted back... */
- /* sort tentative addresses after non-tentative. */
- NM_CMP_DIRECT(NM_FLAGS_HAS(a1->n_ifa_flags, IFA_F_TENTATIVE),
- NM_FLAGS_HAS(a2->n_ifa_flags, IFA_F_TENTATIVE));
-
- /* Sort by address type. For example link local will
- * be sorted *after* site local or global. */
- NM_CMP_DIRECT(_address_pretty_sort_get_prio_6(&a2->address),
- _address_pretty_sort_get_prio_6(&a1->address));
-
- ipv6_privacy1 = NM_FLAGS_ANY(a1->n_ifa_flags, IFA_F_MANAGETEMPADDR | IFA_F_SECONDARY);
- ipv6_privacy2 = NM_FLAGS_ANY(a2->n_ifa_flags, IFA_F_MANAGETEMPADDR | IFA_F_SECONDARY);
- if (ipv6_privacy1 || ipv6_privacy2) {
- gboolean public1 = TRUE;
- gboolean public2 = TRUE;
-
- if (ipv6_privacy1) {
- if (a1->n_ifa_flags & IFA_F_SECONDARY)
- public1 = prefer_temp;
- else
- public1 = !prefer_temp;
- }
- if (ipv6_privacy2) {
- if (a2->n_ifa_flags & IFA_F_SECONDARY)
- public2 = prefer_temp;
- else
- public2 = !prefer_temp;
- }
-
- NM_CMP_DIRECT(public2, public1);
- }
-
- /* Sort the addresses based on their source. */
- NM_CMP_DIRECT(a2->addr_source, a1->addr_source);
-
- /* sort permanent addresses before non-permanent. */
- NM_CMP_DIRECT(NM_FLAGS_HAS(a2->n_ifa_flags, IFA_F_PERMANENT),
- NM_FLAGS_HAS(a1->n_ifa_flags, IFA_F_PERMANENT));
-
- /* finally sort addresses lexically */
- NM_CMP_DIRECT_IN6ADDR(&a1->address, &a2->address);
- NM_CMP_DIRECT_MEMCMP(a1, a2, sizeof(*a1));
- return 0;
-}
-
-void
-nm_platform_ip4_address_hash_update(const NMPlatformIP4Address *obj, NMHashState *h)
-{
- nm_hash_update_vals(h,
- obj->ifindex,
- obj->addr_source,
- obj->use_ip4_broadcast_address ? obj->broadcast_address : ((in_addr_t) 0u),
- obj->timestamp,
- obj->lifetime,
- obj->preferred,
- obj->n_ifa_flags,
- obj->plen,
- obj->address,
- obj->peer_address,
- NM_HASH_COMBINE_BOOLS(guint8,
- obj->use_ip4_broadcast_address,
- obj->a_acd_not_ready,
- obj->a_force_commit));
- nm_hash_update_strarr(h, obj->label);
-}
-
-int
-nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a,
- const NMPlatformIP4Address *b,
- NMPlatformIPAddressCmpType cmp_type)
-{
- NM_CMP_SELF(a, b);
-
- NM_CMP_FIELD(a, b, ifindex);
- NM_CMP_FIELD(a, b, plen);
- NM_CMP_FIELD(a, b, address);
-
- switch (cmp_type) {
- case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_ID:
- /* for IPv4 addresses, you can add the same local address with differing peer-address
- * (IFA_ADDRESS), provided that their net-part differs. */
- NM_CMP_DIRECT_IP4_ADDR_SAME_PREFIX(a->peer_address, b->peer_address, a->plen);
- return 0;
- case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_SEMANTICALLY:
- case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_FULL:
- NM_CMP_FIELD(a, b, peer_address);
- NM_CMP_FIELD_STR(a, b, label);
- if (cmp_type == NM_PLATFORM_IP_ADDRESS_CMP_TYPE_SEMANTICALLY) {
- NM_CMP_RETURN(_address_cmp_expiry((const NMPlatformIPAddress *) a,
- (const NMPlatformIPAddress *) b));
-
- /* Most flags are set by kernel. We only compare the ones that
- * NetworkManager actively sets.
- *
- * NM actively only sets IFA_F_NOPREFIXROUTE (and IFA_F_MANAGETEMPADDR for IPv6),
- * where nm_platform_ip_address_sync() sets IFA_F_NOPREFIXROUTE depending on
- * NMP_IP_ADDRESS_SYNC_FLAGS_WITH_NOPREFIXROUTE.
- * There are thus no flags to compare for IPv4. */
-
- NM_CMP_DIRECT(nm_platform_ip4_broadcast_address_from_addr(a),
- nm_platform_ip4_broadcast_address_from_addr(b));
- } else {
- NM_CMP_FIELD(a, b, timestamp);
- NM_CMP_FIELD(a, b, lifetime);
- NM_CMP_FIELD(a, b, preferred);
- NM_CMP_FIELD(a, b, n_ifa_flags);
- NM_CMP_FIELD(a, b, addr_source);
- NM_CMP_FIELD_UNSAFE(a, b, use_ip4_broadcast_address);
- if (a->use_ip4_broadcast_address)
- NM_CMP_FIELD(a, b, broadcast_address);
- NM_CMP_FIELD_UNSAFE(a, b, a_acd_not_ready);
- NM_CMP_FIELD_UNSAFE(a, b, a_force_commit);
- }
- return 0;
- }
- return nm_assert_unreachable_val(0);
-}
-
-void
-nm_platform_ip6_address_hash_update(const NMPlatformIP6Address *obj, NMHashState *h)
-{
- nm_hash_update_vals(h,
- obj->ifindex,
- obj->addr_source,
- obj->timestamp,
- obj->lifetime,
- obj->preferred,
- obj->n_ifa_flags,
- obj->plen,
- obj->address,
- obj->peer_address,
- NM_HASH_COMBINE_BOOLS(guint8, obj->a_force_commit));
-}
-
-int
-nm_platform_ip6_address_cmp(const NMPlatformIP6Address *a,
- const NMPlatformIP6Address *b,
- NMPlatformIPAddressCmpType cmp_type)
-{
- const struct in6_addr *p_a, *p_b;
-
- NM_CMP_SELF(a, b);
-
- NM_CMP_FIELD(a, b, ifindex);
- NM_CMP_FIELD_IN6ADDR(a, b, address);
-
- switch (cmp_type) {
- case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_ID:
- /* for IPv6 addresses, the prefix length is not part of the primary identifier. */
- return 0;
- case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_SEMANTICALLY:
- case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_FULL:
- NM_CMP_FIELD(a, b, plen);
- p_a = nm_platform_ip6_address_get_peer(a);
- p_b = nm_platform_ip6_address_get_peer(b);
- NM_CMP_DIRECT_MEMCMP(p_a, p_b, sizeof(*p_a));
- if (cmp_type == NM_PLATFORM_IP_ADDRESS_CMP_TYPE_SEMANTICALLY) {
- NM_CMP_RETURN(_address_cmp_expiry((const NMPlatformIPAddress *) a,
- (const NMPlatformIPAddress *) b));
-
- /* Most flags are set by kernel. We only compare the ones that
- * NetworkManager actively sets.
- *
- * NM actively only sets IFA_F_NOPREFIXROUTE and IFA_F_MANAGETEMPADDR,
- * where nm_platform_ip_address_sync() sets IFA_F_NOPREFIXROUTE depending on
- * NMP_IP_ADDRESS_SYNC_FLAGS_WITH_NOPREFIXROUTE.
- * We thus only care about IFA_F_MANAGETEMPADDR. */
- NM_CMP_DIRECT(a->n_ifa_flags & IFA_F_MANAGETEMPADDR,
- b->n_ifa_flags & IFA_F_MANAGETEMPADDR);
- } else {
- NM_CMP_FIELD(a, b, timestamp);
- NM_CMP_FIELD(a, b, lifetime);
- NM_CMP_FIELD(a, b, preferred);
- NM_CMP_FIELD(a, b, n_ifa_flags);
- NM_CMP_FIELD(a, b, addr_source);
- NM_CMP_FIELD_UNSAFE(a, b, a_force_commit);
- }
- return 0;
- }
- return nm_assert_unreachable_val(0);
-}
-
void
nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj,
NMPlatformIPRouteCmpType cmp_type,
@@ -9724,37 +9098,6 @@ nm_platform_netns_push(NMPlatform *self, NMPNetns **netns)
/*****************************************************************************/
-const _NMPlatformVTableAddressUnion nm_platform_vtable_address = {
- .v4 =
- {
- .is_ip4 = TRUE,
- .obj_type = NMP_OBJECT_TYPE_IP4_ADDRESS,
- .addr_family = AF_INET,
- .sizeof_address = sizeof(NMPlatformIP4Address),
- .address_cmp =
- (int (*)(const NMPlatformIPXAddress *a,
- const NMPlatformIPXAddress *b,
- NMPlatformIPAddressCmpType cmp_type)) nm_platform_ip4_address_cmp,
- .address_to_string = (const char *(*) (const NMPlatformIPXAddress *address,
- char *buf,
- gsize len)) nm_platform_ip4_address_to_string,
- },
- .v6 =
- {
- .is_ip4 = FALSE,
- .obj_type = NMP_OBJECT_TYPE_IP6_ADDRESS,
- .addr_family = AF_INET6,
- .sizeof_address = sizeof(NMPlatformIP6Address),
- .address_cmp =
- (int (*)(const NMPlatformIPXAddress *a,
- const NMPlatformIPXAddress *b,
- NMPlatformIPAddressCmpType cmp_type)) nm_platform_ip6_address_cmp,
- .address_to_string = (const char *(*) (const NMPlatformIPXAddress *address,
- char *buf,
- gsize len)) nm_platform_ip6_address_to_string,
- },
-};
-
const _NMPlatformVTableRouteUnion nm_platform_vtable_route = {
.v4 =
{
diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h
index d723fdbb07..2a0f756b8f 100644
--- a/src/libnm-platform/nm-platform.h
+++ b/src/libnm-platform/nm-platform.h
@@ -8,6 +8,7 @@
#include "libnm-platform/nmp-base.h"
#include "libnm-base/nm-base.h"
+#include "nmp-plobj.h"
#define NM_TYPE_PLATFORM (nm_platform_get_type())
#define NM_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_PLATFORM, NMPlatform))
@@ -29,36 +30,14 @@
/*****************************************************************************/
-/* IFNAMSIZ is both defined in <linux/if.h> and <net/if.h>. In the past, these
- * headers conflicted, so we cannot simply include either of them in a header-file.*/
-#define NMP_IFNAMSIZ 16
-
-/*****************************************************************************/
-
struct _NMPWireGuardPeer;
struct udev_device;
typedef gboolean (*NMPObjectPredicateFunc)(const NMPObject *obj, gpointer user_data);
-/* workaround for older libnl version, that does not define these flags. */
-#ifndef IFA_F_MANAGETEMPADDR
-#define IFA_F_MANAGETEMPADDR 0x100
-#endif
-#ifndef IFA_F_NOPREFIXROUTE
-#define IFA_F_NOPREFIXROUTE 0x200
-#endif
-
#define NM_RT_SCOPE_LINK 253 /* RT_SCOPE_LINK */
-/* Define of the IN6_ADDR_GEN_MODE_* values to workaround old kernel headers
- * that don't define it. */
-#define NM_IN6_ADDR_GEN_MODE_UNKNOWN 255 /* no corresponding value. */
-#define NM_IN6_ADDR_GEN_MODE_EUI64 0 /* IN6_ADDR_GEN_MODE_EUI64 */
-#define NM_IN6_ADDR_GEN_MODE_NONE 1 /* IN6_ADDR_GEN_MODE_NONE */
-#define NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY 2 /* IN6_ADDR_GEN_MODE_STABLE_PRIVACY */
-#define NM_IN6_ADDR_GEN_MODE_RANDOM 3 /* IN6_ADDR_GEN_MODE_RANDOM */
-
#define NM_IFF_MULTI_QUEUE 0x0100 /* IFF_MULTI_QUEUE */
#define NM_MPTCP_PM_ADDR_FLAG_SIGNAL ((guint32) (1 << 0))
@@ -101,14 +80,6 @@ typedef enum {
} NMPNlmFlags;
typedef enum {
- NM_PLATFORM_IP_ADDRESS_CMP_TYPE_ID,
-
- NM_PLATFORM_IP_ADDRESS_CMP_TYPE_SEMANTICALLY,
-
- NM_PLATFORM_IP_ADDRESS_CMP_TYPE_FULL,
-} NMPlatformIPAddressCmpType;
-
-typedef enum {
/* compare fields which kernel considers as similar routes.
* It is a looser comparisong then NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID
* and means that `ip route add` would fail to add two routes
@@ -171,35 +142,6 @@ G_STATIC_ASSERT(_nm_alignof(NMPLinkAddress) == 1);
gconstpointer nmp_link_address_get(const NMPLinkAddress *addr, size_t *length);
GBytes *nmp_link_address_get_as_bytes(const NMPLinkAddress *addr);
-typedef enum {
-
- /* match-flags are strictly inclusive. That means,
- * by default nothing is matched, but if you enable a particular
- * flag, a candidate that matches passes the check.
- *
- * In other words: adding more flags can only extend the result
- * set of matching objects.
- *
- * Also, the flags form partitions. Like, an address can be either of
- * ADDRTYPE_NORMAL or ADDRTYPE_LINKLOCAL, but never both. Same for
- * the ADDRSTATE match types.
- */
- NM_PLATFORM_MATCH_WITH_NONE = 0,
-
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL = (1LL << 0),
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL = (1LL << 1),
- NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY =
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL | NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL,
-
- NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL = (1LL << 2),
- NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE = (1LL << 3),
- NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED = (1LL << 4),
- NM_PLATFORM_MATCH_WITH_ADDRSTATE_DEPRECATED = (1LL << 5),
- NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY =
- NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED | NM_PLATFORM_MATCH_WITH_ADDRSTATE_DEPRECATED,
-} NMPlatformMatchFlags;
-
#define NM_PLATFORM_LINK_OTHER_NETNS (-1)
struct _NMPlatformObject {
@@ -208,10 +150,6 @@ struct _NMPlatformObject {
char _dummy_don_t_use_me;
};
-#define __NMPlatformObjWithIfindex_COMMON \
- int ifindex; \
- ;
-
struct _NMPlatformObjWithIfindex {
__NMPlatformObjWithIfindex_COMMON;
};
@@ -295,123 +233,6 @@ typedef enum {
NM_PLATFORM_SIGNAL_REMOVED,
} NMPlatformSignalChangeType;
-#define NM_PLATFORM_IP_ADDRESS_CAST(address) \
- NM_CONSTCAST(NMPlatformIPAddress, \
- (address), \
- NMPlatformIPXAddress, \
- NMPlatformIP4Address, \
- NMPlatformIP6Address)
-
-#define __NMPlatformIPAddress_COMMON \
- __NMPlatformObjWithIfindex_COMMON; \
- NMIPConfigSource addr_source; \
- \
- /* Timestamp in seconds in the reference system of nm_utils_get_monotonic_timestamp_*().
- *
- * The rules are:
- * 1 @lifetime==0: @timestamp and @preferred is irrelevant (but mostly set to 0 too). Such addresses
- * are permanent. This rule is so that unset addresses (calloc) are permanent by default.
- * 2 @lifetime==@preferred==NM_PLATFORM_LIFETIME_PERMANENT: @timestamp is irrelevant (but mostly
- * set to 0). Such addresses are permanent.
- * 3 Non permanent addresses should (almost) always have @timestamp > 0. 0 is not a valid timestamp
- * and never returned by nm_utils_get_monotonic_timestamp_sec(). In this case @valid/@preferred
- * is anchored at @timestamp.
- * 4 Non permanent addresses with @timestamp == 0 are implicitly anchored at *now*, thus the time
- * moves as time goes by. This is usually not useful, except e.g. nm_platform_ip[46]_address_add().
- *
- * Non permanent addresses from DHCP/RA might have the @timestamp set to the moment of when the
- * lease was received. Addresses from kernel might have the @timestamp based on the last modification
- * time of the addresses. But don't rely on this behaviour, the @timestamp is only defined for anchoring
- * @lifetime and @preferred.
- */ \
- guint32 timestamp; \
- guint32 lifetime; /* seconds since timestamp */ \
- guint32 preferred; /* seconds since timestamp */ \
- \
- /* ifa_flags in 'struct ifaddrmsg' from <linux/if_addr.h>, extended to 32 bit by
- * IFA_FLAGS attribute. */ \
- guint32 n_ifa_flags; \
- \
- bool use_ip4_broadcast_address : 1; \
- \
- /* Meta flags not honored by NMPlatform (netlink code). Instead, they can be
- * used by the upper layers which use NMPlatformIPRoute to track addresses that
- * should be configured. */ \
- bool a_force_commit : 1; \
- \
- /* Don't have a bitfield as last field in __NMPlatformIPAddress_COMMON. It would then
- * be unclear how the following fields get merged. We could also use a zero bitfield,
- * but instead we just have there the uint8 field. */ \
- guint8 plen; \
- ;
-
-/**
- * NMPlatformIPAddress:
- *
- * Common parts of NMPlatformIP4Address and NMPlatformIP6Address.
- **/
-typedef struct {
- __NMPlatformIPAddress_COMMON;
- _nm_alignas(NMIPAddr) guint8 address_ptr[];
-} NMPlatformIPAddress;
-
-/**
- * NMPlatformIP4Address:
- * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_sec()
- **/
-struct _NMPlatformIP4Address {
- __NMPlatformIPAddress_COMMON;
-
- /* The local address IFA_LOCAL. */
- _nm_alignas(NMIPAddr) in_addr_t address;
-
- /* The IFA_ADDRESS PTP peer address. This field is rather important, because
- * it constitutes the identifier for the IPv4 address (e.g. you can add two
- * addresses that only differ by their peer's network-part.
- *
- * Beware that for most cases, NetworkManager doesn't want to set an explicit
- * peer-address. However, that corresponds to setting the peer address to @address
- * itself. Leaving peer-address unset/zero, means explicitly setting the peer
- * address to 0.0.0.0, which you probably don't want.
- * */
- in_addr_t peer_address; /* PTP peer address */
-
- /* IFA_BROADCAST.
- *
- * This parameter is ignored unless use_ip4_broadcast_address is TRUE.
- * See nm_platform_ip4_broadcast_address_from_addr(). */
- in_addr_t broadcast_address;
-
- char label[NMP_IFNAMSIZ];
-
- /* Whether the address is ready to be configured. By default, an address is, but this
- * flag may indicate that the address is just for tracking purpose only, but the ACD
- * state is not yet ready for the address to be configured. */
- bool a_acd_not_ready : 1;
-};
-
-/**
- * NMPlatformIP6Address:
- * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_sec()
- **/
-struct _NMPlatformIP6Address {
- __NMPlatformIPAddress_COMMON;
- _nm_alignas(NMIPAddr) struct in6_addr address;
- struct in6_addr peer_address;
-};
-
-typedef union {
- NMPlatformIPAddress ax;
- NMPlatformIP4Address a4;
- NMPlatformIP6Address a6;
-} NMPlatformIPXAddress;
-
-#undef __NMPlatformIPAddress_COMMON
-
-#define NM_PLATFORM_IP4_ADDRESS_INIT(...) (&((const NMPlatformIP4Address){__VA_ARGS__}))
-
-#define NM_PLATFORM_IP6_ADDRESS_INIT(...) (&((const NMPlatformIP6Address){__VA_ARGS__}))
-
/* Default value for adding an IPv4 route. This is also what iproute2 does.
* Note that contrary to IPv6, you can add routes with metric 0 and it is even
* the default.
@@ -539,9 +360,9 @@ typedef union {
*/ \
guint8 type_coerced; \
\
- /* Don't have a bitfield as last field in __NMPlatformIPAddress_COMMON. It would then
+ /* Don't have a bitfield as last field in __NMPlatformIPRoute_COMMON. It would then
* be unclear how the following fields get merged. We could also use a zero bitfield,
- * but instead we just have there the uint8 field. */ \
+ * but instead we just have there the uint8 field. */ \
guint8 plen; \
;
@@ -790,27 +611,6 @@ typedef struct {
typedef struct {
bool is_ip4;
- NMPObjectType obj_type;
- gint8 addr_family;
- guint8 sizeof_address;
- int (*address_cmp)(const NMPlatformIPXAddress *a,
- const NMPlatformIPXAddress *b,
- NMPlatformIPAddressCmpType cmp_type);
- const char *(*address_to_string)(const NMPlatformIPXAddress *address, char *buf, gsize len);
-} NMPlatformVTableAddress;
-
-typedef union {
- struct {
- NMPlatformVTableAddress v6;
- NMPlatformVTableAddress v4;
- };
- NMPlatformVTableAddress vx[2];
-} _NMPlatformVTableAddressUnion;
-
-extern const _NMPlatformVTableAddressUnion nm_platform_vtable_address;
-
-typedef struct {
- bool is_ip4;
gint8 addr_family;
guint8 sizeof_route;
NMPObjectType obj_type;
@@ -1422,23 +1222,6 @@ GType nm_platform_get_type(void);
/*****************************************************************************/
-static inline in_addr_t
-nm_platform_ip4_broadcast_address_from_addr(const NMPlatformIP4Address *addr)
-{
- nm_assert(addr);
-
- if (addr->use_ip4_broadcast_address)
- return addr->broadcast_address;
-
- /* the set broadcast-address gets ignored, and we determine a default brd base
- * on the peer IFA_ADDRESS. */
- if (addr->peer_address != 0u && addr->plen < 31 /* RFC3021 */)
- return nm_ip4_addr_get_broadcast_address(addr->peer_address, addr->plen);
- return 0u;
-}
-
-/*****************************************************************************/
-
/**
* nm_platform_route_table_coerce:
* @table: the route table, in its original value as received
@@ -2228,9 +2011,6 @@ guint16 nm_platform_wpan_get_short_addr(NMPlatform *self, int ifindex);
gboolean nm_platform_wpan_set_short_addr(NMPlatform *self, int ifindex, guint16 short_addr);
gboolean nm_platform_wpan_set_channel(NMPlatform *self, int ifindex, guint8 page, guint8 channel);
-void nm_platform_ip4_address_set_addr(NMPlatformIP4Address *addr, in_addr_t address, guint8 plen);
-const struct in6_addr *nm_platform_ip6_address_get_peer(const NMPlatformIP6Address *addr);
-
const NMPObject *nm_platform_ip_address_get(NMPlatform *self,
int addr_family,
int ifindex,
@@ -2242,6 +2022,9 @@ const NMPlatformIP4Address *nm_platform_ip4_address_get(NMPlatform *self,
guint8 plen,
in_addr_t peer_address);
+const NMPlatformIP6Address *
+nm_platform_ip6_address_get(NMPlatform *self, int ifindex, const struct in6_addr *address);
+
int nm_platform_link_sit_add(NMPlatform *self,
const char *name,
const NMPlatformLnkSit *props,
@@ -2264,9 +2047,6 @@ int nm_platform_link_wireguard_change(NMPlatform *
guint peers_len,
NMPlatformWireGuardChangeFlags change_flags);
-const NMPlatformIP6Address *
-nm_platform_ip6_address_get(NMPlatform *self, int ifindex, const struct in6_addr *address);
-
gboolean nm_platform_object_delete(NMPlatform *self, const NMPObject *route);
gboolean nm_platform_ip4_address_add(NMPlatform *self,
@@ -2339,17 +2119,6 @@ nm_platform_ip_address_get_prune_list(NMPlatform *self,
gboolean nm_platform_ip_address_flush(NMPlatform *self, int addr_family, int ifindex);
-static inline gpointer
-nm_platform_ip_address_get_peer_address(int addr_family, const NMPlatformIPAddress *addr)
-{
- nm_assert_addr_family(addr_family);
- nm_assert(addr);
-
- if (NM_IS_IPv4(addr_family))
- return &((NMPlatformIP4Address *) addr)->peer_address;
- return &((NMPlatformIP6Address *) addr)->peer_address;
-}
-
void nm_platform_ip_route_normalize(int addr_family, NMPlatformIPRoute *route);
static inline guint32
@@ -2448,10 +2217,6 @@ const char *nm_platform_lnk_vrf_to_string(const NMPlatformLnkVrf *lnk, char *buf
const char *nm_platform_lnk_vxlan_to_string(const NMPlatformLnkVxlan *lnk, char *buf, gsize len);
const char *
nm_platform_lnk_wireguard_to_string(const NMPlatformLnkWireGuard *lnk, char *buf, gsize len);
-const char *
-nm_platform_ip4_address_to_string(const NMPlatformIP4Address *address, char *buf, gsize len);
-const char *
-nm_platform_ip6_address_to_string(const NMPlatformIP6Address *address, char *buf, gsize len);
const char *nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsize len);
const char *nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsize len);
const char *
@@ -2490,31 +2255,6 @@ int nm_platform_lnk_vlan_cmp(const NMPlatformLnkVlan *a, const NMPlatformLnkVlan
int nm_platform_lnk_vrf_cmp(const NMPlatformLnkVrf *a, const NMPlatformLnkVrf *b);
int nm_platform_lnk_vxlan_cmp(const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan *b);
int nm_platform_lnk_wireguard_cmp(const NMPlatformLnkWireGuard *a, const NMPlatformLnkWireGuard *b);
-int nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a,
- const NMPlatformIP4Address *b,
- NMPlatformIPAddressCmpType cmp_type);
-int nm_platform_ip6_address_cmp(const NMPlatformIP6Address *a,
- const NMPlatformIP6Address *b,
- NMPlatformIPAddressCmpType cmp_type);
-
-static inline int
-nm_platform_ip4_address_cmp_full(const NMPlatformIP4Address *a, const NMPlatformIP4Address *b)
-{
- return nm_platform_ip4_address_cmp(a, b, NM_PLATFORM_IP_ADDRESS_CMP_TYPE_FULL);
-}
-
-static inline int
-nm_platform_ip6_address_cmp_full(const NMPlatformIP6Address *a, const NMPlatformIP6Address *b)
-{
- return nm_platform_ip6_address_cmp(a, b, NM_PLATFORM_IP_ADDRESS_CMP_TYPE_FULL);
-}
-
-int nm_platform_ip4_address_pretty_sort_cmp(const NMPlatformIP4Address *a1,
- const NMPlatformIP4Address *a2);
-
-int nm_platform_ip6_address_pretty_sort_cmp(const NMPlatformIP6Address *a1,
- const NMPlatformIP6Address *a2,
- gboolean prefer_temp);
GHashTable *nm_platform_ip4_address_addr_to_hash(NMPlatform *self, int ifindex);
@@ -2556,8 +2296,6 @@ int nm_platform_tfilter_cmp(const NMPlatformTfilter *a, const NMPlatformTfilter
int nm_platform_mptcp_addr_cmp(const NMPlatformMptcpAddr *a, const NMPlatformMptcpAddr *b);
void nm_platform_link_hash_update(const NMPlatformLink *obj, NMHashState *h);
-void nm_platform_ip4_address_hash_update(const NMPlatformIP4Address *obj, NMHashState *h);
-void nm_platform_ip6_address_hash_update(const NMPlatformIP6Address *obj, NMHashState *h);
void nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj,
NMPlatformIPRouteCmpType cmp_type,
NMHashState *h);
@@ -2592,13 +2330,6 @@ gboolean nm_platform_mptcp_addr_index_addr_equal(gconstpointer data_a, gconstpoi
#define NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN ((gsize) 162)
-const char *nm_platform_link_flags2str(unsigned flags, char *buf, gsize len);
-const char *nm_platform_link_inet6_addrgenmode2str(guint8 mode, char *buf, gsize len);
-const char *nm_platform_addr_flags2str(unsigned flags, char *buf, gsize len);
-const char *nm_platform_route_scope2str(int scope, char *buf, gsize len);
-
-int nm_platform_ip_address_cmp_expiry(const NMPlatformIPAddress *a, const NMPlatformIPAddress *b);
-
gboolean nm_platform_ethtool_set_wake_on_lan(NMPlatform *self,
int ifindex,
_NMSettingWiredWakeOnLan wol,
@@ -2649,21 +2380,6 @@ struct _NMDedupMultiIndex *nm_platform_get_multi_idx(NMPlatform *self);
/*****************************************************************************/
-NMPlatformIP4Route *nm_platform_ip4_address_generate_device_route(const NMPlatformIP4Address *addr,
- int ifindex,
- guint32 route_table,
- guint32 route_metric,
- gboolean force_commit,
- NMPlatformIP4Route *dst);
-
-/*****************************************************************************/
-
-gboolean nm_platform_ip_address_match(int addr_family,
- const NMPlatformIPAddress *addr,
- NMPlatformMatchFlags match_flag);
-
-/*****************************************************************************/
-
guint16 nm_platform_genl_get_family_id(NMPlatform *self, NMPGenlFamilyType family_type);
int
diff --git a/src/libnm-platform/nmp-base.c b/src/libnm-platform/nmp-base.c
index 1ea327fdb3..c23190b307 100644
--- a/src/libnm-platform/nmp-base.c
+++ b/src/libnm-platform/nmp-base.c
@@ -6,3 +6,63 @@
#include "libnm-glib-aux/nm-default-glib-i18n-lib.h"
#include "nmp-base.h"
+
+#include <linux/rtnetlink.h>
+#include <linux/if.h>
+#include "nm-compat-headers/linux/if_addr.h"
+
+/*****************************************************************************/
+
+NM_UTILS_FLAGS2STR_DEFINE(nm_platform_link_flags2str,
+ unsigned,
+ NM_UTILS_FLAGS2STR(IFF_LOOPBACK, "loopback"),
+ NM_UTILS_FLAGS2STR(IFF_BROADCAST, "broadcast"),
+ NM_UTILS_FLAGS2STR(IFF_POINTOPOINT, "pointopoint"),
+ NM_UTILS_FLAGS2STR(IFF_MULTICAST, "multicast"),
+ NM_UTILS_FLAGS2STR(IFF_NOARP, "noarp"),
+ NM_UTILS_FLAGS2STR(IFF_ALLMULTI, "allmulti"),
+ NM_UTILS_FLAGS2STR(IFF_PROMISC, "promisc"),
+ NM_UTILS_FLAGS2STR(IFF_MASTER, "master"),
+ NM_UTILS_FLAGS2STR(IFF_SLAVE, "slave"),
+ NM_UTILS_FLAGS2STR(IFF_DEBUG, "debug"),
+ NM_UTILS_FLAGS2STR(IFF_DYNAMIC, "dynamic"),
+ NM_UTILS_FLAGS2STR(IFF_AUTOMEDIA, "automedia"),
+ NM_UTILS_FLAGS2STR(IFF_PORTSEL, "portsel"),
+ NM_UTILS_FLAGS2STR(IFF_NOTRAILERS, "notrailers"),
+ NM_UTILS_FLAGS2STR(IFF_UP, "up"),
+ NM_UTILS_FLAGS2STR(IFF_RUNNING, "running"),
+ NM_UTILS_FLAGS2STR(IFF_LOWER_UP, "lowerup"),
+ NM_UTILS_FLAGS2STR(IFF_DORMANT, "dormant"),
+ NM_UTILS_FLAGS2STR(IFF_ECHO, "echo"), );
+
+NM_UTILS_ENUM2STR_DEFINE(nm_platform_link_inet6_addrgenmode2str,
+ guint8,
+ NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_NONE, "none"),
+ NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_EUI64, "eui64"),
+ NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY, "stable-privacy"),
+ NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_RANDOM, "random"), );
+
+NM_UTILS_FLAGS2STR_DEFINE(nm_platform_addr_flags2str,
+ unsigned,
+ NM_UTILS_FLAGS2STR(IFA_F_SECONDARY, "secondary"),
+ NM_UTILS_FLAGS2STR(IFA_F_NODAD, "nodad"),
+ NM_UTILS_FLAGS2STR(IFA_F_OPTIMISTIC, "optimistic"),
+ NM_UTILS_FLAGS2STR(IFA_F_DADFAILED, "dadfailed"),
+ NM_UTILS_FLAGS2STR(IFA_F_HOMEADDRESS, "homeaddress"),
+ NM_UTILS_FLAGS2STR(IFA_F_DEPRECATED, "deprecated"),
+ NM_UTILS_FLAGS2STR(IFA_F_TENTATIVE, "tentative"),
+ NM_UTILS_FLAGS2STR(IFA_F_PERMANENT, "permanent"),
+ NM_UTILS_FLAGS2STR(IFA_F_MANAGETEMPADDR, "mngtmpaddr"),
+ NM_UTILS_FLAGS2STR(IFA_F_NOPREFIXROUTE, "noprefixroute"),
+ NM_UTILS_FLAGS2STR(IFA_F_MCAUTOJOIN, "mcautojoin"),
+ NM_UTILS_FLAGS2STR(IFA_F_STABLE_PRIVACY, "stable-privacy"), );
+
+G_STATIC_ASSERT(IFA_F_SECONDARY == IFA_F_TEMPORARY);
+
+NM_UTILS_ENUM2STR_DEFINE(nm_platform_route_scope2str,
+ int,
+ NM_UTILS_ENUM2STR(RT_SCOPE_NOWHERE, "nowhere"),
+ NM_UTILS_ENUM2STR(RT_SCOPE_HOST, "host"),
+ NM_UTILS_ENUM2STR(RT_SCOPE_LINK, "link"),
+ NM_UTILS_ENUM2STR(RT_SCOPE_SITE, "site"),
+ NM_UTILS_ENUM2STR(RT_SCOPE_UNIVERSE, "global"), );
diff --git a/src/libnm-platform/nmp-base.h b/src/libnm-platform/nmp-base.h
index a6ee3df1d1..9c1c4290f3 100644
--- a/src/libnm-platform/nmp-base.h
+++ b/src/libnm-platform/nmp-base.h
@@ -11,6 +11,22 @@
/*****************************************************************************/
+/* IFNAMSIZ is both defined in <linux/if.h> and <net/if.h>. In the past, these
+ * headers conflicted, so we cannot simply include either of them in a header-file.*/
+#define NMP_IFNAMSIZ 16
+
+/*****************************************************************************/
+
+/* Define of the IN6_ADDR_GEN_MODE_* values to workaround old kernel headers
+ * that don't define it. */
+#define NM_IN6_ADDR_GEN_MODE_UNKNOWN 255 /* no corresponding value. */
+#define NM_IN6_ADDR_GEN_MODE_EUI64 0 /* IN6_ADDR_GEN_MODE_EUI64 */
+#define NM_IN6_ADDR_GEN_MODE_NONE 1 /* IN6_ADDR_GEN_MODE_NONE */
+#define NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY 2 /* IN6_ADDR_GEN_MODE_STABLE_PRIVACY */
+#define NM_IN6_ADDR_GEN_MODE_RANDOM 3 /* IN6_ADDR_GEN_MODE_RANDOM */
+
+/*****************************************************************************/
+
typedef enum {
NM_PLATFORM_LINK_DUPLEX_UNKNOWN,
NM_PLATFORM_LINK_DUPLEX_HALF,
@@ -189,4 +205,11 @@ typedef enum {
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE,
} NMIPRouteTableSyncMode;
+/*****************************************************************************/
+
+const char *nm_platform_link_flags2str(unsigned flags, char *buf, gsize len);
+const char *nm_platform_link_inet6_addrgenmode2str(guint8 mode, char *buf, gsize len);
+const char *nm_platform_addr_flags2str(unsigned flags, char *buf, gsize len);
+const char *nm_platform_route_scope2str(int scope, char *buf, gsize len);
+
#endif /* __NMP_FWD_H__ */
diff --git a/src/libnm-platform/nmp-plobj.c b/src/libnm-platform/nmp-plobj.c
index d6e8fc2c10..c27aa1fcf0 100644
--- a/src/libnm-platform/nmp-plobj.c
+++ b/src/libnm-platform/nmp-plobj.c
@@ -7,3 +7,631 @@
#include "nmp-plobj.h"
+#include "nm-compat-headers/linux/if_addr.h"
+
+#include "libnm-glib-aux/nm-time-utils.h"
+#include "nm-platform-utils.h"
+
+/*****************************************************************************/
+
+#define TO_STRING_IFA_FLAGS_BUF_SIZE 256
+
+static const char *
+_to_string_ifa_flags(guint32 ifa_flags, char *buf, gsize size)
+{
+#define S_FLAGS_PREFIX " flags "
+ nm_assert(buf && size >= TO_STRING_IFA_FLAGS_BUF_SIZE && size > NM_STRLEN(S_FLAGS_PREFIX));
+
+ if (!ifa_flags)
+ buf[0] = '\0';
+ else {
+ nm_platform_addr_flags2str(ifa_flags,
+ &buf[NM_STRLEN(S_FLAGS_PREFIX)],
+ size - NM_STRLEN(S_FLAGS_PREFIX));
+ if (buf[NM_STRLEN(S_FLAGS_PREFIX)] == '\0')
+ buf[0] = '\0';
+ else
+ memcpy(buf, S_FLAGS_PREFIX, NM_STRLEN(S_FLAGS_PREFIX));
+ }
+ return buf;
+}
+
+#define _to_string_dev(arr, ifindex) \
+ ({ \
+ const int _ifindex = (ifindex); \
+ \
+ _ifindex ? nm_sprintf_buf((arr), " dev %d", ifindex) : nm_str_truncate((arr)); \
+ })
+
+static const char *
+_lifetime_to_string(guint32 timestamp, guint32 lifetime, gint32 now, char *buf, size_t buf_size)
+{
+ if (lifetime == NM_PLATFORM_LIFETIME_PERMANENT)
+ return "forever";
+
+ g_snprintf(buf,
+ buf_size,
+ "%usec",
+ nmp_utils_lifetime_rebase_relative_time_on_now(timestamp, lifetime, now));
+ return buf;
+}
+
+static const char *
+_lifetime_summary_to_string(gint32 now,
+ guint32 timestamp,
+ guint32 preferred,
+ guint32 lifetime,
+ char *buf,
+ size_t buf_size)
+{
+ g_snprintf(buf,
+ buf_size,
+ " lifetime %d-%u[%u,%u]",
+ (signed) now,
+ (unsigned) timestamp,
+ (unsigned) preferred,
+ (unsigned) lifetime);
+ return buf;
+}
+
+static int
+_address_cmp_expiry(const NMPlatformIPAddress *a, const NMPlatformIPAddress *b)
+{
+ guint32 lifetime_a;
+ guint32 lifetime_b;
+ guint32 preferred_a;
+ guint32 preferred_b;
+ gint32 now = 0;
+
+ lifetime_a =
+ nmp_utils_lifetime_get(a->timestamp, a->lifetime, a->preferred, &now, &preferred_a);
+ lifetime_b =
+ nmp_utils_lifetime_get(b->timestamp, b->lifetime, b->preferred, &now, &preferred_b);
+
+ NM_CMP_DIRECT(lifetime_a, lifetime_b);
+ NM_CMP_DIRECT(preferred_a, preferred_b);
+ return 0;
+}
+
+/*****************************************************************************/
+
+void
+nm_platform_ip4_address_hash_update(const NMPlatformIP4Address *obj, NMHashState *h)
+{
+ nm_hash_update_vals(h,
+ obj->ifindex,
+ obj->addr_source,
+ obj->use_ip4_broadcast_address ? obj->broadcast_address : ((in_addr_t) 0u),
+ obj->timestamp,
+ obj->lifetime,
+ obj->preferred,
+ obj->n_ifa_flags,
+ obj->plen,
+ obj->address,
+ obj->peer_address,
+ NM_HASH_COMBINE_BOOLS(guint8,
+ obj->use_ip4_broadcast_address,
+ obj->a_acd_not_ready,
+ obj->a_force_commit));
+ nm_hash_update_strarr(h, obj->label);
+}
+
+int
+nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a,
+ const NMPlatformIP4Address *b,
+ NMPlatformIPAddressCmpType cmp_type)
+{
+ NM_CMP_SELF(a, b);
+
+ NM_CMP_FIELD(a, b, ifindex);
+ NM_CMP_FIELD(a, b, plen);
+ NM_CMP_FIELD(a, b, address);
+
+ switch (cmp_type) {
+ case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_ID:
+ /* for IPv4 addresses, you can add the same local address with differing peer-address
+ * (IFA_ADDRESS), provided that their net-part differs. */
+ NM_CMP_DIRECT_IP4_ADDR_SAME_PREFIX(a->peer_address, b->peer_address, a->plen);
+ return 0;
+ case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_SEMANTICALLY:
+ case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_FULL:
+ NM_CMP_FIELD(a, b, peer_address);
+ NM_CMP_FIELD_STR(a, b, label);
+ if (cmp_type == NM_PLATFORM_IP_ADDRESS_CMP_TYPE_SEMANTICALLY) {
+ NM_CMP_RETURN(_address_cmp_expiry((const NMPlatformIPAddress *) a,
+ (const NMPlatformIPAddress *) b));
+
+ /* Most flags are set by kernel. We only compare the ones that
+ * NetworkManager actively sets.
+ *
+ * NM actively only sets IFA_F_NOPREFIXROUTE (and IFA_F_MANAGETEMPADDR for IPv6),
+ * where nm_platform_ip_address_sync() sets IFA_F_NOPREFIXROUTE depending on
+ * NMP_IP_ADDRESS_SYNC_FLAGS_WITH_NOPREFIXROUTE.
+ * There are thus no flags to compare for IPv4. */
+
+ NM_CMP_DIRECT(nm_platform_ip4_broadcast_address_from_addr(a),
+ nm_platform_ip4_broadcast_address_from_addr(b));
+ } else {
+ NM_CMP_FIELD(a, b, timestamp);
+ NM_CMP_FIELD(a, b, lifetime);
+ NM_CMP_FIELD(a, b, preferred);
+ NM_CMP_FIELD(a, b, n_ifa_flags);
+ NM_CMP_FIELD(a, b, addr_source);
+ NM_CMP_FIELD_UNSAFE(a, b, use_ip4_broadcast_address);
+ if (a->use_ip4_broadcast_address)
+ NM_CMP_FIELD(a, b, broadcast_address);
+ NM_CMP_FIELD_UNSAFE(a, b, a_acd_not_ready);
+ NM_CMP_FIELD_UNSAFE(a, b, a_force_commit);
+ }
+ return 0;
+ }
+ return nm_assert_unreachable_val(0);
+}
+
+/*****************************************************************************/
+
+void
+nm_platform_ip6_address_hash_update(const NMPlatformIP6Address *obj, NMHashState *h)
+{
+ nm_hash_update_vals(h,
+ obj->ifindex,
+ obj->addr_source,
+ obj->timestamp,
+ obj->lifetime,
+ obj->preferred,
+ obj->n_ifa_flags,
+ obj->plen,
+ obj->address,
+ obj->peer_address,
+ NM_HASH_COMBINE_BOOLS(guint8, obj->a_force_commit));
+}
+
+int
+nm_platform_ip6_address_cmp(const NMPlatformIP6Address *a,
+ const NMPlatformIP6Address *b,
+ NMPlatformIPAddressCmpType cmp_type)
+{
+ const struct in6_addr *p_a, *p_b;
+
+ NM_CMP_SELF(a, b);
+
+ NM_CMP_FIELD(a, b, ifindex);
+ NM_CMP_FIELD_IN6ADDR(a, b, address);
+
+ switch (cmp_type) {
+ case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_ID:
+ /* for IPv6 addresses, the prefix length is not part of the primary identifier. */
+ return 0;
+ case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_SEMANTICALLY:
+ case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_FULL:
+ NM_CMP_FIELD(a, b, plen);
+ p_a = nm_platform_ip6_address_get_peer(a);
+ p_b = nm_platform_ip6_address_get_peer(b);
+ NM_CMP_DIRECT_MEMCMP(p_a, p_b, sizeof(*p_a));
+ if (cmp_type == NM_PLATFORM_IP_ADDRESS_CMP_TYPE_SEMANTICALLY) {
+ NM_CMP_RETURN(_address_cmp_expiry((const NMPlatformIPAddress *) a,
+ (const NMPlatformIPAddress *) b));
+
+ /* Most flags are set by kernel. We only compare the ones that
+ * NetworkManager actively sets.
+ *
+ * NM actively only sets IFA_F_NOPREFIXROUTE and IFA_F_MANAGETEMPADDR,
+ * where nm_platform_ip_address_sync() sets IFA_F_NOPREFIXROUTE depending on
+ * NMP_IP_ADDRESS_SYNC_FLAGS_WITH_NOPREFIXROUTE.
+ * We thus only care about IFA_F_MANAGETEMPADDR. */
+ NM_CMP_DIRECT(a->n_ifa_flags & IFA_F_MANAGETEMPADDR,
+ b->n_ifa_flags & IFA_F_MANAGETEMPADDR);
+ } else {
+ NM_CMP_FIELD(a, b, timestamp);
+ NM_CMP_FIELD(a, b, lifetime);
+ NM_CMP_FIELD(a, b, preferred);
+ NM_CMP_FIELD(a, b, n_ifa_flags);
+ NM_CMP_FIELD(a, b, addr_source);
+ NM_CMP_FIELD_UNSAFE(a, b, a_force_commit);
+ }
+ return 0;
+ }
+ return nm_assert_unreachable_val(0);
+}
+
+/*****************************************************************************/
+
+static int
+_address_pretty_sort_get_prio_4(in_addr_t addr)
+{
+ if (nm_ip4_addr_is_link_local(addr))
+ return 0;
+ return 1;
+}
+
+static int
+_address_pretty_sort_get_prio_6(const struct in6_addr *addr)
+{
+ if (IN6_IS_ADDR_V4MAPPED(addr))
+ return 0;
+ if (IN6_IS_ADDR_V4COMPAT(addr))
+ return 1;
+ if (IN6_IS_ADDR_UNSPECIFIED(addr))
+ return 2;
+ if (IN6_IS_ADDR_LOOPBACK(addr))
+ return 3;
+ if (IN6_IS_ADDR_LINKLOCAL(addr))
+ return 4;
+ if (IN6_IS_ADDR_SITELOCAL(addr))
+ return 5;
+ return 6;
+}
+
+int
+nm_platform_ip4_address_pretty_sort_cmp(const NMPlatformIP4Address *a1,
+ const NMPlatformIP4Address *a2)
+{
+ in_addr_t n1;
+ in_addr_t n2;
+
+ nm_assert(a1);
+ nm_assert(a2);
+
+ /* Sort by address type. For example link local will
+ * be sorted *after* a global address. */
+ NM_CMP_DIRECT(_address_pretty_sort_get_prio_4(a2->address),
+ _address_pretty_sort_get_prio_4(a1->address));
+
+ /* Sort the addresses based on their source. */
+ NM_CMP_DIRECT(a2->addr_source, a1->addr_source);
+
+ NM_CMP_DIRECT((a2->label[0] == '\0'), (a1->label[0] == '\0'));
+
+ /* Finally, sort addresses lexically. We compare only the
+ * network part so that the order of addresses in the same
+ * subnet (and thus also the primary/secondary role) is
+ * preserved.
+ */
+ n1 = nm_ip4_addr_clear_host_address(a1->address, a1->plen);
+ n2 = nm_ip4_addr_clear_host_address(a2->address, a2->plen);
+ NM_CMP_DIRECT_MEMCMP(&n1, &n2, sizeof(guint32));
+ return 0;
+}
+
+int
+nm_platform_ip6_address_pretty_sort_cmp(const NMPlatformIP6Address *a1,
+ const NMPlatformIP6Address *a2,
+ gboolean prefer_temp)
+{
+ gboolean ipv6_privacy1;
+ gboolean ipv6_privacy2;
+
+ nm_assert(a1);
+ nm_assert(a2);
+
+ /* tentative addresses are always sorted back... */
+ /* sort tentative addresses after non-tentative. */
+ NM_CMP_DIRECT(NM_FLAGS_HAS(a1->n_ifa_flags, IFA_F_TENTATIVE),
+ NM_FLAGS_HAS(a2->n_ifa_flags, IFA_F_TENTATIVE));
+
+ /* Sort by address type. For example link local will
+ * be sorted *after* site local or global. */
+ NM_CMP_DIRECT(_address_pretty_sort_get_prio_6(&a2->address),
+ _address_pretty_sort_get_prio_6(&a1->address));
+
+ ipv6_privacy1 = NM_FLAGS_ANY(a1->n_ifa_flags, IFA_F_MANAGETEMPADDR | IFA_F_SECONDARY);
+ ipv6_privacy2 = NM_FLAGS_ANY(a2->n_ifa_flags, IFA_F_MANAGETEMPADDR | IFA_F_SECONDARY);
+ if (ipv6_privacy1 || ipv6_privacy2) {
+ gboolean public1 = TRUE;
+ gboolean public2 = TRUE;
+
+ if (ipv6_privacy1) {
+ if (a1->n_ifa_flags & IFA_F_SECONDARY)
+ public1 = prefer_temp;
+ else
+ public1 = !prefer_temp;
+ }
+ if (ipv6_privacy2) {
+ if (a2->n_ifa_flags & IFA_F_SECONDARY)
+ public2 = prefer_temp;
+ else
+ public2 = !prefer_temp;
+ }
+
+ NM_CMP_DIRECT(public2, public1);
+ }
+
+ /* Sort the addresses based on their source. */
+ NM_CMP_DIRECT(a2->addr_source, a1->addr_source);
+
+ /* sort permanent addresses before non-permanent. */
+ NM_CMP_DIRECT(NM_FLAGS_HAS(a2->n_ifa_flags, IFA_F_PERMANENT),
+ NM_FLAGS_HAS(a1->n_ifa_flags, IFA_F_PERMANENT));
+
+ /* finally sort addresses lexically */
+ NM_CMP_DIRECT_IN6ADDR(&a1->address, &a2->address);
+ NM_CMP_DIRECT_MEMCMP(a1, a2, sizeof(*a1));
+ return 0;
+}
+
+void
+nm_platform_ip4_address_set_addr(NMPlatformIP4Address *addr, in_addr_t address, guint8 plen)
+{
+ nm_assert(plen <= 32);
+
+ addr->address = address;
+ addr->peer_address = address;
+ addr->plen = plen;
+}
+
+const struct in6_addr *
+nm_platform_ip6_address_get_peer(const NMPlatformIP6Address *addr)
+{
+ if (IN6_IS_ADDR_UNSPECIFIED(&addr->peer_address)
+ || IN6_ARE_ADDR_EQUAL(&addr->peer_address, &addr->address))
+ return &addr->address;
+ return &addr->peer_address;
+}
+
+/*****************************************************************************/
+
+/**
+ * nm_platform_ip4_address_to_string:
+ * @route: pointer to NMPlatformIP4Address address structure
+ * @buf: (allow-none): an optional buffer. If %NULL, a static buffer is used.
+ * @len: the size of the @buf. If @buf is %NULL, this argument is ignored.
+ *
+ * A method for converting an address struct into a string representation.
+ *
+ * Example output: ""
+ *
+ * Returns: a string representation of the address.
+ */
+const char *
+nm_platform_ip4_address_to_string(const NMPlatformIP4Address *address, char *buf, gsize len)
+{
+ char s_flags[TO_STRING_IFA_FLAGS_BUF_SIZE];
+ char s_address[INET_ADDRSTRLEN];
+ char s_peer[INET_ADDRSTRLEN];
+ char str_dev[30];
+ char str_label[32];
+ char str_lft[30];
+ char str_pref[30];
+ char str_time[50];
+ char s_source[50];
+ char *str_peer = NULL;
+ const char *str_lft_p, *str_pref_p, *str_time_p;
+ gint32 now = nm_utils_get_monotonic_timestamp_sec();
+ in_addr_t broadcast_address;
+ char str_broadcast[INET_ADDRSTRLEN];
+
+ if (!nm_utils_to_string_buffer_init_null(address, &buf, &len))
+ return buf;
+
+ inet_ntop(AF_INET, &address->address, s_address, sizeof(s_address));
+
+ if (address->peer_address != address->address) {
+ inet_ntop(AF_INET, &address->peer_address, s_peer, sizeof(s_peer));
+ str_peer = g_strconcat(" ptp ", s_peer, NULL);
+ }
+
+ if (*address->label)
+ g_snprintf(str_label, sizeof(str_label), " label %s", address->label);
+ else
+ str_label[0] = 0;
+
+ str_lft_p = _lifetime_to_string(address->timestamp,
+ address->lifetime ?: NM_PLATFORM_LIFETIME_PERMANENT,
+ now,
+ str_lft,
+ sizeof(str_lft)),
+ str_pref_p =
+ (address->lifetime == address->preferred)
+ ? str_lft_p
+ : (_lifetime_to_string(address->timestamp,
+ address->lifetime ? MIN(address->preferred, address->lifetime)
+ : NM_PLATFORM_LIFETIME_PERMANENT,
+ now,
+ str_pref,
+ sizeof(str_pref)));
+ str_time_p = _lifetime_summary_to_string(now,
+ address->timestamp,
+ address->preferred,
+ address->lifetime,
+ str_time,
+ sizeof(str_time));
+
+ broadcast_address = nm_platform_ip4_broadcast_address_from_addr(address);
+
+ g_snprintf(
+ buf,
+ len,
+ "%s/%d"
+ "%s%s" /* broadcast */
+ " lft %s"
+ " pref %s"
+ "%s" /* time */
+ "%s" /* peer */
+ "%s" /* dev */
+ "%s" /* flags */
+ "%s" /* label */
+ " src %s"
+ "%s" /* a_acd_not_ready */
+ "%s" /* a_force_commit */
+ "",
+ s_address,
+ address->plen,
+ broadcast_address != 0u || address->use_ip4_broadcast_address
+ ? (address->use_ip4_broadcast_address ? " brd " : " brd* ")
+ : "",
+ broadcast_address != 0u || address->use_ip4_broadcast_address
+ ? nm_inet4_ntop(broadcast_address, str_broadcast)
+ : "",
+ str_lft_p,
+ str_pref_p,
+ str_time_p,
+ str_peer ?: "",
+ _to_string_dev(str_dev, address->ifindex),
+ _to_string_ifa_flags(address->n_ifa_flags, s_flags, sizeof(s_flags)),
+ str_label,
+ nmp_utils_ip_config_source_to_string(address->addr_source, s_source, sizeof(s_source)),
+ address->a_acd_not_ready ? " ip4acd-not-ready" : "",
+ address->a_force_commit ? " force-commit" : "");
+ g_free(str_peer);
+ return buf;
+}
+
+/**
+ * nm_platform_ip6_address_to_string:
+ * @route: pointer to NMPlatformIP6Address address structure
+ * @buf: (allow-none): an optional buffer. If %NULL, a static buffer is used.
+ * @len: the size of the @buf. If @buf is %NULL, this argument is ignored.
+ *
+ * A method for converting an address struct into a string representation.
+ *
+ * Example output: "2001:db8:0:f101::1/64 lft 4294967295 pref 4294967295 time 16922666 on dev em1"
+ *
+ * Returns: a string representation of the address.
+ */
+const char *
+nm_platform_ip6_address_to_string(const NMPlatformIP6Address *address, char *buf, gsize len)
+{
+ char s_flags[TO_STRING_IFA_FLAGS_BUF_SIZE];
+ char s_address[INET6_ADDRSTRLEN];
+ char s_peer[INET6_ADDRSTRLEN];
+ char str_lft[30];
+ char str_pref[30];
+ char str_time[50];
+ char s_source[50];
+ char str_dev[30];
+ char *str_peer = NULL;
+ const char *str_lft_p, *str_pref_p, *str_time_p;
+ gint32 now = nm_utils_get_monotonic_timestamp_sec();
+
+ if (!nm_utils_to_string_buffer_init_null(address, &buf, &len))
+ return buf;
+
+ inet_ntop(AF_INET6, &address->address, s_address, sizeof(s_address));
+
+ if (!IN6_IS_ADDR_UNSPECIFIED(&address->peer_address)) {
+ inet_ntop(AF_INET6, &address->peer_address, s_peer, sizeof(s_peer));
+ str_peer = g_strconcat(" ptp ", s_peer, NULL);
+ }
+
+ str_lft_p = _lifetime_to_string(address->timestamp,
+ address->lifetime ?: NM_PLATFORM_LIFETIME_PERMANENT,
+ now,
+ str_lft,
+ sizeof(str_lft)),
+ str_pref_p =
+ (address->lifetime == address->preferred)
+ ? str_lft_p
+ : (_lifetime_to_string(address->timestamp,
+ address->lifetime ? MIN(address->preferred, address->lifetime)
+ : NM_PLATFORM_LIFETIME_PERMANENT,
+ now,
+ str_pref,
+ sizeof(str_pref)));
+ str_time_p = _lifetime_summary_to_string(now,
+ address->timestamp,
+ address->preferred,
+ address->lifetime,
+ str_time,
+ sizeof(str_time));
+
+ g_snprintf(
+ buf,
+ len,
+ "%s/%d lft %s pref %s%s%s%s%s src %s"
+ "%s" /* a_force_commit */
+ "",
+ s_address,
+ address->plen,
+ str_lft_p,
+ str_pref_p,
+ str_time_p,
+ str_peer ?: "",
+ _to_string_dev(str_dev, address->ifindex),
+ _to_string_ifa_flags(address->n_ifa_flags, s_flags, sizeof(s_flags)),
+ nmp_utils_ip_config_source_to_string(address->addr_source, s_source, sizeof(s_source)),
+ address->a_force_commit ? " force-commit" : "");
+ g_free(str_peer);
+ return buf;
+}
+
+/*****************************************************************************/
+
+gboolean
+nm_platform_ip_address_match(int addr_family,
+ const NMPlatformIPAddress *address,
+ NMPlatformMatchFlags match_flag)
+{
+ nm_assert(!NM_FLAGS_ANY(
+ match_flag,
+ ~(NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY)));
+ nm_assert(NM_FLAGS_ANY(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY));
+ nm_assert(NM_FLAGS_ANY(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY));
+
+ if (addr_family == AF_INET) {
+ if (nm_ip4_addr_is_link_local(((NMPlatformIP4Address *) address)->address)) {
+ if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL))
+ return FALSE;
+ } else {
+ if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL))
+ return FALSE;
+ }
+ } else {
+ if (IN6_IS_ADDR_LINKLOCAL(address->address_ptr)) {
+ if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL))
+ return FALSE;
+ } else {
+ if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL))
+ return FALSE;
+ }
+ }
+
+ if (NM_FLAGS_HAS(address->n_ifa_flags, IFA_F_DADFAILED)) {
+ if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED))
+ return FALSE;
+ } else if (NM_FLAGS_HAS(address->n_ifa_flags, IFA_F_TENTATIVE)
+ && !NM_FLAGS_HAS(address->n_ifa_flags, IFA_F_OPTIMISTIC)) {
+ if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE))
+ return FALSE;
+ } else if (NM_FLAGS_HAS(address->n_ifa_flags, IFA_F_DEPRECATED)) {
+ if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_DEPRECATED))
+ return FALSE;
+ } else {
+ if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*****************************************************************************/
+
+const _NMPlatformVTableAddressUnion nm_platform_vtable_address = {
+ .v4 =
+ {
+ .is_ip4 = TRUE,
+ .obj_type = NMP_OBJECT_TYPE_IP4_ADDRESS,
+ .addr_family = AF_INET,
+ .sizeof_address = sizeof(NMPlatformIP4Address),
+ .address_cmp =
+ (int (*)(const NMPlatformIPXAddress *a,
+ const NMPlatformIPXAddress *b,
+ NMPlatformIPAddressCmpType cmp_type)) nm_platform_ip4_address_cmp,
+ .address_to_string = (const char *(*) (const NMPlatformIPXAddress *address,
+ char *buf,
+ gsize len)) nm_platform_ip4_address_to_string,
+ },
+ .v6 =
+ {
+ .is_ip4 = FALSE,
+ .obj_type = NMP_OBJECT_TYPE_IP6_ADDRESS,
+ .addr_family = AF_INET6,
+ .sizeof_address = sizeof(NMPlatformIP6Address),
+ .address_cmp =
+ (int (*)(const NMPlatformIPXAddress *a,
+ const NMPlatformIPXAddress *b,
+ NMPlatformIPAddressCmpType cmp_type)) nm_platform_ip6_address_cmp,
+ .address_to_string = (const char *(*) (const NMPlatformIPXAddress *address,
+ char *buf,
+ gsize len)) nm_platform_ip6_address_to_string,
+ },
+};
diff --git a/src/libnm-platform/nmp-plobj.h b/src/libnm-platform/nmp-plobj.h
index e18983f187..d33abef241 100644
--- a/src/libnm-platform/nmp-plobj.h
+++ b/src/libnm-platform/nmp-plobj.h
@@ -6,4 +6,276 @@
#ifndef __NMP_PLOBJ_H__
#define __NMP_PLOBJ_H__
+#include "libnm-base/nm-base.h"
+
+#include "nmp-base.h"
+
+/*****************************************************************************/
+
+#define __NMPlatformObjWithIfindex_COMMON \
+ int ifindex; \
+ ;
+
+/*****************************************************************************/
+
+#define __NMPlatformIPAddress_COMMON \
+ __NMPlatformObjWithIfindex_COMMON; \
+ NMIPConfigSource addr_source; \
+ \
+ /* Timestamp in seconds in the reference system of nm_utils_get_monotonic_timestamp_*().
+ *
+ * The rules are:
+ * 1 @lifetime==0: @timestamp and @preferred is irrelevant (but mostly set to 0 too). Such addresses
+ * are permanent. This rule is so that unset addresses (calloc) are permanent by default.
+ * 2 @lifetime==@preferred==NM_PLATFORM_LIFETIME_PERMANENT: @timestamp is irrelevant (but mostly
+ * set to 0). Such addresses are permanent.
+ * 3 Non permanent addresses should (almost) always have @timestamp > 0. 0 is not a valid timestamp
+ * and never returned by nm_utils_get_monotonic_timestamp_sec(). In this case @valid/@preferred
+ * is anchored at @timestamp.
+ * 4 Non permanent addresses with @timestamp == 0 are implicitly anchored at *now*, thus the time
+ * moves as time goes by. This is usually not useful, except e.g. nm_platform_ip[46]_address_add().
+ *
+ * Non permanent addresses from DHCP/RA might have the @timestamp set to the moment of when the
+ * lease was received. Addresses from kernel might have the @timestamp based on the last modification
+ * time of the addresses. But don't rely on this behaviour, the @timestamp is only defined for anchoring
+ * @lifetime and @preferred.
+ */ \
+ guint32 timestamp; \
+ guint32 lifetime; /* seconds since timestamp */ \
+ guint32 preferred; /* seconds since timestamp */ \
+ \
+ /* ifa_flags in 'struct ifaddrmsg' from <linux/if_addr.h>, extended to 32 bit by
+ * IFA_FLAGS attribute. */ \
+ guint32 n_ifa_flags; \
+ \
+ bool use_ip4_broadcast_address : 1; \
+ \
+ /* Meta flags not honored by NMPlatform (netlink code). Instead, they can be
+ * used by the upper layers which use NMPlatformIPRoute to track addresses that
+ * should be configured. */ \
+ bool a_force_commit : 1; \
+ \
+ /* Don't have a bitfield as last field in __NMPlatformIPAddress_COMMON. It would then
+ * be unclear how the following fields get merged. We could also use a zero bitfield,
+ * but instead we just have there the uint8 field. */ \
+ guint8 plen; \
+ ;
+
+/**
+ * NMPlatformIPAddress:
+ *
+ * Common parts of NMPlatformIP4Address and NMPlatformIP6Address.
+ **/
+typedef struct {
+ __NMPlatformIPAddress_COMMON;
+ _nm_alignas(NMIPAddr) guint8 address_ptr[];
+} NMPlatformIPAddress;
+
+/**
+ * NMPlatformIP4Address:
+ * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_sec()
+ **/
+struct _NMPlatformIP4Address {
+ __NMPlatformIPAddress_COMMON;
+
+ /* The local address IFA_LOCAL. */
+ _nm_alignas(NMIPAddr) in_addr_t address;
+
+ /* The IFA_ADDRESS PTP peer address. This field is rather important, because
+ * it constitutes the identifier for the IPv4 address (e.g. you can add two
+ * addresses that only differ by their peer's network-part.
+ *
+ * Beware that for most cases, NetworkManager doesn't want to set an explicit
+ * peer-address. However, that corresponds to setting the peer address to @address
+ * itself. Leaving peer-address unset/zero, means explicitly setting the peer
+ * address to 0.0.0.0, which you probably don't want.
+ * */
+ in_addr_t peer_address; /* PTP peer address */
+
+ /* IFA_BROADCAST.
+ *
+ * This parameter is ignored unless use_ip4_broadcast_address is TRUE.
+ * See nm_platform_ip4_broadcast_address_from_addr(). */
+ in_addr_t broadcast_address;
+
+ char label[NMP_IFNAMSIZ];
+
+ /* Whether the address is ready to be configured. By default, an address is, but this
+ * flag may indicate that the address is just for tracking purpose only, but the ACD
+ * state is not yet ready for the address to be configured. */
+ bool a_acd_not_ready : 1;
+};
+
+/**
+ * NMPlatformIP6Address:
+ * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_sec()
+ **/
+struct _NMPlatformIP6Address {
+ __NMPlatformIPAddress_COMMON;
+ _nm_alignas(NMIPAddr) struct in6_addr address;
+ struct in6_addr peer_address;
+};
+
+typedef union {
+ NMPlatformIPAddress ax;
+ NMPlatformIP4Address a4;
+ NMPlatformIP6Address a6;
+} NMPlatformIPXAddress;
+
+#undef __NMPlatformIPAddress_COMMON
+
+/*****************************************************************************/
+
+typedef enum {
+ NM_PLATFORM_IP_ADDRESS_CMP_TYPE_ID,
+
+ NM_PLATFORM_IP_ADDRESS_CMP_TYPE_SEMANTICALLY,
+
+ NM_PLATFORM_IP_ADDRESS_CMP_TYPE_FULL,
+} NMPlatformIPAddressCmpType;
+
+#define NM_PLATFORM_IP_ADDRESS_CAST(address) \
+ NM_CONSTCAST(NMPlatformIPAddress, \
+ (address), \
+ NMPlatformIPXAddress, \
+ NMPlatformIP4Address, \
+ NMPlatformIP6Address)
+
+#define NM_PLATFORM_IP4_ADDRESS_INIT(...) (&((const NMPlatformIP4Address){__VA_ARGS__}))
+
+#define NM_PLATFORM_IP6_ADDRESS_INIT(...) (&((const NMPlatformIP6Address){__VA_ARGS__}))
+
+/*****************************************************************************/
+
+typedef struct {
+ bool is_ip4;
+ NMPObjectType obj_type;
+ gint8 addr_family;
+ guint8 sizeof_address;
+ int (*address_cmp)(const NMPlatformIPXAddress *a,
+ const NMPlatformIPXAddress *b,
+ NMPlatformIPAddressCmpType cmp_type);
+ const char *(*address_to_string)(const NMPlatformIPXAddress *address, char *buf, gsize len);
+} NMPlatformVTableAddress;
+
+typedef union {
+ struct {
+ NMPlatformVTableAddress v6;
+ NMPlatformVTableAddress v4;
+ };
+ NMPlatformVTableAddress vx[2];
+} _NMPlatformVTableAddressUnion;
+
+extern const _NMPlatformVTableAddressUnion nm_platform_vtable_address;
+
+void nm_platform_ip4_address_hash_update(const NMPlatformIP4Address *obj, NMHashState *h);
+
+int nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a,
+ const NMPlatformIP4Address *b,
+ NMPlatformIPAddressCmpType cmp_type);
+
+static inline int
+nm_platform_ip4_address_cmp_full(const NMPlatformIP4Address *a, const NMPlatformIP4Address *b)
+{
+ return nm_platform_ip4_address_cmp(a, b, NM_PLATFORM_IP_ADDRESS_CMP_TYPE_FULL);
+}
+
+void nm_platform_ip6_address_hash_update(const NMPlatformIP6Address *obj, NMHashState *h);
+
+int nm_platform_ip6_address_cmp(const NMPlatformIP6Address *a,
+ const NMPlatformIP6Address *b,
+ NMPlatformIPAddressCmpType cmp_type);
+
+static inline int
+nm_platform_ip6_address_cmp_full(const NMPlatformIP6Address *a, const NMPlatformIP6Address *b)
+{
+ return nm_platform_ip6_address_cmp(a, b, NM_PLATFORM_IP_ADDRESS_CMP_TYPE_FULL);
+}
+
+int nm_platform_ip4_address_pretty_sort_cmp(const NMPlatformIP4Address *a1,
+ const NMPlatformIP4Address *a2);
+
+int nm_platform_ip6_address_pretty_sort_cmp(const NMPlatformIP6Address *a1,
+ const NMPlatformIP6Address *a2,
+ gboolean prefer_temp);
+
+static inline in_addr_t
+nm_platform_ip4_broadcast_address_from_addr(const NMPlatformIP4Address *addr)
+{
+ nm_assert(addr);
+
+ if (addr->use_ip4_broadcast_address)
+ return addr->broadcast_address;
+
+ /* the set broadcast-address gets ignored, and we determine a default brd base
+ * on the peer IFA_ADDRESS. */
+ if (addr->peer_address != 0u && addr->plen < 31 /* RFC3021 */)
+ return nm_ip4_addr_get_broadcast_address(addr->peer_address, addr->plen);
+ return 0u;
+}
+
+void nm_platform_ip4_address_set_addr(NMPlatformIP4Address *addr, in_addr_t address, guint8 plen);
+
+const struct in6_addr *nm_platform_ip6_address_get_peer(const NMPlatformIP6Address *addr);
+
+static inline gpointer
+nm_platform_ip_address_get_peer_address(int addr_family, const NMPlatformIPAddress *addr)
+{
+ nm_assert_addr_family(addr_family);
+ nm_assert(addr);
+
+ if (NM_IS_IPv4(addr_family))
+ return &((NMPlatformIP4Address *) addr)->peer_address;
+ return &((NMPlatformIP6Address *) addr)->peer_address;
+}
+
+const char *
+nm_platform_ip4_address_to_string(const NMPlatformIP4Address *address, char *buf, gsize len);
+const char *
+nm_platform_ip6_address_to_string(const NMPlatformIP6Address *address, char *buf, gsize len);
+
+int nm_platform_ip_address_cmp_expiry(const NMPlatformIPAddress *a, const NMPlatformIPAddress *b);
+
+NMPlatformIP4Route *nm_platform_ip4_address_generate_device_route(const NMPlatformIP4Address *addr,
+ int ifindex,
+ guint32 route_table,
+ guint32 route_metric,
+ gboolean force_commit,
+ NMPlatformIP4Route *dst);
+
+typedef enum {
+
+ /* match-flags are strictly inclusive. That means,
+ * by default nothing is matched, but if you enable a particular
+ * flag, a candidate that matches passes the check.
+ *
+ * In other words: adding more flags can only extend the result
+ * set of matching objects.
+ *
+ * Also, the flags form partitions. Like, an address can be either of
+ * ADDRTYPE_NORMAL or ADDRTYPE_LINKLOCAL, but never both. Same for
+ * the ADDRSTATE match types.
+ */
+ NM_PLATFORM_MATCH_WITH_NONE = 0,
+
+ NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL = (1LL << 0),
+ NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL = (1LL << 1),
+ NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY =
+ NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL | NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL,
+
+ NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL = (1LL << 2),
+ NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE = (1LL << 3),
+ NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED = (1LL << 4),
+ NM_PLATFORM_MATCH_WITH_ADDRSTATE_DEPRECATED = (1LL << 5),
+ NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY =
+ NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE
+ | NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED | NM_PLATFORM_MATCH_WITH_ADDRSTATE_DEPRECATED,
+} NMPlatformMatchFlags;
+
+gboolean nm_platform_ip_address_match(int addr_family,
+ const NMPlatformIPAddress *addr,
+ NMPlatformMatchFlags match_flag);
+
+/*****************************************************************************/
+
#endif /* __NMP_PLOBJ_H__ */