platform: merge branch 'th/platform-obj-rename-pt1'

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1384
This commit is contained in:
Thomas Haller 2022-09-23 11:45:13 +02:00
commit f094977a86
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
22 changed files with 1112 additions and 1011 deletions

View file

@ -317,7 +317,10 @@ The second include is the header that belongs to the C source file. This
is so that header files are self-contained (aside what default dependencies that
they get and everybody can rely on).
The next includes are system headers with `<>`.
The next includes are system headers with `<>`. Exceptions are headers like
"libnm-std-aux/nm-linux-compat.h" and "nm-compat-headers/\*" which are our small
wrappers around system headers. These are also to be included together with system
headers.
Finally, all other headers from our source tree. Note that all build targets
have `-I. -I./src/` in their build arguments. So to include a header like

View file

@ -596,6 +596,8 @@ src_libnm_platform_libnm_platform_la_SOURCES = \
src/linux-headers/nl80211-vnd-intel.h \
src/linux-headers/nl802154.h \
\
src/nm-compat-headers/linux/if_addr.h \
\
src/libnm-platform/nm-linux-platform.c \
src/libnm-platform/nm-linux-platform.h \
src/libnm-platform/nm-netlink.c \
@ -605,6 +607,7 @@ src_libnm_platform_libnm_platform_la_SOURCES = \
src/libnm-platform/nm-platform-utils.h \
src/libnm-platform/nm-platform.c \
src/libnm-platform/nm-platform.h \
src/libnm-platform/nmp-base.c \
src/libnm-platform/nmp-base.h \
src/libnm-platform/nmp-global-tracker.c \
src/libnm-platform/nmp-global-tracker.h \
@ -612,6 +615,8 @@ src_libnm_platform_libnm_platform_la_SOURCES = \
src/libnm-platform/nmp-netns.h \
src/libnm-platform/nmp-object.c \
src/libnm-platform/nmp-object.h \
src/libnm-platform/nmp-plobj.c \
src/libnm-platform/nmp-plobj.h \
src/libnm-platform/wifi/nm-wifi-utils-nl80211.c \
src/libnm-platform/wifi/nm-wifi-utils-nl80211.h \
src/libnm-platform/wifi/nm-wifi-utils-private.h \

View file

@ -18,7 +18,7 @@
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <linux/if.h>
#include <linux/if_addr.h>
#include "nm-compat-headers/linux/if_addr.h"
#include <linux/rtnetlink.h>
#include <linux/if_ether.h>
#include <linux/if_infiniband.h>

View file

@ -8,7 +8,7 @@
#include <stdlib.h>
#include <netinet/in.h>
#include <linux/if_addr.h>
#include "nm-compat-headers/linux/if_addr.h"
#include "nm-setting-ip6-config.h"
#include "NetworkManagerUtils.h"

View file

@ -5,7 +5,7 @@
#include "nm-l3-config-data.h"
#include <linux/if.h>
#include <linux/if_addr.h>
#include "nm-compat-headers/linux/if_addr.h"
#include <linux/rtnetlink.h>
#include "libnm-core-intern/nm-core-internal.h"

View file

@ -4,7 +4,7 @@
#include "nm-l3-ipv6ll.h"
#include <linux/if_addr.h>
#include "nm-compat-headers/linux/if_addr.h"
#include "nm-core-utils.h"

View file

@ -7,7 +7,7 @@
#include "libnm-std-aux/nm-linux-compat.h"
#include <net/if.h>
#include <linux/if_addr.h>
#include "nm-compat-headers/linux/if_addr.h"
#include <linux/if_ether.h>
#include <linux/rtnetlink.h>

View file

@ -73,7 +73,7 @@ test_cleanup_internal(void)
addr4,
plen4,
addr4,
nm_platform_ip4_broadcast_address_create(addr4, plen4),
nm_ip4_addr_get_broadcast_address(addr4, plen4),
lifetime,
preferred,
0,

View file

