diff --git a/shared/nm-macros-internal.h b/shared/nm-macros-internal.h index 4176231800..384bca66fe 100644 --- a/shared/nm-macros-internal.h +++ b/shared/nm-macros-internal.h @@ -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: diff --git a/shared/nm-test-utils.h b/shared/nm-test-utils.h index 2503245761..b792a69c85 100644 --- a/shared/nm-test-utils.h +++ b/shared/nm-test-utils.h @@ -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; diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index dde9af9481..3d949ec2d8 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -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; diff --git a/src/devices/tests/test-arping.c b/src/devices/tests/test-arping.c index 72d28a7ac4..244d0715ec 100644 --- a/src/devices/tests/test-arping.c +++ b/src/devices/tests/test-arping.c @@ -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); diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index 1b7f536d03..bff85e6c94 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -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) diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index 769e6a2753..9539fefd3d 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -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); diff --git a/src/dhcp-manager/nm-dhcp-systemd.c b/src/dhcp-manager/nm-dhcp-systemd.c index 91fa880305..5d49c27e44 100644 --- a/src/dhcp-manager/nm-dhcp-systemd.c +++ b/src/dhcp-manager/nm-dhcp-systemd.c @@ -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; diff --git a/src/dhcp-manager/nm-dhcp-utils.c b/src/dhcp-manager/nm-dhcp-utils.c index be563a6971..a88a7e6d51 100644 --- a/src/dhcp-manager/nm-dhcp-utils.c +++ b/src/dhcp-manager/nm-dhcp-utils.c @@ -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); diff --git a/src/dhcp-manager/tests/test-dhcp-utils.c b/src/dhcp-manager/tests/test-dhcp-utils.c index 162f2dd4cd..f477c061fb 100644 --- a/src/dhcp-manager/tests/test-dhcp-utils.c +++ b/src/dhcp-manager/tests/test-dhcp-utils.c @@ -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); diff --git a/src/dnsmasq-manager/nm-dnsmasq-utils.c b/src/dnsmasq-manager/nm-dnsmasq-utils.c index bf8faecd52..3786f37d44 100644 --- a/src/dnsmasq-manager/nm-dnsmasq-utils.c +++ b/src/dnsmasq-manager/nm-dnsmasq-utils.c @@ -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; diff --git a/src/dnsmasq-manager/tests/test-dnsmasq-utils.c b/src/dnsmasq-manager/tests/test-dnsmasq-utils.c index 850ae4f6fb..aeec5879a1 100644 --- a/src/dnsmasq-manager/tests/test-dnsmasq-utils.c +++ b/src/dnsmasq-manager/tests/test-dnsmasq-utils.c @@ -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); diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index 6cdd00e0d7..714aaa9279 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -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) { diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h index f77b43e2a3..280be04736 100644 --- a/src/nm-core-utils.h +++ b/src/nm-core-utils.h @@ -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 \ diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index 5a697537c1..20f7729a43 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -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; diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 4b27edf74b..d6f6a9b3fc 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -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++ ) { diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 02bc8b07f1..b1a5768740 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -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 */ diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 6d83bd53a3..0b32901bf1 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -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 && diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 5ca64ac372..5e66d500e4 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -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 */ diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c index 3cf241186b..05e28c7426 100644 --- a/src/nm-route-manager.c +++ b/src/nm-route-manager.c @@ -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)); } diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index fdb11eac56..15d9c54301 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -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; diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 3282e698ce..ded019e642 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -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; diff --git a/src/platform/nm-linux-platform.h b/src/platform/nm-linux-platform.h index a9e2cd82f9..4ae2fd1400 100644 --- a/src/platform/nm-linux-platform.h +++ b/src/platform/nm-linux-platform.h @@ -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__ */ diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index d0c92a787c..b4542adf8d 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -30,6 +30,7 @@ #include #include #include +#include #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; + } +} + diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h index 976bd8db40..f259474719 100644 --- a/src/platform/nm-platform-utils.h +++ b/src/platform/nm-platform-utils.h @@ -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__ */ diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 5a399b316a..69b0d420ca 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -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)); diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 15bd2fdeef..9f055b042c 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -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); diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index adeb3aabe3..eb7e1ca401 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -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, diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index 6d5b9627ce..c5241037d5 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -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, diff --git a/src/platform/tests/Makefile.am b/src/platform/tests/Makefile.am index ebf20e15d6..5af4ce91d4 100644 --- a/src/platform/tests/Makefile.am +++ b/src/platform/tests/Makefile.am @@ -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 \ diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c index 83a0bfd3c2..05a1444814 100644 --- a/src/platform/tests/test-address.c +++ b/src/platform/tests/test-address.c @@ -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); diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c index 4036daad10..3b52487a56 100644 --- a/src/platform/tests/test-cleanup.c +++ b/src/platform/tests/test-cleanup.c @@ -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)); diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index e9fffe9041..b1947a6d11 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -27,11 +27,11 @@ #include "test-common.h" -#include "nm-test-utils.h" - #define SIGNAL_DATA_FMT "'%s-%s' ifindex %d%s%s%s (%d times received)" #define SIGNAL_DATA_ARG(data) (data)->name, nm_platform_signal_change_type_to_string ((data)->change_type), (data)->ifindex, (data)->ifname ? " ifname '" : "", (data)->ifname ? (data)->ifname : "", (data)->ifname ? "'" : "", (data)->received_count +/*****************************************************************************/ + gboolean nmtstp_is_root_test (void) { @@ -47,6 +47,20 @@ nmtstp_is_sysfs_writable (void) || (access ("/sys/devices", W_OK) == 0); } +static void +_init_platform (NMPlatform **platform, gboolean external_command) +{ + g_assert (platform); + if (!*platform) + *platform = NM_PLATFORM_GET; + g_assert (NM_IS_PLATFORM (*platform)); + + if (external_command) + g_assert (NM_IS_LINUX_PLATFORM (*platform)); +} + +/*****************************************************************************/ + SignalData * add_signal_full (const char *name, NMPlatformSignalChangeType change_type, GCallback callback, int ifindex, const char *ifname) { @@ -180,8 +194,10 @@ link_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlat g_error ("Added/changed link not found in the local cache."); } +/*****************************************************************************/ + gboolean -ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric) +nmtstp_ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric) { gs_free char *arg_network = NULL; const char *argv[] = { @@ -205,7 +221,7 @@ ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric) g_assert (!strstr (ifname, " metric ")); g_assert (plen >= 0 && plen <= 32); - if (!NM_IS_LINUX_PLATFORM (nm_platform_get ())) { + if (!nmtstp_is_root_test ()) { /* If we don't test against linux-platform, we don't actually configure any * routes in the system. */ return -1; @@ -259,15 +275,17 @@ 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) +_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) { int ifindex; gboolean exists_checked; + _init_platform (&platform, FALSE); + /* Check for existance of the route by spawning iproute2. Do this because platform * code might be entirely borked, but we expect ip-route to give a correct result. * If the ip command cannot be found, we accept this as success. */ - exists_checked = ip4_route_exists (ifname, network, plen, metric); + exists_checked = nmtstp_ip4_route_exists (ifname, network, plen, metric); if (exists_checked != -1 && !exists_checked != !exists) { g_error ("[%s:%u] %s(): We expect the ip4 route %s/%d metric %u %s, but it %s", file, line, func, @@ -276,9 +294,9 @@ _assert_ip4_route_exists (const char *file, guint line, const char *func, gboole exists ? "doesn't" : "does"); } - ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, ifname); + ifindex = nm_platform_link_get_ifindex (platform, ifname); g_assert (ifindex > 0); - if (!nm_platform_ip4_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric) != !exists) { + if (!nm_platform_ip4_route_get (platform, ifindex, network, plen, metric) != !exists) { g_error ("[%s:%u] %s(): The ip4 route %s/%d metric %u %s, but platform thinks %s", file, line, func, nm_utils_inet4_ntop (network, NULL), plen, metric, @@ -287,6 +305,8 @@ _assert_ip4_route_exists (const char *file, guint line, const char *func, gboole } } +/*****************************************************************************/ + int nmtstp_run_command (const char *format, ...) { @@ -309,7 +329,7 @@ nmtstp_run_command (const char *format, ...) typedef struct { GMainLoop *loop; - gboolean timeout; + guint signal_counts; guint id; } WaitForSignalData; @@ -323,6 +343,8 @@ _wait_for_signal_cb (NMPlatform *platform, { WaitForSignalData *data = user_data; + data->signal_counts++; + nm_clear_g_source (&data->id); g_main_loop_quit (data->loop); } @@ -331,20 +353,19 @@ _wait_for_signal_timeout (gpointer user_data) { WaitForSignalData *data = user_data; - data->timeout = TRUE; + g_assert (data->id); data->id = 0; g_main_loop_quit (data->loop); return G_SOURCE_REMOVE; } -gboolean +guint nmtstp_wait_for_signal (NMPlatform *platform, guint timeout_ms) { WaitForSignalData data = { 0 }; gulong id_link, id_ip4_address, id_ip6_address, id_ip4_route, id_ip6_route; - if (!platform) - platform = NM_PLATFORM_GET; + _init_platform (&platform, FALSE); data.loop = g_main_loop_new (NULL, FALSE); @@ -359,33 +380,34 @@ nmtstp_wait_for_signal (NMPlatform *platform, guint timeout_ms) g_main_loop_run (data.loop); + g_assert (!data.id); g_assert (nm_clear_g_signal_handler (platform, &id_link)); g_assert (nm_clear_g_signal_handler (platform, &id_ip4_address)); g_assert (nm_clear_g_signal_handler (platform, &id_ip6_address)); g_assert (nm_clear_g_signal_handler (platform, &id_ip4_route)); g_assert (nm_clear_g_signal_handler (platform, &id_ip6_route)); - if (nm_clear_g_source (&data.id)) - g_assert (timeout_ms != 0 && !data.timeout); - g_clear_pointer (&data.loop, g_main_loop_unref); - return !data.timeout; + /* return the number of signals, or 0 if timeout was reached .*/ + return data.signal_counts; } -gboolean +guint nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms) { gint64 now; + guint signal_counts; while (TRUE) { now = nm_utils_get_monotonic_timestamp_ms (); if (until_ms < now) - return FALSE; + return 0; - if (nmtstp_wait_for_signal (platform, MAX (1, until_ms - now))) - return TRUE; + signal_counts = nmtstp_wait_for_signal (platform, MAX (1, until_ms - now)); + if (signal_counts) + return signal_counts; } } @@ -401,10 +423,12 @@ nmtstp_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType const NMPlatformLink *plink; gint64 now; + _init_platform (&platform, FALSE); + while (TRUE) { now = nm_utils_get_monotonic_timestamp_ms (); - plink = nm_platform_link_get_by_ifname (platform ?: NM_PLATFORM_GET, ifname); + plink = nm_platform_link_get_by_ifname (platform, ifname); if ( plink && (expected_link_type == NM_LINK_TYPE_NONE || plink->type == expected_link_type)) return plink; @@ -432,6 +456,8 @@ nmtstp_assert_wait_for_link_until (NMPlatform *platform, const char *ifname, NML return plink; } +/*****************************************************************************/ + int nmtstp_run_command_check_external_global (void) { @@ -460,6 +486,8 @@ nmtstp_run_command_check_external (int external_command) return (nmtst_get_rand_int () % 2) == 0; } +/*****************************************************************************/ + #define CHECK_LIFETIME_MAX_DIFF 2 gboolean @@ -556,8 +584,11 @@ nmtstp_ip_address_assert_lifetime (const NMPlatformIPAddress *addr, g_assert (nmtstp_ip_address_check_lifetime (addr, n, expected_lifetime, expected_preferred)); } +/*****************************************************************************/ + static void -_ip_address_add (gboolean external_command, +_ip_address_add (NMPlatform *platform, + gboolean external_command, gboolean is_v4, int ifindex, const NMIPAddr *address, @@ -572,6 +603,8 @@ _ip_address_add (gboolean external_command, external_command = nmtstp_run_command_check_external (external_command); + _init_platform (&platform, external_command); + if (external_command) { const char *ifname; gs_free char *s_valid = NULL; @@ -579,7 +612,7 @@ _ip_address_add (gboolean external_command, gs_free char *s_label = NULL; char b1[NM_UTILS_INET_ADDRSTRLEN], b2[NM_UTILS_INET_ADDRSTRLEN]; - ifname = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex); + ifname = nm_platform_link_get_name (platform, ifindex); g_assert (ifname); if (lifetime != NM_PLATFORM_LIFETIME_PERMANENT) @@ -628,7 +661,7 @@ _ip_address_add (gboolean external_command, gboolean success; if (is_v4) { - success = nm_platform_ip4_address_add (NM_PLATFORM_GET, + success = nm_platform_ip4_address_add (platform, ifindex, address->addr4, plen, @@ -639,7 +672,7 @@ _ip_address_add (gboolean external_command, label); } else { g_assert (label == NULL); - success = nm_platform_ip6_address_add (NM_PLATFORM_GET, + success = nm_platform_ip6_address_add (platform, ifindex, address->addr6, plen, @@ -656,14 +689,14 @@ _ip_address_add (gboolean external_command, do { if (external_command) - nm_platform_process_events (NM_PLATFORM_GET); + nm_platform_process_events (platform); /* let's wait until we see the address as we added it. */ if (is_v4) { const NMPlatformIP4Address *a; g_assert (flags == 0); - a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, address->addr4, plen, peer_address->addr4); + a = nm_platform_ip4_address_get (platform, ifindex, address->addr4, plen, peer_address->addr4); if ( a && a->peer_address == peer_address->addr4 && nmtstp_ip_address_check_lifetime ((NMPlatformIPAddress*) a, -1, lifetime, preferred) @@ -675,7 +708,7 @@ _ip_address_add (gboolean external_command, g_assert (label == NULL); g_assert (flags == 0); - a = nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, address->addr6, plen); + a = nm_platform_ip6_address_get (platform, ifindex, address->addr6, plen); if ( a && !memcmp (nm_platform_ip6_address_get_peer (a), (IN6_IS_ADDR_UNSPECIFIED (&peer_address->addr6) || IN6_ARE_ADDR_EQUAL (&address->addr6, &peer_address->addr6)) @@ -688,10 +721,188 @@ _ip_address_add (gboolean external_command, /* for internal command, we expect not to reach this line.*/ g_assert (external_command); - g_assert (nmtstp_wait_for_signal_until (NM_PLATFORM_GET, end_time)); + nmtstp_assert_wait_for_signal_until (platform, end_time); } while (TRUE); } +void +nmtstp_ip4_address_add (NMPlatform *platform, + gboolean external_command, + int ifindex, + in_addr_t address, + int plen, + in_addr_t peer_address, + guint32 lifetime, + guint32 preferred, + guint32 flags, + const char *label) +{ + _ip_address_add (platform, + external_command, + TRUE, + ifindex, + (NMIPAddr *) &address, + plen, + (NMIPAddr *) &peer_address, + lifetime, + preferred, + flags, + label); +} + +void +nmtstp_ip6_address_add (NMPlatform *platform, + gboolean external_command, + int ifindex, + struct in6_addr address, + int plen, + struct in6_addr peer_address, + guint32 lifetime, + guint32 preferred, + guint32 flags) +{ + _ip_address_add (platform, + external_command, + FALSE, + ifindex, + (NMIPAddr *) &address, + plen, + (NMIPAddr *) &peer_address, + lifetime, + preferred, + flags, + NULL); +} + +/*****************************************************************************/ + +static void +_ip_address_del (NMPlatform *platform, + gboolean external_command, + gboolean is_v4, + int ifindex, + const NMIPAddr *address, + int plen, + const NMIPAddr *peer_address) +{ + gint64 end_time; + + external_command = nmtstp_run_command_check_external (external_command); + + _init_platform (&platform, external_command); + + if (external_command) { + const char *ifname; + char b1[NM_UTILS_INET_ADDRSTRLEN], b2[NM_UTILS_INET_ADDRSTRLEN]; + int success; + gboolean had_address; + + ifname = nm_platform_link_get_name (platform, ifindex); + g_assert (ifname); + + /* let's wait until we see the address as we added it. */ + if (is_v4) + had_address = !!nm_platform_ip4_address_get (platform, ifindex, address->addr4, plen, peer_address->addr4); + else + had_address = !!nm_platform_ip6_address_get (platform, ifindex, address->addr6, plen); + + if (is_v4) { + success = nmtstp_run_command ("ip address delete %s%s%s/%d dev %s", + nm_utils_inet4_ntop (address->addr4, b1), + peer_address->addr4 != address->addr4 ? " peer " : "", + peer_address->addr4 != address->addr4 ? nm_utils_inet4_ntop (peer_address->addr4, b2) : "", + plen, + ifname); + } else { + g_assert (!peer_address); + success = nmtstp_run_command ("ip address delete %s/%d dev %s", + nm_utils_inet6_ntop (&address->addr6, b1), + plen, + ifname); + } + g_assert (success == 0 || !had_address); + } else { + gboolean success; + + if (is_v4) { + success = nm_platform_ip4_address_delete (platform, + ifindex, + address->addr4, + plen, + peer_address->addr4); + } else { + g_assert (!peer_address); + success = nm_platform_ip6_address_delete (platform, + ifindex, + address->addr6, + plen); + } + g_assert (success); + } + + /* Let's wait until we get the result */ + end_time = nm_utils_get_monotonic_timestamp_ms () + 250; + do { + if (external_command) + nm_platform_process_events (platform); + + /* let's wait until we see the address as we added it. */ + if (is_v4) { + const NMPlatformIP4Address *a; + + a = nm_platform_ip4_address_get (platform, ifindex, address->addr4, plen, peer_address->addr4); + if (!a) + break; + } else { + const NMPlatformIP6Address *a; + + a = nm_platform_ip6_address_get (platform, ifindex, address->addr6, plen); + if (!a) + break; + } + + /* for internal command, we expect not to reach this line.*/ + g_assert (external_command); + + nmtstp_assert_wait_for_signal_until (platform, end_time); + } while (TRUE); +} + +void +nmtstp_ip4_address_del (NMPlatform *platform, + gboolean external_command, + int ifindex, + in_addr_t address, + int plen, + in_addr_t peer_address) +{ + _ip_address_del (platform, + external_command, + TRUE, + ifindex, + (NMIPAddr *) &address, + plen, + (NMIPAddr *) &peer_address); +} + +void +nmtstp_ip6_address_del (NMPlatform *platform, + gboolean external_command, + int ifindex, + struct in6_addr address, + int plen) +{ + _ip_address_del (platform, + external_command, + FALSE, + ifindex, + (NMIPAddr *) &address, + plen, + NULL); +} + +/*****************************************************************************/ + #define _assert_pllink(platform, success, pllink, name, type) \ G_STMT_START { \ const NMPlatformLink *_pllink = (pllink); \ @@ -706,7 +917,8 @@ _ip_address_add (gboolean external_command, } G_STMT_END const NMPlatformLink * -nmtstp_link_dummy_add (gboolean external_command, +nmtstp_link_dummy_add (NMPlatform *platform, + gboolean external_command, const char *name) { const NMPlatformLink *pllink = NULL; @@ -716,21 +928,24 @@ nmtstp_link_dummy_add (gboolean external_command, external_command = nmtstp_run_command_check_external (external_command); + _init_platform (&platform, external_command); + if (external_command) { success = !nmtstp_run_command ("ip link add %s type dummy", name); if (success) - pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_DUMMY, 100); + pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_DUMMY, 100); } else - success = nm_platform_link_dummy_add (NM_PLATFORM_GET, name, &pllink) == NM_PLATFORM_ERROR_SUCCESS; + success = nm_platform_link_dummy_add (platform, name, &pllink) == NM_PLATFORM_ERROR_SUCCESS; g_assert (success); - _assert_pllink (NM_PLATFORM_GET, success, pllink, name, NM_LINK_TYPE_DUMMY); + _assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_DUMMY); return pllink; } const NMPlatformLink * -nmtstp_link_gre_add (gboolean external_command, +nmtstp_link_gre_add (NMPlatform *platform, + gboolean external_command, const char *name, const NMPlatformLnkGre *lnk) { @@ -742,11 +957,13 @@ nmtstp_link_gre_add (gboolean external_command, external_command = nmtstp_run_command_check_external (external_command); + _init_platform (&platform, external_command); + if (external_command) { gs_free char *dev = NULL; if (lnk->parent_ifindex) - dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (NM_PLATFORM_GET, lnk->parent_ifindex)); + dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex)); success = !nmtstp_run_command ("ip tunnel add %s mode gre %s local %s remote %s ttl %u tos %02x %s", name, @@ -757,17 +974,18 @@ nmtstp_link_gre_add (gboolean external_command, lnk->tos, lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); if (success) - pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_GRE, 100); + pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_GRE, 100); } else - success = nm_platform_link_gre_add (NM_PLATFORM_GET, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; + success = nm_platform_link_gre_add (platform, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; - _assert_pllink (NM_PLATFORM_GET, success, pllink, name, NM_LINK_TYPE_GRE); + _assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_GRE); return pllink; } const NMPlatformLink * -nmtstp_link_ip6tnl_add (gboolean external_command, +nmtstp_link_ip6tnl_add (NMPlatform *platform, + gboolean external_command, const char *name, const NMPlatformLnkIp6Tnl *lnk) { @@ -779,12 +997,14 @@ nmtstp_link_ip6tnl_add (gboolean external_command, external_command = nmtstp_run_command_check_external (external_command); + _init_platform (&platform, external_command); + if (external_command) { gs_free char *dev = NULL; const char *mode; if (lnk->parent_ifindex) - dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (NM_PLATFORM_GET, lnk->parent_ifindex)); + dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex)); switch (lnk->proto) { case IPPROTO_IPIP: @@ -808,17 +1028,18 @@ nmtstp_link_ip6tnl_add (gboolean external_command, lnk->encap_limit, lnk->flow_label); if (success) - pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_IP6TNL, 100); + pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_IP6TNL, 100); } else - success = nm_platform_link_ip6tnl_add (NM_PLATFORM_GET, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; + success = nm_platform_link_ip6tnl_add (platform, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; - _assert_pllink (NM_PLATFORM_GET, success, pllink, name, NM_LINK_TYPE_IP6TNL); + _assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_IP6TNL); return pllink; } const NMPlatformLink * -nmtstp_link_ipip_add (gboolean external_command, +nmtstp_link_ipip_add (NMPlatform *platform, + gboolean external_command, const char *name, const NMPlatformLnkIpIp *lnk) { @@ -830,11 +1051,13 @@ nmtstp_link_ipip_add (gboolean external_command, external_command = nmtstp_run_command_check_external (external_command); + _init_platform (&platform, external_command); + if (external_command) { gs_free char *dev = NULL; if (lnk->parent_ifindex) - dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (NM_PLATFORM_GET, lnk->parent_ifindex)); + dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex)); success = !nmtstp_run_command ("ip tunnel add %s mode ipip %s local %s remote %s ttl %u tos %02x %s", name, @@ -845,17 +1068,18 @@ nmtstp_link_ipip_add (gboolean external_command, lnk->tos, lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); if (success) - pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_IPIP, 100); + pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_IPIP, 100); } else - success = nm_platform_link_ipip_add (NM_PLATFORM_GET, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; + success = nm_platform_link_ipip_add (platform, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; - _assert_pllink (NM_PLATFORM_GET, success, pllink, name, NM_LINK_TYPE_IPIP); + _assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_IPIP); return pllink; } const NMPlatformLink * -nmtstp_link_macvlan_add (gboolean external_command, +nmtstp_link_macvlan_add (NMPlatform *platform, + gboolean external_command, const char *name, int parent, const NMPlatformLnkMacvlan *lnk) @@ -868,6 +1092,8 @@ nmtstp_link_macvlan_add (gboolean external_command, external_command = nmtstp_run_command_check_external (external_command); + _init_platform (&platform, external_command); + link_type = lnk->tap ? NM_LINK_TYPE_MACVTAP : NM_LINK_TYPE_MACVLAN; if (external_command) { @@ -879,7 +1105,7 @@ nmtstp_link_macvlan_add (gboolean external_command, [MACVLAN_MODE_PASSTHRU] = "passthru", }; - dev = nm_platform_link_get_name (NM_PLATFORM_GET, parent); + dev = nm_platform_link_get_name (platform, parent); g_assert (dev); g_assert_cmpint (lnk->mode, <, G_N_ELEMENTS (modes)); @@ -890,17 +1116,18 @@ nmtstp_link_macvlan_add (gboolean external_command, modes[lnk->mode], lnk->no_promisc ? "nopromisc" : ""); if (success) - pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, link_type, 100); + pllink = nmtstp_assert_wait_for_link (platform, name, link_type, 100); } else - success = nm_platform_link_macvlan_add (NM_PLATFORM_GET, name, parent, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; + success = nm_platform_link_macvlan_add (platform, name, parent, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; - _assert_pllink (NM_PLATFORM_GET, success, pllink, name, link_type); + _assert_pllink (platform, success, pllink, name, link_type); return pllink; } const NMPlatformLink * -nmtstp_link_sit_add (gboolean external_command, +nmtstp_link_sit_add (NMPlatform *platform, + gboolean external_command, const char *name, const NMPlatformLnkSit *lnk) { @@ -912,13 +1139,15 @@ nmtstp_link_sit_add (gboolean external_command, external_command = nmtstp_run_command_check_external (external_command); + _init_platform (&platform, external_command); + if (external_command) { const char *dev = ""; if (lnk->parent_ifindex) { const char *parent_name; - parent_name = nm_platform_link_get_name (NM_PLATFORM_GET, lnk->parent_ifindex); + parent_name = nm_platform_link_get_name (platform, lnk->parent_ifindex); g_assert (parent_name); dev = nm_sprintf_bufa (100, " dev %s", parent_name); } @@ -932,17 +1161,18 @@ nmtstp_link_sit_add (gboolean external_command, lnk->tos, lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); if (success) - pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_SIT, 100); + pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_SIT, 100); } else - success = nm_platform_link_sit_add (NM_PLATFORM_GET, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; + success = nm_platform_link_sit_add (platform, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; - _assert_pllink (NM_PLATFORM_GET, success, pllink, name, NM_LINK_TYPE_SIT); + _assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_SIT); return pllink; } const NMPlatformLink * -nmtstp_link_vxlan_add (gboolean external_command, +nmtstp_link_vxlan_add (NMPlatform *platform, + gboolean external_command, const char *name, const NMPlatformLnkVxlan *lnk) { @@ -954,12 +1184,14 @@ nmtstp_link_vxlan_add (gboolean external_command, external_command = nmtstp_run_command_check_external (external_command); + _init_platform (&platform, external_command); + if (external_command) { gs_free char *dev = NULL; gs_free char *local = NULL, *remote = NULL; if (lnk->parent_ifindex) - dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (NM_PLATFORM_GET, lnk->parent_ifindex)); + dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex)); if (lnk->local) local = g_strdup_printf ("%s", nm_utils_inet4_ntop (lnk->local, NULL)); @@ -985,12 +1217,12 @@ nmtstp_link_vxlan_add (gboolean external_command, /* Older versions of iproute2 don't support adding vxlan devices. * On failure, fallback to using platform code. */ if (err == 0) - pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_VXLAN, 100); + pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_VXLAN, 100); else _LOGI ("Adding vxlan device via iproute2 failed. Assume iproute2 is not up to the task."); } if (!pllink) { - plerr = nm_platform_link_vxlan_add (NM_PLATFORM_GET, name, lnk, &pllink); + plerr = nm_platform_link_vxlan_add (platform, name, lnk, &pllink); g_assert_cmpint (plerr, ==, NM_PLATFORM_ERROR_SUCCESS); g_assert (pllink); } @@ -1000,168 +1232,7 @@ nmtstp_link_vxlan_add (gboolean external_command, return pllink; } -void -nmtstp_ip4_address_add (gboolean external_command, - int ifindex, - in_addr_t address, - int plen, - in_addr_t peer_address, - guint32 lifetime, - guint32 preferred, - guint32 flags, - const char *label) -{ - _ip_address_add (external_command, - TRUE, - ifindex, - (NMIPAddr *) &address, - plen, - (NMIPAddr *) &peer_address, - lifetime, - preferred, - flags, - label); -} - -void -nmtstp_ip6_address_add (gboolean external_command, - int ifindex, - struct in6_addr address, - int plen, - struct in6_addr peer_address, - guint32 lifetime, - guint32 preferred, - guint32 flags) -{ - _ip_address_add (external_command, - FALSE, - ifindex, - (NMIPAddr *) &address, - plen, - (NMIPAddr *) &peer_address, - lifetime, - preferred, - flags, - NULL); -} - -static void -_ip_address_del (gboolean external_command, - gboolean is_v4, - int ifindex, - const NMIPAddr *address, - int plen, - const NMIPAddr *peer_address) -{ - gint64 end_time; - - external_command = nmtstp_run_command_check_external (external_command); - - if (external_command) { - const char *ifname; - char b1[NM_UTILS_INET_ADDRSTRLEN], b2[NM_UTILS_INET_ADDRSTRLEN]; - int success; - gboolean had_address; - - ifname = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex); - g_assert (ifname); - - /* let's wait until we see the address as we added it. */ - if (is_v4) - had_address = !!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, address->addr4, plen, peer_address->addr4); - else - had_address = !!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, address->addr6, plen); - - if (is_v4) { - success = nmtstp_run_command ("ip address delete %s%s%s/%d dev %s", - nm_utils_inet4_ntop (address->addr4, b1), - peer_address->addr4 != address->addr4 ? " peer " : "", - peer_address->addr4 != address->addr4 ? nm_utils_inet4_ntop (peer_address->addr4, b2) : "", - plen, - ifname); - } else { - g_assert (!peer_address); - success = nmtstp_run_command ("ip address delete %s/%d dev %s", - nm_utils_inet6_ntop (&address->addr6, b1), - plen, - ifname); - } - g_assert (success == 0 || !had_address); - } else { - gboolean success; - - if (is_v4) { - success = nm_platform_ip4_address_delete (NM_PLATFORM_GET, - ifindex, - address->addr4, - plen, - peer_address->addr4); - } else { - g_assert (!peer_address); - success = nm_platform_ip6_address_delete (NM_PLATFORM_GET, - ifindex, - address->addr6, - plen); - } - g_assert (success); - } - - /* Let's wait until we get the result */ - end_time = nm_utils_get_monotonic_timestamp_ms () + 250; - do { - if (external_command) - nm_platform_process_events (NM_PLATFORM_GET); - - /* let's wait until we see the address as we added it. */ - if (is_v4) { - const NMPlatformIP4Address *a; - - a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, address->addr4, plen, peer_address->addr4); - if (!a) - break; - } else { - const NMPlatformIP6Address *a; - - a = nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, address->addr6, plen); - if (!a) - break; - } - - /* for internal command, we expect not to reach this line.*/ - g_assert (external_command); - - g_assert (nmtstp_wait_for_signal_until (NM_PLATFORM_GET, end_time)); - } while (TRUE); -} - -void -nmtstp_ip4_address_del (gboolean external_command, - int ifindex, - in_addr_t address, - int plen, - in_addr_t peer_address) -{ - _ip_address_del (external_command, - TRUE, - ifindex, - (NMIPAddr *) &address, - plen, - (NMIPAddr *) &peer_address); -} - -void -nmtstp_ip6_address_del (gboolean external_command, - int ifindex, - struct in6_addr address, - int plen) -{ - _ip_address_del (external_command, - FALSE, - ifindex, - (NMIPAddr *) &address, - plen, - NULL); -} +/*****************************************************************************/ const NMPlatformLink * nmtstp_link_get_typed (NMPlatform *platform, @@ -1171,8 +1242,7 @@ nmtstp_link_get_typed (NMPlatform *platform, { const NMPlatformLink *pllink = NULL; - if (!platform) - platform = NM_PLATFORM_GET; + _init_platform (&platform, FALSE); if (ifindex > 0) { pllink = nm_platform_link_get (platform, ifindex); @@ -1210,8 +1280,11 @@ nmtstp_link_get (NMPlatform *platform, return nmtstp_link_get_typed (platform, ifindex, name, NM_LINK_TYPE_NONE); } +/*****************************************************************************/ + void -nmtstp_link_del (gboolean external_command, +nmtstp_link_del (NMPlatform *platform, + gboolean external_command, int ifindex, const char *name) { @@ -1220,19 +1293,21 @@ nmtstp_link_del (gboolean external_command, gboolean success; gs_free char *name_copy = NULL; - pllink = nmtstp_link_get (NM_PLATFORM_GET, ifindex, name); + external_command = nmtstp_run_command_check_external (external_command); + + _init_platform (&platform, external_command); + + pllink = nmtstp_link_get (platform, ifindex, name); g_assert (pllink); name = name_copy = g_strdup (pllink->name); ifindex = pllink->ifindex; - external_command = nmtstp_run_command_check_external (external_command); - if (external_command) { nmtstp_run_command_check ("ip link delete %s", name); } else { - success = nm_platform_link_delete (NM_PLATFORM_GET, ifindex); + success = nm_platform_link_delete (platform, ifindex); g_assert (success); } @@ -1240,22 +1315,25 @@ nmtstp_link_del (gboolean external_command, end_time = nm_utils_get_monotonic_timestamp_ms () + 250; do { if (external_command) - nm_platform_process_events (NM_PLATFORM_GET); + nm_platform_process_events (platform); - if (!nm_platform_link_get (NM_PLATFORM_GET, ifindex)) { - g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, name)); + if (!nm_platform_link_get (platform, ifindex)) { + g_assert (!nm_platform_link_get_by_ifname (platform, name)); break; } /* for internal command, we expect not to reach this line.*/ g_assert (external_command); - g_assert (nmtstp_wait_for_signal_until (NM_PLATFORM_GET, end_time)); + nmtstp_assert_wait_for_signal_until (platform, end_time); } while (TRUE); } +/*****************************************************************************/ + void -nmtstp_link_set_updown (gboolean external_command, +nmtstp_link_set_updown (NMPlatform *platform, + gboolean external_command, int ifindex, gboolean up) { @@ -1264,10 +1342,12 @@ nmtstp_link_set_updown (gboolean external_command, external_command = nmtstp_run_command_check_external (external_command); + _init_platform (&platform, external_command); + if (external_command) { const char *ifname; - ifname = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex); + ifname = nm_platform_link_get_name (platform, ifindex); g_assert (ifname); nmtstp_run_command_check ("ip link set %s %s", @@ -1275,19 +1355,19 @@ nmtstp_link_set_updown (gboolean external_command, up ? "up" : "down"); } else { if (up) - g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, ifindex, NULL)); + g_assert (nm_platform_link_set_up (platform, ifindex, NULL)); else - g_assert (nm_platform_link_set_down (NM_PLATFORM_GET, ifindex)); + g_assert (nm_platform_link_set_down (platform, ifindex)); } /* Let's wait until we get the result */ end_time = nm_utils_get_monotonic_timestamp_ms () + 250; do { if (external_command) - nm_platform_process_events (NM_PLATFORM_GET); + nm_platform_process_events (platform); /* let's wait until we see the address as we added it. */ - plink = nm_platform_link_get (NM_PLATFORM_GET, ifindex); + plink = nm_platform_link_get (platform, ifindex); g_assert (plink); if (NM_FLAGS_HAS (plink->n_ifi_flags, IFF_UP) == !!up) @@ -1296,7 +1376,7 @@ nmtstp_link_set_updown (gboolean external_command, /* for internal command, we expect not to reach this line.*/ g_assert (external_command); - g_assert (nmtstp_wait_for_signal_until (NM_PLATFORM_GET, end_time)); + nmtstp_assert_wait_for_signal_until (platform, end_time); } while (TRUE); } @@ -1513,7 +1593,7 @@ main (int argc, char **argv) int result; const char *program = *argv; - init_tests (&argc, &argv); + _nmtstp_init_tests (&argc, &argv); if ( nmtstp_is_root_test () && (geteuid () != 0 || getegid () != 0)) { @@ -1571,7 +1651,7 @@ main (int argc, char **argv) SETUP (); - setup_tests (); + _nmtstp_setup_tests (); result = g_test_run (); diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index 825611934c..0e3cf10ba4 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -4,7 +4,6 @@ #include #include -#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); diff --git a/src/platform/tests/test-general.c b/src/platform/tests/test-general.c index 66f72fa570..d8d925614b 100644 --- a/src/platform/tests/test-general.c +++ b/src/platform/tests/test-general.c @@ -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); } diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 94695edcd1..9d548aabdb 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -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)); diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index 85851854ea..a50392a66f 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -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); diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c index 18a28690e0..89a7addf84 100644 --- a/src/ppp-manager/nm-ppp-manager.c +++ b/src/ppp-manager/nm-ppp-manager.c @@ -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)) { diff --git a/src/tests/test-general.c b/src/tests/test-general.c index b25125904b..a45357e810 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -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); diff --git a/src/tests/test-ip4-config.c b/src/tests/test-ip4-config.c index 2b743c8c3c..9d38dc27b7 100644 --- a/src/tests/test-ip4-config.c +++ b/src/tests/test-ip4-config.c @@ -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); diff --git a/src/tests/test-route-manager.c b/src/tests/test-route-manager.c index b32775da6c..c753174d8e 100644 --- a/src/tests/test-route-manager.c +++ b/src/tests/test-route-manager.c @@ -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); diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index cbc7c69d34..2945ad34ad 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -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);