platform: merge branch 'th/platform-ipv4-peer-address-bgo756356'

https://bugzilla.gnome.org/show_bug.cgi?id=756356
This commit is contained in:
Thomas Haller 2015-10-14 16:16:42 +02:00
commit 6786164e78
17 changed files with 1008 additions and 208 deletions

View file

@ -577,6 +577,12 @@ nmtst_get_rand (void)
return __nmtst_internal.rand;
}
inline static guint32
nmtst_get_rand_int (void)
{
return g_rand_int (nmtst_get_rand ());
}
inline static const char *
nmtst_get_sudo_cmd (void)
{

View file

@ -4862,8 +4862,8 @@ check_and_add_ipv6ll_addr (NMDevice *self)
if (!nm_platform_ip6_address_add (NM_PLATFORM_GET,
ip_ifindex,
lladdr,
in6addr_any,
64,
in6addr_any,
NM_PLATFORM_LIFETIME_PERMANENT,
NM_PLATFORM_LIFETIME_PERMANENT,
0)) {
@ -6856,12 +6856,21 @@ nm_device_set_ip4_config (NMDevice *self,
if (nm_device_uses_generated_assumed_connection (self)) {
NMConnection *connection = nm_device_get_applied_connection (self);
NMConnection *settings_connection = NM_CONNECTION (nm_device_get_settings_connection (self));
NMSetting *s_ip4;
g_object_freeze_notify (G_OBJECT (connection));
g_object_freeze_notify (G_OBJECT (settings_connection));
nm_connection_remove_setting (settings_connection, NM_TYPE_SETTING_IP4_CONFIG);
s_ip4 = nm_ip4_config_create_setting (priv->ip4_config);
nm_connection_add_setting (settings_connection, s_ip4);
nm_connection_remove_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
s_ip4 = nm_ip4_config_create_setting (priv->ip4_config);
nm_connection_add_setting (connection, s_ip4);
g_object_thaw_notify (G_OBJECT (settings_connection));
g_object_thaw_notify (G_OBJECT (connection));
}
@ -7014,12 +7023,21 @@ nm_device_set_ip6_config (NMDevice *self,
if (nm_device_uses_generated_assumed_connection (self)) {
NMConnection *connection = nm_device_get_applied_connection (self);
NMConnection *settings_connection = NM_CONNECTION (nm_device_get_settings_connection (self));
NMSetting *s_ip6;
g_object_freeze_notify (G_OBJECT (connection));
g_object_freeze_notify (G_OBJECT (settings_connection));
nm_connection_remove_setting (settings_connection, NM_TYPE_SETTING_IP6_CONFIG);
s_ip6 = nm_ip6_config_create_setting (priv->ip6_config);
nm_connection_add_setting (settings_connection, s_ip6);
nm_connection_remove_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
s_ip6 = nm_ip6_config_create_setting (priv->ip6_config);
nm_connection_add_setting (connection, s_ip6);
g_object_thaw_notify (G_OBJECT (settings_connection));
g_object_thaw_notify (G_OBJECT (connection));
}

View file

@ -176,9 +176,11 @@ nm_ip4_config_capture_resolv_conf (GArray *nameservers,
}
static gboolean
addresses_are_duplicate (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b, gboolean consider_plen)
addresses_are_duplicate (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b)
{
return a->address == b->address && (!consider_plen || a->plen == b->plen);
return a->address == b->address
&& a->plen == b->plen
&& nm_platform_ip4_address_equal_peer_net (a, b);
}
static gboolean
@ -661,8 +663,7 @@ _addresses_get_index (const NMIP4Config *self, const NMPlatformIP4Address *addr)
for (i = 0; i < priv->addresses->len; i++) {
const NMPlatformIP4Address *a = &g_array_index (priv->addresses, NMPlatformIP4Address, i);
if (addr->address == a->address &&
addr->plen == a->plen)
if (addresses_are_duplicate (addr, a))
return (int) i;
}
return -1;
@ -994,7 +995,8 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev
if (nm_platform_ip4_address_cmp (src_addr = nm_ip4_config_get_address (src, i),
dst_addr = nm_ip4_config_get_address (dst, i))) {
are_equal = FALSE;
if (!addresses_are_duplicate (src_addr, dst_addr, TRUE)) {
if ( !addresses_are_duplicate (src_addr, dst_addr)
|| (nm_platform_ip4_address_get_peer (src_addr) != nm_platform_ip4_address_get_peer (dst_addr))) {
has_relevant_changes = TRUE;
break;
}
@ -1367,7 +1369,7 @@ nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *new)
for (i = 0; i < priv->addresses->len; i++ ) {
NMPlatformIP4Address *item = &g_array_index (priv->addresses, NMPlatformIP4Address, i);
if (addresses_are_duplicate (item, new, FALSE)) {
if (addresses_are_duplicate (item, new)) {
if (nm_platform_ip4_address_cmp (item, new) == 0)
return;
@ -1434,16 +1436,7 @@ gboolean
nm_ip4_config_address_exists (const NMIP4Config *config,
const NMPlatformIP4Address *needle)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
guint i;
for (i = 0; i < priv->addresses->len; i++) {
const NMPlatformIP4Address *haystack = &g_array_index (priv->addresses, NMPlatformIP4Address, i);
if (needle->address == haystack->address && needle->plen == haystack->plen)
return TRUE;
}
return FALSE;
return _addresses_get_index (config, needle) >= 0;
}
/******************************************************************/
@ -2023,6 +2016,7 @@ nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only
const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i);
hash_u32 (sum, address->address);
hash_u32 (sum, address->plen);
hash_u32 (sum, nm_platform_ip4_address_get_peer_net (address));
}
for (i = 0; i < nm_ip4_config_get_num_routes (config); i++) {
@ -2169,6 +2163,12 @@ get_property (GObject *object, guint prop_id,
g_variant_builder_add (&addr_builder, "{sv}",
"prefix",
g_variant_new_uint32 (address->plen));
if ( address->peer_address
&& address->peer_address != address->address) {
g_variant_builder_add (&addr_builder, "{sv}",
"peer",
g_variant_new_string (nm_utils_inet4_ntop (address->peer_address, NULL)));
}
if (*address->label) {
g_variant_builder_add (&addr_builder, "{sv}",

View file

@ -176,9 +176,9 @@ nm_ip6_config_capture_resolv_conf (GArray *nameservers,
}
static gboolean
addresses_are_duplicate (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b, gboolean consider_plen)
addresses_are_duplicate (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b)
{
return IN6_ARE_ADDR_EQUAL (&a->address, &b->address) && (!consider_plen || a->plen == b->plen);
return IN6_ARE_ADDR_EQUAL (&a->address, &b->address);
}
static gboolean
@ -731,7 +731,7 @@ _addresses_get_index (const NMIP6Config *self, const NMPlatformIP6Address *addr)
for (i = 0; i < priv->addresses->len; i++) {
const NMPlatformIP6Address *a = &g_array_index (priv->addresses, NMPlatformIP6Address, i);
if (IN6_ARE_ADDR_EQUAL (&addr->address, &a->address))
if (addresses_are_duplicate (a, addr))
return (int) i;
}
return -1;
@ -1012,7 +1012,10 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
if (nm_platform_ip6_address_cmp (src_addr = nm_ip6_config_get_address (src, i),
dst_addr = nm_ip6_config_get_address (dst, i))) {
are_equal = FALSE;
if (!addresses_are_duplicate (src_addr, dst_addr, TRUE)) {
if ( !addresses_are_duplicate (src_addr, dst_addr)
|| src_addr->plen != dst_addr->plen
|| !IN6_ARE_ADDR_EQUAL (nm_platform_ip6_address_get_peer (src_addr),
nm_platform_ip6_address_get_peer (dst_addr))) {
has_relevant_changes = TRUE;
break;
}
@ -1283,7 +1286,7 @@ nm_ip6_config_add_address (NMIP6Config *config, const NMPlatformIP6Address *new)
for (i = 0; i < priv->addresses->len; i++ ) {
NMPlatformIP6Address *item = &g_array_index (priv->addresses, NMPlatformIP6Address, i);
if (IN6_ARE_ADDR_EQUAL (&item->address, &new->address)) {
if (addresses_are_duplicate (item, new)) {
if (nm_platform_ip6_address_cmp (item, new) == 0)
return;
@ -1350,17 +1353,7 @@ gboolean
nm_ip6_config_address_exists (const NMIP6Config *config,
const NMPlatformIP6Address *needle)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
guint i;
for (i = 0; i < priv->addresses->len; i++) {
const NMPlatformIP6Address *haystack = &g_array_index (priv->addresses, NMPlatformIP6Address, i);
if ( IN6_ARE_ADDR_EQUAL (&needle->address, &haystack->address)
&& needle->plen == haystack->plen)
return TRUE;
}
return FALSE;
return _addresses_get_index (config, needle) >= 0;
}
/******************************************************************/
@ -1940,6 +1933,12 @@ get_property (GObject *object, guint prop_id,
g_variant_builder_add (&addr_builder, "{sv}",
"prefix",
g_variant_new_uint32 (address->plen));
if ( !IN6_IS_ADDR_UNSPECIFIED (&address->peer_address)
&& !IN6_ARE_ADDR_EQUAL (&address->peer_address, &address->address)) {
g_variant_builder_add (&addr_builder, "{sv}",
"peer",
g_variant_new_string (nm_utils_inet6_ntop (&address->peer_address, NULL)));
}
g_variant_builder_add (&array_builder, "a{sv}", &addr_builder);
}

View file

@ -87,9 +87,14 @@ G_DEFINE_TYPE (NMFakePlatform, nm_fake_platform, NM_TYPE_PLATFORM)
static void link_changed (NMPlatform *platform, NMFakePlatformLink *device, gboolean raise_signal);
static gboolean ip6_address_add (NMPlatform *platform, int ifindex,
struct in6_addr addr, struct in6_addr peer_addr,
int plen, guint32 lifetime, guint32 preferred, guint flags);
static gboolean ip6_address_add (NMPlatform *platform,
int ifindex,
struct in6_addr addr,
int plen,
struct in6_addr peer_addr,
guint32 lifetime,
guint32 preferred,
guint flags);
static gboolean ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen);
/******************************************************************/
@ -335,7 +340,7 @@ link_changed (NMPlatform *platform, NMFakePlatformLink *device, gboolean raise_s
if (device->link.ifindex && !IN6_IS_ADDR_UNSPECIFIED (&device->ip6_lladdr)) {
if (device->link.connected)
ip6_address_add (platform, device->link.ifindex, device->ip6_lladdr, in6addr_any, 64, NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, 0);
ip6_address_add (platform, device->link.ifindex, in6addr_any, 64, device->ip6_lladdr, NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, 0);
else
ip6_address_delete (platform, device->link.ifindex, device->ip6_lladdr, 64);
}
@ -886,9 +891,13 @@ ip6_address_get_all (NMPlatform *platform, int ifindex)
}
static gboolean
ip4_address_add (NMPlatform *platform, int ifindex,
in_addr_t addr, in_addr_t peer_addr,
int plen, guint32 lifetime, guint32 preferred,
ip4_address_add (NMPlatform *platform,
int ifindex,
in_addr_t addr,
int plen,
in_addr_t peer_addr,
guint32 lifetime,
guint32 preferred,
const char *label)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
@ -899,7 +908,7 @@ ip4_address_add (NMPlatform *platform, int ifindex,
address.source = NM_IP_CONFIG_SOURCE_KERNEL;
address.ifindex = ifindex;
address.address = addr;
address.peer_address = peer_addr;
address.peer_address = peer_addr && peer_addr != addr ? peer_addr : 0;
address.plen = plen;
address.timestamp = nm_utils_get_monotonic_timestamp_s ();
address.lifetime = lifetime;
@ -916,6 +925,8 @@ ip4_address_add (NMPlatform *platform, int ifindex,
continue;
if (item->plen != address.plen)
continue;
if (!nm_platform_ip4_address_equal_peer_net (item, &address))
continue;
memcpy (item, &address, sizeof (address));
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex, &address, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL);
@ -929,9 +940,13 @@ ip4_address_add (NMPlatform *platform, int ifindex,
}
static gboolean
ip6_address_add (NMPlatform *platform, int ifindex,
struct in6_addr addr, struct in6_addr peer_addr,
int plen, guint32 lifetime, guint32 preferred, guint flags)
ip6_address_add (NMPlatform *platform,
int ifindex,
struct in6_addr addr,
int plen,
struct in6_addr peer_addr,
guint32 lifetime,
guint32 preferred, guint flags)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
NMPlatformIP6Address address;
@ -941,7 +956,7 @@ ip6_address_add (NMPlatform *platform, int ifindex,
address.source = NM_IP_CONFIG_SOURCE_KERNEL;
address.ifindex = ifindex;
address.address = addr;
address.peer_address = peer_addr;
address.peer_address = (IN6_IS_ADDR_UNSPECIFIED (&peer_addr) || IN6_ARE_ADDR_EQUAL (&addr, &peer_addr)) ? in6addr_any : peer_addr;
address.plen = plen;
address.timestamp = nm_utils_get_monotonic_timestamp_s ();
address.lifetime = lifetime;
@ -1018,15 +1033,24 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int
}
static const NMPlatformIP4Address *
ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen)
ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in_addr_t peer_address)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
NMPlatformIP4Address a = {
.ifindex = ifindex,
.address = addr,
.plen = plen,
.peer_address = peer_address,
};
for (i = 0; i < priv->ip4_addresses->len; i++) {
NMPlatformIP4Address *address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i);
if (address->ifindex == ifindex && address->plen == plen && address->address == addr)
if ( address->ifindex == ifindex
&& address->plen == plen
&& address->address == addr
&& nm_platform_ip4_address_equal_peer_net (address, &a))
return address;
}

View file

@ -4238,8 +4238,8 @@ static gboolean
ip4_address_add (NMPlatform *platform,
int ifindex,
in_addr_t addr,
in_addr_t peer_addr,
int plen,
in_addr_t peer_addr,
guint32 lifetime,
guint32 preferred,
const char *label)
@ -4252,7 +4252,7 @@ ip4_address_add (NMPlatform *platform,
plen, lifetime, preferred, 0,
label);
return do_add_addrroute (platform,
nmp_object_stackinit_id_ip4_address (&obj_needle, ifindex, addr, plen),
nmp_object_stackinit_id_ip4_address (&obj_needle, ifindex, addr, plen, peer_addr),
nlo);
}
@ -4260,8 +4260,8 @@ static gboolean
ip6_address_add (NMPlatform *platform,
int ifindex,
struct in6_addr addr,
struct in6_addr peer_addr,
int plen,
struct in6_addr peer_addr,
guint32 lifetime,
guint32 preferred,
guint flags)
@ -4283,8 +4283,7 @@ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen,
{
NMPObject obj_needle;
nmp_object_stackinit_id_ip4_address (&obj_needle, ifindex, addr, plen);
obj_needle.ip4_address.peer_address = peer_address;
nmp_object_stackinit_id_ip4_address (&obj_needle, ifindex, addr, plen, peer_address);
return do_delete_object (platform, &obj_needle, NULL);
}
@ -4298,12 +4297,12 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int
}
static const NMPlatformIP4Address *
ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen)
ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in_addr_t peer_address)
{
NMPObject obj_needle;
const NMPObject *obj;
nmp_object_stackinit_id_ip4_address (&obj_needle, ifindex, addr, plen);
nmp_object_stackinit_id_ip4_address (&obj_needle, ifindex, addr, plen, peer_address);
obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle);
if (nmp_object_is_visible (obj))
return &obj->ip4_address;

View file

@ -1823,6 +1823,43 @@ _to_string_dev (NMPlatform *self, int ifindex, char *buf, size_t size)
/******************************************************************/
in_addr_t
nm_platform_ip4_address_get_peer (const NMPlatformIP4Address *addr)
{
return addr->peer_address ?: addr->address;
}
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;
}
in_addr_t
nm_platform_ip4_address_get_peer_net (const NMPlatformIP4Address *addr)
{
return (addr->peer_address ?: addr->address) & nm_utils_ip4_prefix_to_netmask (addr->plen);
}
gboolean
nm_platform_ip4_address_equal_peer_net (const NMPlatformIP4Address *addr1, const NMPlatformIP4Address *addr2)
{
guint32 a1, a2;
if (addr1->plen != addr2->plen)
return FALSE;
/* For kernel, if the peer address is unset, that effectively means that
* the peer address equals the local address. */
a1 = addr1->peer_address ? addr1->peer_address : addr1->address;
a2 = addr2->peer_address ? addr2->peer_address : addr2->address;
return ((a1 ^ a2) & nm_utils_ip4_prefix_to_netmask (addr1->plen)) == 0;
}
GArray *
nm_platform_ip4_address_get_all (NMPlatform *self, int ifindex)
{
@ -1849,8 +1886,8 @@ gboolean
nm_platform_ip4_address_add (NMPlatform *self,
int ifindex,
in_addr_t address,
in_addr_t peer_address,
int plen,
in_addr_t peer_address,
guint32 lifetime,
guint32 preferred,
const char *label)
@ -1879,15 +1916,15 @@ nm_platform_ip4_address_add (NMPlatform *self,
_LOGD ("address: adding or updating IPv4 address: %s", nm_platform_ip4_address_to_string (&addr));
}
return klass->ip4_address_add (self, ifindex, address, peer_address, plen, lifetime, preferred, label);
return klass->ip4_address_add (self, ifindex, address, plen, peer_address, lifetime, preferred, label);
}
gboolean
nm_platform_ip6_address_add (NMPlatform *self,
int ifindex,
struct in6_addr address,
struct in6_addr peer_address,
int plen,
struct in6_addr peer_address,
guint32 lifetime,
guint32 preferred,
guint flags)
@ -1914,7 +1951,7 @@ nm_platform_ip6_address_add (NMPlatform *self,
_LOGD ("address: adding or updating IPv6 address: %s", nm_platform_ip6_address_to_string (&addr));
}
return klass->ip6_address_add (self, ifindex, address, peer_address, plen, lifetime, preferred, flags);
return klass->ip6_address_add (self, ifindex, address, plen, peer_address, lifetime, preferred, flags);
}
gboolean
@ -1957,13 +1994,13 @@ nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr a
}
const NMPlatformIP4Address *
nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, int plen)
nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, int plen, guint32 peer_address)
{
_CHECK_SELF (self, klass, NULL);
g_return_val_if_fail (plen > 0, NULL);
return klass->ip4_address_get (self, ifindex, address, plen);
return klass->ip4_address_get (self, ifindex, address, plen, peer_address);
}
const NMPlatformIP6Address *
@ -1985,7 +2022,9 @@ array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address
for (i = 0; i < len; i++) {
NMPlatformIP4Address *candidate = &g_array_index (addresses, NMPlatformIP4Address, i);
if (candidate->address == address->address && candidate->plen == address->plen) {
if ( candidate->address == address->address
&& candidate->plen == address->plen
&& nm_platform_ip4_address_equal_peer_net (candidate, address)) {
guint32 lifetime, preferred;
if (nmp_utils_lifetime_get (candidate->timestamp, candidate->lifetime, candidate->preferred,
@ -2069,7 +2108,7 @@ nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known
now, ADDRESS_LIFETIME_PADDING, &lifetime, &preferred))
continue;
if (!nm_platform_ip4_address_add (self, ifindex, known_address->address, known_address->peer_address, known_address->plen, lifetime, preferred, known_address->label))
if (!nm_platform_ip4_address_add (self, ifindex, known_address->address, known_address->plen, known_address->peer_address, lifetime, preferred, known_address->label))
return FALSE;
if (out_added_addresses) {
@ -2130,7 +2169,7 @@ nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known
continue;
if (!nm_platform_ip6_address_add (self, ifindex, known_address->address,
known_address->peer_address, known_address->plen,
known_address->plen, known_address->peer_address,
lifetime, preferred, known_address->flags))
return FALSE;
}
@ -2692,7 +2731,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route)
return _nm_platform_to_string_buffer;
}
#define _CMP_POINTER(a, b) \
#define _CMP_SELF(a, b) \
G_STMT_START { \
if ((a) == (b)) \
return 0; \
@ -2702,6 +2741,19 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route)
return 1; \
} G_STMT_END
#define _CMP_DIRECT(a, b) \
G_STMT_START { \
if ((a) != (b)) \
return ((a) < (b)) ? -1 : 1; \
} G_STMT_END
#define _CMP_DIRECT_MEMCMP(a, b, size) \
G_STMT_START { \
int c = memcmp ((a), (b), (size)); \
if (c != 0) \
return c < 0 ? -1 : 1; \
} G_STMT_END
#define _CMP_FIELD(a, b, field) \
G_STMT_START { \
if (((a)->field) != ((b)->field)) \
@ -2757,7 +2809,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route)
int
nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b)
{
_CMP_POINTER (a, b);
_CMP_SELF (a, b);
_CMP_FIELD (a, b, ifindex);
_CMP_FIELD (a, b, type);
_CMP_FIELD_STR (a, b, name);
@ -2784,12 +2836,20 @@ nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b)
int
nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b)
{
_CMP_POINTER (a, b);
in_addr_t p_a, p_b;
_CMP_SELF (a, b);
_CMP_FIELD (a, b, ifindex);
_CMP_FIELD (a, b, source);
_CMP_FIELD (a, b, address);
_CMP_FIELD (a, b, peer_address);
_CMP_FIELD (a, b, plen);
/* a peer-address of zero is the same as setting it to address.
* Here we consider the full address, including the host-part. */
p_a = nm_platform_ip4_address_get_peer (a);
p_b = nm_platform_ip4_address_get_peer (b);
_CMP_DIRECT (p_a, p_b);
_CMP_FIELD (a, b, timestamp);
_CMP_FIELD (a, b, lifetime);
_CMP_FIELD (a, b, preferred);
@ -2800,11 +2860,17 @@ nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4A
int
nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b)
{
_CMP_POINTER (a, b);
const struct in6_addr *p_a, *p_b;
_CMP_SELF (a, b);
_CMP_FIELD (a, b, ifindex);
_CMP_FIELD (a, b, source);
_CMP_FIELD_MEMCMP (a, b, address);
_CMP_FIELD_MEMCMP (a, b, peer_address);
p_a = nm_platform_ip6_address_get_peer (a);
p_b = nm_platform_ip6_address_get_peer (b);
_CMP_DIRECT_MEMCMP (p_a, p_b, sizeof (*p_a));
_CMP_FIELD (a, b, plen);
_CMP_FIELD (a, b, timestamp);
_CMP_FIELD (a, b, lifetime);
@ -2816,7 +2882,7 @@ nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6A
int
nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b)
{
_CMP_POINTER (a, b);
_CMP_SELF (a, b);
_CMP_FIELD (a, b, ifindex);
_CMP_FIELD (a, b, source);
_CMP_FIELD (a, b, network);
@ -2832,7 +2898,7 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route
int
nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b)
{
_CMP_POINTER (a, b);
_CMP_SELF (a, b);
_CMP_FIELD (a, b, ifindex);
_CMP_FIELD (a, b, source);
_CMP_FIELD_MEMCMP (a, b, network);
@ -2843,9 +2909,6 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
return 0;
}
#undef _CMP_FIELD
#undef _CMP_FIELD_MEMCMP
/**
* nm_platform_ip_address_cmp_expiry:
* @a: a NMPlatformIPAddress to compare
@ -2864,7 +2927,7 @@ nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPlatfor
{
gint64 ta = 0, tb = 0;
_CMP_POINTER (a, b);
_CMP_SELF (a, b);
if (a->lifetime == NM_PLATFORM_LIFETIME_PERMANENT || a->lifetime == 0)
ta = G_MAXINT64;
@ -2897,8 +2960,6 @@ nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPlatfor
return ta < tb ? -1 : 1;
}
#undef _CMP_POINTER
const char *
nm_platform_signal_change_type_to_string (NMPlatformSignalChangeType change_type)
{

View file

@ -513,16 +513,25 @@ typedef struct {
GArray * (*ip4_address_get_all) (NMPlatform *, int ifindex);
GArray * (*ip6_address_get_all) (NMPlatform *, int ifindex);
gboolean (*ip4_address_add) (NMPlatform *, int ifindex,
in_addr_t address, in_addr_t peer_address, int plen,
guint32 lifetime, guint32 preferred_lft,
gboolean (*ip4_address_add) (NMPlatform *,
int ifindex,
in_addr_t address,
int plen,
in_addr_t peer_address,
guint32 lifetime,
guint32 preferred_lft,
const char *label);
gboolean (*ip6_address_add) (NMPlatform *, int ifindex,
struct in6_addr address, struct in6_addr peer_address, int plen,
guint32 lifetime, guint32 preferred_lft, guint flags);
gboolean (*ip6_address_add) (NMPlatform *,
int ifindex,
struct in6_addr address,
int plen,
struct in6_addr peer_address,
guint32 lifetime,
guint32 preferred_lft,
guint flags);
gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, int plen, in_addr_t peer_address);
gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, int plen);
const NMPlatformIP4Address *(*ip4_address_get) (NMPlatform *, int ifindex, in_addr_t address, int plen);
const NMPlatformIP4Address *(*ip4_address_get) (NMPlatform *, int ifindex, in_addr_t address, int plen, in_addr_t peer_address);
const NMPlatformIP6Address *(*ip6_address_get) (NMPlatform *, int ifindex, struct in6_addr address, int plen);
GArray * (*ip4_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteFlags flags);
@ -696,17 +705,31 @@ guint32 nm_platform_mesh_get_channel (NMPlatform *self, int ifindex);
gboolean nm_platform_mesh_set_channel (NMPlatform *self, int ifindex, guint32 channel);
gboolean nm_platform_mesh_set_ssid (NMPlatform *self, int ifindex, const guint8 *ssid, gsize len);
const NMPlatformIP4Address *nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, int plen);
in_addr_t nm_platform_ip4_address_get_peer (const NMPlatformIP4Address *addr);
const struct in6_addr *nm_platform_ip6_address_get_peer (const NMPlatformIP6Address *addr);
in_addr_t nm_platform_ip4_address_get_peer_net (const NMPlatformIP4Address *addr);
gboolean nm_platform_ip4_address_equal_peer_net (const NMPlatformIP4Address *addr1, const NMPlatformIP4Address *addr2);
const NMPlatformIP4Address *nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, int plen, in_addr_t peer_address);
const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, int plen);
GArray *nm_platform_ip4_address_get_all (NMPlatform *self, int ifindex);
GArray *nm_platform_ip6_address_get_all (NMPlatform *self, int ifindex);
gboolean nm_platform_ip4_address_add (NMPlatform *self, int ifindex,
in_addr_t address, in_addr_t peer_address, int plen,
guint32 lifetime, guint32 preferred_lft,
gboolean nm_platform_ip4_address_add (NMPlatform *self,
int ifindex,
in_addr_t address,
int plen,
in_addr_t peer_address,
guint32 lifetime,
guint32 preferred_lft,
const char *label);
gboolean nm_platform_ip6_address_add (NMPlatform *self, int ifindex,
struct in6_addr address, struct in6_addr peer_address, int plen,
guint32 lifetime, guint32 preferred_lft, guint flags);
gboolean nm_platform_ip6_address_add (NMPlatform *self,
int ifindex,
struct in6_addr address,
int plen,
struct in6_addr peer_address,
guint32 lifetime,
guint32 preferred_lft,
guint flags);
gboolean nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address, int plen, in_addr_t peer_address);
gboolean nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, int plen);
gboolean nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, GPtrArray **out_added_addresses);

View file

@ -296,19 +296,20 @@ _vt_cmd_obj_stackinit_id_link (NMPObject *obj, const NMPObject *src)
}
const NMPObject *
nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, int plen)
nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, int plen, guint32 peer_address)
{
nmp_object_stackinit (obj, NMP_OBJECT_TYPE_IP4_ADDRESS, NULL);
obj->ip4_address.ifindex = ifindex;
obj->ip4_address.address = address;
obj->ip4_address.plen = plen;
obj->ip4_address.peer_address = peer_address;
return obj;
}
static void
_vt_cmd_obj_stackinit_id_ip4_address (NMPObject *obj, const NMPObject *src)
{
nmp_object_stackinit_id_ip4_address (obj, src->ip_address.ifindex, src->ip4_address.address, src->ip_address.plen);
nmp_object_stackinit_id_ip4_address (obj, src->ip_address.ifindex, src->ip4_address.address, src->ip_address.plen, src->ip4_address.peer_address);
}
const NMPObject *
@ -425,17 +426,21 @@ _vt_cmd_plobj_to_string_id_##type (const NMPlatformObject *_obj, char *buf, gsiz
{ \
plat_type *const obj = (plat_type *) _obj; \
char buf1[NM_UTILS_INET_ADDRSTRLEN]; \
char buf2[NM_UTILS_INET_ADDRSTRLEN]; \
\
(void) buf1; \
(void) buf2; \
g_snprintf (buf, buf_len, \
__VA_ARGS__); \
return buf; \
}
_vt_cmd_plobj_to_string_id (link, NMPlatformLink, "%d", obj->ifindex);
_vt_cmd_plobj_to_string_id (ip4_address, NMPlatformIP4Address, "%d: %s/%d", obj->ifindex, nm_utils_inet4_ntop ( obj->address, buf1), obj->plen);
_vt_cmd_plobj_to_string_id (ip6_address, NMPlatformIP6Address, "%d: %s/%d", obj->ifindex, nm_utils_inet6_ntop (&obj->address, buf1), obj->plen);
_vt_cmd_plobj_to_string_id (ip4_route, NMPlatformIP4Route, "%d: %s/%d %d", obj->ifindex, nm_utils_inet4_ntop ( obj->network, buf1), obj->plen, obj->metric);
_vt_cmd_plobj_to_string_id (ip6_route, NMPlatformIP6Route, "%d: %s/%d %d", obj->ifindex, nm_utils_inet6_ntop (&obj->network, buf1), obj->plen, obj->metric);
_vt_cmd_plobj_to_string_id (link, NMPlatformLink, "%d", obj->ifindex);
_vt_cmd_plobj_to_string_id (ip4_address, NMPlatformIP4Address, "%d: %s/%d%s%s", obj->ifindex, nm_utils_inet4_ntop ( obj->address, buf1), obj->plen,
obj->peer_address && obj->peer_address != obj->address ? "," : "",
obj->peer_address && obj->peer_address != obj->address ? nm_utils_inet4_ntop (nm_platform_ip4_address_get_peer_net (obj), buf2) : "");
_vt_cmd_plobj_to_string_id (ip6_address, NMPlatformIP6Address, "%d: %s", obj->ifindex, nm_utils_inet6_ntop (&obj->address, buf1));
_vt_cmd_plobj_to_string_id (ip4_route, NMPlatformIP4Route, "%d: %s/%d %d", obj->ifindex, nm_utils_inet4_ntop ( obj->network, buf1), obj->plen, obj->metric);
_vt_cmd_plobj_to_string_id (ip6_route, NMPlatformIP6Route, "%d: %s/%d %d", obj->ifindex, nm_utils_inet6_ntop (&obj->network, buf1), obj->plen, obj->metric);
int
nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2)
@ -533,10 +538,10 @@ _vt_cmd_plobj_id_copy (ip4_address, NMPlatformIP4Address, {
dst->ifindex = src->ifindex;
dst->plen = src->plen;
dst->address = src->address;
dst->peer_address = src->peer_address;
});
_vt_cmd_plobj_id_copy (ip6_address, NMPlatformIP6Address, {
dst->ifindex = src->ifindex;
dst->plen = src->plen;
dst->address = src->address;
});
_vt_cmd_plobj_id_copy (ip4_route, NMPlatformIP4Route, {
@ -619,10 +624,13 @@ _vt_cmd_plobj_id_equal (link, NMPlatformLink,
_vt_cmd_plobj_id_equal (ip4_address, NMPlatformIP4Address,
obj1->ifindex == obj2->ifindex
&& obj1->plen == obj2->plen
&& obj1->address == obj2->address);
&& obj1->address == obj2->address
/* for IPv4 addresses, you can add the same local address with differing peer-adddress
* (IFA_ADDRESS), provided that their net-part differs. */
&& nm_platform_ip4_address_equal_peer_net (obj1, obj2));
_vt_cmd_plobj_id_equal (ip6_address, NMPlatformIP6Address,
obj1->ifindex == obj2->ifindex
&& obj1->plen == obj2->plen
/* for IPv6 addresses, the prefix length is not part of the primary identifier. */
&& IN6_ARE_ADDR_EQUAL (&obj1->address, &obj2->address));
_vt_cmd_plobj_id_equal (ip4_route, NMPlatformIP4Route,
obj1->ifindex == obj2->ifindex
@ -655,34 +663,25 @@ _vt_cmd_plobj_id_hash_##type (const NMPlatformObject *_obj) \
return hash; \
}
_vt_cmd_plobj_id_hash (link, NMPlatformLink, {
/* libnl considers:
* .oo_id_attrs = LINK_ATTR_IFINDEX | LINK_ATTR_FAMILY,
*/
hash = (guint) 3982791431u;
hash = hash + ((guint) obj->ifindex);
})
_vt_cmd_plobj_id_hash (ip4_address, NMPlatformIP4Address, {
/* libnl considers:
* .oo_id_attrs = (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX |
* ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN),
*/
hash = (guint) 3591309853u;
hash = hash + ((guint) obj->ifindex);
hash = hash * 33 + ((guint) obj->plen);
hash = hash * 33 + ((guint) obj->address);
/* for IPv4 we must also consider the net-part of the peer-address (IFA_ADDRESS) */
hash = hash * 33 + ((guint) (nm_platform_ip4_address_get_peer_net (obj)));
})
_vt_cmd_plobj_id_hash (ip6_address, NMPlatformIP6Address, {
hash = (guint) 2907861637u;
hash = hash + ((guint) obj->ifindex);
hash = hash * 33 + ((guint) obj->plen);
/* for IPv6 addresses, the prefix length is not part of the primary identifier. */
hash = hash * 33 + _id_hash_ip6_addr (&obj->address);
})
_vt_cmd_plobj_id_hash (ip4_route, NMPlatformIP4Route, {
/* libnl considers:
* .oo_id_attrs = (ROUTE_ATTR_FAMILY | ROUTE_ATTR_TOS |
* ROUTE_ATTR_TABLE | ROUTE_ATTR_DST |
* ROUTE_ATTR_PRIO),
*/
hash = (guint) 2569857221u;
hash = hash + ((guint) obj->ifindex);
hash = hash * 33 + ((guint) obj->plen);

View file

@ -269,7 +269,7 @@ NMPObject *nmp_object_new_link (int ifindex);
const NMPObject *nmp_object_stackinit (NMPObject *obj, NMPObjectType obj_type, const NMPlatformObject *plobj);
const NMPObject *nmp_object_stackinit_id (NMPObject *obj, const NMPObject *src);
const NMPObject *nmp_object_stackinit_id_link (NMPObject *obj, int ifindex);
const NMPObject *nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, int plen);
const NMPObject *nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, int plen, guint32 peer_address);
const NMPObject *nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifindex, const struct in6_addr *address, int plen);
const NMPObject *nmp_object_stackinit_id_ip4_route (NMPObject *obj, int ifindex, guint32 network, int plen, guint32 metric);
const NMPObject *nmp_object_stackinit_id_ip6_route (NMPObject *obj, int ifindex, const struct in6_addr *network, int plen, guint32 metric);