@ -691,17 +691,16 @@ test_ip4_route_options(gconstpointer test_data)
const NMPlatformIP4Address *a = &addr[i];
g_assert(a->ifindex == IFINDEX);
g_assert(nm_platform_ip4_address_add(
NM_PLATFORM_GET,
a->ifindex,
a->address,
a->plen,
a->peer_address,
nm_platform_ip4_broadcast_address_create(a->address, a->plen),
a->lifetime,
a->preferred,
a->n_ifa_flags,
a->label));
g_assert(nm_platform_ip4_address_add(NM_PLATFORM_GET,
a->ifindex,
a->address,
a->plen,
a->peer_address,
nm_ip4_addr_get_broadcast_address(a->address, a->plen),
a->lifetime,
a->preferred,
a->n_ifa_flags,
a->label));
if (a->peer_address == a->address)
_wait_for_ipv4_addr_device_route(NM_PLATFORM_GET, 200, a->ifindex, a->address, a->plen);
}

View file

@ -2,7 +2,7 @@
#include "src/core/nm-default-daemon.h"
#include <linux/if_addr.h>
#include "nm-compat-headers/linux/if_addr.h"
#include "nm-l3cfg.h"
#include "nm-l3-ipv4ll.h"

View file

@ -174,6 +174,12 @@ nm_ip4_addr_netmask_from_prefix(guint32 prefix)
guint32 nm_ip4_addr_get_default_prefix0(in_addr_t ip);
guint32 nm_ip4_addr_get_default_prefix(in_addr_t ip);
static inline in_addr_t
nm_ip4_addr_get_broadcast_address(in_addr_t address, guint8 plen)
{
return address | ~nm_ip4_addr_netmask_from_prefix(plen);
}
gconstpointer
nm_ip_addr_clear_host_address(int family, gpointer dst, gconstpointer src, guint32 plen);

View file

