platform: merge branch 'th/platform-route-resync'

Lots of cleanup and refactoring. Most notably, make the
prefix-length property guint8.

Also fix keeping the route cache in sync when "modifying"
an existing route via `ip route change` or `ip route replace`.

(cherry picked from commit 514245b1d7)
This commit is contained in:
Thomas Haller 2016-04-11 12:17:34 +02:00
commit b973efdfa5
41 changed files with 1475 additions and 799 deletions

View file

@ -26,7 +26,9 @@
/********************************************************/
#define nm_auto(fcn) __attribute ((cleanup(fcn)))
#define _nm_packed __attribute__ ((packed))
#define nm_auto(fcn) __attribute__ ((cleanup(fcn)))
/**
* nm_auto_free:

View file

@ -782,6 +782,34 @@ nmtst_get_rand_int (void)
return g_rand_int (nmtst_get_rand ());
}
inline static gpointer
nmtst_rand_buf (GRand *rand, gpointer buffer, gsize buffer_length)
{
guint32 v;
guint8 *b = buffer;
if (!buffer_length)
return buffer;
g_assert (buffer);
if (!rand)
rand = nmtst_get_rand ();
for (; buffer_length >= sizeof (guint32); buffer_length -= sizeof (guint32), b += sizeof (guint32)) {
v = g_rand_int (rand);
memcpy (b, &v, sizeof (guint32));
}
if (buffer_length > 0) {
v = g_rand_int (rand);
do {
*(b++) = v & 0xFF;
v >>= 8;
} while (--buffer_length > 0);
}
return buffer;
}
inline static void *
nmtst_rand_perm (GRand *rand, void *dst, const void *src, gsize elmt_size, gsize n_elmt)
{
@ -1151,11 +1179,54 @@ _nmtst_assert_resolve_relative_path_equals (const char *f1, const char *f2, cons
#ifdef __NETWORKMANAGER_PLATFORM_H__
inline static NMPlatformIP4Address *
nmtst_platform_ip4_address (const char *address, const char *peer_address, guint plen)
{
static NMPlatformIP4Address addr;
g_assert (plen <= 32);
memset (&addr, 0, sizeof (addr));
addr.address = nmtst_inet4_from_string (address);
if (peer_address)
addr.peer_address = nmtst_inet4_from_string (peer_address);
else
addr.peer_address = addr.address;
addr.plen = plen;
return &addr;
}
inline static NMPlatformIP4Address *
nmtst_platform_ip4_address_full (const char *address, const char *peer_address, guint plen,
int ifindex, NMIPConfigSource source, guint32 timestamp,
guint32 lifetime, guint32 preferred, guint32 flags,
const char *label)
{
NMPlatformIP4Address *addr = nmtst_platform_ip4_address (address, peer_address, plen);
G_STATIC_ASSERT (IFNAMSIZ == sizeof (addr->label));
g_assert (!label || strlen (label) < IFNAMSIZ);
addr->ifindex = ifindex;
addr->source = source;
addr->timestamp = timestamp;
addr->lifetime = lifetime;
addr->preferred = preferred;
addr->n_ifa_flags = flags;
if (label)
g_strlcpy (addr->label, label, sizeof (addr->label));
return addr;
}
inline static NMPlatformIP6Address *
nmtst_platform_ip6_address (const char *address, const char *peer_address, guint plen)
{
static NMPlatformIP6Address addr;
g_assert (plen <= 128);
memset (&addr, 0, sizeof (addr));
addr.address = *nmtst_inet6_from_string (address);
addr.peer_address = *nmtst_inet6_from_string (peer_address);
@ -1186,6 +1257,8 @@ nmtst_platform_ip4_route (const char *network, guint plen, const char *gateway)
{
static NMPlatformIP4Route route;
g_assert (plen <= 32);
memset (&route, 0, sizeof (route));
route.network = nmtst_inet4_from_string (network);
route.plen = plen;
@ -1218,6 +1291,8 @@ nmtst_platform_ip6_route (const char *network, guint plen, const char *gateway)
{
static NMPlatformIP6Route route;
nm_assert (plen <= 128);
memset (&route, 0, sizeof (route));
route.network = *nmtst_inet6_from_string (network);
route.plen = plen;

View file

@ -5725,6 +5725,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self)
if (discovered_route->plen > 0) {
memset (&route, 0, sizeof (route));
route.network = discovered_route->network;
nm_assert (discovered_route->plen <= 128);
route.plen = discovered_route->plen;
route.gateway = discovered_route->gateway;
route.source = NM_IP_CONFIG_SOURCE_RDISC;

View file

@ -79,7 +79,7 @@ test_arping_common (test_fixture *fixture, TestInfo *info)
g_assert (nm_arping_manager_add_address (manager, info->addresses[i]));
for (i = 0; info->peer_addresses[i]; i++) {
nmtstp_ip4_address_add (FALSE, fixture->ifindex1, info->peer_addresses[i],
nmtstp_ip4_address_add (NULL, FALSE, fixture->ifindex1, info->peer_addresses[i],
24, 0, 3600, 1800, 0, NULL);
}
@ -126,13 +126,13 @@ fixture_teardown (test_fixture *fixture, gconstpointer user_data)
}
void
init_tests (int *argc, char ***argv)
_nmtstp_init_tests (int *argc, char ***argv)
{
nmtst_init_with_logging (argc, argv, NULL, "ALL");
}
void
setup_tests (void)
_nmtstp_setup_tests (void)
{
g_test_add ("/arping/1", test_fixture, NULL, fixture_setup, test_arping_1, fixture_teardown);
g_test_add ("/arping/2", test_fixture, NULL, fixture_setup, test_arping_2, fixture_teardown);

View file

@ -435,13 +435,13 @@ _test_recv_fixture_teardown (TestRecvFixture *fixture, gconstpointer user_data)
/*****************************************************************************/
void
init_tests (int *argc, char ***argv)
_nmtstp_init_tests (int *argc, char ***argv)
{
nmtst_init_assert_logging (argc, argv, "WARN", "ALL");
}
void
setup_tests (void)
_nmtstp_setup_tests (void)
{
#define _TEST_ADD_RECV(testpath, testdata) \
g_test_add (testpath, TestRecvFixture, testdata, _test_recv_fixture_setup, test_recv, _test_recv_fixture_teardown)

View file

@ -870,7 +870,8 @@ static_stage3_ip4_done (NMModemBroadband *self)
address.peer_address = address_network;
address.plen = mm_bearer_ip_config_get_prefix (self->priv->ipv4_config);
address.source = NM_IP_CONFIG_SOURCE_WWAN;
nm_ip4_config_add_address (config, &address);
if (address.plen <= 32)
nm_ip4_config_add_address (config, &address);
nm_log_info (LOGD_MB, " address %s/%d", address_string, address.plen);
@ -960,7 +961,8 @@ stage3_ip6_done (NMModemBroadband *self)
config = nm_ip6_config_new (nm_platform_link_get_ifindex (NM_PLATFORM_GET, data_port));
address.plen = mm_bearer_ip_config_get_prefix (self->priv->ipv6_config);
nm_ip6_config_add_address (config, &address);
if (address.plen <= 128)
nm_ip6_config_add_address (config, &address);
nm_log_info (LOGD_MB, " address %s/%d", address_string, address.plen);

View file

@ -312,7 +312,8 @@ lease_to_ip4_config (const char *iface,
continue;
route.network = a.s_addr;
if (sd_dhcp_route_get_destination_prefix_length (routes[i], &plen) < 0)
if ( sd_dhcp_route_get_destination_prefix_length (routes[i], &plen) < 0
|| plen > 32)
continue;
route.plen = plen;

View file

@ -60,7 +60,7 @@ ip4_process_dhcpcd_rfc3442_routes (const char *str,
*slash = '\0';
errno = 0;
rt_cidr = strtol (slash + 1, NULL, 10);
if ((errno == EINVAL) || (errno == ERANGE)) {
if (errno || rt_cidr > 32) {
nm_log_warn (LOGD_DHCP4, "DHCP provided invalid classless static route cidr: '%s'", slash + 1);
continue;
}
@ -382,7 +382,8 @@ nm_dhcp_utils_ip4_config_from_options (int ifindex,
in_addr_t addr;
NMPlatformIP4Address address;
char *str = NULL;
guint32 gwaddr = 0, plen = 0;
guint32 gwaddr = 0;
guint8 plen = 0;
g_return_val_if_fail (options != NULL, NULL);

View file

@ -208,6 +208,8 @@ ip4_test_route (NMIP4Config *ip4_config,
const NMPlatformIP4Route *route;
guint32 tmp;
g_assert (expected_prefix <= 32);
route = nm_ip4_config_get_route (ip4_config, route_num);
g_assert (inet_pton (AF_INET, expected_dest, &tmp) > 0);
g_assert (route->network == tmp);

View file

@ -34,7 +34,7 @@ nm_dnsmasq_utils_get_range (const NMPlatformIP4Address *addr,
char **out_error_desc)
{
guint32 host = addr->address;
guint32 prefix = addr->plen;
guint8 prefix = addr->plen;
guint32 netmask = nm_utils_ip4_prefix_to_netmask (prefix);
guint32 first, last, reserved;

View file

@ -26,14 +26,6 @@
#include "nm-test-utils.h"
static NMPlatformIP4Address *
_set_addr (NMPlatformIP4Address *addr, const char *address, int plen)
{
memset (addr, 0, sizeof (*addr));
nm_platform_ip4_address_set_addr (addr, nmtst_inet4_from_string (address), plen);
return addr;
}
static void
test_address_ranges (void)
{
@ -42,50 +34,50 @@ test_address_ranges (void)
char last[INET_ADDRSTRLEN];
char *error_desc = NULL;
_set_addr (&addr, "192.168.0.1", 24);
addr = *nmtst_platform_ip4_address ("192.168.0.1", NULL, 24);
g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc));
g_assert (error_desc == NULL);
g_assert_cmpstr (first, ==, "192.168.0.10");
g_assert_cmpstr (last, ==, "192.168.0.254");
_set_addr (&addr, "192.168.0.99", 24);
addr = *nmtst_platform_ip4_address ("192.168.0.99", NULL, 24);
g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc));
g_assert (error_desc == NULL);
g_assert_cmpstr (first, ==, "192.168.0.108");
g_assert_cmpstr (last, ==, "192.168.0.254");
_set_addr (&addr, "192.168.0.254", 24);
addr = *nmtst_platform_ip4_address ("192.168.0.254", NULL, 24);
g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc));
g_assert (error_desc == NULL);
g_assert_cmpstr (first, ==, "192.168.0.1");
g_assert_cmpstr (last, ==, "192.168.0.245");
/* Smaller networks */
_set_addr (&addr, "1.2.3.1", 30);
addr = *nmtst_platform_ip4_address ("1.2.3.1", NULL, 30);
g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc));
g_assert (error_desc == NULL);
g_assert_cmpstr (first, ==, "1.2.3.2");
g_assert_cmpstr (last, ==, "1.2.3.2");
_set_addr (&addr, "1.2.3.1", 29);
addr = *nmtst_platform_ip4_address ("1.2.3.1", NULL, 29);
g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc));
g_assert (error_desc == NULL);
g_assert_cmpstr (first, ==, "1.2.3.2");
g_assert_cmpstr (last, ==, "1.2.3.6");
_set_addr (&addr, "1.2.3.1", 28);
addr = *nmtst_platform_ip4_address ("1.2.3.1", NULL, 28);
g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc));
g_assert (error_desc == NULL);
g_assert_cmpstr (first, ==, "1.2.3.3");
g_assert_cmpstr (last, ==, "1.2.3.14");
_set_addr (&addr, "1.2.3.1", 26);
addr = *nmtst_platform_ip4_address ("1.2.3.1", NULL, 26);
g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc));
g_assert (error_desc == NULL);
g_assert_cmpstr (first, ==, "1.2.3.8");
g_assert_cmpstr (last, ==, "1.2.3.62");
_set_addr (&addr, "1.2.3.1", 31);
addr = *nmtst_platform_ip4_address ("1.2.3.1", NULL, 31);
g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc) == FALSE);
g_assert (error_desc);
g_free (error_desc);

View file

@ -233,7 +233,6 @@ nm_ethernet_address_is_valid (gconstpointer addr, gssize len)
return TRUE;
}
/* nm_utils_ip4_address_clear_host_address:
* @addr: source ip6 address
* @plen: prefix length of network
@ -279,6 +278,32 @@ nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_
return dst;
}
gboolean
nm_utils_ip6_address_same_prefix (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen)
{
int nbytes;
guint8 t, m;
if (plen >= 128)
return memcmp (addr_a, addr_b, sizeof (struct in6_addr)) == 0;
nbytes = plen / 8;
if (nbytes) {
if (memcmp (addr_a, addr_b, nbytes) != 0)
return FALSE;
}
plen = plen % 8;
if (plen == 0)
return TRUE;
m = ~((1 << (8 - plen)) - 1);
t = ((((const guint8 *) addr_a))[nbytes]) ^ ((((const guint8 *) addr_b))[nbytes]);
return (t & m) == 0;
}
/*****************************************************************************/
void
nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len)
{

View file

@ -100,6 +100,7 @@ gboolean nm_ethernet_address_is_valid (gconstpointer addr, gssize len);
in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen);
const struct in6_addr *nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen);
gboolean nm_utils_ip6_address_same_prefix (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen);
/**
* nm_utils_ip6_route_metric_normalize:
@ -220,11 +221,13 @@ fcn_name (lookup_type val, char *buf, gsize len) \
/*****************************************************************************/
#define NM_UTILS_LOOKUP_DEFAULT(v) return (v)
#define NM_UTILS_LOOKUP_DEFAULT_WARN(v) g_return_val_if_reached (v)
#define NM_UTILS_LOOKUP_ITEM(v, n) (void) 0; case v: return (n); (void) 0
#define NM_UTILS_LOOKUP_STR_ITEM(v, n) NM_UTILS_LOOKUP_ITEM(v, ""n"")
#define NM_UTILS_LOOKUP_ITEM_IGNORE(v) (void) 0; case v: break; (void) 0
#define NM_UTILS_LOOKUP_DEFAULT(v) return (v)
#define NM_UTILS_LOOKUP_DEFAULT_WARN(v) g_return_val_if_reached (v)
#define NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT(v) { nm_assert_not_reached (); return (v); }
#define NM_UTILS_LOOKUP_ITEM(v, n) (void) 0; case v: return (n); (void) 0
#define NM_UTILS_LOOKUP_STR_ITEM(v, n) NM_UTILS_LOOKUP_ITEM(v, ""n"")
#define NM_UTILS_LOOKUP_ITEM_IGNORE(v) (void) 0; case v: break; (void) 0
#define NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER() (void) 0; default: break; (void) 0
#define _NM_UTILS_LOOKUP_DEFINE(scope, fcn_name, lookup_type, result_type, unknown_val, ...) \
scope result_type \

View file

@ -213,7 +213,8 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da
* local configuration or user preferences are, so sending routes
* with a prefix length of 0 is quite rude and thus ignored.
*/
if (discovered_route->plen > 0) {
if ( discovered_route->plen > 0
&& discovered_route->plen <= 128) {
memset (&route, 0, sizeof (route));
route.network = discovered_route->network;
route.plen = discovered_route->plen;

View file

@ -365,6 +365,8 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_fu
if (addr->plen == 0)
continue;
nm_assert (addr->plen <= 32);
route.ifindex = ifindex;
route.source = NM_IP_CONFIG_SOURCE_KERNEL;
@ -466,6 +468,7 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu
nm_ip_address_get_address_binary (s_addr, &address.address);
address.peer_address = address.address;
address.plen = nm_ip_address_get_prefix (s_addr);
nm_assert (address.plen <= 32);
address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
address.preferred = NM_PLATFORM_LIFETIME_PERMANENT;
address.source = NM_IP_CONFIG_SOURCE_USER;
@ -486,7 +489,12 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu
memset (&route, 0, sizeof (route));
nm_ip_route_get_dest_binary (s_route, &route.network);
route.plen = nm_ip_route_get_prefix (s_route);
nm_assert (route.plen <= 32);
if (route.plen == 0)
continue;
nm_ip_route_get_next_hop_binary (s_route, &route.gateway);
if (nm_ip_route_get_metric (s_route) == -1)
route.metric = default_route_metric;
@ -494,8 +502,6 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu
route.metric = nm_ip_route_get_metric (s_route);
route.source = NM_IP_CONFIG_SOURCE_USER;
g_assert (route.plen > 0);
nm_ip4_config_add_route (config, &route);
}
@ -561,6 +567,10 @@ nm_ip4_config_create_setting (const NMIP4Config *config)
continue;
}
/* FIXME: NMIPAddress doesn't support zero prefixes. */
if (address->plen == 0)
continue;
/* Static address found. */
if (!method)
method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
@ -1328,7 +1338,7 @@ nm_ip4_config_dump (const NMIP4Config *config, const char *detail)
}
gboolean
nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 network, int plen)
nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 network, guint8 plen)
{
guint naddresses = nm_ip4_config_get_num_addresses (config);
int i;
@ -1567,7 +1577,7 @@ nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *new)
int i;
g_return_if_fail (new != NULL);
g_return_if_fail (new->plen > 0);
g_return_if_fail (new->plen > 0 && new->plen <= 32);
g_assert (priv->ifindex);
for (i = 0; i < priv->routes->len; i++ ) {

View file

@ -79,7 +79,7 @@ void nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMe
void nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src);
void nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src);
gboolean nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes);
gboolean nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 dest, int plen);
gboolean nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 dest, guint8 plen);
void nm_ip4_config_dump (const NMIP4Config *config, const char *detail);
/* Gateways */

View file