View file

@ -583,7 +583,7 @@ do_ip4_address_add (char **argv)
guint32 lifetime = strtol (*argv++, NULL, 10);
guint32 preferred = strtol (*argv++, NULL, 10);
gboolean value = nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, address, 0, plen, lifetime, preferred, NULL);
gboolean value = nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, address, plen, 0, lifetime, preferred, NULL);
return value;
} else
return FALSE;
@ -601,7 +601,7 @@ do_ip6_address_add (char **argv)
guint32 preferred = strtol (*argv++, NULL, 10);
guint flags = (*argv) ? rtnl_addr_str2flags (*argv++) : 0;
gboolean value = nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, address, in6addr_any, plen, lifetime, preferred, flags);
gboolean value = nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, address, plen, in6addr_any, lifetime, preferred, flags);
return value;
} else
return FALSE;
@ -624,11 +624,11 @@ do_ip6_address_add (char **argv)
} else \
return FALSE; \
}
#define ADDR_CMD(cmdname) ADDR_CMD_FULL (ip4, cmdname, FALSE, 0) ADDR_CMD_FULL (ip6, cmdname, FALSE)
#define ADDR_CMD_PRINT(cmdname) ADDR_CMD_FULL (ip4, cmdname, TRUE) ADDR_CMD_FULL (ip6, cmdname, TRUE)
#define ADDR_CMD(cmdname, ...) ADDR_CMD_FULL (ip4, cmdname, FALSE, 0, ##__VA_ARGS__) ADDR_CMD_FULL (ip6, cmdname, FALSE)
#define ADDR_CMD_PRINT(cmdname, ...) ADDR_CMD_FULL (ip4, cmdname, TRUE, ##__VA_ARGS__) ADDR_CMD_FULL (ip6, cmdname, TRUE)
ADDR_CMD (delete)
ADDR_CMD_PRINT (get)
ADDR_CMD_PRINT (get, 0)
static gboolean
do_ip4_route_get_all (char **argv)