@ -495,6 +495,17 @@ nm_strdup_not_empty(const char *str)
return !nm_str_is_empty(str) ? g_strdup(str) : NULL;
}
static inline char *
nm_str_truncate(char *str)
{
/* This is trivial, and is only useful in a macro, to
* ensure that we access the macro argument only once. */
nm_assert(str);
str[0] = '\0';
return str;
}
static inline char *
nm_str_realloc(char *str)
{

View file

@ -7,9 +7,11 @@ libnm_platform = static_library(
'nm-netlink.c',
'nm-platform-utils.c',
'nm-platform.c',
'nmp-base.c',
'nmp-global-tracker.c',
'nmp-netns.c',
'nmp-object.c',
'nmp-plobj.c',
'wifi/nm-wifi-utils-nl80211.c',
'wifi/nm-wifi-utils.c',
'wpan/nm-wpan-utils.c',

View file

@ -3305,52 +3305,14 @@ nm_platform_wpan_set_channel(NMPlatform *self, int ifindex, guint8 page, guint8
return klass->wpan_set_channel(self, ifindex, page, channel);
}
#define TO_STRING_DEV_BUF_SIZE (5 + 15 + 1)
static const char *
_to_string_dev(NMPlatform *self, int ifindex, char *buf, size_t size)
{
nm_assert(buf);
nm_assert(size >= TO_STRING_DEV_BUF_SIZE);
/*****************************************************************************/
if (ifindex) {
const char *name = ifindex > 0 && self ? nm_platform_link_get_name(self, ifindex) : NULL;
char *buf2;
strcpy(buf, " dev ");
buf2 = buf + 5;
size -= 5;
if (name)
g_strlcpy(buf2, name, size);
else
g_snprintf(buf2, size, "%d", ifindex);
} else
buf[0] = 0;
return buf;
}
#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)); \
})
/*****************************************************************************/
@ -3557,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,
@ -3722,7 +3618,7 @@ nm_platform_ip4_address_delete(NMPlatform *self,
guint8 plen,
in_addr_t peer_address)
{
char str_dev[TO_STRING_DEV_BUF_SIZE];
char str_dev[30];
char b1[NM_INET_ADDRSTRLEN];
char b2[NM_INET_ADDRSTRLEN];
char str_peer[INET_ADDRSTRLEN + 50];
@ -3738,14 +3634,14 @@ nm_platform_ip4_address_delete(NMPlatform *self,
peer_address != address
? nm_sprintf_buf(str_peer, "peer %s, ", nm_inet4_ntop(peer_address, b2))
: "",
_to_string_dev(self, ifindex, str_dev, sizeof(str_dev)));
_to_string_dev(str_dev, ifindex));
return klass->ip4_address_delete(self, ifindex, address, plen, peer_address);
}
gboolean
nm_platform_ip6_address_delete(NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen)
{
char str_dev[TO_STRING_DEV_BUF_SIZE];
char str_dev[30];
char sbuf[NM_INET_ADDRSTRLEN];
_CHECK_SELF(self, klass, FALSE);
@ -3756,7 +3652,7 @@ nm_platform_ip6_address_delete(NMPlatform *self, int ifindex, struct in6_addr ad
_LOG3D("address: deleting IPv6 address %s/%d, %s",
nm_inet6_ntop(&address, sbuf),
plen,
_to_string_dev(self, ifindex, str_dev, sizeof(str_dev)));
_to_string_dev(str_dev, ifindex));
return klass->ip6_address_delete(self, ifindex, address, plen);
}
@ -5836,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
@ -6532,7 +6397,7 @@ nm_platform_lnk_vxlan_to_string(const NMPlatformLnkVxlan *lnk, char *buf, gsize
char str_group6[100];
char str_local[100];
char str_local6[100];
char str_dev[25];
char str_dev[30];
char str_limit[25];
char str_src_port[35];
char str_dst_port[25];
@ -6603,7 +6468,7 @@ nm_platform_lnk_vxlan_to_string(const NMPlatformLnkVxlan *lnk, char *buf, gsize
str_group6,
str_local,
str_local6,
lnk->parent_ifindex ? nm_sprintf_buf(str_dev, " dev %d", lnk->parent_ifindex) : "",
_to_string_dev(str_dev, lnk->parent_ifindex),
lnk->src_port_min || lnk->src_port_max
? nm_sprintf_buf(str_src_port, " srcport %u %u", lnk->src_port_min, lnk->src_port_max)
: "",
@ -6707,242 +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[TO_STRING_DEV_BUF_SIZE];
char str_label[32];
char str_lft[30], str_pref[30], str_time[50], 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);
}
_to_string_dev(NULL, address->ifindex, str_dev, sizeof(str_dev));
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 ?: "",
str_dev,
_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], str_pref[30], str_time[50], s_source[50];
char str_dev[TO_STRING_DEV_BUF_SIZE];
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);
}
_to_string_dev(NULL, address->ifindex, str_dev, sizeof(str_dev));
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 ?: "",
str_dev,
_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"),
@ -6995,7 +6624,7 @@ nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsiz
char s_network[INET_ADDRSTRLEN];
char s_gateway[INET_ADDRSTRLEN];
char s_pref_src[INET_ADDRSTRLEN];
char str_dev[TO_STRING_DEV_BUF_SIZE];
char str_dev[30];
char str_mss[32];
char str_table[30];
char str_scope[30];
@ -7021,8 +6650,6 @@ nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsiz
else
inet_ntop(AF_INET, &route->gateway, s_gateway, sizeof(s_gateway));
_to_string_dev(NULL, route->ifindex, str_dev, sizeof(str_dev));
g_snprintf(
buf,
len,
@ -7060,7 +6687,7 @@ nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsiz
route->plen,
s_gateway[0] ? " via " : "",
s_gateway,
str_dev,
_to_string_dev(str_dev, route->ifindex),
route->metric_any
? (route->metric ? nm_sprintf_buf(str_metric, "??+%u", route->metric) : "??")
: nm_sprintf_buf(str_metric, "%u", route->metric),
@ -7137,7 +6764,7 @@ nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsiz
char str_table[30];
char str_pref[40];
char str_pref2[30];
char str_dev[TO_STRING_DEV_BUF_SIZE];
char str_dev[30];
char str_mss[32];
char s_source[50];
char str_window[32];
@ -7164,8 +6791,6 @@ nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsiz
else
inet_ntop(AF_INET6, &route->pref_src, s_pref_src, sizeof(s_pref_src));
_to_string_dev(NULL, route->ifindex, str_dev, sizeof(str_dev));
g_snprintf(
buf,
len,
@ -7203,7 +6828,7 @@ nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsiz
route->plen,
s_gateway[0] ? " via " : "",
s_gateway,
str_dev,
_to_string_dev(str_dev, route->ifindex),
route->metric_any
? (route->metric ? nm_sprintf_buf(str_metric, "??+%u", route->metric) : "??")
: nm_sprintf_buf(str_metric, "%u", route->metric),
@ -7485,7 +7110,7 @@ nm_platform_routing_rule_to_string(const NMPlatformRoutingRule *routing_rule, ch
const char *
nm_platform_qdisc_to_string(const NMPlatformQdisc *qdisc, char *buf, gsize len)
{
char str_dev[TO_STRING_DEV_BUF_SIZE];
char str_dev[30];
const char *buf0;
if (!nm_utils_to_string_buffer_init_null(qdisc, &buf, &len))
@ -7497,7 +7122,7 @@ nm_platform_qdisc_to_string(const NMPlatformQdisc *qdisc, char *buf, gsize len)
&len,
"%s%s family %u handle %x parent %x info %x",
qdisc->kind,
_to_string_dev(NULL, qdisc->ifindex, str_dev, sizeof(str_dev)),
_to_string_dev(str_dev, qdisc->ifindex),
qdisc->addr_family,
qdisc->handle,
qdisc->parent,
@ -7622,7 +7247,7 @@ nm_platform_qdisc_cmp(const NMPlatformQdisc *a, const NMPlatformQdisc *b)
const char *
nm_platform_tfilter_to_string(const NMPlatformTfilter *tfilter, char *buf, gsize len)
{
char str_dev[TO_STRING_DEV_BUF_SIZE];
char str_dev[30];
char act_buf[300];
char *p;
gsize l;
@ -7663,7 +7288,7 @@ nm_platform_tfilter_to_string(const NMPlatformTfilter *tfilter, char *buf, gsize
len,
"%s%s family %u handle %x parent %x info %x%s",
tfilter->kind,
_to_string_dev(NULL, tfilter->ifindex, str_dev, sizeof(str_dev)),
_to_string_dev(str_dev, tfilter->ifindex),
tfilter->addr_family,
tfilter->handle,
tfilter->parent,
@ -8452,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,
@ -9742,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 =
{

View file

@ -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,29 +1222,6 @@ GType nm_platform_get_type(void);
/*****************************************************************************/
static inline in_addr_t
nm_platform_ip4_broadcast_address_create(in_addr_t address, guint8 plen)
{
return address | ~nm_ip4_addr_netmask_from_prefix(plen);
}
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_platform_ip4_broadcast_address_create(addr->peer_address, addr->plen);
return 0u;
}
/*****************************************************************************/
/**
* nm_platform_route_table_coerce:
* @table: the route table, in its original value as received
@ -2234,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,
@ -2248,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,
@ -2270,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,
@ -2345,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
@ -2454,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 *
@ -2496,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);
@ -2562,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);
@ -2598,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,
@ -2655,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

View file

@ -0,0 +1,68 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2015 - 2018 Red Hat, Inc.
*/
#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"), );

View file

@ -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__ */

View file

@ -0,0 +1,637 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2015 - 2018 Red Hat, Inc.
*/
#include "libnm-glib-aux/nm-default-glib-i18n-lib.h"
#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,
},
};

View file

@ -0,0 +1,281 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2015 - 2018 Red Hat, Inc.
*/
#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__ */

View file

@ -8,3 +8,8 @@ certain version of kernel API.
These headers should be taken without modification
from Linux.
Don't include any of these these headers directly, instead
include "libnm-std-aux/nm-linux-compat.h" which drags these
headers in. This ensures that we include at all places our own
patched variant, instead of the system headers.

View file

@ -0,0 +1,10 @@
nm-compat-headers
=================
When we build against older system headers, we sometimes
want to use newer features. This directory contains compat
headers that patch the included sources with what we need.
The goal is similar to linux-headers directory, but the approach
is different. The former completely replaces system headers
while this uses system headers and extends them.

View file

@ -0,0 +1,16 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#ifndef __NM_COMPAT_HEADER_LINUX_IF_ADDR_H__
#define __NM_COMPAT_HEADER_LINUX_IF_ADDR_H__
#include <linux/if_addr.h>
#ifndef IFA_F_MANAGETEMPADDR
#define IFA_F_MANAGETEMPADDR 0x100
#endif
#ifndef IFA_F_NOPREFIXROUTE
#define IFA_F_NOPREFIXROUTE 0x200
#endif
#endif /* __NM_COMPAT_HEADER_LINUX_IF_ADDR_H__ */