@ -95,24 +95,6 @@ nm_ip6_config_get_ifindex (const NMIP6Config *config)
/******************************************************************/
static gboolean
same_prefix (const struct in6_addr *address1, const struct in6_addr *address2, int plen)
{
const guint8 *bytes1 = (const guint8 *) address1;
const guint8 *bytes2 = (const guint8 *) address2;
int nbytes = plen / 8;
int nbits = plen % 8;
int masked1 = bytes1[nbytes] >> (8 - nbits);
int masked2 = bytes2[nbytes] >> (8 - nbits);
if (nbytes && memcmp (bytes1, bytes2, nbytes))
return FALSE;
return masked1 == masked2;
}
/******************************************************************/
/**
* nm_ip6_config_capture_resolv_conf():
* @nameservers: array of struct in6_addr
@ -472,6 +454,7 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu
memset (&address, 0, sizeof (address));
nm_ip_address_get_address_binary (s_addr, &address.address);
address.plen = nm_ip_address_get_prefix (s_addr);
nm_assert (address.plen <= 128);
address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
address.preferred = NM_PLATFORM_LIFETIME_PERMANENT;
address.source = NM_IP_CONFIG_SOURCE_USER;
@ -488,7 +471,12 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu
memset (&route, 0, sizeof (route));
nm_ip_route_get_dest_binary (s_route, &route.network);
route.plen = nm_ip_route_get_prefix (s_route);
nm_assert (route.plen <= 128);
if (route.plen == 0)
continue;
nm_ip_route_get_next_hop_binary (s_route, &route.gateway);
if (nm_ip_route_get_metric (s_route) == -1)
route.metric = default_route_metric;
@ -496,8 +484,6 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu
route.metric = nm_ip_route_get_metric (s_route);
route.source = NM_IP_CONFIG_SOURCE_USER;
g_assert (route.plen > 0);
nm_ip6_config_add_route (config, &route);
}
@ -570,6 +556,10 @@ nm_ip6_config_create_setting (const NMIP6Config *config)
continue;
}
/* FIXME: NMIPAddress does not support zero prefixes. */
if (address->plen == 0)
continue;
/* Static address found. */
if (!method || strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0)
method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
@ -708,16 +698,20 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFl
}
gboolean
nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6_addr *network, int plen)
nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6_addr *network, guint8 plen)
{
int num = nm_ip6_config_get_num_addresses (config);
int i;
nm_assert (network);
nm_assert (plen <= 128);
for (i = 0; i < num; i++) {
const NMPlatformIP6Address *item = nm_ip6_config_get_address (config, i);
if (item->plen <= plen && same_prefix (&item->address, network, item->plen) &&
!(item->n_ifa_flags & IFA_F_NOPREFIXROUTE))
if ( item->plen <= plen
&& !NM_FLAGS_HAS (item->n_ifa_flags, IFA_F_NOPREFIXROUTE)
&& nm_utils_ip6_address_same_prefix (&item->address, network, item->plen))
return TRUE;
}
@ -1415,7 +1409,7 @@ nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *new)
int i;
g_return_if_fail (new != NULL);
g_return_if_fail (new->plen > 0);
g_return_if_fail (new->plen > 0 && new->plen <= 128);
g_assert (priv->ifindex);
for (i = 0; i < priv->routes->len; i++ ) {
@ -1473,7 +1467,6 @@ nm_ip6_config_get_direct_route_for_host (const NMIP6Config *config, const struct
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
guint i;
struct in6_addr network2, host2;
NMPlatformIP6Route *best_route = NULL;
g_return_val_if_fail (host && !IN6_IS_ADDR_UNSPECIFIED (host), NULL);
@ -1487,10 +1480,7 @@ nm_ip6_config_get_direct_route_for_host (const NMIP6Config *config, const struct
if (best_route && best_route->plen > item->plen)
continue;
nm_utils_ip6_address_clear_host_address (&host2, host, item->plen);
nm_utils_ip6_address_clear_host_address (&network2, &item->network, item->plen);
if (!IN6_ARE_ADDR_EQUAL (&network2, &host2))
if (!nm_utils_ip6_address_same_prefix (host, &item->network, item->plen))
continue;
if (best_route &&

View file

@ -81,7 +81,7 @@ void nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMe
void nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src);
void nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src);
gboolean nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes);
int nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6_addr *dest, int plen);
int nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6_addr *dest, guint8 plen);
void nm_ip6_config_dump (const NMIP6Config *config, const char *detail);
/* Gateways */

View file

@ -221,7 +221,7 @@ _v6_route_dest_cmp (const NMPlatformIP6Route *r1, const NMPlatformIP6Route *r2)
CMP_AND_RETURN_INT (r1->plen, r2->plen);
nm_utils_ip6_address_clear_host_address (&n1, &r1->network, r1->plen);
nm_utils_ip6_address_clear_host_address (&n2, &r2->network, r2->plen);
nm_utils_ip6_address_clear_host_address (&n2, &r2->network, r2->plen );
return memcmp (&n1, &n2, sizeof (n1));
}

View file

@ -91,17 +91,17 @@ static void link_changed (NMPlatform *platform, NMFakePlatformLink *device, gboo
static gboolean ip6_address_add (NMPlatform *platform,
int ifindex,
struct in6_addr addr,
int plen,
guint8 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);
static gboolean ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen);
/******************************************************************/
static gboolean
_ip4_address_equal_peer_net (in_addr_t peer1, in_addr_t peer2, int plen)
_ip4_address_equal_peer_net (in_addr_t peer1, in_addr_t peer2, guint8 plen)
{
return ((peer1 ^ peer2) & nm_utils_ip4_prefix_to_netmask (plen)) == 0;
}
@ -886,7 +886,7 @@ static gboolean
ip4_address_add (NMPlatform *platform,
int ifindex,
in_addr_t addr,
int plen,
guint8 plen,
in_addr_t peer_addr,
guint32 lifetime,
guint32 preferred,
@ -938,7 +938,7 @@ static gboolean
ip6_address_add (NMPlatform *platform,
int ifindex,
struct in6_addr addr,
int plen,
guint8 plen,
struct in6_addr peer_addr,
guint32 lifetime,
guint32 preferred,
@ -982,7 +982,7 @@ ip6_address_add (NMPlatform *platform,
}
static gboolean
ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in_addr_t peer_address)
ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, guint8 plen, in_addr_t peer_address)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
@ -1007,7 +1007,7 @@ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen,
}
static gboolean
ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen)
ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
@ -1031,7 +1031,7 @@ 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, in_addr_t peer_address)
ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, guint8 plen, in_addr_t peer_address)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
@ -1050,7 +1050,7 @@ ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in
}
static const NMPlatformIP6Address *
ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen)
ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
@ -1058,8 +1058,9 @@ ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr, int pl
for (i = 0; i < priv->ip6_addresses->len; i++) {
NMPlatformIP6Address *address = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i);
if (address->ifindex == ifindex && address->plen == plen &&
IN6_ARE_ADDR_EQUAL (&address->address, &addr))
if ( address->ifindex == ifindex
&& address->plen == plen
&& IN6_ARE_ADDR_EQUAL (&address->address, &addr))
return address;
}
@ -1129,7 +1130,7 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags fl
}
static gboolean
ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric)
ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
@ -1153,7 +1154,7 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen
}
static gboolean
ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric)
ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
@ -1180,7 +1181,7 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, in
static gboolean
ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
in_addr_t network, int plen, in_addr_t gateway,
in_addr_t network, guint8 plen, in_addr_t gateway,
in_addr_t pref_src, guint32 metric, guint32 mss)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
@ -1188,6 +1189,8 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
guint i;
guint8 scope;
g_assert (plen <= 32);
scope = gateway == 0 ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
memset (&route, 0, sizeof (route));
@ -1247,7 +1250,7 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
static gboolean
ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
struct in6_addr network, guint8 plen, struct in6_addr gateway,
guint32 metric, guint32 mss)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
@ -1313,7 +1316,7 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
}
static const NMPlatformIP4Route *
ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric)
ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
@ -1332,7 +1335,7 @@ ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, g
}
static const NMPlatformIP6Route *
ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric)
ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;

View file