View file

@ -4,10 +4,17 @@
#define DEVICE_NAME "nm-test-device"
#define IP4_ADDRESS "192.0.2.1"
#define IP4_ADDRESS_PEER "192.0.2.2"
#define IP4_ADDRESS_PEER2 "192.0.3.1"
#define IP4_PLEN 24
#define IP6_ADDRESS "2001:db8:a:b:1:2:3:4"
#define IP6_PLEN 64
static int DEVICE_IFINDEX = -1;
static int EX = -1;
/*****************************************************************************/
static void
ip4_address_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformIP4Address *received, NMPlatformSignalChangeType change_type, NMPlatformReason reason, SignalData *data)
{
@ -48,10 +55,12 @@ ip6_address_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex,
_LOGD ("Received signal '%s' %dth time.", data->name, data->received_count);
}
/*****************************************************************************/
static void
test_ip4_address (void)
test_ip4_address_general (void)
{
int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
const int ifindex = DEVICE_IFINDEX;
SignalData *address_added = add_signal_ifindex (NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip4_address_callback, ifindex);
SignalData *address_changed = add_signal_ifindex (NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, ip4_address_callback, ifindex);
SignalData *address_removed = add_signal_ifindex (NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip4_address_callback, ifindex);
@ -64,13 +73,13 @@ test_ip4_address (void)
inet_pton (AF_INET, IP4_ADDRESS, &addr);
/* Add address */
g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN));
g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr, 0, IP4_PLEN, lifetime, preferred, NULL));
g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN));
g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, 0, lifetime, preferred, NULL);
g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
accept_signal (address_added);
/* Add address again (aka update) */
g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr, 0, IP4_PLEN, lifetime, preferred, NULL));
nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, 0, lifetime + 100, preferred + 50, NULL);
accept_signals (address_changed, 0, 1);
/* Test address listing */
@ -84,12 +93,12 @@ test_ip4_address (void)
g_array_unref (addresses);
/* Remove address */
g_assert (nm_platform_ip4_address_delete (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN));
nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, 0);
g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
accept_signal (address_removed);
/* Remove address again */
g_assert (nm_platform_ip4_address_delete (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, 0);
free_signal (address_added);
free_signal (address_changed);
@ -97,9 +106,9 @@ test_ip4_address (void)
}
static void
test_ip6_address (void)
test_ip6_address_general (void)
{
int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
const int ifindex = DEVICE_IFINDEX;
SignalData *address_added = add_signal_ifindex (NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip6_address_callback, ifindex);
SignalData *address_changed = add_signal_ifindex (NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, ip6_address_callback, ifindex);
SignalData *address_removed = add_signal_ifindex (NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip6_address_callback, ifindex);
@ -114,12 +123,12 @@ test_ip6_address (void)
/* Add address */
g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags));
nmtstp_ip6_address_add (EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags);
g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
accept_signal (address_added);
/* Add address again (aka update) */
g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags));
nmtstp_ip6_address_add (EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags);
accept_signals (address_changed, 0, 1);
/* Test address listing */
@ -133,12 +142,12 @@ test_ip6_address (void)
g_array_unref (addresses);
/* Remove address */
g_assert (nm_platform_ip6_address_delete (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
nmtstp_ip6_address_del (EX, ifindex, addr, IP6_PLEN);
g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
accept_signal (address_removed);
/* Remove address again */
g_assert (nm_platform_ip6_address_delete (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
nmtstp_ip6_address_del (EX, ifindex, addr, IP6_PLEN);
free_signal (address_added);
free_signal (address_changed);
@ -146,11 +155,11 @@ test_ip6_address (void)
}
static void
test_ip4_address_external (void)
test_ip4_address_general_2 (void)
{
const int ifindex = DEVICE_IFINDEX;
SignalData *address_added = add_signal (NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip4_address_callback);
SignalData *address_removed = add_signal (NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip4_address_callback);
int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
in_addr_t addr;
guint32 lifetime = 2000;
guint32 preferred = 1000;
@ -161,38 +170,31 @@ test_ip4_address_external (void)
/* Looks like addresses are not announced by kerenl when the interface
* is down. Link-local IPv6 address is automatically added.
*/
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME), NULL));
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, DEVICE_IFINDEX, NULL));
/* Add/delete notification */
run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d",
IP4_ADDRESS, IP4_PLEN, DEVICE_NAME, lifetime, preferred);
wait_signal (address_added);
g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN));
run_command ("ip address delete %s/%d dev %s", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME);
wait_signal (address_removed);
g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN));
nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, 0, lifetime, preferred, NULL);
accept_signal (address_added);
g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, 0);
accept_signal (address_removed);
g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
/* Add/delete conflict */
run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d",
IP4_ADDRESS, IP4_PLEN, DEVICE_NAME, lifetime, preferred);
g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr, 0, IP4_PLEN, lifetime, preferred, NULL));
g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN));
nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, 0, lifetime, preferred, NULL);
g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
accept_signal (address_added);
/*run_command ("ip address delete %s/%d dev %s", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME);
g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN, 0));
g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN));
accept_signal (address_removed);*/
free_signal (address_added);
free_signal (address_removed);
}
static void
test_ip6_address_external (void)
test_ip6_address_general_2 (void)
{
const int ifindex = DEVICE_IFINDEX;
SignalData *address_added = add_signal (NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip6_address_callback);
SignalData *address_removed = add_signal (NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip6_address_callback);
int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
struct in6_addr addr;
guint32 lifetime = 2000;
guint32 preferred = 1000;
@ -201,51 +203,143 @@ test_ip6_address_external (void)
inet_pton (AF_INET6, IP6_ADDRESS, &addr);
/* Add/delete notification */
run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d",
IP6_ADDRESS, IP6_PLEN, DEVICE_NAME, lifetime, preferred);
wait_signal (address_added);
nmtstp_ip6_address_add (EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0);
accept_signal (address_added);
g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
run_command ("ip address delete %s/%d dev %s", IP6_ADDRESS, IP6_PLEN, DEVICE_NAME);
wait_signal (address_removed);
nmtstp_ip6_address_del (EX, ifindex, addr, IP6_PLEN);
accept_signal (address_removed);
g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
/* Add/delete conflict */
run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d",
IP6_ADDRESS, IP6_PLEN, DEVICE_NAME, lifetime, preferred);
g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags));
g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
nmtstp_ip6_address_add (EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0);
accept_signal (address_added);
/*run_command ("ip address delete %s/%d dev %s", IP6_ADDRESS, IP6_PLEN, DEVICE_NAME);
g_assert (nm_platform_ip6_address_delete (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
wait_signal (address_removed);*/
g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
nmtstp_ip6_address_add (EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags);
ensure_no_signal (address_added);
g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
free_signal (address_added);
free_signal (address_removed);
}
/*****************************************************************************/
static void
test_ip4_address_peer (void)
{
const int ifindex = DEVICE_IFINDEX;
SignalData *address_added = add_signal (NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip4_address_callback);
SignalData *address_removed = add_signal (NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip4_address_callback);
in_addr_t addr, addr_peer, addr_peer2;
guint32 lifetime = 2000;
guint32 preferred = 1000;
const NMPlatformIP4Address *a;
inet_pton (AF_INET, IP4_ADDRESS, &addr);
inet_pton (AF_INET, IP4_ADDRESS_PEER, &addr_peer);
inet_pton (AF_INET, IP4_ADDRESS_PEER2, &addr_peer2);
g_assert (ifindex > 0);
g_assert (addr != addr_peer);
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, ifindex, NULL));
accept_signals (address_removed, 0, G_MAXINT);
accept_signals (address_added, 0, G_MAXINT);
/* Add/delete notification */
nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr_peer, lifetime, preferred, NULL);
accept_signal (address_added);
g_assert ((a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer)));
g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2));
nmtstp_ip_address_assert_lifetime ((NMPlatformIPAddress *) a, -1, lifetime, preferred);
nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr_peer2, lifetime, preferred, NULL);
accept_signal (address_added);
g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer));
g_assert ((a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2)));
nmtstp_ip_address_assert_lifetime ((NMPlatformIPAddress *) a, -1, lifetime, preferred);
g_assert (addr != addr_peer);
nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, addr_peer);
accept_signal (address_removed);
g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer));
g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2));
free_signal (address_added);
free_signal (address_removed);
}
/*****************************************************************************/
void
init_tests (int *argc, char ***argv)
{
nmtst_init_with_logging (argc, argv, NULL, "ALL");
}
void
setup_tests (void)
/*****************************************************************************
* SETUP TESTS
*****************************************************************************/
typedef struct {
const char *testpath;
GTestFunc test_func;
} TestSetup;
static void
_g_test_run (gconstpointer user_data)
{
SignalData *link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, DEVICE_NAME);
const TestSetup *s = user_data;
int ifindex;
_LOGt ("TEST: start %s", s->testpath);
nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME));
g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, DEVICE_NAME));
g_assert (nm_platform_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL) == NM_PLATFORM_ERROR_SUCCESS);
accept_signal (link_added);
free_signal (link_added);
g_assert_cmpint (nm_platform_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL), ==, NM_PLATFORM_ERROR_SUCCESS);
g_test_add_func ("/address/internal/ip4", test_ip4_address);
g_test_add_func ("/address/internal/ip6", test_ip6_address);
ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
g_assert_cmpint (ifindex, >, 0);
g_assert_cmpint (DEVICE_IFINDEX, ==, -1);
if (strcmp (g_type_name (G_TYPE_FROM_INSTANCE (nm_platform_get ())), "NMFakePlatform")) {
g_test_add_func ("/address/external/ip4", test_ip4_address_external);
g_test_add_func ("/address/external/ip6", test_ip6_address_external);
}
DEVICE_IFINDEX = ifindex;
EX = nmtstp_run_command_check_external_global ();
s->test_func ();
g_assert_cmpint (DEVICE_IFINDEX, ==, ifindex);
DEVICE_IFINDEX = -1;
g_assert_cmpint (ifindex, ==, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME));
g_assert (nm_platform_link_delete (NM_PLATFORM_GET, ifindex));
_LOGt ("TEST: finished %s", s->testpath);
}
static void
_g_test_add_func (const char *testpath,
GTestFunc test_func)
{
TestSetup *s;
s = g_new0 (TestSetup, 1);
s->testpath = testpath;
s->test_func = test_func;
g_test_add_data_func_full (testpath, s, _g_test_run, g_free);
}
void
setup_tests (void)
{
_g_test_add_func ("/address/ipv4/general", test_ip4_address_general);
_g_test_add_func ("/address/ipv6/general", test_ip6_address_general);
_g_test_add_func ("/address/ipv4/general-2", test_ip4_address_general_2);
_g_test_add_func ("/address/ipv6/general-2", test_ip6_address_general_2);
_g_test_add_func ("/address/ipv4/peer", test_ip4_address_peer);
}

