mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-09-06 17:14:02 +00:00
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.
This commit is contained in:
parent
4366dc6582
commit
c43fe3d33d
|
@ -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 =
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
|
@ -100,14 +79,6 @@ typedef enum {
|
|||
NMP_NLM_FLAG_TEST = NMP_NLM_FLAG_F_EXCL,
|
||||
} 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
|
||||
|
@ -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; \
|
||||
;
|
||||
|
||||
|
@ -788,27 +609,6 @@ typedef struct {
|
|||
NMPlatformAction action;
|
||||
} NMPlatformTfilter;
|
||||
|
||||
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;
|
||||
|
@ -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
|
||||
|
|
|
@ -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"), );
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -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__ */
|
||||
|
|
Loading…
Reference in a new issue