@ -176,13 +176,22 @@
* Forward declarations and enums
******************************************************************/
enum {
DELAYED_ACTION_IDX_REFRESH_ALL_LINKS,
DELAYED_ACTION_IDX_REFRESH_ALL_IP4_ADDRESSES,
DELAYED_ACTION_IDX_REFRESH_ALL_IP6_ADDRESSES,
DELAYED_ACTION_IDX_REFRESH_ALL_IP4_ROUTES,
DELAYED_ACTION_IDX_REFRESH_ALL_IP6_ROUTES,
_DELAYED_ACTION_IDX_REFRESH_ALL_NUM,
};
typedef enum {
DELAYED_ACTION_TYPE_NONE = 0,
DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS = (1LL << 0),
DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES = (1LL << 1),
DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES = (1LL << 2),
DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES = (1LL << 3),
DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES = (1LL << 4),
DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS = (1LL << DELAYED_ACTION_IDX_REFRESH_ALL_LINKS),
DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES = (1LL << DELAYED_ACTION_IDX_REFRESH_ALL_IP4_ADDRESSES),
DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES = (1LL << DELAYED_ACTION_IDX_REFRESH_ALL_IP6_ADDRESSES),
DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES = (1LL << DELAYED_ACTION_IDX_REFRESH_ALL_IP4_ROUTES),
DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES = (1LL << DELAYED_ACTION_IDX_REFRESH_ALL_IP6_ROUTES),
DELAYED_ACTION_TYPE_REFRESH_LINK = (1LL << 5),
DELAYED_ACTION_TYPE_MASTER_CONNECTED = (1LL << 6),
DELAYED_ACTION_TYPE_READ_NETLINK = (1LL << 7),
@ -198,6 +207,10 @@ typedef enum {
DELAYED_ACTION_TYPE_MAX = __DELAYED_ACTION_TYPE_MAX -1,
} DelayedActionType;
#define FOR_EACH_DELAYED_ACTION(iflags, flags_all) \
for ((iflags) = (DelayedActionType) 0x1LL; (iflags) <= DELAYED_ACTION_TYPE_MAX; (iflags) <<= 1) \
if (NM_FLAGS_HAS (flags_all, iflags))
typedef enum {
/* Negative values are errors from kernel. Add dummy member to
* make enum signed. */
@ -290,49 +303,9 @@ _support_user_ipv6ll_detect (struct nlattr **tb)
* Various utilities
******************************************************************/
static guint
_nm_ip_config_source_to_rtprot (NMIPConfigSource source)
{
switch (source) {
case NM_IP_CONFIG_SOURCE_UNKNOWN:
return RTPROT_UNSPEC;
case NM_IP_CONFIG_SOURCE_KERNEL:
case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL:
return RTPROT_KERNEL;
case NM_IP_CONFIG_SOURCE_DHCP:
return RTPROT_DHCP;
case NM_IP_CONFIG_SOURCE_RDISC:
return RTPROT_RA;
default:
return RTPROT_STATIC;
}
}
static NMIPConfigSource
_nm_ip_config_source_from_rtprot (guint rtprot)
{
switch (rtprot) {
case RTPROT_UNSPEC:
return NM_IP_CONFIG_SOURCE_UNKNOWN;
case RTPROT_KERNEL:
return NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
case RTPROT_REDIRECT:
return NM_IP_CONFIG_SOURCE_KERNEL;
case RTPROT_RA:
return NM_IP_CONFIG_SOURCE_RDISC;
case RTPROT_DHCP:
return NM_IP_CONFIG_SOURCE_DHCP;
default:
return NM_IP_CONFIG_SOURCE_USER;
}
}
static void
clear_host_address (int family, const void *network, int plen, void *dst)
clear_host_address (int family, const void *network, guint8 plen, void *dst)
{
g_return_if_fail (plen == (guint8)plen);
g_return_if_fail (network);
switch (family) {
@ -1641,6 +1614,9 @@ _new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only)
? sizeof (in_addr_t)
: sizeof (struct in6_addr);
if (ifa->ifa_prefixlen > (is_v4 ? 32 : 128))
goto errout;
/*****************************************************************/
obj = nmp_object_new (is_v4 ? NMP_OBJECT_TYPE_IP4_ADDRESS : NMP_OBJECT_TYPE_IP6_ADDRESS, NULL);
@ -1779,6 +1755,9 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
? sizeof (in_addr_t)
: sizeof (struct in6_addr);
if (rtm->rtm_dst_len > (is_v4 ? 32 : 128))
goto errout;
/*****************************************************************
* parse nexthops. Only handle routes with one nh.
*****************************************************************/
@ -1906,7 +1885,7 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
* */
obj->ip_route.source = _NM_IP_CONFIG_SOURCE_RTM_F_CLONED;
} else
obj->ip_route.source = _nm_ip_config_source_from_rtprot (rtm->rtm_protocol);
obj->ip_route.source = nmp_utils_ip_config_source_from_rtprot (rtm->rtm_protocol);
obj_result = obj;
obj = NULL;
@ -2158,7 +2137,7 @@ _nl_msg_new_address (int nlmsg_type,
int family,
int ifindex,
gconstpointer address,
int plen,
guint8 plen,
gconstpointer peer_address,
guint32 flags,
int scope,
@ -2255,7 +2234,7 @@ _nl_msg_new_route (int nlmsg_type,
NMIPConfigSource source,
unsigned char scope,
gconstpointer network,
int plen,
guint8 plen,
gconstpointer gateway,
guint32 metric,
guint32 mss,
@ -2266,7 +2245,7 @@ _nl_msg_new_route (int nlmsg_type,
.rtm_family = family,
.rtm_tos = 0,
.rtm_table = RT_TABLE_MAIN, /* omit setting RTA_TABLE attribute */
.rtm_protocol = _nm_ip_config_source_to_rtprot (source),
.rtm_protocol = nmp_utils_ip_config_source_to_rtprot (source),
.rtm_scope = scope,
.rtm_type = RTN_UNICAST,
.rtm_flags = 0,
@ -2369,9 +2348,10 @@ _support_kernel_extended_ifa_flags_get (void)
typedef struct {
guint32 seq_number;
gint64 timeout_abs_ns;
WaitForNlResponseResult seq_result;
gint64 timeout_abs_ns;
WaitForNlResponseResult *out_seq_result;
gint *out_refresh_all_in_progess;
} DelayedActionWaitForNlResponseData;
typedef struct _NMLinuxPlatformPrivate NMLinuxPlatformPrivate;
@ -2379,7 +2359,10 @@ typedef struct _NMLinuxPlatformPrivate NMLinuxPlatformPrivate;
struct _NMLinuxPlatformPrivate {
struct nl_sock *nlh;
guint32 nlh_seq_next;
#ifdef NM_MORE_LOGGING
guint32 nlh_seq_last_handled;
#endif
guint32 nlh_seq_last_seen;
NMPCache *cache;
GIOChannel *event_channel;
guint event_id;
@ -2390,10 +2373,18 @@ struct _NMLinuxPlatformPrivate {
GUdevClient *udev_client;
struct {
/* which delayed actions are scheduled, as marked in @flags.
* Some types have additional arguments in the fields below. */
DelayedActionType flags;
/* counter that a refresh all action is in progress, separated
* by type. */
gint refresh_all_in_progess[_DELAYED_ACTION_IDX_REFRESH_ALL_NUM];
GPtrArray *list_master_connected;
GPtrArray *list_refresh_link;
GArray *list_wait_for_nl_response;
gint is_handling;
} delayed_action;
@ -2412,12 +2403,21 @@ NM_LINUX_PLATFORM_GET_PRIVATE (const void *self)
G_DEFINE_TYPE (NMLinuxPlatform, nm_linux_platform, NM_TYPE_PLATFORM)
NMPlatform *
nm_linux_platform_new (gboolean netns_support)
{
return g_object_new (NM_TYPE_LINUX_PLATFORM,
NM_PLATFORM_REGISTER_SINGLETON, FALSE,
NM_PLATFORM_NETNS_SUPPORT, netns_support,
NULL);
}
void
nm_linux_platform_setup (void)
{
g_object_new (NM_TYPE_LINUX_PLATFORM,
NM_PLATFORM_NETNS_SUPPORT, FALSE,
NM_PLATFORM_REGISTER_SINGLETON, TRUE,
NM_PLATFORM_NETNS_SUPPORT, FALSE,
NULL);
}
@ -2733,49 +2733,51 @@ do_emit_signal (NMPlatform *platform, const NMPObject *obj, NMPCacheOpsType cach
/******************************************************************/
static DelayedActionType
delayed_action_refresh_from_object_type (NMPObjectType obj_type)
{
switch (obj_type) {
case NMP_OBJECT_TYPE_LINK: return DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS;
case NMP_OBJECT_TYPE_IP4_ADDRESS: return DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES;
case NMP_OBJECT_TYPE_IP6_ADDRESS: return DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES;
case NMP_OBJECT_TYPE_IP4_ROUTE: return DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES;
case NMP_OBJECT_TYPE_IP6_ROUTE: return DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES;
default: g_return_val_if_reached (DELAYED_ACTION_TYPE_NONE);
}
}
_NM_UTILS_LOOKUP_DEFINE (static, delayed_action_refresh_from_object_type, NMPObjectType, DelayedActionType,
NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT (DELAYED_ACTION_TYPE_NONE),
NM_UTILS_LOOKUP_ITEM (NMP_OBJECT_TYPE_LINK, DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS),
NM_UTILS_LOOKUP_ITEM (NMP_OBJECT_TYPE_IP4_ADDRESS, DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES),
NM_UTILS_LOOKUP_ITEM (NMP_OBJECT_TYPE_IP6_ADDRESS, DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES),
NM_UTILS_LOOKUP_ITEM (NMP_OBJECT_TYPE_IP4_ROUTE, DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES),
NM_UTILS_LOOKUP_ITEM (NMP_OBJECT_TYPE_IP6_ROUTE, DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES),
NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER (),
);
static NMPObjectType
delayed_action_refresh_to_object_type (DelayedActionType action_type)
{
switch (action_type) {
case DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS: return NMP_OBJECT_TYPE_LINK;
case DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES: return NMP_OBJECT_TYPE_IP4_ADDRESS;
case DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES: return NMP_OBJECT_TYPE_IP6_ADDRESS;
case DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES: return NMP_OBJECT_TYPE_IP4_ROUTE;
case DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES: return NMP_OBJECT_TYPE_IP6_ROUTE;
default: g_return_val_if_reached (NMP_OBJECT_TYPE_UNKNOWN);
}
}
_NM_UTILS_LOOKUP_DEFINE (static, delayed_action_refresh_to_object_type, DelayedActionType, NMPObjectType,
NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT (NMP_OBJECT_TYPE_UNKNOWN),
NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS, NMP_OBJECT_TYPE_LINK),
NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES, NMP_OBJECT_TYPE_IP4_ADDRESS),
NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES, NMP_OBJECT_TYPE_IP6_ADDRESS),
NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES, NMP_OBJECT_TYPE_IP4_ROUTE),
NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, NMP_OBJECT_TYPE_IP6_ROUTE),
NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER (),
);
static const char *
delayed_action_to_string (DelayedActionType action_type)
{
switch (action_type) {
case DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS : return "refresh-all-links";
case DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES : return "refresh-all-ip4-addresses";
case DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES : return "refresh-all-ip6-addresses";
case DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES : return "refresh-all-ip4-routes";
case DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES : return "refresh-all-ip6-routes";
case DELAYED_ACTION_TYPE_REFRESH_LINK : return "refresh-link";
case DELAYED_ACTION_TYPE_MASTER_CONNECTED : return "master-connected";
case DELAYED_ACTION_TYPE_READ_NETLINK : return "read-netlink";
case DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE : return "wait-for-nl-response";
default:
return "unknown";
}
}
_NM_UTILS_LOOKUP_DEFINE (static, delayed_action_refresh_all_to_idx, DelayedActionType, guint,
NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT (0),
NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS, DELAYED_ACTION_IDX_REFRESH_ALL_LINKS),
NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES, DELAYED_ACTION_IDX_REFRESH_ALL_IP4_ADDRESSES),
NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES, DELAYED_ACTION_IDX_REFRESH_ALL_IP6_ADDRESSES),
NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES, DELAYED_ACTION_IDX_REFRESH_ALL_IP4_ROUTES),
NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, DELAYED_ACTION_IDX_REFRESH_ALL_IP6_ROUTES),
NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER (),
);
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (delayed_action_to_string, DelayedActionType,
NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"),
NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS, "refresh-all-links"),
NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES, "refresh-all-ip4-addresses"),
NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES, "refresh-all-ip6-addresses"),
NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES, "refresh-all-ip4-routes"),
NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, "refresh-all-ip6-routes"),
NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_LINK, "refresh-link"),
NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_MASTER_CONNECTED, "master-connected"),
NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_READ_NETLINK, "read-netlink"),
NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE, "wait-for-nl-response"),
NM_UTILS_LOOKUP_ITEM_IGNORE (DELAYED_ACTION_TYPE_NONE),
NM_UTILS_LOOKUP_ITEM_IGNORE (DELAYED_ACTION_TYPE_REFRESH_ALL),
NM_UTILS_LOOKUP_ITEM_IGNORE (__DELAYED_ACTION_TYPE_MAX),
);
static const char *
delayed_action_to_string_full (DelayedActionType action_type, gpointer user_data, char *buf, gsize buf_size)
@ -2826,6 +2828,24 @@ delayed_action_to_string_full (DelayedActionType action_type, gpointer user_data
/*****************************************************************************/
static gboolean
delayed_action_refresh_all_in_progress (NMPlatform *platform, DelayedActionType action_type)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
nm_assert (nm_utils_is_power_of_two (action_type));
nm_assert (NM_FLAGS_ANY (action_type, DELAYED_ACTION_TYPE_REFRESH_ALL));
nm_assert (!NM_FLAGS_ANY (action_type, ~DELAYED_ACTION_TYPE_REFRESH_ALL));
if (NM_FLAGS_ANY (priv->delayed_action.flags, action_type))
return TRUE;
if (priv->delayed_action.refresh_all_in_progess[delayed_action_refresh_all_to_idx (action_type)] > 0)
return TRUE;
return FALSE;
}
static void
delayed_action_wait_for_nl_response_complete (NMPlatform *platform,
guint idx,
@ -2833,7 +2853,6 @@ delayed_action_wait_for_nl_response_complete (NMPlatform *platform,
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
DelayedActionWaitForNlResponseData *data;
WaitForNlResponseResult *out_seq_result;
nm_assert (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE));
nm_assert (idx < priv->delayed_action.list_wait_for_nl_response->len);
@ -2843,16 +2862,16 @@ delayed_action_wait_for_nl_response_complete (NMPlatform *platform,
_LOGt_delayed_action (DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE, data, "complete");
out_seq_result = data->out_seq_result;
if (priv->delayed_action.list_wait_for_nl_response->len <= 1)
priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE;
if (data->out_seq_result)
*data->out_seq_result = seq_result;
if (data->out_refresh_all_in_progess) {
nm_assert (*data->out_refresh_all_in_progess > 0);
*data->out_refresh_all_in_progess -= 1;
}
g_array_remove_index_fast (priv->delayed_action.list_wait_for_nl_response, idx);
/* Note: @data is invalidated at this point */
if (priv->delayed_action.list_wait_for_nl_response->len <= 0)
priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE;
if (out_seq_result)
*out_seq_result = seq_result;
}
static void
@ -2961,9 +2980,8 @@ delayed_action_handle_one (NMPlatform *platform)
priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_ALL;
if (_LOGt_ENABLED ()) {
for (iflags = (DelayedActionType) 0x1LL; iflags <= DELAYED_ACTION_TYPE_MAX; iflags <<= 1) {
if (NM_FLAGS_HAS (flags, iflags))
_LOGt_delayed_action (iflags, NULL, "handle");
FOR_EACH_DELAYED_ACTION (iflags, flags) {
_LOGt_delayed_action (iflags, NULL, "handle");
}
}
@ -3048,9 +3066,8 @@ delayed_action_schedule (NMPlatform *platform, DelayedActionType action_type, gp
priv->delayed_action.flags |= action_type;
if (_LOGt_ENABLED ()) {
for (iflags = (DelayedActionType) 0x1LL; iflags <= DELAYED_ACTION_TYPE_MAX; iflags <<= 1) {
if (NM_FLAGS_HAS (action_type, iflags))
_LOGt_delayed_action (iflags, user_data, "schedule");
FOR_EACH_DELAYED_ACTION (iflags, action_type) {
_LOGt_delayed_action (iflags, user_data, "schedule");
}
}
}
@ -3058,12 +3075,14 @@ delayed_action_schedule (NMPlatform *platform, DelayedActionType action_type, gp
static void
delayed_action_schedule_WAIT_FOR_NL_RESPONSE (NMPlatform *platform,
guint32 seq_number,
WaitForNlResponseResult *out_seq_result)
WaitForNlResponseResult *out_seq_result,
gint *out_refresh_all_in_progess)
{
DelayedActionWaitForNlResponseData data = {
.seq_number = seq_number,
.timeout_abs_ns = nm_utils_get_monotonic_timestamp_ns () + (200 * (NM_UTILS_NS_PER_SECOND / 1000)),
.out_seq_result = out_seq_result,
.out_refresh_all_in_progess = out_refresh_all_in_progess,
};
delayed_action_schedule (platform,
@ -3150,7 +3169,7 @@ cache_prune_candidates_prune (NMPlatform *platform)
static void
cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMPCacheOpsType ops_type, gpointer user_data)
{
NMPlatform *platform = NM_PLATFORM (user_data);
NMPlatform *platform = user_data;
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
const NMPClass *klass;
char str_buf[sizeof (_nm_utils_to_string_buffer)];
@ -3162,6 +3181,7 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
nm_assert (ops_type != NMP_CACHE_OPS_REMOVED || (new == NULL && NMP_OBJECT_IS_VALID (old) && nmp_object_is_alive (old)));
nm_assert (ops_type != NMP_CACHE_OPS_UPDATED || (NMP_OBJECT_IS_VALID (old) && nmp_object_is_alive (old) && NMP_OBJECT_IS_VALID (new) && nmp_object_is_alive (new)));
nm_assert (new == NULL || old == NULL || nmp_object_id_equal (new, old));
nm_assert (!old || !new || NMP_OBJECT_GET_CLASS (old) == NMP_OBJECT_GET_CLASS (new));
klass = old ? NMP_OBJECT_GET_CLASS (old) : NMP_OBJECT_GET_CLASS (new);
@ -3368,17 +3388,56 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
NULL);
}
}
break;
default:
break;
}
}
static void
cache_post (NMPlatform *platform,
struct nlmsghdr *msghdr,
NMPCacheOpsType cache_op,
NMPObject *obj,
NMPObject *obj_cache)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
nm_assert (NMP_OBJECT_IS_VALID (obj));
nm_assert (!obj_cache || nmp_object_id_equal (obj, obj_cache));
if (msghdr->nlmsg_type == RTM_NEWROUTE) {
DelayedActionType action_type;
action_type = NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_IP4_ROUTE
? DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES
: DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES;
if ( !delayed_action_refresh_all_in_progress (platform, action_type)
&& nmp_cache_find_other_route_for_same_destination (priv->cache, obj)) {
/* via `iproute route change` the user can update an existing route which effectively
* means that a new object (with a different ID) comes into existance, replacing the
* old on. In other words, as the ID of the object changes, we really see a new
* object with the old one deleted.
* However, kernel decides not to send a RTM_DELROUTE event for that.
*
* To hack around that, check if the update leaves us with multiple routes for the
* same network/plen,metric part. In that case, we cannot do better then requesting
* all routes anew, which sucks.
*
* One mitigation to avoid a dump is only to request a new dump, if we are not in
* the middle of an ongoing dump (delayed_action_refresh_all_in_progress). */
delayed_action_schedule (platform, action_type, NULL);
}
}
}
/******************************************************************/
static int
_nl_send_auto_with_seq (NMPlatform *platform,
struct nl_msg *nlmsg,
WaitForNlResponseResult *out_seq_result)
WaitForNlResponseResult *out_seq_result,
gint *out_refresh_all_in_progess)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
guint32 seq;
@ -3393,7 +3452,7 @@ _nl_send_auto_with_seq (NMPlatform *platform,
if (nle >= 0) {
nle = 0;
delayed_action_schedule_WAIT_FOR_NL_RESPONSE (platform, seq, out_seq_result);
delayed_action_schedule_WAIT_FOR_NL_RESPONSE (platform, seq, out_seq_result, out_refresh_all_in_progess);
} else
_LOGD ("netlink: send: failed sending message: %s (%d)", nl_geterror (nle), nle);
@ -3427,7 +3486,7 @@ do_request_link_no_delayed_actions (NMPlatform *platform, int ifindex, const cha
0,
0);
if (nlmsg)
_nl_send_auto_with_seq (platform, nlmsg, NULL);
_nl_send_auto_with_seq (platform, nlmsg, NULL, NULL);
}
static void
@ -3446,48 +3505,51 @@ do_request_all_no_delayed_actions (NMPlatform *platform, DelayedActionType actio
nm_assert (!NM_FLAGS_ANY (action_type, ~DELAYED_ACTION_TYPE_REFRESH_ALL));
action_type &= DELAYED_ACTION_TYPE_REFRESH_ALL;
for (iflags = (DelayedActionType) 0x1LL; iflags <= DELAYED_ACTION_TYPE_MAX; iflags <<= 1) {
if (NM_FLAGS_HAS (action_type, iflags))
cache_prune_candidates_record_all (platform, delayed_action_refresh_to_object_type (iflags));
FOR_EACH_DELAYED_ACTION (iflags, action_type) {
cache_prune_candidates_record_all (platform, delayed_action_refresh_to_object_type (iflags));
}
for (iflags = (DelayedActionType) 0x1LL; iflags <= DELAYED_ACTION_TYPE_MAX; iflags <<= 1) {
if (NM_FLAGS_HAS (action_type, iflags)) {
NMPObjectType obj_type = delayed_action_refresh_to_object_type (iflags);
const NMPClass *klass = nmp_class_from_type (obj_type);
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
struct rtgenmsg gmsg = {
.rtgen_family = klass->addr_family,
};
int nle;
FOR_EACH_DELAYED_ACTION (iflags, action_type) {
NMPObjectType obj_type = delayed_action_refresh_to_object_type (iflags);
const NMPClass *klass = nmp_class_from_type (obj_type);
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
struct rtgenmsg gmsg = {
.rtgen_family = klass->addr_family,
};
int nle;
gint *out_refresh_all_in_progess;
/* clear any delayed action that request a refresh of this object type. */
priv->delayed_action.flags &= ~iflags;
_LOGt_delayed_action (iflags, NULL, "handle (do-request-all)");
if (obj_type == NMP_OBJECT_TYPE_LINK) {
priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK;
g_ptr_array_set_size (priv->delayed_action.list_refresh_link, 0);
_LOGt_delayed_action (DELAYED_ACTION_TYPE_REFRESH_LINK, NULL, "clear (do-request-all)");
}
out_refresh_all_in_progess = &priv->delayed_action.refresh_all_in_progess[delayed_action_refresh_all_to_idx (iflags)];
nm_assert (*out_refresh_all_in_progess >= 0);
*out_refresh_all_in_progess += 1;
event_handler_read_netlink (platform, FALSE);
/* reimplement
* nl_rtgen_request (sk, klass->rtm_gettype, klass->addr_family, NLM_F_DUMP);
* because we need the sequence number.
*/
nlmsg = nlmsg_alloc_simple (klass->rtm_gettype, NLM_F_DUMP);
if (!nlmsg)
goto next;
nle = nlmsg_append (nlmsg, &gmsg, sizeof (gmsg), NLMSG_ALIGNTO);
if (nle < 0)
goto next;
_nl_send_auto_with_seq (platform, nlmsg, NULL);
/* clear any delayed action that request a refresh of this object type. */
priv->delayed_action.flags &= ~iflags;
_LOGt_delayed_action (iflags, NULL, "handle (do-request-all)");
if (obj_type == NMP_OBJECT_TYPE_LINK) {
priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK;
g_ptr_array_set_size (priv->delayed_action.list_refresh_link, 0);
_LOGt_delayed_action (DELAYED_ACTION_TYPE_REFRESH_LINK, NULL, "clear (do-request-all)");
}
event_handler_read_netlink (platform, FALSE);
/* reimplement
* nl_rtgen_request (sk, klass->rtm_gettype, klass->addr_family, NLM_F_DUMP);
* because we need the sequence number.
*/
nlmsg = nlmsg_alloc_simple (klass->rtm_gettype, NLM_F_DUMP);
if (!nlmsg)
continue;
nle = nlmsg_append (nlmsg, &gmsg, sizeof (gmsg), NLMSG_ALIGNTO);
if (nle < 0)
continue;
if (_nl_send_auto_with_seq (platform, nlmsg, NULL, out_refresh_all_in_progess) < 0) {
nm_assert (*out_refresh_all_in_progess > 0);
*out_refresh_all_in_progess -= 1;
}
next:
;
}
}
@ -3499,14 +3561,41 @@ do_request_one_type (NMPlatform *platform, NMPObjectType obj_type)
}
static void
event_seq_check (NMPlatform *platform, struct nl_msg *msg, WaitForNlResponseResult seq_result)
event_seq_check_refresh_all (NMPlatform *platform, guint32 seq_number)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
DelayedActionWaitForNlResponseData *data;
guint32 seq_number;
guint i;
seq_number = nlmsg_hdr (msg)->nlmsg_seq;
if (NM_IN_SET (seq_number, 0, priv->nlh_seq_last_seen))
return;
if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) {
nm_assert (priv->delayed_action.list_wait_for_nl_response->len > 0);
for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; i++) {
data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, i);
if (data->seq_number == priv->nlh_seq_last_seen) {
if (data->out_refresh_all_in_progess) {
nm_assert (*data->out_refresh_all_in_progess > 0);
*data->out_refresh_all_in_progess -= 1;
data->out_refresh_all_in_progess = NULL;
break;
}
}
}
}
priv->nlh_seq_last_seen = seq_number;
}
static void
event_seq_check (NMPlatform *platform, guint32 seq_number, WaitForNlResponseResult seq_result)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
DelayedActionWaitForNlResponseData *data;
guint i;
if (seq_number == 0)
return;
@ -3531,9 +3620,11 @@ event_seq_check (NMPlatform *platform, struct nl_msg *msg, WaitForNlResponseResu
}
}
#ifdef NM_MORE_LOGGING
if (seq_number != priv->nlh_seq_last_handled)
_LOGt ("netlink: recvmsg: unwaited sequence number %u", seq_number);
priv->nlh_seq_last_handled = seq_number;
#endif
}
static void
@ -3581,6 +3672,9 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event
case RTM_NEWADDR:
case RTM_NEWROUTE:
cache_op = nmp_cache_update_netlink (priv->cache, obj, &obj_cache, &was_visible, cache_pre_hook, platform);
cache_post (platform, msghdr, cache_op, obj, obj_cache);
do_emit_signal (platform, obj_cache, cache_op, was_visible);
break;
@ -3730,7 +3824,7 @@ do_add_link_with_lookup (NMPlatform *platform,
}
}
nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result);
nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL);
if (nle < 0) {
_LOGE ("do-add-link[%s/%s]: failed sending netlink request \"%s\" (%d)",
name,
@ -3781,7 +3875,7 @@ do_add_addrroute (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
event_handler_read_netlink (platform, FALSE);
nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result);
nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL);
if (nle < 0) {
_LOGE ("do-add-%s[%s]: failure sending netlink request \"%s\" (%d)",
NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name,
@ -3834,7 +3928,7 @@ do_delete_object (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
event_handler_read_netlink (platform, FALSE);
nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result);
nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL);
if (nle < 0) {
_LOGE ("do-delete-%s[%s]: failure sending netlink request \"%s\" (%d)",
NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name,
@ -3895,7 +3989,7 @@ do_change_link (NMPlatform *platform,
return NM_PLATFORM_ERROR_UNSPECIFIED;
retry:
nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result);
nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL);
if (nle < 0) {
_LOGE ("do-change-link[%d]: failure sending netlink request \"%s\" (%d)",
ifindex,
@ -3964,7 +4058,7 @@ link_add (NMPlatform *platform,
name, nm_link_type_to_string (type), (int) type);
nlmsg = _nl_msg_new_link (RTM_NEWLINK,
NLM_F_CREATE,
NLM_F_CREATE | NLM_F_EXCL,
0,
name,
0,
@ -4356,7 +4450,7 @@ vlan_add (NMPlatform *platform,
name, parent, vlan_id, (unsigned int) vlan_flags);
nlmsg = _nl_msg_new_link (RTM_NEWLINK,
NLM_F_CREATE,
NLM_F_CREATE | NLM_F_EXCL,
0,
name,
0,
@ -4400,7 +4494,7 @@ link_gre_add (NMPlatform *platform,
nm_utils_inet4_ntop (props->remote, buffer));
nlmsg = _nl_msg_new_link (RTM_NEWLINK,
NLM_F_CREATE,
NLM_F_CREATE | NLM_F_EXCL,
0,
name,
0,
@ -4456,7 +4550,7 @@ link_ip6tnl_add (NMPlatform *platform,
nm_utils_inet6_ntop (&props->remote, buffer));
nlmsg = _nl_msg_new_link (RTM_NEWLINK,
NLM_F_CREATE,
NLM_F_CREATE | NLM_F_EXCL,
0,
name,
0,
@ -4516,7 +4610,7 @@ link_ipip_add (NMPlatform *platform,
nm_utils_inet4_ntop (props->remote, buffer));
nlmsg = _nl_msg_new_link (RTM_NEWLINK,
NLM_F_CREATE,
NLM_F_CREATE | NLM_F_EXCL,
0,
name,
0,
@ -4566,7 +4660,7 @@ link_macvlan_add (NMPlatform *platform,
props->mode);
nlmsg = _nl_msg_new_link (RTM_NEWLINK,
NLM_F_CREATE,
NLM_F_CREATE | NLM_F_EXCL,
0,
name,
0,
@ -4616,7 +4710,7 @@ link_sit_add (NMPlatform *platform,
nm_utils_inet4_ntop (props->remote, buffer));
nlmsg = _nl_msg_new_link (RTM_NEWLINK,
NLM_F_CREATE,
NLM_F_CREATE | NLM_F_EXCL,
0,
name,
0,
@ -4665,7 +4759,7 @@ link_vxlan_add (NMPlatform *platform,
name, props->parent_ifindex, props->id);
nlmsg = _nl_msg_new_link (RTM_NEWLINK,
NLM_F_CREATE,
NLM_F_CREATE | NLM_F_EXCL,
0,
name,
0,
@ -5266,7 +5360,7 @@ static gboolean
ip4_address_add (NMPlatform *platform,
int ifindex,
in_addr_t addr,
int plen,
guint8 plen,
in_addr_t peer_addr,
guint32 lifetime,
guint32 preferred,
@ -5297,7 +5391,7 @@ static gboolean
ip6_address_add (NMPlatform *platform,
int ifindex,
struct in6_addr addr,
int plen,
guint8 plen,
struct in6_addr peer_addr,
guint32 lifetime,
guint32 preferred,
@ -5324,7 +5418,7 @@ ip6_address_add (NMPlatform *platform,
}
static gboolean
ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in_addr_t peer_address)
ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, guint8 plen, in_addr_t peer_address)
{
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
NMPObject obj_id;
@ -5349,7 +5443,7 @@ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen,
}
static gboolean
ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen)
ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen)
{
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
NMPObject obj_id;
@ -5374,7 +5468,7 @@ 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, in_addr_t peer_address)
ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, guint8 plen, in_addr_t peer_address)
{
NMPObject obj_id;
const NMPObject *obj;
@ -5387,7 +5481,7 @@ ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in
}
static const NMPlatformIP6Address *
ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen)
ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen)
{
NMPObject obj_id;
const NMPObject *obj;
@ -5454,7 +5548,7 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags fl
static gboolean
ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
in_addr_t network, int plen, in_addr_t gateway,
in_addr_t network, guint8 plen, in_addr_t gateway,
in_addr_t pref_src, guint32 metric, guint32 mss)
{
NMPObject obj_id;
@ -5479,7 +5573,7 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
static gboolean
ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
struct in6_addr network, guint8 plen, struct in6_addr gateway,
guint32 metric, guint32 mss)
{
NMPObject obj_id;
@ -5503,7 +5597,7 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
}
static gboolean
ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric)
ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
@ -5559,7 +5653,7 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen
}
static gboolean
ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric)
ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
{
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
NMPObject obj_id;
@ -5587,7 +5681,7 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, in
}
static const NMPlatformIP4Route *
ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric)
ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
{
NMPObject obj_id;
const NMPObject *obj;
@ -5600,7 +5694,7 @@ ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, g
}
static const NMPlatformIP6Route *
ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric)
ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
{
NMPObject obj_id;
const NMPObject *obj;
@ -5684,6 +5778,8 @@ continue_reading:
while (nlmsg_ok (hdr, n)) {
nm_auto_nlmsg struct nl_msg *msg = NULL;
gboolean abort_parsing = FALSE;
gboolean process_valid_msg = FALSE;
guint32 seq_number;
msg = nlmsg_convert (hdr);
if (!msg) {
@ -5768,7 +5864,21 @@ continue_reading:
seq_result = -errsv;
} else
seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK;
} else {
} else
process_valid_msg = TRUE;
seq_number = nlmsg_hdr (msg)->nlmsg_seq;
/* check whether the seq number is different from before, and
* whether the previous number (@nlh_seq_last_seen) is a pending
* refresh-all request. In that case, the pending request is thereby
* completed.
*
* We must do that before processing the message with event_valid_msg(),
* because we must track the completion of the pending request before that. */
event_seq_check_refresh_all (platform, seq_number);
if (process_valid_msg) {
/* Valid message (not checking for MULTIPART bit to
* get along with broken kernels. NL_SKIP has no
* effect on this. */
@ -5778,7 +5888,7 @@ continue_reading:
seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK;
}
event_seq_check (platform, msg, seq_result);
event_seq_check (platform, seq_number, seq_result);
if (abort_parsing)
goto stop;

View file

@ -48,6 +48,8 @@ typedef struct {
GType nm_linux_platform_get_type (void);
NMPlatform *nm_linux_platform_new (gboolean netns_support);
void nm_linux_platform_setup (void);
#endif /* __NETWORKMANAGER_LINUX_PLATFORM_H__ */

View file

@ -30,6 +30,7 @@
#include <linux/sockios.h>
#include <linux/mii.h>
#include <linux/version.h>
#include <linux/rtnetlink.h>
#include "nm-utils.h"
#include "nm-setting-wired.h"
@ -412,6 +413,10 @@ out:
return g_intern_string (driver);
}
/******************************************************************************
* utils
*****************************************************************************/
gboolean
nmp_utils_device_exists (const char *name)
{
@ -427,3 +432,43 @@ nmp_utils_device_exists (const char *name)
nm_utils_ifname_cpy (&sysdir[NM_STRLEN (SYS_CLASS_NET)], name);
return g_file_test (sysdir, G_FILE_TEST_EXISTS);
}
guint
nmp_utils_ip_config_source_to_rtprot (NMIPConfigSource source)
{
switch (source) {
case NM_IP_CONFIG_SOURCE_UNKNOWN:
return RTPROT_UNSPEC;
case NM_IP_CONFIG_SOURCE_KERNEL:
case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL:
return RTPROT_KERNEL;
case NM_IP_CONFIG_SOURCE_DHCP:
return RTPROT_DHCP;
case NM_IP_CONFIG_SOURCE_RDISC:
return RTPROT_RA;
default:
return RTPROT_STATIC;
}
}
NMIPConfigSource
nmp_utils_ip_config_source_from_rtprot (guint rtprot)
{
switch (rtprot) {
case RTPROT_UNSPEC:
return NM_IP_CONFIG_SOURCE_UNKNOWN;
case RTPROT_KERNEL:
return NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
case RTPROT_REDIRECT:
return NM_IP_CONFIG_SOURCE_KERNEL;
case RTPROT_RA:
return NM_IP_CONFIG_SOURCE_RDISC;
case RTPROT_DHCP:
return NM_IP_CONFIG_SOURCE_DHCP;
default:
return NM_IP_CONFIG_SOURCE_USER;
}
}

View file

@ -54,4 +54,7 @@ const char *nmp_utils_udev_get_driver (GUdevDevice *device);
gboolean nmp_utils_device_exists (const char *name);
guint nmp_utils_ip_config_source_to_rtprot (NMIPConfigSource source);
NMIPConfigSource nmp_utils_ip_config_source_from_rtprot (guint rtprot);
#endif /* __NM_PLATFORM_UTILS_H__ */

View file

@ -2459,8 +2459,10 @@ nm_platform_ethtool_get_link_speed (NMPlatform *self, const char *ifname, guint3
/******************************************************************/
void
nm_platform_ip4_address_set_addr (NMPlatformIP4Address *addr, in_addr_t address, int plen)
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;
@ -2499,7 +2501,7 @@ gboolean
nm_platform_ip4_address_add (NMPlatform *self,
int ifindex,
in_addr_t address,
int plen,
guint8 plen,
in_addr_t peer_address,
guint32 lifetime,
guint32 preferred,
@ -2509,7 +2511,7 @@ nm_platform_ip4_address_add (NMPlatform *self,
_CHECK_SELF (self, klass, FALSE);
g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (plen > 0, FALSE);
g_return_val_if_fail (plen <= 32, FALSE);
g_return_val_if_fail (lifetime > 0, FALSE);
g_return_val_if_fail (preferred <= lifetime, FALSE);
g_return_val_if_fail (!label || strlen (label) < sizeof (((NMPlatformIP4Address *) NULL)->label), FALSE);
@ -2537,7 +2539,7 @@ gboolean
nm_platform_ip6_address_add (NMPlatform *self,
int ifindex,
struct in6_addr address,
int plen,
guint8 plen,
struct in6_addr peer_address,
guint32 lifetime,
guint32 preferred,
@ -2546,7 +2548,7 @@ nm_platform_ip6_address_add (NMPlatform *self,
_CHECK_SELF (self, klass, FALSE);
g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (plen > 0, FALSE);
g_return_val_if_fail (plen <= 128, FALSE);
g_return_val_if_fail (lifetime > 0, FALSE);
g_return_val_if_fail (preferred <= lifetime, FALSE);
@ -2568,7 +2570,7 @@ nm_platform_ip6_address_add (NMPlatform *self,
}
gboolean
nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address, int plen, in_addr_t peer_address)
nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address)
{
char str_dev[TO_STRING_DEV_BUF_SIZE];
char str_peer2[NM_UTILS_INET_ADDRSTRLEN];
@ -2577,7 +2579,7 @@ nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address
_CHECK_SELF (self, klass, FALSE);
g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (plen > 0, FALSE);
g_return_val_if_fail (plen <= 32, FALSE);
_LOGD ("address: deleting IPv4 address %s/%d, %sifindex %d%s",
nm_utils_inet4_ntop (address, NULL), plen,
@ -2589,14 +2591,14 @@ nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address
}
gboolean
nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, int plen)
nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen)
{
char str_dev[TO_STRING_DEV_BUF_SIZE];
_CHECK_SELF (self, klass, FALSE);
g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (plen > 0, FALSE);
g_return_val_if_fail (plen <= 128, FALSE);
_LOGD ("address: deleting IPv6 address %s/%d, ifindex %d%s",
nm_utils_inet6_ntop (&address, NULL), plen, ifindex,
@ -2605,21 +2607,21 @@ 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, guint32 peer_address)
nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, guint32 peer_address)
{
_CHECK_SELF (self, klass, NULL);
g_return_val_if_fail (plen > 0, NULL);
g_return_val_if_fail (plen <= 32, NULL);
return klass->ip4_address_get (self, ifindex, address, plen, peer_address);
}
const NMPlatformIP6Address *
nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, int plen)
nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen)
{
_CHECK_SELF (self, klass, NULL);
g_return_val_if_fail (plen > 0, NULL);
g_return_val_if_fail (plen <= 128, NULL);
return klass->ip6_address_get (self, ifindex, address, plen);
}
@ -2854,13 +2856,13 @@ nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRoute
gboolean
nm_platform_ip4_route_add (NMPlatform *self,
int ifindex, NMIPConfigSource source,
in_addr_t network, int plen,
in_addr_t network, guint8 plen,
in_addr_t gateway, in_addr_t pref_src,
guint32 metric, guint32 mss)
{
_CHECK_SELF (self, klass, FALSE);
g_return_val_if_fail (0 <= plen && plen <= 32, FALSE);
g_return_val_if_fail (plen <= 32, FALSE);
if (_LOGD_ENABLED ()) {
NMPlatformIP4Route route = { 0 };
@ -2882,12 +2884,12 @@ nm_platform_ip4_route_add (NMPlatform *self,
gboolean
nm_platform_ip6_route_add (NMPlatform *self,
int ifindex, NMIPConfigSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
struct in6_addr network, guint8 plen, struct in6_addr gateway,
guint32 metric, guint32 mss)
{
_CHECK_SELF (self, klass, FALSE);
g_return_val_if_fail (0 <= plen && plen <= 128, FALSE);
g_return_val_if_fail (plen <= 128, FALSE);
if (_LOGD_ENABLED ()) {
NMPlatformIP6Route route = { 0 };
@ -2906,7 +2908,7 @@ nm_platform_ip6_route_add (NMPlatform *self,
}
gboolean
nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric)
nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
{
char str_dev[TO_STRING_DEV_BUF_SIZE];
@ -2919,7 +2921,7 @@ nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network,
}
gboolean
nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric)
nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
{
char str_dev[TO_STRING_DEV_BUF_SIZE];
@ -2932,7 +2934,7 @@ nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr net
}
const NMPlatformIP4Route *
nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric)
nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
{
_CHECK_SELF (self, klass, FALSE);
@ -2940,7 +2942,7 @@ nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, int
}
const NMPlatformIP6Route *
nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric)
nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
{
_CHECK_SELF (self, klass, FALSE);
@ -3631,7 +3633,8 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
"%s%s" /* scope */
"%s%s" /* pref-src */
"",
s_network, route->plen,
s_network,
route->plen,
s_gateway,
str_dev,
route->metric,
@ -3678,7 +3681,8 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
" mss %"G_GUINT32_FORMAT
" src %s" /* source */
"",
s_network, route->plen,
s_network,
route->plen,
s_gateway,
str_dev,
route->metric,
@ -4257,7 +4261,7 @@ nm_platform_class_init (NMPlatformClass *platform_class)
g_object_class_install_property
(object_class, PROP_NETNS_SUPPORT,
g_param_spec_boolean (NM_PLATFORM_NETNS_SUPPORT, "", "",
FALSE,
NM_PLATFORM_NETNS_SUPPORT_DEFAULT,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));

View file

@ -40,6 +40,8 @@
#define NM_IS_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_PLATFORM))
#define NM_PLATFORM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_PLATFORM, NMPlatformClass))
#define NM_PLATFORM_NETNS_SUPPORT_DEFAULT FALSE
/******************************************************************/
#define NM_PLATFORM_NETNS_SUPPORT "netns-support"
@ -226,7 +228,7 @@ typedef struct {
* IFA_FLAGS attribute. */ \
guint32 n_ifa_flags; \
\
int plen; \
guint8 plen; \
;
/**
@ -302,7 +304,7 @@ typedef union {
#define __NMPlatformIPRoute_COMMON \
__NMPlatformObject_COMMON; \
NMIPConfigSource source; \
int plen; \
guint8 plen; \
guint32 metric; \
guint32 mss; \
;
@ -593,7 +595,7 @@ typedef struct {
gboolean (*ip4_address_add) (NMPlatform *,
int ifindex,
in_addr_t address,
int plen,
guint8 plen,
in_addr_t peer_address,
guint32 lifetime,
guint32 preferred_lft,
@ -602,28 +604,28 @@ typedef struct {
gboolean (*ip6_address_add) (NMPlatform *,
int ifindex,
struct in6_addr address,
int plen,
guint8 plen,
struct in6_addr peer_address,
guint32 lifetime,
guint32 preferred_lft,
guint32 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, in_addr_t peer_address);
const NMPlatformIP6Address *(*ip6_address_get) (NMPlatform *, int ifindex, struct in6_addr address, int plen);
gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address);
gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, guint8 plen);
const NMPlatformIP4Address *(*ip4_address_get) (NMPlatform *, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address);
const NMPlatformIP6Address *(*ip6_address_get) (NMPlatform *, int ifindex, struct in6_addr address, guint8 plen);
GArray * (*ip4_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteFlags flags);
GArray * (*ip6_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteFlags flags);
gboolean (*ip4_route_add) (NMPlatform *, int ifindex, NMIPConfigSource source,
in_addr_t network, int plen, in_addr_t gateway,
in_addr_t network, guint8 plen, in_addr_t gateway,
in_addr_t pref_src, guint32 metric, guint32 mss);
gboolean (*ip6_route_add) (NMPlatform *, int ifindex, NMIPConfigSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
struct in6_addr network, guint8 plen, struct in6_addr gateway,
guint32 metric, guint32 mss);
gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, int plen, guint32 metric);
gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, int plen, guint32 metric);
const NMPlatformIP4Route *(*ip4_route_get) (NMPlatform *, int ifindex, in_addr_t network, int plen, guint32 metric);
const NMPlatformIP6Route *(*ip6_route_get) (NMPlatform *, int ifindex, struct in6_addr network, int plen, guint32 metric);
gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
const NMPlatformIP4Route *(*ip4_route_get) (NMPlatform *, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
const NMPlatformIP6Route *(*ip6_route_get) (NMPlatform *, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *);
gboolean (*check_support_user_ipv6ll) (NMPlatform *);
@ -835,10 +837,10 @@ 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);
void nm_platform_ip4_address_set_addr (NMPlatformIP4Address *addr, in_addr_t address, int plen);
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 NMPlatformIP4Address *nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, int plen, in_addr_t peer_address);
const NMPlatformIP4Address *nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address);
NMPlatformError nm_platform_link_gre_add (NMPlatform *self,
const char *name,
@ -862,13 +864,13 @@ NMPlatformError nm_platform_link_sit_add (NMPlatform *self,
const NMPlatformLnkSit *props,
const NMPlatformLink **out_link);
const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, int plen);
const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, guint8 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,
int plen,
guint8 plen,
in_addr_t peer_address,
guint32 lifetime,
guint32 preferred_lft,
@ -877,29 +879,29 @@ gboolean nm_platform_ip4_address_add (NMPlatform *self,
gboolean nm_platform_ip6_address_add (NMPlatform *self,
int ifindex,
struct in6_addr address,
int plen,
guint8 plen,
struct in6_addr peer_address,
guint32 lifetime,
guint32 preferred_lft,
guint32 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_delete (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address);
gboolean nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen);
gboolean nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, GPtrArray **out_added_addresses);
gboolean nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, gboolean keep_link_local);
gboolean nm_platform_address_flush (NMPlatform *self, int ifindex);
const NMPlatformIP4Route *nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric);
const NMPlatformIP6Route *nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric);
const NMPlatformIP4Route *nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
const NMPlatformIP6Route *nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
GArray *nm_platform_ip4_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags);
GArray *nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags);
gboolean nm_platform_ip4_route_add (NMPlatform *self, int ifindex, NMIPConfigSource source,
in_addr_t network, int plen, in_addr_t gateway,
in_addr_t network, guint8 plen, in_addr_t gateway,
in_addr_t pref_src, guint32 metric, guint32 mss);
gboolean nm_platform_ip6_route_add (NMPlatform *self, int ifindex, NMIPConfigSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
struct in6_addr network, guint8 plen, struct in6_addr gateway,
guint32 metric, guint32 mss);
gboolean nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric);
gboolean nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric);
gboolean nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
gboolean nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
const char *nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len);
const char *nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len);

View file

@ -343,7 +343,7 @@ _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, guint32 peer_address)
nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, guint8 plen, guint32 peer_address)
{
nmp_object_stackinit (obj, NMP_OBJECT_TYPE_IP4_ADDRESS, NULL);
obj->ip4_address.ifindex = ifindex;
@ -360,7 +360,7 @@ _vt_cmd_obj_stackinit_id_ip4_address (NMPObject *obj, const NMPObject *src)
}
const NMPObject *
nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifindex, const struct in6_addr *address, int plen)
nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifindex, const struct in6_addr *address, guint8 plen)
{
nmp_object_stackinit (obj, NMP_OBJECT_TYPE_IP6_ADDRESS, NULL);
obj->ip4_address.ifindex = ifindex;
@ -377,7 +377,7 @@ _vt_cmd_obj_stackinit_id_ip6_address (NMPObject *obj, const NMPObject *src)
}
const NMPObject *
nmp_object_stackinit_id_ip4_route (NMPObject *obj, int ifindex, guint32 network, int plen, guint32 metric)
nmp_object_stackinit_id_ip4_route (NMPObject *obj, int ifindex, guint32 network, guint8 plen, guint32 metric)
{
nmp_object_stackinit (obj, NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
obj->ip4_route.ifindex = ifindex;
@ -394,7 +394,7 @@ _vt_cmd_obj_stackinit_id_ip4_route (NMPObject *obj, const NMPObject *src)
}
const NMPObject *
nmp_object_stackinit_id_ip6_route (NMPObject *obj, int ifindex, const struct in6_addr *network, int plen, guint32 metric)
nmp_object_stackinit_id_ip6_route (NMPObject *obj, int ifindex, const struct in6_addr *network, guint8 plen, guint32 metric)
{
nmp_object_stackinit (obj, NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
obj->ip6_route.ifindex = ifindex;
@ -952,26 +952,46 @@ _vt_cmd_obj_is_visible_link (const NMPObject *obj)
/******************************************************************/
#define _STRUCT_SIZE(struct_type, field) \
(G_STRUCT_OFFSET (struct_type, field) + sizeof (((struct_type *) NULL)->field))
_NM_UTILS_LOOKUP_DEFINE (static, _nmp_cache_id_size_by_type, NMPCacheIdType, guint,
NM_UTILS_LOOKUP_DEFAULT (({ nm_assert_not_reached (); sizeof (NMPCacheId); })),
NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_OBJECT_TYPE, _STRUCT_SIZE (NMPCacheId, object_type)),
NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_OBJECT_TYPE_VISIBLE_ONLY, _STRUCT_SIZE (NMPCacheId, object_type)),
NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_NO_DEFAULT, _STRUCT_SIZE (NMPCacheId, object_type)),
NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_ONLY_DEFAULT, _STRUCT_SIZE (NMPCacheId, object_type)),
NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX, _STRUCT_SIZE (NMPCacheId, object_type_by_ifindex)),
NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_NO_DEFAULT, _STRUCT_SIZE (NMPCacheId, object_type_by_ifindex)),
NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_ONLY_DEFAULT, _STRUCT_SIZE (NMPCacheId, object_type_by_ifindex)),
NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_LINK_BY_IFNAME, _STRUCT_SIZE (NMPCacheId, link_by_ifname)),
NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP4, _STRUCT_SIZE (NMPCacheId, routes_by_destination_ip4)),
NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP6, _STRUCT_SIZE (NMPCacheId, routes_by_destination_ip6)),
NM_UTILS_LOOKUP_ITEM_IGNORE (NMP_CACHE_ID_TYPE_NONE),
NM_UTILS_LOOKUP_ITEM_IGNORE (__NMP_CACHE_ID_TYPE_MAX),
);
gboolean
nmp_cache_id_equal (const NMPCacheId *a, const NMPCacheId *b)
{
/* just memcmp() the entire id. This is potentially dangerous, because
* the struct is not __attribute__((packed)) and not all types have the
* same size. It is important, to memset() the entire struct to 0,
* not only the relevant fields.
*
* You anyway should use the nmp_cache_id_init_*() functions on a stack-allocated
* struct. */
return memcmp (a, b, sizeof (NMPCacheId)) == 0;
if (a->_id_type != b->_id_type)
return FALSE;
return memcmp (a, b, _nmp_cache_id_size_by_type (a->_id_type)) == 0;
}
guint
nmp_cache_id_hash (const NMPCacheId *id)
{
guint hash = 5381;
guint i;
guint i, n;
for (i = 0; i < sizeof (NMPCacheId); i++)
/* for hashing we only iterate over the actually set bytes and skip the
* zero padding at the end (which depends on the type of the id).
*
* For the equal implementation, we don't care about that and compare the
* entire NMPCacheId sized struct. */
n = _nmp_cache_id_size_by_type (id->_id_type);
for (i = 0; i < n; i++)
hash = ((hash << 5) + hash) + ((char *) id)[i]; /* hash * 33 + c */
return hash;
}
@ -980,27 +1000,42 @@ NMPCacheId *
nmp_cache_id_clone (const NMPCacheId *id)
{
NMPCacheId *id2;
guint n;
id2 = g_slice_new (NMPCacheId);
memcpy (id2, id, sizeof (NMPCacheId));
n = _nmp_cache_id_size_by_type (id->_id_type);
id2 = g_slice_alloc (n);
memcpy (id2, id, n);
return id2;
}
void
nmp_cache_id_destroy (NMPCacheId *id)
{
g_slice_free (NMPCacheId, id);
guint n;
n = _nmp_cache_id_size_by_type (id->_id_type);
g_slice_free1 (n, id);
}
/******************************************************************/
NMPCacheId _nmp_cache_id_static;
static NMPCacheId *
static void
_nmp_cache_id_init (NMPCacheId *id, NMPCacheIdType id_type)
{
memset (id, 0, sizeof (NMPCacheId));
id->_id_type = id_type;
}
NMPCacheId *
nmp_cache_id_copy (NMPCacheId *id, const NMPCacheId *src)
{
guint n;
memset (id, 0, sizeof (NMPCacheId));
n = _nmp_cache_id_size_by_type (src->_id_type);
memcpy (id, src, n);
return id;
}
@ -1028,7 +1063,7 @@ nmp_cache_id_init_addrroute_visible_by_ifindex (NMPCacheId *id,
_nmp_cache_id_init (id, NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX);
id->object_type_by_ifindex.obj_type = obj_type;
id->object_type_by_ifindex.ifindex = ifindex;
memcpy (&id->object_type_by_ifindex._misaligned_ifindex, &ifindex, sizeof (int));
return id;
}
@ -1055,7 +1090,7 @@ nmp_cache_id_init_routes_visible (NMPCacheId *id,
g_return_val_if_reached (NULL);
id->object_type_by_ifindex.obj_type = obj_type;
id->object_type_by_ifindex.ifindex = ifindex;
memcpy (&id->object_type_by_ifindex._misaligned_ifindex, &ifindex, sizeof (int));
return id;
}
@ -1077,6 +1112,33 @@ nmp_cache_id_init_link_by_ifname (NMPCacheId *id,
return id;
}
NMPCacheId *
nmp_cache_id_init_routes_by_destination_ip4 (NMPCacheId *id,
guint32 network,
guint8 plen,
guint32 metric)
{
_nmp_cache_id_init (id, NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP4);
id->routes_by_destination_ip4.plen = plen;
memcpy (&id->routes_by_destination_ip4._misaligned_metric, &metric, sizeof (guint32));
memcpy (&id->routes_by_destination_ip4._misaligned_network, &network, sizeof (guint32));
return id;
}
NMPCacheId *
nmp_cache_id_init_routes_by_destination_ip6 (NMPCacheId *id,
const struct in6_addr *network,
guint8 plen,
guint32 metric)
{
_nmp_cache_id_init (id, NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP6);
id->routes_by_destination_ip4.plen = plen;
memcpy (&id->routes_by_destination_ip6._misaligned_metric, &metric, sizeof (guint32));
if (network)
memcpy (&id->routes_by_destination_ip6._misaligned_network, network, sizeof (struct in6_addr));
return id;
}
/******************************************************************/
static gboolean
@ -1100,6 +1162,13 @@ _nmp_object_init_cache_id (const NMPObject *obj, NMPCacheIdType id_type, NMPCach
}
}
static const guint8 _supported_cache_ids_link[] = {
NMP_CACHE_ID_TYPE_OBJECT_TYPE,
NMP_CACHE_ID_TYPE_OBJECT_TYPE_VISIBLE_ONLY,
NMP_CACHE_ID_TYPE_LINK_BY_IFNAME,
0,
};
static gboolean
_vt_cmd_obj_init_cache_id_link (const NMPObject *obj, NMPCacheIdType id_type, NMPCacheId *id, const NMPCacheId **out_id)
{
@ -1117,6 +1186,13 @@ _vt_cmd_obj_init_cache_id_link (const NMPObject *obj, NMPCacheIdType id_type, NM
return TRUE;
}
static const guint8 _supported_cache_ids_ipx_address[] = {
NMP_CACHE_ID_TYPE_OBJECT_TYPE,
NMP_CACHE_ID_TYPE_OBJECT_TYPE_VISIBLE_ONLY,
NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX,
0,
};
static gboolean
_vt_cmd_obj_init_cache_id_ipx_address (const NMPObject *obj, NMPCacheIdType id_type, NMPCacheId *id, const NMPCacheId **out_id)
{
@ -1135,6 +1211,30 @@ _vt_cmd_obj_init_cache_id_ipx_address (const NMPObject *obj, NMPCacheIdType id_t
return TRUE;
}
static const guint8 _supported_cache_ids_ip4_route[] = {
NMP_CACHE_ID_TYPE_OBJECT_TYPE,
NMP_CACHE_ID_TYPE_OBJECT_TYPE_VISIBLE_ONLY,
NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX,
NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_NO_DEFAULT,
NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_ONLY_DEFAULT,
NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_NO_DEFAULT,
NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_ONLY_DEFAULT,
NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP4,
0,
};
static const guint8 _supported_cache_ids_ip6_route[] = {
NMP_CACHE_ID_TYPE_OBJECT_TYPE,
NMP_CACHE_ID_TYPE_OBJECT_TYPE_VISIBLE_ONLY,
NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX,
NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_NO_DEFAULT,
NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_ONLY_DEFAULT,
NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_NO_DEFAULT,
NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_ONLY_DEFAULT,
NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP6,
0,
};
static gboolean
_vt_cmd_obj_init_cache_id_ipx_route (const NMPObject *obj, NMPCacheIdType id_type, NMPCacheId *id, const NMPCacheId **out_id)
{
@ -1178,6 +1278,18 @@ _vt_cmd_obj_init_cache_id_ipx_route (const NMPObject *obj, NMPCacheIdType id_typ
return TRUE;
}
break;
case NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP4:
if (NMP_OBJECT_GET_CLASS (obj)->obj_type == NMP_OBJECT_TYPE_IP4_ROUTE) {
*out_id = nmp_cache_id_init_routes_by_destination_ip4 (id, obj->ip4_route.network, obj->ip_route.plen, obj->ip_route.metric);
return TRUE;
}
return FALSE;
case NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP6:
if (NMP_OBJECT_GET_CLASS (obj)->obj_type == NMP_OBJECT_TYPE_IP6_ROUTE) {
*out_id = nmp_cache_id_init_routes_by_destination_ip6 (id, &obj->ip6_route.network, obj->ip_route.plen, obj->ip_route.metric);
return TRUE;
}
return FALSE;
default:
return FALSE;
}
@ -1346,6 +1458,51 @@ nmp_cache_lookup_link (const NMPCache *cache, int ifindex)
return nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&obj_needle, ifindex));
}
/**
* nmp_cache_find_other_route_for_same_destination:
* @cache:
* @route:
*
* Look into the cache whether there is a route to the same destination,
* in terms of network/plen,metric.
*
* Returns: (transfer none): the first found route object from the cache
* that has the same (network/plen,metric) values as @route, but has different
* ID. Or %NULL, if no such route exists.
*/
const NMPObject *
nmp_cache_find_other_route_for_same_destination (const NMPCache *cache, const NMPObject *route)
{
NMPCacheId cache_id;
const NMPlatformObject *const *list;
nm_assert (cache);
switch (NMP_OBJECT_GET_TYPE (route)) {
case NMP_OBJECT_TYPE_IP4_ROUTE:
nmp_cache_id_init_routes_by_destination_ip4 (&cache_id, route->ip4_route.network, route->ip_route.plen, route->ip_route.metric);
break;
case NMP_OBJECT_TYPE_IP6_ROUTE:
nmp_cache_id_init_routes_by_destination_ip6 (&cache_id, &route->ip6_route.network, route->ip_route.plen, route->ip_route.metric);
break;
default:
g_return_val_if_reached (NULL);
}
list = nmp_cache_lookup_multi (cache, &cache_id, NULL);
if (list) {
for (; *list; list++) {
const NMPObject *candidate = NMP_OBJECT_UP_CAST (*list);
nm_assert (NMP_OBJECT_GET_CLASS (route) == NMP_OBJECT_GET_CLASS (candidate));
if (!nmp_object_id_equal (route, candidate))
return candidate;
}
}
return NULL;
}
const NMPObject *
nmp_cache_lookup_link_full (const NMPCache *cache,
int ifindex,
@ -1425,13 +1582,13 @@ nmp_cache_lookup_all_to_hash (const NMPCache *cache,
static void
_nmp_cache_update_cache (NMPCache *cache, NMPObject *obj, gboolean remove)
{
NMPCacheIdType id_type;
const guint8 *id_type;
for (id_type = 0; id_type <= NMP_CACHE_ID_TYPE_MAX; id_type++) {
for (id_type = NMP_OBJECT_GET_CLASS (obj)->supported_cache_ids; *id_type; id_type++) {
NMPCacheId cache_id_storage;
const NMPCacheId *cache_id;
if (!_nmp_object_init_cache_id (obj, id_type, &cache_id_storage, &cache_id))
if (!_nmp_object_init_cache_id (obj, *id_type, &cache_id_storage, &cache_id))
continue;
if (!cache_id)
continue;
@ -1480,19 +1637,19 @@ _nmp_cache_update_remove (NMPCache *cache, NMPObject *obj)
static void
_nmp_cache_update_update (NMPCache *cache, NMPObject *obj, const NMPObject *new)
{
NMPCacheIdType id_type;
const guint8 *id_type;
nm_assert (NMP_OBJECT_GET_CLASS (obj) == NMP_OBJECT_GET_CLASS (new));
nm_assert (obj->is_cached);
nm_assert (!new->is_cached);
for (id_type = 0; id_type <= NMP_CACHE_ID_TYPE_MAX; id_type++) {
for (id_type = NMP_OBJECT_GET_CLASS (obj)->supported_cache_ids; *id_type; id_type++) {
NMPCacheId cache_id_storage_obj, cache_id_storage_new;
const NMPCacheId *cache_id_obj, *cache_id_new;
if (!_nmp_object_init_cache_id (obj, id_type, &cache_id_storage_obj, &cache_id_obj))
if (!_nmp_object_init_cache_id (obj, *id_type, &cache_id_storage_obj, &cache_id_obj))
continue;
if (!_nmp_object_init_cache_id (new, id_type, &cache_id_storage_new, &cache_id_new))
if (!_nmp_object_init_cache_id (new, *id_type, &cache_id_storage_new, &cache_id_new))
g_assert_not_reached ();
if (!nm_multi_index_move (cache->idx_multi, (NMMultiIndexId *) cache_id_obj, (NMMultiIndexId *) cache_id_new, &obj->object))
g_assert_not_reached ();
@ -1891,13 +2048,13 @@ ASSERT_nmp_cache_is_consistent (const NMPCache *cache)
g_hash_table_iter_init (&iter_hash, cache->idx_main);
while (g_hash_table_iter_next (&iter_hash, (gpointer *) &obj, NULL)) {
NMPCacheIdType id_type;
const guint8 *id_type;
g_assert (NMP_OBJECT_IS_VALID (obj));
g_assert (nmp_object_is_alive (obj));
for (id_type = 0; id_type <= NMP_CACHE_ID_TYPE_MAX; id_type++) {
if (!_nmp_object_init_cache_id (obj, id_type, &cache_id_storage, &cache_id))
for (id_type = NMP_OBJECT_GET_CLASS (obj)->supported_cache_ids; *id_type; id_type++) {
if (!_nmp_object_init_cache_id (obj, *id_type, &cache_id_storage, &cache_id))
continue;
if (!cache_id)
continue;
@ -1943,6 +2100,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.rtm_gettype = RTM_GETLINK,
.signal_type_id = NM_PLATFORM_SIGNAL_ID_LINK,
.signal_type = NM_PLATFORM_SIGNAL_LINK_CHANGED,
.supported_cache_ids = _supported_cache_ids_link,
.cmd_obj_init_cache_id = _vt_cmd_obj_init_cache_id_link,
.cmd_obj_cmp = _vt_cmd_obj_cmp_link,
.cmd_obj_copy = _vt_cmd_obj_copy_link,
@ -1967,6 +2125,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.rtm_gettype = RTM_GETADDR,
.signal_type_id = NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS,
.signal_type = NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
.supported_cache_ids = _supported_cache_ids_ipx_address,
.cmd_obj_init_cache_id = _vt_cmd_obj_init_cache_id_ipx_address,
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip4_address,
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_address,
@ -1986,6 +2145,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.rtm_gettype = RTM_GETADDR,
.signal_type_id = NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS,
.signal_type = NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
.supported_cache_ids = _supported_cache_ids_ipx_address,
.cmd_obj_init_cache_id = _vt_cmd_obj_init_cache_id_ipx_address,
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip6_address,
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_address,
@ -2005,6 +2165,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.rtm_gettype = RTM_GETROUTE,
.signal_type_id = NM_PLATFORM_SIGNAL_ID_IP4_ROUTE,
.signal_type = NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED,
.supported_cache_ids = _supported_cache_ids_ip4_route,
.cmd_obj_init_cache_id = _vt_cmd_obj_init_cache_id_ipx_route,
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip4_route,
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route,
@ -2024,6 +2185,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.rtm_gettype = RTM_GETROUTE,
.signal_type_id = NM_PLATFORM_SIGNAL_ID_IP6_ROUTE,
.signal_type = NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED,
.supported_cache_ids = _supported_cache_ids_ip6_route,
.cmd_obj_init_cache_id = _vt_cmd_obj_init_cache_id_ipx_route,
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip6_route,
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route,

View file

@ -57,6 +57,8 @@ typedef enum { /*< skip >*/
* matching v4/v6 and ifindex -- or maybe not at all if it isn't visible.
* */
typedef enum { /*< skip >*/
NMP_CACHE_ID_TYPE_NONE,
/* all the objects of a certain type */
NMP_CACHE_ID_TYPE_OBJECT_TYPE,
@ -77,6 +79,17 @@ typedef enum { /*< skip >*/
NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_NO_DEFAULT,
NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_ONLY_DEFAULT,
/* Consider all the destination fields of a route, that is, the ID without the ifindex
* and gateway (meaning: network/plen,metric).
* The reason for this is that `ip route change` can replace an existing route
* and modify it's ifindex/gateway. Effectively, that means it deletes an existing
* route and adds a different one (as the ID of the route changes). However, it only
* sends one RTM_NEWADDR notification without notifying about the deletion. We detect
* that by having this index to contain overlapping routes which require special
* cache-resync. */
NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP4,
NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP6,
__NMP_CACHE_ID_TYPE_MAX,
NMP_CACHE_ID_TYPE_MAX = __NMP_CACHE_ID_TYPE_MAX - 1,
} NMPCacheIdType;
@ -87,7 +100,7 @@ typedef struct {
union {
NMMultiIndexId base;
guint8 _id_type; /* NMPCacheIdType as guint8 */
struct {
struct _nm_packed {
/* NMP_CACHE_ID_TYPE_OBJECT_TYPE */
/* NMP_CACHE_ID_TYPE_OBJECT_TYPE_VISIBLE_ONLY */
/* NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_NO_DEFAULT */
@ -95,19 +108,33 @@ typedef struct {
guint8 _id_type;
guint8 obj_type; /* NMPObjectType as guint8 */
} object_type;
struct {
struct _nm_packed {
/* NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX */
/* NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_NO_DEFAULT */
/* NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_ONLY_DEFAULT */
guint8 _id_type;
guint8 obj_type; /* NMPObjectType as guint8 */
int ifindex;
int _misaligned_ifindex;
} object_type_by_ifindex;
struct {
struct _nm_packed {
/* NMP_CACHE_ID_TYPE_LINK_BY_IFNAME */
guint8 _id_type;
char ifname_short[IFNAMSIZ - 1]; /* don't include the trailing NUL so the struct fits in 4 bytes. */
} link_by_ifname;
struct _nm_packed {
/* NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP6 */
guint8 _id_type;
guint8 plen;
guint32 _misaligned_metric;
guint32 _misaligned_network;
} routes_by_destination_ip4;
struct _nm_packed {
/* NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP4 */
guint8 _id_type;
guint8 plen;
guint32 _misaligned_metric;
struct in6_addr _misaligned_network;
} routes_by_destination_ip6;
};
} NMPCacheId;
@ -124,6 +151,8 @@ typedef struct {
const char *obj_type_name;
const char *signal_type;
const guint8 *supported_cache_ids;
/* Only for NMPObjectLnk* types. */
NMLinkType lnk_link_type;
@ -341,10 +370,10 @@ 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, 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);
const NMPObject *nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, guint8 plen, guint32 peer_address);
const NMPObject *nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifindex, const struct in6_addr *address, guint8 plen);
const NMPObject *nmp_object_stackinit_id_ip4_route (NMPObject *obj, int ifindex, guint32 network, guint8 plen, guint32 metric);
const NMPObject *nmp_object_stackinit_id_ip6_route (NMPObject *obj, int ifindex, const struct in6_addr *network, guint8 plen, guint32 metric);
const char *nmp_object_to_string (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size);
int nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2);
@ -375,16 +404,21 @@ guint nmp_cache_id_hash (const NMPCacheId *id);
NMPCacheId *nmp_cache_id_clone (const NMPCacheId *id);
void nmp_cache_id_destroy (NMPCacheId *id);
NMPCacheId *nmp_cache_id_copy (NMPCacheId *id, const NMPCacheId *src);
NMPCacheId *nmp_cache_id_init_object_type (NMPCacheId *id, NMPObjectType obj_type, gboolean visible_only);
NMPCacheId *nmp_cache_id_init_addrroute_visible_by_ifindex (NMPCacheId *id, NMPObjectType obj_type, int ifindex);
NMPCacheId *nmp_cache_id_init_routes_visible (NMPCacheId *id, NMPObjectType obj_type, gboolean with_default, gboolean with_non_default, int ifindex);
NMPCacheId *nmp_cache_id_init_link_by_ifname (NMPCacheId *id, const char *ifname);
NMPCacheId *nmp_cache_id_init_routes_by_destination_ip4 (NMPCacheId *id, guint32 network, guint8 plen, guint32 metric);
NMPCacheId *nmp_cache_id_init_routes_by_destination_ip6 (NMPCacheId *id, const struct in6_addr *network, guint8 plen, guint32 metric);
const NMPlatformObject *const *nmp_cache_lookup_multi (const NMPCache *cache, const NMPCacheId *cache_id, guint *out_len);
GArray *nmp_cache_lookup_multi_to_array (const NMPCache *cache, NMPObjectType obj_type, const NMPCacheId *cache_id);
const NMPObject *nmp_cache_lookup_obj (const NMPCache *cache, const NMPObject *obj);
const NMPObject *nmp_cache_lookup_link (const NMPCache *cache, int ifindex);
const NMPObject *nmp_cache_find_other_route_for_same_destination (const NMPCache *cache, const NMPObject *route);
const NMPObject *nmp_cache_lookup_link_full (const NMPCache *cache,
int ifindex,
const char *ifname,

View file

@ -50,56 +50,56 @@ EXTRA_DIST = test-common.h
monitor_SOURCES = monitor.c $(PLATFORM_SOURCES)
monitor_LDADD = $(PLATFORM_LDADD)
test_link_fake_SOURCES = test-link.c $(TEST_SOURCES)
test_link_fake_SOURCES = $(TEST_SOURCES) test-link.c
test_link_fake_CPPFLAGS = \
$(AM_CPPFLAGS) \
-DSETUP=nm_fake_platform_setup \
-DKERNEL_HACKS=0
test_link_fake_LDADD = $(PLATFORM_LDADD)
test_link_linux_SOURCES = test-link.c $(TEST_SOURCES)
test_link_linux_SOURCES = $(TEST_SOURCES) test-link.c
test_link_linux_CPPFLAGS = \
$(AM_CPPFLAGS) \
-DSETUP=nm_linux_platform_setup \
-DKERNEL_HACKS=1
test_link_linux_LDADD = $(PLATFORM_LDADD)
test_address_fake_SOURCES = test-address.c $(TEST_SOURCES)
test_address_fake_SOURCES = $(TEST_SOURCES) test-address.c
test_address_fake_CPPFLAGS = \
$(AM_CPPFLAGS) \
-DSETUP=nm_fake_platform_setup \
-DKERNEL_HACKS=0
test_address_fake_LDADD = $(PLATFORM_LDADD)
test_address_linux_SOURCES = test-address.c $(TEST_SOURCES)
test_address_linux_SOURCES = $(TEST_SOURCES) test-address.c
test_address_linux_CPPFLAGS = \
$(AM_CPPFLAGS) \
-DSETUP=nm_linux_platform_setup \
-DKERNEL_HACKS=1
test_address_linux_LDADD = $(PLATFORM_LDADD)
test_route_fake_SOURCES = test-route.c $(TEST_SOURCES)
test_route_fake_SOURCES = $(TEST_SOURCES) test-route.c
test_route_fake_CPPFLAGS = \
$(AM_CPPFLAGS) \
-DSETUP=nm_fake_platform_setup \
-DKERNEL_HACKS=0
test_route_fake_LDADD = $(PLATFORM_LDADD)
test_route_linux_SOURCES = test-route.c $(TEST_SOURCES)
test_route_linux_SOURCES = $(TEST_SOURCES) test-route.c
test_route_linux_CPPFLAGS = \
$(AM_CPPFLAGS) \
-DSETUP=nm_linux_platform_setup \
-DKERNEL_HACKS=1
test_route_linux_LDADD = $(PLATFORM_LDADD)
test_cleanup_fake_SOURCES = test-cleanup.c $(TEST_SOURCES)
test_cleanup_fake_SOURCES = $(TEST_SOURCES) test-cleanup.c
test_cleanup_fake_CPPFLAGS = \
$(AM_CPPFLAGS) \
-DSETUP=nm_fake_platform_setup \
-DKERNEL_HACKS=0
test_cleanup_fake_LDADD = $(PLATFORM_LDADD)
test_cleanup_linux_SOURCES = test-cleanup.c $(TEST_SOURCES)
test_cleanup_linux_SOURCES = $(TEST_SOURCES) test-cleanup.c
test_cleanup_linux_CPPFLAGS = \
$(AM_CPPFLAGS) \
-DSETUP=nm_linux_platform_setup \

View file

@ -94,12 +94,12 @@ test_ip4_address_general (void)
/* Add address */
g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
accept_signal (address_added);
/* Add address again (aka update) */
nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime + 100, preferred + 50, 0, NULL);
nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime + 100, preferred + 50, 0, NULL);
accept_signals (address_changed, 0, 1);
/* Test address listing */
@ -114,12 +114,12 @@ test_ip4_address_general (void)
g_array_unref (addresses);
/* Remove address */
nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, addr);
nmtstp_ip4_address_del (NULL, EX, ifindex, addr, IP4_PLEN, addr);
g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
accept_signal (address_removed);
/* Remove address again */
nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, addr);
nmtstp_ip4_address_del (NULL, EX, ifindex, addr, IP4_PLEN, addr);
free_signal (address_added);
free_signal (address_changed);
@ -144,12 +144,12 @@ test_ip6_address_general (void)
/* Add address */
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);
nmtstp_ip6_address_add (NULL, 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) */
nmtstp_ip6_address_add (EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags);
nmtstp_ip6_address_add (NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags);
accept_signals (address_changed, 0, 1);
/* Test address listing */
@ -163,12 +163,12 @@ test_ip6_address_general (void)
g_array_unref (addresses);
/* Remove address */
nmtstp_ip6_address_del (EX, ifindex, addr, IP6_PLEN);
nmtstp_ip6_address_del (NULL, 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 */
nmtstp_ip6_address_del (EX, ifindex, addr, IP6_PLEN);
nmtstp_ip6_address_del (NULL, EX, ifindex, addr, IP6_PLEN);
/* ensure not pending signal. */
accept_signals (address_changed, 0, 1);
@ -197,15 +197,15 @@ test_ip4_address_general_2 (void)
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, DEVICE_IFINDEX, NULL));
/* Add/delete notification */
nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
accept_signal (address_added);
g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, addr);
nmtstp_ip4_address_del (NULL, EX, ifindex, addr, IP4_PLEN, addr);
accept_signal (address_removed);
g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
/* Add/delete conflict */
nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
accept_signal (address_added);
@ -227,20 +227,20 @@ test_ip6_address_general_2 (void)
inet_pton (AF_INET6, IP6_ADDRESS, &addr);
/* Add/delete notification */
nmtstp_ip6_address_add (EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0);
nmtstp_ip6_address_add (NULL, 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));
nmtstp_ip6_address_del (EX, ifindex, addr, IP6_PLEN);
nmtstp_ip6_address_del (NULL, 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 */
nmtstp_ip6_address_add (EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0);
nmtstp_ip6_address_add (NULL, 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));
nmtstp_ip6_address_add (EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags);
nmtstp_ip6_address_add (NULL, 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));
@ -273,7 +273,7 @@ test_ip4_address_peer (void)
accept_signals (address_added, 0, G_MAXINT);
/* Add/delete notification */
nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr_peer, lifetime, preferred, 0, NULL);
nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr_peer, lifetime, preferred, 0, NULL);
accept_signal (address_added);
a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer);
g_assert (a);
@ -281,7 +281,7 @@ test_ip4_address_peer (void)
nmtstp_ip_address_assert_lifetime ((NMPlatformIPAddress *) a, -1, lifetime, preferred);
nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr_peer2, lifetime, preferred, 0, NULL);
nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr_peer2, lifetime, preferred, 0, NULL);
accept_signal (address_added);
g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer));
a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2);
@ -290,7 +290,7 @@ test_ip4_address_peer (void)
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);
nmtstp_ip4_address_del (NULL, 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));
@ -308,7 +308,7 @@ test_ip4_address_peer_zero (void)
in_addr_t addr, addr_peer;
guint32 lifetime = 2000;
guint32 preferred = 1000;
const int plen = 24;
const gint8 plen = 24;
const char *label = NULL;
in_addr_t peers[3], r_peers[3];
int i;
@ -328,7 +328,7 @@ test_ip4_address_peer_zero (void)
for (i = 0; i < G_N_ELEMENTS (peers); i++) {
g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, plen, r_peers[i]));
nmtstp_ip4_address_add (EX, ifindex, addr, plen, r_peers[i], lifetime, preferred, 0, label);
nmtstp_ip4_address_add (NULL, EX, ifindex, addr, plen, r_peers[i], lifetime, preferred, 0, label);
addrs = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
g_assert (addrs);
@ -343,7 +343,7 @@ test_ip4_address_peer_zero (void)
for (i = 0; i < G_N_ELEMENTS (peers); i++) {
g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, plen, r_peers[i]));
nmtstp_ip4_address_del (EX, ifindex, addr, plen, r_peers[i]);
nmtstp_ip4_address_del (NULL, EX, ifindex, addr, plen, r_peers[i]);
addrs = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
g_assert (addrs);
@ -355,7 +355,7 @@ test_ip4_address_peer_zero (void)
/*****************************************************************************/
void
init_tests (int *argc, char ***argv)
_nmtstp_init_tests (int *argc, char ***argv)
{
nmtst_init_with_logging (argc, argv, NULL, "ALL");
}
@ -412,7 +412,7 @@ _g_test_add_func (const char *testpath,
}
void
setup_tests (void)
_nmtstp_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);