View file

@ -43,8 +43,8 @@ test_cleanup_internal (void)
g_assert (ifindex > 0);
/* Add routes and addresses */
g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr4, 0, plen4, lifetime, preferred, NULL));
g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr6, in6addr_any, plen6, lifetime, preferred, flags));
g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr4, plen4, 0, lifetime, preferred, NULL));
g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr6, plen6, in6addr_any, lifetime, preferred, flags));
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway4, 32, INADDR_ANY, 0, metric, mss));
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network4, plen4, gateway4, 0, metric, mss));
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway4, 0, metric, mss));

View file

@ -10,9 +10,16 @@
#define SIGNAL_DATA_FMT "'%s-%s' ifindex %d%s%s%s (%d times received)"
#define SIGNAL_DATA_ARG(data) (data)->name, nm_platform_signal_change_type_to_string ((data)->change_type), (data)->ifindex, (data)->ifname ? " ifname '" : "", (data)->ifname ? (data)->ifname : "", (data)->ifname ? "'" : "", (data)->received_count
typedef struct {
union {
guint8 addr_ptr[1];
in_addr_t addr4;
struct in6_addr addr6;
};
} IPAddr;
gboolean
nmtst_platform_is_root_test (void)
nmtstp_is_root_test (void)
{
NM_PRAGMA_WARNING_DISABLE("-Wtautological-compare")
return (SETUP == nm_linux_platform_setup);
@ -20,9 +27,9 @@ nmtst_platform_is_root_test (void)
}
gboolean
nmtst_platform_is_sysfs_writable (void)
nmtstp_is_sysfs_writable (void)
{
return !nmtst_platform_is_root_test ()
return !nmtstp_is_root_test ()
|| (access ("/sys/devices", W_OK) == 0);
}
@ -69,6 +76,19 @@ _ensure_no_signal (const char *file, int line, const char *func, SignalData *dat
g_error ("NMPlatformSignalAssert: %s:%d, %s(): failure to accept signal 0 times: "SIGNAL_DATA_FMT, file, line, func, SIGNAL_DATA_ARG (data));
}
void
_accept_or_wait_signal (const char *file, int line, const char *func, SignalData *data)
{
_LOGD ("NMPlatformSignalAssert: %s:%d, %s(): accept-or-wait signal: "SIGNAL_DATA_FMT, file, line, func, SIGNAL_DATA_ARG (data));
if (data->received_count == 0) {
data->loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (data->loop);
g_clear_pointer (&data->loop, g_main_loop_unref);
}
_accept_signal (file, line, func, data);
}
void
_wait_signal (const char *file, int line, const char *func, SignalData *data)
{
@ -253,21 +273,534 @@ _assert_ip4_route_exists (const char *file, guint line, const char *func, gboole
}
}
void
run_command (const char *format, ...)
int
nmtstp_run_command (const char *format, ...)
{
char *command;
int result;
gs_free char *command = NULL;
va_list ap;
va_start (ap, format);
command = g_strdup_vprintf (format, ap);
va_end (ap);
_LOGD ("Running command: %s", command);
g_assert (!system (command));
_LOGD ("Command finished.");
g_free (command);
result = system (command);
_LOGD ("Command finished: result=%d", result);
return result;
}
/*****************************************************************************/
typedef struct {
GMainLoop *loop;
gboolean timeout;
guint id;
} WaitForSignalData;
static void
_wait_for_signal_cb (NMPlatform *platform,
NMPObjectType obj_type,
int ifindex,
NMPlatformLink *plink,
NMPlatformSignalChangeType change_type,
NMPlatformReason reason,
gpointer user_data)
{
WaitForSignalData *data = user_data;
g_main_loop_quit (data->loop);
}
static gboolean
_wait_for_signal_timeout (gpointer user_data)
{
WaitForSignalData *data = user_data;
data->timeout = TRUE;
data->id = 0;
g_main_loop_quit (data->loop);
return G_SOURCE_REMOVE;
}
gboolean
nmtstp_wait_for_signal (guint timeout_ms)
{
WaitForSignalData data = { 0 };
guint id_link, id_ip4_address, id_ip6_address, id_ip4_route, id_ip6_route;
data.loop = g_main_loop_new (NULL, FALSE);
id_link = g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data);
id_ip4_address = g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data);
id_ip6_address = g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data);
id_ip4_route = g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data);
id_ip6_route = g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data);
if (timeout_ms != 0)
data.id = g_timeout_add (timeout_ms, _wait_for_signal_timeout, &data);
g_main_loop_run (data.loop);
g_assert (nm_clear_g_signal_handler (NM_PLATFORM_GET, &id_link));
g_assert (nm_clear_g_signal_handler (NM_PLATFORM_GET, &id_ip4_address));
g_assert (nm_clear_g_signal_handler (NM_PLATFORM_GET, &id_ip6_address));
g_assert (nm_clear_g_signal_handler (NM_PLATFORM_GET, &id_ip4_route));
g_assert (nm_clear_g_signal_handler (NM_PLATFORM_GET, &id_ip6_route));
if (nm_clear_g_source (&data.id))
g_assert (timeout_ms != 0 && !data.timeout);
g_clear_pointer (&data.loop, g_main_loop_unref);
return !data.timeout;
}
gboolean
nmtstp_wait_for_signal_until (gint64 until_ms)
{
gint64 now;
while (TRUE) {
now = nm_utils_get_monotonic_timestamp_ms ();
if (until_ms < now)
return FALSE;
if (nmtstp_wait_for_signal (MAX (1, until_ms - now)))
return TRUE;
}
}
int
nmtstp_run_command_check_external_global (void)
{
if (!nmtstp_is_root_test ())
return FALSE;
switch (nmtst_get_rand_int () % 3) {
case 0:
return -1;
case 1:
return FALSE;
default:
return TRUE;
}
}
gboolean
nmtstp_run_command_check_external (int external_command)
{
if (external_command != -1) {
g_assert (NM_IN_SET (external_command, FALSE, TRUE));
g_assert (!external_command || nmtstp_is_root_test ());
return !!external_command;
}
if (!nmtstp_is_root_test ())
return FALSE;
return (nmtst_get_rand_int () % 2) == 0;
}
#define CHECK_LIFETIME_MAX_DIFF 2
gboolean
nmtstp_ip_address_check_lifetime (const NMPlatformIPAddress *addr,
gint64 now,
guint32 expected_lifetime,
guint32 expected_preferred)
{
gint64 offset;
int i;
g_assert (addr);
if (now == -1)
now = nm_utils_get_monotonic_timestamp_s ();
g_assert (now > 0);
g_assert (expected_preferred <= expected_lifetime);
if ( expected_lifetime == NM_PLATFORM_LIFETIME_PERMANENT
&& expected_lifetime == NM_PLATFORM_LIFETIME_PERMANENT) {
return addr->timestamp == 0
&& addr->lifetime == NM_PLATFORM_LIFETIME_PERMANENT
&& addr->preferred == NM_PLATFORM_LIFETIME_PERMANENT;
}
if (addr->timestamp == 0)
return FALSE;
offset = (gint64) now - addr->timestamp;
for (i = 0; i < 2; i++) {
guint32 lft = i ? expected_lifetime : expected_preferred;
guint32 adr = i ? addr->lifetime : addr->preferred;
if (lft == NM_PLATFORM_LIFETIME_PERMANENT) {
if (adr != NM_PLATFORM_LIFETIME_PERMANENT)
return FALSE;
} else {
if ( adr - offset <= lft - CHECK_LIFETIME_MAX_DIFF
|| adr - offset >= lft + CHECK_LIFETIME_MAX_DIFF)
return FALSE;
}
}
return TRUE;
}
void
nmtstp_ip_address_assert_lifetime (const NMPlatformIPAddress *addr,
gint64 now,
guint32 expected_lifetime,
guint32 expected_preferred)
{
gint64 n = now;
gint64 offset;
int i;
g_assert (addr);
if (now == -1)
now = nm_utils_get_monotonic_timestamp_s ();
g_assert (now > 0);
g_assert (expected_preferred <= expected_lifetime);
if ( expected_lifetime == NM_PLATFORM_LIFETIME_PERMANENT
&& expected_lifetime == NM_PLATFORM_LIFETIME_PERMANENT) {
g_assert_cmpint (addr->timestamp, ==, 0);
g_assert_cmpint (addr->lifetime, ==, NM_PLATFORM_LIFETIME_PERMANENT);
g_assert_cmpint (addr->preferred, ==, NM_PLATFORM_LIFETIME_PERMANENT);
return;
}
g_assert_cmpint (addr->timestamp, >, 0);
g_assert_cmpint (addr->timestamp, <=, now);
offset = (gint64) now - addr->timestamp;
g_assert_cmpint (offset, >=, 0);
for (i = 0; i < 2; i++) {
guint32 lft = i ? expected_lifetime : expected_preferred;
guint32 adr = i ? addr->lifetime : addr->preferred;
if (lft == NM_PLATFORM_LIFETIME_PERMANENT)
g_assert_cmpint (adr, ==, NM_PLATFORM_LIFETIME_PERMANENT);
else {
g_assert_cmpint (adr, <=, lft);
g_assert_cmpint (offset, <=, adr);
g_assert_cmpint (adr - offset, <=, lft + CHECK_LIFETIME_MAX_DIFF);
g_assert_cmpint (adr - offset, >=, lft - CHECK_LIFETIME_MAX_DIFF);
}
}
g_assert (nmtstp_ip_address_check_lifetime (addr, n, expected_lifetime, expected_preferred));
}
static void
_ip_address_add (gboolean external_command,
gboolean is_v4,
int ifindex,
const IPAddr *address,
int plen,
const IPAddr *peer_address,
guint32 lifetime,
guint32 preferred,
const char *label,
guint flags)
{
gint64 end_time;
external_command = nmtstp_run_command_check_external (external_command);
if (external_command) {
const char *ifname;
gs_free char *s_valid = NULL;
gs_free char *s_preferred = NULL;
gs_free char *s_label = NULL;
char b1[NM_UTILS_INET_ADDRSTRLEN], b2[NM_UTILS_INET_ADDRSTRLEN];
ifname = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex);
g_assert (ifname);
if (peer_address == address)
peer_address = 0;
if (lifetime != NM_PLATFORM_LIFETIME_PERMANENT)
s_valid = g_strdup_printf (" valid_lft %d", lifetime);
if (preferred != NM_PLATFORM_LIFETIME_PERMANENT)
s_preferred = g_strdup_printf (" preferred_lft %d", preferred);
if (label)
s_label = g_strdup_printf ("%s:%s", ifname, label);
if (is_v4) {
g_assert (flags == 0);
nmtstp_run_command_check ("ip address change %s%s%s/%d dev %s%s%s%s",
nm_utils_inet4_ntop (address->addr4, b1),
peer_address->addr4 ? " peer " : "",
peer_address->addr4 ? nm_utils_inet4_ntop (peer_address->addr4, b2) : "",
plen,
ifname,
s_valid ?: "",
s_preferred ?: "",
s_label ?: "");
} else {
g_assert (label == NULL);
/* flags not implemented (yet) */
g_assert (flags == 0);
nmtstp_run_command_check ("ip address change %s%s%s/%d dev %s%s%s%s",
nm_utils_inet6_ntop (&address->addr6, b1),
!IN6_IS_ADDR_UNSPECIFIED (&peer_address->addr6) ? " peer " : "",
!IN6_IS_ADDR_UNSPECIFIED (&peer_address->addr6) ? nm_utils_inet6_ntop (&peer_address->addr6, b2) : "",
plen,
ifname,
s_valid ?: "",
s_preferred ?: "",
s_label ?: "");
}
} else {
gboolean success;
if (is_v4) {
g_assert (flags == 0);
success = nm_platform_ip4_address_add (NM_PLATFORM_GET,
ifindex,
address->addr4,
plen,
peer_address->addr4,
lifetime,
preferred,
label);
} else {
g_assert (label == NULL);
success = nm_platform_ip6_address_add (NM_PLATFORM_GET,
ifindex,
address->addr6,
plen,
peer_address->addr6,
lifetime,
preferred,
flags);
}
g_assert (success);
}
/* Let's wait until we see the address. */
end_time = nm_utils_get_monotonic_timestamp_ms () + 250;
do {
if (external_command)
nm_platform_process_events (NM_PLATFORM_GET);
/* let's wait until we see the address as we added it. */
if (is_v4) {
const NMPlatformIP4Address *a;
g_assert (flags == 0);
a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, address->addr4, plen, peer_address->addr4);
if ( a
&& nm_platform_ip4_address_get_peer (a) == (peer_address->addr4 ? peer_address->addr4 : address->addr4)
&& nmtstp_ip_address_check_lifetime ((NMPlatformIPAddress*) a, -1, lifetime, preferred)
&& strcmp (a->label, label ?: "") == 0)
break;
} else {
const NMPlatformIP6Address *a;
g_assert (label == NULL);
g_assert (flags == 0);
a = nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, address->addr6, plen);
if ( a
&& !memcmp (nm_platform_ip6_address_get_peer (a),
(IN6_IS_ADDR_UNSPECIFIED (&peer_address->addr6) || IN6_ARE_ADDR_EQUAL (&address->addr6, &peer_address->addr6))
? &address->addr6 : &peer_address->addr6,
sizeof (struct in6_addr))
&& nmtstp_ip_address_check_lifetime ((NMPlatformIPAddress*) a, -1, lifetime, preferred))
break;
}
/* for internal command, we expect not to reach this line.*/
g_assert (external_command);
/* timeout? */
g_assert (nm_utils_get_monotonic_timestamp_ms () < end_time);
g_assert (nmtstp_wait_for_signal_until (end_time));
} while (TRUE);
}
void
nmtstp_ip4_address_add (gboolean external_command,
int ifindex,
in_addr_t address,
int plen,
in_addr_t peer_address,
guint32 lifetime,
guint32 preferred,
const char *label)
{
_ip_address_add (external_command,
TRUE,
ifindex,
(IPAddr *) &address,
plen,
(IPAddr *) &peer_address,
lifetime,
preferred,
label,
0);
}
void
nmtstp_ip6_address_add (gboolean external_command,
int ifindex,
struct in6_addr address,
int plen,
struct in6_addr peer_address,
guint32 lifetime,
guint32 preferred,
guint flags)
{
_ip_address_add (external_command,
FALSE,
ifindex,
(IPAddr *) &address,
plen,
(IPAddr *) &peer_address,
lifetime,
preferred,
NULL,
flags);
}
static void
_ip_address_del (gboolean external_command,
gboolean is_v4,
int ifindex,
const IPAddr *address,
int plen,
const IPAddr *peer_address)
{
gint64 end_time;
external_command = nmtstp_run_command_check_external (external_command);
if (external_command) {
const char *ifname;
char b1[NM_UTILS_INET_ADDRSTRLEN], b2[NM_UTILS_INET_ADDRSTRLEN];
int success;
gboolean had_address;
ifname = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex);
g_assert (ifname);
if (peer_address == address)
peer_address = 0;
/* let's wait until we see the address as we added it. */
if (is_v4)
had_address = !!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, address->addr4, plen, peer_address->addr4);
else
had_address = !!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, address->addr6, plen);
if (is_v4) {
success = nmtstp_run_command ("ip address delete %s%s%s/%d dev %s",
nm_utils_inet4_ntop (address->addr4, b1),
peer_address->addr4 ? " peer " : "",
peer_address->addr4 ? nm_utils_inet4_ntop (peer_address->addr4, b2) : "",
plen,
ifname);
} else {
g_assert (!peer_address);
success = nmtstp_run_command ("ip address delete %s/%d dev %s",
nm_utils_inet6_ntop (&address->addr6, b1),
plen,
ifname);
}
g_assert (success == 0 || !had_address);
} else {
gboolean success;
if (is_v4) {
success = nm_platform_ip4_address_delete (NM_PLATFORM_GET,
ifindex,
address->addr4,
plen,
peer_address->addr4);
} else {
g_assert (!peer_address);
success = nm_platform_ip6_address_delete (NM_PLATFORM_GET,
ifindex,
address->addr6,
plen);
}
g_assert (success);
}
/* Let's wait until we get the result */
end_time = nm_utils_get_monotonic_timestamp_ms () + 250;
do {
if (external_command)
nm_platform_process_events (NM_PLATFORM_GET);
/* let's wait until we see the address as we added it. */
if (is_v4) {
const NMPlatformIP4Address *a;
a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, address->addr4, plen, peer_address->addr4);
if (!a)
break;
} else {
const NMPlatformIP6Address *a;
a = nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, address->addr6, plen);
if (!a)
break;
}
/* for internal command, we expect not to reach this line.*/
g_assert (external_command);
/* timeout? */
g_assert (nm_utils_get_monotonic_timestamp_ms () < end_time);
g_assert (nmtstp_wait_for_signal_until (end_time));
} while (TRUE);
}
void
nmtstp_ip4_address_del (gboolean external_command,
int ifindex,
in_addr_t address,
int plen,
in_addr_t peer_address)
{
_ip_address_del (external_command,
TRUE,
ifindex,
(IPAddr *) &address,
plen,
(IPAddr *) &peer_address);
}
void
nmtstp_ip6_address_del (gboolean external_command,
int ifindex,
struct in6_addr address,
int plen)
{
_ip_address_del (external_command,
FALSE,
ifindex,
(IPAddr *) &address,
plen,
NULL);
}
/*****************************************************************************/
NMTST_DEFINE();
static gboolean
@ -318,7 +851,7 @@ main (int argc, char **argv)
init_tests (&argc, &argv);
if ( nmtst_platform_is_root_test ()
if ( nmtstp_is_root_test ()
&& (geteuid () != 0 || getegid () != 0)) {
if ( g_getenv ("NMTST_FORCE_REAL_ROOT")
|| !unshare_user ()) {
@ -335,7 +868,7 @@ main (int argc, char **argv)
}
}
if (nmtst_platform_is_root_test () && !g_getenv ("NMTST_NO_UNSHARE")) {
if (nmtstp_is_root_test () && !g_getenv ("NMTST_NO_UNSHARE")) {
int errsv;
if (unshare (CLONE_NEWNET | CLONE_NEWNS) != 0) {

View file

@ -43,8 +43,8 @@ typedef struct {
const char *ifname;
} SignalData;
gboolean nmtst_platform_is_root_test (void);
gboolean nmtst_platform_is_sysfs_writable (void);
gboolean nmtstp_is_root_test (void);
gboolean nmtstp_is_sysfs_writable (void);
SignalData *add_signal_full (const char *name, NMPlatformSignalChangeType change_type, GCallback callback, int ifindex, const char *ifname);
#define add_signal(name, change_type, callback) add_signal_full (name, change_type, (GCallback) callback, 0, NULL)
@ -53,11 +53,13 @@ SignalData *add_signal_full (const char *name, NMPlatformSignalChangeType change
void _accept_signal (const char *file, int line, const char *func, SignalData *data);
void _accept_signals (const char *file, int line, const char *func, SignalData *data, int min, int max);
void _wait_signal (const char *file, int line, const char *func, SignalData *data);
void _accept_or_wait_signal (const char *file, int line, const char *func, SignalData *data);
void _ensure_no_signal (const char *file, int line, const char *func, SignalData *data);
void _free_signal (const char *file, int line, const char *func, SignalData *data);
#define accept_signal(data) _accept_signal(__FILE__, __LINE__, G_STRFUNC, data)
#define accept_signals(data, min, max) _accept_signals(__FILE__, __LINE__, G_STRFUNC, data, min, max)
#define wait_signal(data) _wait_signal(__FILE__, __LINE__, G_STRFUNC, data)
#define accept_or_wait_signal(data) _accept_or_wait_signal(__FILE__, __LINE__, G_STRFUNC, data)
#define ensure_no_signal(data) _ensure_no_signal(__FILE__, __LINE__, G_STRFUNC, data)
#define free_signal(data) _free_signal(__FILE__, __LINE__, G_STRFUNC, data)
@ -68,7 +70,49 @@ void _assert_ip4_route_exists (const char *file, guint line, const char *func, g
void link_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformLink *received, NMPlatformSignalChangeType change_type, NMPlatformReason reason, SignalData *data);
void run_command (const char *format, ...);
int nmtstp_run_command (const char *format, ...) __attribute__((__format__ (__printf__, 1, 2)));
#define nmtstp_run_command_check(format, ...) do { g_assert_cmpint (nmtstp_run_command (format, __VA_ARGS__), ==, 0); } while (0)
gboolean nmtstp_wait_for_signal (guint timeout_ms);
gboolean nmtstp_wait_for_signal_until (gint64 until_ms);
int nmtstp_run_command_check_external_global (void);
gboolean nmtstp_run_command_check_external (int external_command);
gboolean nmtstp_ip_address_check_lifetime (const NMPlatformIPAddress *addr,
gint64 now,
guint32 expected_lifetime,
guint32 expected_preferred);
void nmtstp_ip_address_assert_lifetime (const NMPlatformIPAddress *addr,
gint64 now,
guint32 expected_lifetime,
guint32 expected_preferred);
void nmtstp_ip4_address_add (gboolean external_command,
int ifindex,
in_addr_t address,
int plen,
in_addr_t peer_address,
guint32 lifetime,
guint32 preferred,
const char *label);
void nmtstp_ip6_address_add (gboolean external_command,
int ifindex,
struct in6_addr address,
int plen,
struct in6_addr peer_address,
guint32 lifetime,
guint32 preferred,
guint flags);
void nmtstp_ip4_address_del (gboolean external_command,
int ifindex,
in_addr_t address,
int plen,
in_addr_t peer_address);
void nmtstp_ip6_address_del (gboolean external_command,
int ifindex,
struct in6_addr address,
int plen);
void init_tests (int *argc, char ***argv);
void setup_tests (void);

View file

@ -262,7 +262,7 @@ test_slave (int master, int type, SignalData *master_changed)
/* Set slave option */
switch (type) {
case NM_LINK_TYPE_BRIDGE:
if (nmtst_platform_is_sysfs_writable ()) {
if (nmtstp_is_sysfs_writable ()) {
g_assert (nm_platform_slave_set_option (NM_PLATFORM_GET, ifindex, "priority", "789"));
value = nm_platform_slave_get_option (NM_PLATFORM_GET, ifindex, "priority");
g_assert_cmpstr (value, ==, "789");
@ -341,7 +341,7 @@ test_software (NMLinkType link_type, const char *link_typename)
/* Set master option */
switch (link_type) {
case NM_LINK_TYPE_BRIDGE:
if (nmtst_platform_is_sysfs_writable ()) {
if (nmtstp_is_sysfs_writable ()) {
g_assert (nm_platform_master_set_option (NM_PLATFORM_GET, ifindex, "forward_delay", "789"));
value = nm_platform_master_get_option (NM_PLATFORM_GET, ifindex, "forward_delay");
g_assert_cmpstr (value, ==, "789");
@ -349,7 +349,7 @@ test_software (NMLinkType link_type, const char *link_typename)
}
break;
case NM_LINK_TYPE_BOND:
if (nmtst_platform_is_sysfs_writable ()) {
if (nmtstp_is_sysfs_writable ()) {
g_assert (nm_platform_master_set_option (NM_PLATFORM_GET, ifindex, "mode", "active-backup"));
value = nm_platform_master_get_option (NM_PLATFORM_GET, ifindex, "mode");
/* When reading back, the output looks slightly different. */
@ -408,7 +408,7 @@ test_bridge (void)
static void
test_bond (void)
{
if (nmtst_platform_is_root_test () &&
if (nmtstp_is_root_test () &&
!g_file_test ("/proc/1/net/bonding", G_FILE_TEST_IS_DIR) &&
system("modprobe --show bonding") != 0) {
g_test_skip ("Skipping test for bonding: bonding module not available");
@ -519,7 +519,7 @@ test_external (void)
SignalData *link_changed, *link_removed;
int ifindex;
run_command ("ip link add %s type %s", DEVICE_NAME, "dummy");
nmtstp_run_command_check ("ip link add %s type %s", DEVICE_NAME, "dummy");
wait_signal (link_added);
g_assert (nm_platform_link_get_by_ifname (NM_PLATFORM_GET, DEVICE_NAME));
@ -543,24 +543,24 @@ test_external (void)
g_assert (!nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex));
g_assert (!nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex));
run_command ("ip link set %s up", DEVICE_NAME);
nmtstp_run_command_check ("ip link set %s up", DEVICE_NAME);
wait_signal (link_changed);
g_assert (nm_platform_link_is_up (NM_PLATFORM_GET, ifindex));
g_assert (nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex));
run_command ("ip link set %s down", DEVICE_NAME);
nmtstp_run_command_check ("ip link set %s down", DEVICE_NAME);
wait_signal (link_changed);
g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex));
g_assert (!nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex));
run_command ("ip link set %s arp on", DEVICE_NAME);
nmtstp_run_command_check ("ip link set %s arp on", DEVICE_NAME);
wait_signal (link_changed);
g_assert (nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex));
run_command ("ip link set %s arp off", DEVICE_NAME);
nmtstp_run_command_check ("ip link set %s arp off", DEVICE_NAME);
wait_signal (link_changed);
g_assert (!nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex));
run_command ("ip link del %s", DEVICE_NAME);
nmtstp_run_command_check ("ip link del %s", DEVICE_NAME);
wait_signal (link_removed);
accept_signals (link_changed, 0, 1);
g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, DEVICE_NAME));

View file

@ -377,8 +377,8 @@ setup_dev0_ip6 (int ifindex)
nm_platform_ip6_address_add (NM_PLATFORM_GET,
ifindex,
*nmtst_inet6_from_string ("2001:db8:8086::666"),
in6addr_any,
64,
in6addr_any,
3600,
3600,
0);
@ -481,8 +481,8 @@ update_dev0_ip6 (int ifindex)
nm_platform_ip6_address_add (NM_PLATFORM_GET,
ifindex,
*nmtst_inet6_from_string ("2001:db8:8086::2"),
in6addr_any,
64,
in6addr_any,
3600,
3600,
0);