mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-15 20:45:32 +00:00
platform: merge branch 'th/platform-obj-rename-pt1'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1384
This commit is contained in:
commit
f094977a86
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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 =
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
68
src/libnm-platform/nmp-base.c
Normal file
68
src/libnm-platform/nmp-base.c
Normal 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"), );
|
|
@ -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__ */
|
||||
|
|
637
src/libnm-platform/nmp-plobj.c
Normal file
637
src/libnm-platform/nmp-plobj.c
Normal 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,
|
||||
},
|
||||
};
|
281
src/libnm-platform/nmp-plobj.h
Normal file
281
src/libnm-platform/nmp-plobj.h
Normal 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__ */
|
|
@ -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.
|
||||
|
|
10
src/nm-compat-headers/README.md
Normal file
10
src/nm-compat-headers/README.md
Normal 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.
|
16
src/nm-compat-headers/linux/if_addr.h
Normal file
16
src/nm-compat-headers/linux/if_addr.h
Normal 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__ */
|
Loading…
Reference in a new issue