View file

@ -107,13 +107,13 @@ test_cleanup_internal (void)
}
void
init_tests (int *argc, char ***argv)
_nmtstp_init_tests (int *argc, char ***argv)
{
nmtst_init_with_logging (argc, argv, NULL, "ALL");
}
void
setup_tests (void)
_nmtstp_setup_tests (void)
{
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));

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,6 @@
#include <string.h>
#include <arpa/inet.h>
#include "nm-default.h"
#include "nm-platform.h"
#include "nm-fake-platform.h"
#include "nm-linux-platform.h"
@ -38,16 +37,6 @@
/*********************************************************************************************/
typedef struct {
gulong handler_id;
const char *name;
NMPlatformSignalChangeType change_type;
gint received_count;
GMainLoop *loop;
int ifindex;
const char *ifname;
} SignalData;
gboolean nmtstp_is_root_test (void);
gboolean nmtstp_is_sysfs_writable (void);
@ -64,6 +53,16 @@ int nmtstp_namespace_get_fd_for_process (pid_t pid, const char *ns_name);
/******************************************************************************/
typedef struct {
gulong handler_id;
const char *name;
NMPlatformSignalChangeType change_type;
gint received_count;
GMainLoop *loop;
int ifindex;
const char *ifname;
} SignalData;
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)
#define add_signal_ifindex(name, change_type, callback, ifindex) add_signal_full (name, change_type, (GCallback) callback, ifindex, NULL)
@ -81,27 +80,49 @@ void _free_signal (const char *file, int line, const char *func, SignalData *dat
#define ensure_no_signal(data) _ensure_no_signal(__FILE__, __LINE__, G_STRFUNC, data)
#define free_signal(data) _free_signal(__FILE__, __LINE__, G_STRFUNC, data)
gboolean ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric);
void _assert_ip4_route_exists (const char *file, guint line, const char *func, gboolean exists, const char *ifname, guint32 network, int plen, guint32 metric);
#define assert_ip4_route_exists(exists, ifname, network, plen, metric) _assert_ip4_route_exists (__FILE__, __LINE__, G_STRFUNC, exists, ifname, network, plen, metric)
void link_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformLink *received, NMPlatformSignalChangeType change_type, SignalData *data);
/*****************************************************************************/
int nmtstp_run_command (const char *format, ...) __attribute__((__format__ (__printf__, 1, 2)));
#define nmtstp_run_command_check(...) do { g_assert_cmpint (nmtstp_run_command (__VA_ARGS__), ==, 0); } while (0)
gboolean nmtstp_wait_for_signal (NMPlatform *platform, guint timeout_ms);
gboolean nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms);
/*****************************************************************************/
guint nmtstp_wait_for_signal (NMPlatform *platform, guint timeout_ms);
guint nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms);
const NMPlatformLink *nmtstp_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, guint timeout_ms);
const NMPlatformLink *nmtstp_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 until_ms);
#define nmtstp_assert_wait_for_signal(platform, timeout_ms) \
G_STMT_START { \
if (nmtstp_wait_for_signal (platform, timeout_ms) == 0) \
g_assert_not_reached (); \
} G_STMT_END
#define nmtstp_assert_wait_for_signal_until(platform, until_ms) \
G_STMT_START { \
if (nmtstp_wait_for_signal_until (platform, until_ms) == 0) \
g_assert_not_reached (); \
} G_STMT_END
const NMPlatformLink *nmtstp_assert_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, guint timeout_ms);
const NMPlatformLink *nmtstp_assert_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 until_ms);
/*****************************************************************************/
int nmtstp_run_command_check_external_global (void);
gboolean nmtstp_run_command_check_external (int external_command);
/*****************************************************************************/
gboolean nmtstp_ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric);
void _nmtstp_assert_ip4_route_exists (const char *file, guint line, const char *func, NMPlatform *platform, gboolean exists, const char *ifname, guint32 network, int plen, guint32 metric);
#define nmtstp_assert_ip4_route_exists(platform, exists, ifname, network, plen, metric) _nmtstp_assert_ip4_route_exists (__FILE__, __LINE__, G_STRFUNC, platform, exists, ifname, network, plen, metric)
/*****************************************************************************/
gboolean nmtstp_ip_address_check_lifetime (const NMPlatformIPAddress *addr,
gint64 now,
guint32 expected_lifetime,
@ -110,7 +131,9 @@ 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,
void nmtstp_ip4_address_add (NMPlatform *platform,
gboolean external_command,
int ifindex,
in_addr_t address,
int plen,
@ -119,7 +142,8 @@ void nmtstp_ip4_address_add (gboolean external_command,
guint32 preferred,
guint32 flags,
const char *label);
void nmtstp_ip6_address_add (gboolean external_command,
void nmtstp_ip6_address_add (NMPlatform *platform,
gboolean external_command,
int ifindex,
struct in6_addr address,
int plen,
@ -127,49 +151,64 @@ void nmtstp_ip6_address_add (gboolean external_command,
guint32 lifetime,
guint32 preferred,
guint32 flags);
void nmtstp_ip4_address_del (gboolean external_command,
void nmtstp_ip4_address_del (NMPlatform *platform,
gboolean external_command,
int ifindex,
in_addr_t address,
int plen,
in_addr_t peer_address);
void nmtstp_ip6_address_del (gboolean external_command,
void nmtstp_ip6_address_del (NMPlatform *platform,
gboolean external_command,
int ifindex,
struct in6_addr address,
int plen);
/*****************************************************************************/
const NMPlatformLink *nmtstp_link_get_typed (NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type);
const NMPlatformLink *nmtstp_link_get (NMPlatform *platform, int ifindex, const char *name);
void nmtstp_link_set_updown (gboolean external_command,
void nmtstp_link_set_updown (NMPlatform *platform,
gboolean external_command,
int ifindex,
gboolean up);
const NMPlatformLink *nmtstp_link_dummy_add (gboolean external_command,
const NMPlatformLink *nmtstp_link_dummy_add (NMPlatform *platform,
gboolean external_command,
const char *name);
const NMPlatformLink *nmtstp_link_gre_add (gboolean external_command,
const NMPlatformLink *nmtstp_link_gre_add (NMPlatform *platform,
gboolean external_command,
const char *name,
const NMPlatformLnkGre *lnk);
const NMPlatformLink *nmtstp_link_ip6tnl_add (gboolean external_command,
const NMPlatformLink *nmtstp_link_ip6tnl_add (NMPlatform *platform,
gboolean external_command,
const char *name,
const NMPlatformLnkIp6Tnl *lnk);
const NMPlatformLink *nmtstp_link_ipip_add (gboolean external_command,
const NMPlatformLink *nmtstp_link_ipip_add (NMPlatform *platform,
gboolean external_command,
const char *name,
const NMPlatformLnkIpIp *lnk);
const NMPlatformLink *nmtstp_link_macvlan_add (gboolean external_command,
const NMPlatformLink *nmtstp_link_macvlan_add (NMPlatform *platform,
gboolean external_command,
const char *name,
int parent,
const NMPlatformLnkMacvlan *lnk);
const NMPlatformLink *nmtstp_link_sit_add (gboolean external_command,
const NMPlatformLink *nmtstp_link_sit_add (NMPlatform *platform,
gboolean external_command,
const char *name,
const NMPlatformLnkSit *lnk);
const NMPlatformLink *nmtstp_link_vxlan_add (gboolean external_command,
const NMPlatformLink *nmtstp_link_vxlan_add (NMPlatform *platform,
gboolean external_command,
const char *name,
const NMPlatformLnkVxlan *lnk);
void nmtstp_link_del (gboolean external_command,
void nmtstp_link_del (NMPlatform *platform,
gboolean external_command,
int ifindex,
const char *name);
void init_tests (int *argc, char ***argv);
void setup_tests (void);
/*****************************************************************************/
void _nmtstp_init_tests (int *argc, char ***argv);
void _nmtstp_setup_tests (void);

View file

@ -35,7 +35,7 @@ test_init_linux_platform (void)
{
gs_unref_object NMPlatform *platform = NULL;
platform = g_object_new (NM_TYPE_LINUX_PLATFORM, NULL);
platform = nm_linux_platform_new (NM_PLATFORM_NETNS_SUPPORT_DEFAULT);
}
/******************************************************************/
@ -46,7 +46,7 @@ test_link_get_all (void)
gs_unref_object NMPlatform *platform = NULL;
gs_unref_array GArray *links = NULL;
platform = g_object_new (NM_TYPE_LINUX_PLATFORM, NULL);
platform = nm_linux_platform_new (NM_PLATFORM_NETNS_SUPPORT_DEFAULT);
links = nm_platform_link_get_all (platform);
}

View file

@ -343,7 +343,7 @@ test_slave (int master, int type, SignalData *master_changed)
ensure_no_signal (link_added);
ensure_no_signal (link_changed);
ensure_no_signal (link_removed);
nmtstp_link_del (-1, ifindex, NULL);
nmtstp_link_del (NULL, -1, ifindex, NULL);
accept_signals (master_changed, 0, 1);
accept_signals (link_changed, 0, 1);
accept_signal (link_removed);
@ -437,7 +437,7 @@ test_software (NMLinkType link_type, const char *link_typename)
free_signal (link_changed);
/* Delete */
nmtstp_link_del (-1, ifindex, DEVICE_NAME);
nmtstp_link_del (NULL, -1, ifindex, DEVICE_NAME);
accept_signal (link_removed);
/* Delete again */
@ -448,7 +448,7 @@ test_software (NMLinkType link_type, const char *link_typename)
if (link_type == NM_LINK_TYPE_VLAN) {
SignalData *link_removed_parent = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, link_callback, vlan_parent);
nmtstp_link_del (-1, vlan_parent, NULL);
nmtstp_link_del (NULL, -1, vlan_parent, NULL);
accept_signal (link_removed_parent);
free_signal (link_removed_parent);
}
@ -531,7 +531,7 @@ test_bridge_addr (void)
g_assert_cmpint (plink->addr.len, ==, sizeof (addr));
g_assert (!memcmp (plink->addr.data, addr, sizeof (addr)));
nmtstp_link_del (-1, link.ifindex, link.name);
nmtstp_link_del (NULL, -1, link.ifindex, link.name);
}
/*****************************************************************************/
@ -606,7 +606,7 @@ test_internal (void)
accept_signal (link_changed);
/* Delete device */
nmtstp_link_del (-1, ifindex, DEVICE_NAME);
nmtstp_link_del (NULL, -1, ifindex, DEVICE_NAME);
accept_signal (link_removed);
/* Try to delete again */
@ -717,7 +717,7 @@ test_software_detect (gconstpointer user_data)
gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ip_gre", NULL) != 0;
}
if (!nmtstp_link_gre_add (ext, DEVICE_NAME, &lnk_gre)) {
if (!nmtstp_link_gre_add (NULL, ext, DEVICE_NAME, &lnk_gre)) {
if (gracefully_skip) {
g_test_skip ("Cannot create gre tunnel because of missing ip_gre module (modprobe ip_gre)");
goto out_delete_parent;
@ -741,7 +741,7 @@ test_software_detect (gconstpointer user_data)
lnk_ipip.tos = 32;
lnk_ipip.path_mtu_discovery = FALSE;
if (!nmtstp_link_ipip_add (ext, DEVICE_NAME, &lnk_ipip)) {
if (!nmtstp_link_ipip_add (NULL, ext, DEVICE_NAME, &lnk_ipip)) {
if (gracefully_skip) {
g_test_skip ("Cannot create ipip tunnel because of missing ipip module (modprobe ipip)");
goto out_delete_parent;
@ -767,7 +767,7 @@ test_software_detect (gconstpointer user_data)
lnk_ip6tnl.flow_label = 1337;
lnk_ip6tnl.proto = IPPROTO_IPV6;
if (!nmtstp_link_ip6tnl_add (ext, DEVICE_NAME, &lnk_ip6tnl)) {
if (!nmtstp_link_ip6tnl_add (NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) {
if (gracefully_skip) {
g_test_skip ("Cannot create ip6tnl tunnel because of missing ip6_tunnel module (modprobe ip6_tunnel)");
goto out_delete_parent;
@ -783,7 +783,7 @@ test_software_detect (gconstpointer user_data)
lnk_macvlan.no_promisc = FALSE;
lnk_macvlan.tap = FALSE;
if (!nmtstp_link_macvlan_add (ext, DEVICE_NAME, ifindex_parent, &lnk_macvlan))
if (!nmtstp_link_macvlan_add (NULL, ext, DEVICE_NAME, ifindex_parent, &lnk_macvlan))
g_error ("Failed adding MACVLAN interface");
break;
}
@ -794,7 +794,7 @@ test_software_detect (gconstpointer user_data)
lnk_macvtap.no_promisc = FALSE;
lnk_macvtap.tap = TRUE;
if (!nmtstp_link_macvlan_add (ext, DEVICE_NAME, ifindex_parent, &lnk_macvtap))
if (!nmtstp_link_macvlan_add (NULL, ext, DEVICE_NAME, ifindex_parent, &lnk_macvtap))
g_error ("Failed adding MACVTAP interface");
break;
}
@ -814,7 +814,7 @@ test_software_detect (gconstpointer user_data)
gracefully_skip = nm_utils_modprobe (NULL, TRUE, "sit", NULL) != 0;
}
if (!nmtstp_link_sit_add (ext, DEVICE_NAME, &lnk_sit)) {
if (!nmtstp_link_sit_add (NULL, ext, DEVICE_NAME, &lnk_sit)) {
if (gracefully_skip) {
g_test_skip ("Cannot create sit tunnel because of missing sit module (modprobe sit)");
goto out_delete_parent;
@ -853,7 +853,7 @@ test_software_detect (gconstpointer user_data)
break;
}
g_assert (nmtstp_link_vxlan_add (ext, DEVICE_NAME, &lnk_vxlan));
g_assert (nmtstp_link_vxlan_add (NULL, ext, DEVICE_NAME, &lnk_vxlan));
break;
}
default:
@ -862,7 +862,7 @@ test_software_detect (gconstpointer user_data)
ifindex = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, DEVICE_NAME, test_data->link_type, 100)->ifindex;
nmtstp_link_set_updown (-1, ifindex_parent, TRUE);
nmtstp_link_set_updown (NULL, -1, ifindex_parent, TRUE);
for (i_step = 0; i_step < 5; i_step++) {
@ -880,7 +880,7 @@ test_software_detect (gconstpointer user_data)
* https://bugzilla.redhat.com/show_bug.cgi?id=1277131 */
g_usleep (1);
}
nmtstp_link_set_updown (-1, ifindex, set_up);
nmtstp_link_set_updown (NULL, -1, ifindex, set_up);
}
lnk = nm_platform_link_get_lnk (NM_PLATFORM_GET, ifindex, test_data->link_type, &plink);
@ -1017,9 +1017,9 @@ test_software_detect (gconstpointer user_data)
}
}
nmtstp_link_del (-1, ifindex, DEVICE_NAME);
nmtstp_link_del (NULL, -1, ifindex, DEVICE_NAME);
out_delete_parent:
nmtstp_link_del (-1, ifindex_parent, PARENT_NAME);
nmtstp_link_del (NULL, -1, ifindex_parent, PARENT_NAME);
}
static void
@ -1597,8 +1597,8 @@ test_vlan_set_xgress (void)
_assert_vlan_flags (ifindex, NM_VLAN_FLAG_REORDER_HEADERS | NM_VLAN_FLAG_GVRP);
}
nmtstp_link_del (-1, ifindex, DEVICE_NAME);
nmtstp_link_del (-1, ifindex_parent, PARENT_NAME);
nmtstp_link_del (NULL, -1, ifindex, DEVICE_NAME);
nmtstp_link_del (NULL, -1, ifindex_parent, PARENT_NAME);
}
/*****************************************************************************/
@ -1625,7 +1625,7 @@ test_create_many_links_do (guint n_devices)
* while adding all the links. */
nmtstp_run_command_check ("ip link add %s type dummy", name);
} else
nmtstp_link_dummy_add (EX, name);
nmtstp_link_dummy_add (NULL, EX, name);
}
_LOGI (">>> process events after creating devices...");
@ -1654,7 +1654,7 @@ test_create_many_links_do (guint n_devices)
if (EX == 2)
nmtstp_run_command_check ("ip link delete %s", name);
else
nmtstp_link_del (EX, g_array_index (ifindexes, int, i), name);
nmtstp_link_del (NULL, EX, g_array_index (ifindexes, int, i), name);
}
_LOGI (">>> process events after deleting devices...");
@ -1743,7 +1743,7 @@ test_nl_bugs_veth (void)
});
out:
nmtstp_link_del (-1, ifindex_veth0, IFACE_VETH0);
nmtstp_link_del (NULL, -1, ifindex_veth0, IFACE_VETH0);
g_assert (!nmtstp_link_get (NM_PLATFORM_GET, ifindex_veth0, IFACE_VETH0));
g_assert (!nmtstp_link_get (NM_PLATFORM_GET, ifindex_veth1, IFACE_VETH1));
nmtstp_namespace_handle_release (ns_handle);
@ -1768,7 +1768,7 @@ test_nl_bugs_spuroius_newlink (void)
nmtstp_run_command_check ("ip link add %s type bond", IFACE_BOND0);
ifindex_bond0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_BOND0, NM_LINK_TYPE_BOND, 100)->ifindex;
nmtstp_link_set_updown (-1, ifindex_bond0, TRUE);
nmtstp_link_set_updown (NULL, -1, ifindex_bond0, TRUE);
nmtstp_run_command_check ("ip link set %s master %s", IFACE_DUMMY0, IFACE_BOND0);
NMTST_WAIT_ASSERT (100, {
@ -1796,7 +1796,7 @@ again:
}
g_assert (!nmtstp_link_get (NM_PLATFORM_GET, ifindex_bond0, IFACE_BOND0));
nmtstp_link_del (-1, ifindex_dummy0, IFACE_DUMMY0);
nmtstp_link_del (NULL, -1, ifindex_dummy0, IFACE_DUMMY0);
}
/*****************************************************************************/
@ -1818,7 +1818,7 @@ test_nl_bugs_spuroius_dellink (void)
nmtstp_run_command_check ("ip link add %s type bridge", IFACE_BRIDGE0);
ifindex_bridge0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_BRIDGE0, NM_LINK_TYPE_BRIDGE, 100)->ifindex;
nmtstp_link_set_updown (-1, ifindex_bridge0, TRUE);
nmtstp_link_set_updown (NULL, -1, ifindex_bridge0, TRUE);
nmtstp_run_command_check ("ip link set %s master %s", IFACE_DUMMY0, IFACE_BRIDGE0);
NMTST_WAIT_ASSERT (100, {
@ -1850,8 +1850,8 @@ again:
goto again;
}
nmtstp_link_del (-1, ifindex_bridge0, IFACE_BRIDGE0);
nmtstp_link_del (-1, ifindex_dummy0, IFACE_DUMMY0);
nmtstp_link_del (NULL, -1, ifindex_bridge0, IFACE_BRIDGE0);
nmtstp_link_del (NULL, -1, ifindex_dummy0, IFACE_DUMMY0);
}
/******************************************************************/
@ -1880,7 +1880,7 @@ _test_netns_create_platform (void)
netns = nmp_netns_new ();
g_assert (NMP_IS_NETNS (netns));
platform = g_object_new (NM_TYPE_LINUX_PLATFORM, NM_PLATFORM_NETNS_SUPPORT, TRUE, NULL);
platform = nm_linux_platform_new (TRUE);
g_assert (NM_IS_LINUX_PLATFORM (platform));
nmp_netns_pop (netns);
@ -1932,7 +1932,7 @@ test_netns_general (gpointer fixture, gconstpointer test_data)
if (_test_netns_check_skip ())
return;
platform_1 = g_object_new (NM_TYPE_LINUX_PLATFORM, NM_PLATFORM_NETNS_SUPPORT, TRUE, NULL);
platform_1 = nm_linux_platform_new (TRUE);
platform_2 = _test_netns_create_platform ();
/* add some dummy devices. The "other-*" devices are there to bump the ifindex */
@ -2028,7 +2028,7 @@ test_netns_set_netns (gpointer fixture, gconstpointer test_data)
if (_test_netns_check_skip ())
return;
platforms[0] = platform_0 = g_object_new (NM_TYPE_LINUX_PLATFORM, NM_PLATFORM_NETNS_SUPPORT, TRUE, NULL);
platforms[0] = platform_0 = nm_linux_platform_new (TRUE);
platforms[1] = platform_1 = _test_netns_create_platform ();
platforms[2] = platform_2 = _test_netns_create_platform ();
@ -2125,7 +2125,7 @@ test_netns_push (gpointer fixture, gconstpointer test_data)
if (_test_netns_check_skip ())
return;
pl[0].platform = platform_0 = g_object_new (NM_TYPE_LINUX_PLATFORM, NM_PLATFORM_NETNS_SUPPORT, TRUE, NULL);
pl[0].platform = platform_0 = nm_linux_platform_new (TRUE);
pl[1].platform = platform_1 = _test_netns_create_platform ();
pl[2].platform = platform_2 = _test_netns_create_platform ();
@ -2257,7 +2257,7 @@ test_netns_bind_to_path (gpointer fixture, gconstpointer test_data)
if (_test_netns_check_skip ())
return;
platforms[0] = platform_0 = g_object_new (NM_TYPE_LINUX_PLATFORM, NM_PLATFORM_NETNS_SUPPORT, TRUE, NULL);
platforms[0] = platform_0 = nm_linux_platform_new (TRUE);
platforms[1] = platform_1 = _test_netns_create_platform ();
platforms[2] = platform_2 = _test_netns_create_platform ();
@ -2293,13 +2293,13 @@ test_netns_bind_to_path (gpointer fixture, gconstpointer test_data)
/*****************************************************************************/
void
init_tests (int *argc, char ***argv)
_nmtstp_init_tests (int *argc, char ***argv)
{
nmtst_init_with_logging (argc, argv, NULL, "ALL");
}
void
setup_tests (void)
_nmtstp_setup_tests (void)
{
nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME));
nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, SLAVE_NAME));

View file

@ -82,50 +82,50 @@ test_ip4_route_metric0 (void)
int mss = 1000;
/* No routes initially */
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, metric);
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric);
/* add the first route */
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, metric, mss));
accept_signal (route_added);
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
assert_ip4_route_exists (TRUE, DEVICE_NAME, network, plen, metric);
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
/* Deleting route with metric 0 does nothing */
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
ensure_no_signal (route_removed);
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
assert_ip4_route_exists (TRUE, DEVICE_NAME, network, plen, metric);
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
/* add the second route */
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, 0, mss));
accept_signal (route_added);
assert_ip4_route_exists (TRUE, DEVICE_NAME, network, plen, 0);
assert_ip4_route_exists (TRUE, DEVICE_NAME, network, plen, metric);
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, 0);
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
/* Delete route with metric 0 */
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
accept_signal (route_removed);
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
assert_ip4_route_exists (TRUE, DEVICE_NAME, network, plen, metric);
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
/* Delete route with metric 0 again (we expect nothing to happen) */
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
ensure_no_signal (route_removed);
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
assert_ip4_route_exists (TRUE, DEVICE_NAME, network, plen, metric);
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
/* Delete the other route */
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
accept_signal (route_removed);
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, metric);
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric);
free_signal (route_added);
free_signal (route_changed);
@ -142,7 +142,7 @@ test_ip4_route (void)
GArray *routes;
NMPlatformIP4Route rts[3];
in_addr_t network;
int plen = 24;
guint8 plen = 24;
in_addr_t gateway;
/* Choose a high metric so that we hopefully don't conflict. */
int metric = 22986;
@ -156,9 +156,9 @@ test_ip4_route (void)
accept_signal (route_added);
/* Add route */
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, metric);
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric);
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss));
assert_ip4_route_exists (TRUE, DEVICE_NAME, network, plen, metric);
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
accept_signal (route_added);
/* Add route again */
@ -166,9 +166,9 @@ test_ip4_route (void)
accept_signals (route_changed, 0, 1);
/* Add default route */
assert_ip4_route_exists (FALSE, DEVICE_NAME, 0, 0, metric);
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, 0, 0, metric);
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss));
assert_ip4_route_exists (TRUE, DEVICE_NAME, 0, 0, metric);
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, 0, 0, metric);
accept_signal (route_added);
/* Add default route again */
@ -208,7 +208,7 @@ test_ip4_route (void)
/* Remove route */
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, metric);
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric);
accept_signal (route_removed);
/* Remove route again */
@ -229,7 +229,7 @@ test_ip6_route (void)
GArray *routes;
NMPlatformIP6Route rts[3];
struct in6_addr network;
int plen = 64;
guint8 plen = 64;
struct in6_addr gateway;
/* Choose a high metric so that we hopefully don't conflict. */
int metric = 22987;
@ -329,13 +329,13 @@ test_ip4_zero_gateway (void)
/*****************************************************************************/
void
init_tests (int *argc, char ***argv)
_nmtstp_init_tests (int *argc, char ***argv)
{
nmtst_init_with_logging (argc, argv, NULL, "ALL");
}
void
setup_tests (void)
_nmtstp_setup_tests (void)
{
SignalData *link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, DEVICE_NAME);

View file

@ -481,7 +481,7 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager,
if (g_variant_lookup (config_dict, NM_PPP_IP4_CONFIG_PREFIX, "u", &u32))
address.plen = u32;
if (address.address && address.plen) {
if (address.address && address.plen && address.plen <= 32) {
address.source = NM_IP_CONFIG_SOURCE_PPP;
nm_ip4_config_add_address (config, &address);
} else {
@ -554,6 +554,7 @@ impl_ppp_manager_set_ip6_config (NMPPPManager *manager,
NMPlatformIP6Address addr;
struct in6_addr a;
NMUtilsIPv6IfaceId iid = NM_UTILS_IPV6_IFACE_ID_INIT;
gboolean has_peer = FALSE;
_LOGI ("(IPv6 Config Get) reply received.");
@ -567,9 +568,12 @@ impl_ppp_manager_set_ip6_config (NMPPPManager *manager,
if (iid_value_to_ll6_addr (config_dict, NM_PPP_IP6_CONFIG_PEER_IID, &a, NULL)) {
nm_ip6_config_set_gateway (config, &a);
addr.peer_address = a;
has_peer = TRUE;
}
if (iid_value_to_ll6_addr (config_dict, NM_PPP_IP6_CONFIG_OUR_IID, &addr.address, &iid)) {
if (!has_peer)
addr.peer_address = addr.address;
nm_ip6_config_add_address (config, &addr);
if (set_ip_config_common (manager, config_dict, NM_PPP_IP6_CONFIG_INTERFACE, NULL)) {

View file

@ -98,6 +98,122 @@ test_nm_utils_ip6_address_clear_host_address (void)
g_rand_free (r);
}
/*****************************************************************************/
static void
_test_same_prefix (const char *a1, const char *a2, guint8 plen)
{
struct in6_addr a = *nmtst_inet6_from_string (a1);
struct in6_addr b = *nmtst_inet6_from_string (a2);
g_assert (nm_utils_ip6_address_same_prefix (&a, &b, plen));
}
static void
test_nm_utils_ip6_address_same_prefix (void)
{
guint n, i;
const guint N = 100;
union {
guint8 ptr[sizeof (struct in6_addr)];
struct in6_addr val;
} a, b, addrmask, addrmask_bit;
guint8 plen;
/* test#1 */
for (n = 0; n < N; n++) {
gboolean is_same = n < N / 2;
gboolean result;
nmtst_rand_buf (NULL, a.ptr, sizeof (a));
nmtst_rand_buf (NULL, b.ptr, sizeof (b));
again_plen:
plen = nmtst_get_rand_int () % 129;
if (!is_same && NM_IN_SET (plen, 0, 128))
goto again_plen;
if (plen < 128) {
for (i = 0; (i + 1) * 8 <= plen; i++)
b.ptr[i] = a.ptr[i];
if (plen % 8) {
guint8 mask;
g_assert (i < sizeof (a));
mask = ~((1 << (8 - (plen % 8))) - 1);
b.ptr[i] = (a.ptr[i] & mask) | (b.ptr[i] & ~mask);
if (!is_same) {
mask = (1 << (8 - (plen % 8)));
b.ptr[i] = (b.ptr[i] & ~mask) | ~(b.ptr[i] & mask);
}
} else if (!is_same) {
g_assert (i > 0);
b.ptr[i - 1] = (b.ptr[i - 1] & ~0x1) | ~(b.ptr[i - 1] & 0x1);
}
} else
b = a;
result = nm_utils_ip6_address_same_prefix (&a.val, &b.val, plen);
g_assert (result == is_same);
g_assert (NM_IN_SET (result, TRUE, FALSE));
}
/* test#2 */
for (n = 0; n < N; n++) {
nmtst_rand_buf (NULL, a.ptr, sizeof (a));
nmtst_rand_buf (NULL, b.ptr, sizeof (b));
plen = nmtst_get_rand_int () % 129;
memset (addrmask.ptr, 0xFF, sizeof (addrmask));
nm_utils_ip6_address_clear_host_address (&addrmask.val, &addrmask.val, plen);
for (i = 0; i < sizeof (a); i++)
b.ptr[i] = (a.ptr[i] & addrmask.ptr[i]) | (b.ptr[i] & ~addrmask.ptr[i]);
g_assert (nm_utils_ip6_address_same_prefix (&a.val, &b.val, plen) == TRUE);
}
/* test#3 */
for (n = 0; n < N; n++) {
gboolean reached = FALSE;
nmtst_rand_buf (NULL, a.ptr, sizeof (a));
nmtst_rand_buf (NULL, b.ptr, sizeof (b));
plen = nmtst_get_rand_int () % 129;
if (!plen)
continue;
memset (addrmask.ptr, 0xFF, sizeof (addrmask));
nm_utils_ip6_address_clear_host_address (&addrmask.val, &addrmask.val, plen);
memset (addrmask_bit.ptr, 0xFF, sizeof (addrmask_bit));
nm_utils_ip6_address_clear_host_address (&addrmask_bit.val, &addrmask_bit.val, plen - 1);
for (i = 0; i < sizeof (a); i++)
b.ptr[i] = (a.ptr[i] & addrmask.ptr[i]) | (b.ptr[i] & ~addrmask.ptr[i]);
/* flip the last bit. */
for (i = 0; i < sizeof (a); i++) {
guint8 mask = addrmask.ptr[i] ^ addrmask_bit.ptr[i];
if (mask) {
g_assert (!reached);
g_assert (nm_utils_is_power_of_two (mask));
reached = TRUE;
b.ptr[i] = (b.ptr[i] & ~mask) | ~(b.ptr[i] & mask);
}
}
g_assert (reached);
g_assert (nm_utils_ip6_address_same_prefix (&a.val, &b.val, plen) == FALSE);
}
/* test#4 */
_test_same_prefix ("::", "::1", 10);
_test_same_prefix ("abcd::", "abcd::1", 10);
}
/*****************************************************************************/
static void
test_nm_utils_log_connection_diff (void)
@ -1257,6 +1373,7 @@ main (int argc, char **argv)
g_test_add_func ("/general/nm_utils_strbuf_append", test_nm_utils_strbuf_append);
g_test_add_func ("/general/nm_utils_ip6_address_clear_host_address", test_nm_utils_ip6_address_clear_host_address);
g_test_add_func ("/general/nm_utils_ip6_address_same_prefix", test_nm_utils_ip6_address_same_prefix);
g_test_add_func ("/general/nm_utils_log_connection_diff", test_nm_utils_log_connection_diff);
g_test_add_func ("/general/connection-match/basic", test_connection_match_basic);

View file

@ -28,44 +28,6 @@
#include "nm-test-utils.h"
static void
addr_init (NMPlatformIP4Address *a, const char *addr, const char *peer, guint plen)
{
memset (a, 0, sizeof (*a));
g_assert (inet_pton (AF_INET, addr, (void *) &a->address) == 1);
if (peer)
g_assert (inet_pton (AF_INET, peer, (void *) &a->peer_address) == 1);
else
a->peer_address = a->address;
a->plen = plen;
}
static void
route_new (NMPlatformIP4Route *route, const char *network, guint plen, const char *gw)
{
guint n;
g_assert (route);
memset (route, 0, sizeof (*route));
g_assert (inet_pton (AF_INET, network, (void *) &n) == 1);
route->network = n;
route->plen = plen;
if (gw) {
n = 0;
g_assert (inet_pton (AF_INET, gw, (void *) &n) == 1);
route->gateway = n;
}
}
static guint32
addr_to_num (const char *addr)
{
guint n;
g_assert (inet_pton (AF_INET, addr, (void *) &n) == 1);
return n;
}
static NMIP4Config *
build_test_config (void)
{
@ -76,29 +38,29 @@ build_test_config (void)
/* Build up the config to subtract */
config = nm_ip4_config_new (1);
addr_init (&addr, "192.168.1.10", "1.2.3.4", 24);
addr = *nmtst_platform_ip4_address ("192.168.1.10", "1.2.3.4", 24);
nm_ip4_config_add_address (config, &addr);
route_new (&route, "10.0.0.0", 8, "192.168.1.1");
route = *nmtst_platform_ip4_route ("10.0.0.0", 8, "192.168.1.1");
nm_ip4_config_add_route (config, &route);
route_new (&route, "172.16.0.0", 16, "192.168.1.1");
route = *nmtst_platform_ip4_route ("172.16.0.0", 16, "192.168.1.1");
nm_ip4_config_add_route (config, &route);
nm_ip4_config_set_gateway (config, addr_to_num ("192.168.1.1"));
nm_ip4_config_set_gateway (config, nmtst_inet4_from_string ("192.168.1.1"));
nm_ip4_config_add_nameserver (config, addr_to_num ("4.2.2.1"));
nm_ip4_config_add_nameserver (config, addr_to_num ("4.2.2.2"));
nm_ip4_config_add_nameserver (config, nmtst_inet4_from_string ("4.2.2.1"));
nm_ip4_config_add_nameserver (config, nmtst_inet4_from_string ("4.2.2.2"));
nm_ip4_config_add_domain (config, "foobar.com");
nm_ip4_config_add_domain (config, "baz.com");
nm_ip4_config_add_search (config, "blahblah.com");
nm_ip4_config_add_search (config, "beatbox.com");
nm_ip4_config_add_nis_server (config, addr_to_num ("1.2.3.9"));
nm_ip4_config_add_nis_server (config, addr_to_num ("1.2.3.10"));
nm_ip4_config_add_nis_server (config, nmtst_inet4_from_string ("1.2.3.9"));
nm_ip4_config_add_nis_server (config, nmtst_inet4_from_string ("1.2.3.10"));
nm_ip4_config_add_wins (config, addr_to_num ("4.2.3.9"));
nm_ip4_config_add_wins (config, addr_to_num ("4.2.3.10"));
nm_ip4_config_add_wins (config, nmtst_inet4_from_string ("4.2.3.9"));
nm_ip4_config_add_wins (config, nmtst_inet4_from_string ("4.2.3.10"));
return config;
}
@ -116,12 +78,12 @@ test_subtract (void)
const char *expected_route_dest = "8.7.6.5";
guint32 expected_route_plen = 8;
const char *expected_route_next_hop = "192.168.1.1";
guint32 expected_ns1 = addr_to_num ("8.8.8.8");
guint32 expected_ns2 = addr_to_num ("8.8.8.9");
guint32 expected_ns1 = nmtst_inet4_from_string ("8.8.8.8");
guint32 expected_ns2 = nmtst_inet4_from_string ("8.8.8.9");
const char *expected_domain = "wonderfalls.com";
const char *expected_search = "somewhere.com";
guint32 expected_nis = addr_to_num ("1.2.3.13");
guint32 expected_wins = addr_to_num ("2.3.4.5");
guint32 expected_nis = nmtst_inet4_from_string ("1.2.3.13");
guint32 expected_wins = nmtst_inet4_from_string ("2.3.4.5");
guint32 expected_mss = 1400;
guint32 expected_mtu = 1492;
@ -129,10 +91,10 @@ test_subtract (void)
/* add a couple more things to the test config */
dst = build_test_config ();
addr_init (&addr, expected_addr, NULL, expected_addr_plen);
addr = *nmtst_platform_ip4_address (expected_addr, NULL, expected_addr_plen);
nm_ip4_config_add_address (dst, &addr);
route_new (&route, expected_route_dest, expected_route_plen, expected_route_next_hop);
route = *nmtst_platform_ip4_route (expected_route_dest, expected_route_plen, expected_route_next_hop);
nm_ip4_config_add_route (dst, &route);
nm_ip4_config_add_nameserver (dst, expected_ns1);
@ -152,7 +114,7 @@ test_subtract (void)
g_assert_cmpuint (nm_ip4_config_get_num_addresses (dst), ==, 1);
test_addr = nm_ip4_config_get_address (dst, 0);
g_assert (test_addr != NULL);
g_assert_cmpuint (test_addr->address, ==, addr_to_num (expected_addr));
g_assert_cmpuint (test_addr->address, ==, nmtst_inet4_from_string (expected_addr));
g_assert_cmpuint (test_addr->peer_address, ==, test_addr->address);
g_assert_cmpuint (test_addr->plen, ==, expected_addr_plen);
@ -161,9 +123,9 @@ test_subtract (void)
g_assert_cmpuint (nm_ip4_config_get_num_routes (dst), ==, 1);
test_route = nm_ip4_config_get_route (dst, 0);
g_assert (test_route != NULL);
g_assert_cmpuint (test_route->network, ==, addr_to_num (expected_route_dest));
g_assert_cmpuint (test_route->network, ==, nmtst_inet4_from_string (expected_route_dest));
g_assert_cmpuint (test_route->plen, ==, expected_route_plen);
g_assert_cmpuint (test_route->gateway, ==, addr_to_num (expected_route_next_hop));
g_assert_cmpuint (test_route->gateway, ==, nmtst_inet4_from_string (expected_route_next_hop));
g_assert_cmpuint (nm_ip4_config_get_num_nameservers (dst), ==, 2);
g_assert_cmpuint (nm_ip4_config_get_nameserver (dst, 0), ==, expected_ns1);
@ -198,7 +160,7 @@ test_compare_with_source (void)
b = nm_ip4_config_new (2);
/* Address */
addr_init (&addr, "1.2.3.4", NULL, 24);
addr = *nmtst_platform_ip4_address ("1.2.3.4", NULL, 24);
addr.source = NM_IP_CONFIG_SOURCE_USER;
nm_ip4_config_add_address (a, &addr);
@ -206,7 +168,7 @@ test_compare_with_source (void)
nm_ip4_config_add_address (b, &addr);
/* Route */
route_new (&route, "10.0.0.0", 8, "192.168.1.1");
route = *nmtst_platform_ip4_route ("10.0.0.0", 8, "192.168.1.1");
route.source = NM_IP_CONFIG_SOURCE_USER;
nm_ip4_config_add_route (a, &route);
@ -230,7 +192,7 @@ test_add_address_with_source (void)
a = nm_ip4_config_new (1);
/* Test that a higher priority source is not overwritten */
addr_init (&addr, "1.2.3.4", NULL, 24);
addr = *nmtst_platform_ip4_address ("1.2.3.4", NULL, 24);
addr.source = NM_IP_CONFIG_SOURCE_USER;
nm_ip4_config_add_address (a, &addr);
@ -270,7 +232,7 @@ test_add_route_with_source (void)
a = nm_ip4_config_new (1);
/* Test that a higher priority source is not overwritten */
route_new (&route, "1.2.3.4", 24, "1.2.3.1");
route = *nmtst_platform_ip4_route ("1.2.3.4", 24, "1.2.3.1");
route.source = NM_IP_CONFIG_SOURCE_USER;
nm_ip4_config_add_route (a, &route);

View file

@ -906,13 +906,13 @@ fixture_teardown (test_fixture *fixture, gconstpointer user_data)
/*****************************************************************************/
void
init_tests (int *argc, char ***argv)
_nmtstp_init_tests (int *argc, char ***argv)
{
nmtst_init_assert_logging (argc, argv, "WARN", "ALL");
}
void
setup_tests (void)
_nmtstp_setup_tests (void)
{
g_test_add ("/route-manager/ip4", test_fixture, NULL, fixture_setup, test_ip4, fixture_teardown);
g_test_add ("/route-manager/ip6", test_fixture, NULL, fixture_setup, test_ip6, fixture_teardown);

View file

@ -1387,11 +1387,11 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
if (g_variant_lookup (dict, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, "u", &u32))
address.plen = u32;
if (address.address && address.plen) {
if (address.address && address.plen && address.plen <= 32) {
address.source = NM_IP_CONFIG_SOURCE_VPN;
nm_ip4_config_add_address (config, &address);
} else {
_LOGE ("invalid IP4 config received!");
_LOGW ("invalid IP4 config received!");
g_object_unref (config);
nm_vpn_connection_config_maybe_complete (self, FALSE);
return;
@ -1439,6 +1439,9 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
route.metric = route_metric;
route.source = NM_IP_CONFIG_SOURCE_VPN;
if (route.plen > 32)
break;
/* Ignore host routes to the VPN gateway since NM adds one itself
* below. Since NM knows more about the routing situation than
* the VPN server, we want to use the NM created route instead of
@ -1448,7 +1451,7 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
nm_ip4_config_add_route (config, &route);
break;
default:
_LOGW ("VPN connection: received invalid IPv4 route");
break;
}
g_variant_unref (v);
}
@ -1521,11 +1524,11 @@ nm_vpn_connection_ip6_config_get (NMVpnConnection *self, GVariant *dict)
if (g_variant_lookup (dict, NM_VPN_PLUGIN_IP6_CONFIG_PREFIX, "u", &u32))
address.plen = u32;
if (!IN6_IS_ADDR_UNSPECIFIED (&address.address) && address.plen) {
if (!IN6_IS_ADDR_UNSPECIFIED (&address.address) && address.plen && address.plen <= 128) {
address.source = NM_IP_CONFIG_SOURCE_VPN;
nm_ip6_config_add_address (config, &address);
} else {
_LOGE ("invalid IP6 config received!");
_LOGW ("invalid IP6 config received!");
g_object_unref (config);
nm_vpn_connection_config_maybe_complete (self, FALSE);
return;
@ -1565,10 +1568,11 @@ nm_vpn_connection_ip6_config_get (NMVpnConnection *self, GVariant *dict)
memset (&route, 0, sizeof (route));
if (!ip6_addr_from_variant (dest, &route.network)) {
_LOGW ("VPN connection: received invalid IPv6 dest address");
if (!ip6_addr_from_variant (dest, &route.network))
goto next;
if (prefix > 128)
goto next;
}
route.plen = prefix;
ip6_addr_from_variant (next_hop, &route.gateway);