summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-11-13 11:50:44 +0100
committerThomas Haller <thaller@redhat.com>2017-11-13 11:51:08 +0100
commitd44a3eb80caeeccc3f34c2c2a1b69828f0ef75aa (patch)
tree14030512f24f23aa549a208dc5702a77a5a62e8c
parenta33baf8bf7e66d95bf9678c0c66ca869006c3b0f (diff)
parentcb47ed0fcdddf7a6b13514a117b5566ffbdd4eda (diff)
downloadNetworkManager-d44a3eb80caeeccc3f34c2c2a1b69828f0ef75aa.tar.gz
all: merge branch 'th/platform-routes-onlink-rh1428334'
https://bugzilla.redhat.com/show_bug.cgi?id=1428334
-rw-r--r--Makefile.am1
-rw-r--r--configure.ac16
-rw-r--r--libnm-core/nm-setting-ip-config.c1
-rw-r--r--libnm-core/nm-setting-ip-config.h1
-rw-r--r--shared/nm-utils/nm-macros-internal.h39
-rw-r--r--shared/nm-utils/nm-shared-utils.h47
-rw-r--r--src/devices/nm-device.c4
-rw-r--r--src/devices/nm-device.h2
-rw-r--r--src/nm-ip4-config.c110
-rw-r--r--src/nm-ip4-config.h75
-rw-r--r--src/nm-ip6-config.c64
-rw-r--r--src/platform/nm-linux-platform.c18
-rw-r--r--src/platform/nm-platform.c67
-rw-r--r--src/platform/nm-platform.h39
-rw-r--r--src/platform/nmp-object.c3
-rw-r--r--src/platform/tests/test-route.c204
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c95
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c7
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected20
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes6
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c49
-rw-r--r--src/tests/test-ip4-config.c2
22 files changed, 572 insertions, 298 deletions
diff --git a/Makefile.am b/Makefile.am
index af1d445d86..eafc8ca54d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2104,6 +2104,7 @@ EXTRA_DIST += \
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected \
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected \
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected \
+ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected \
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected \
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected \
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected \
diff --git a/configure.ac b/configure.ac
index ad188a7763..a2405c625b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1227,6 +1227,22 @@ fi
AC_SUBST(SANITIZERS, [$sanitizers])
+AC_MSG_CHECKING([CC support C11 _Generic()])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[int foo(void); int foo() { int a = 0; int b = _Generic (a, int: 4); return b + a; }]],
+ [[foo();]])],
+ [cc_support_generic=1],
+ [cc_support_generic=0])
+AC_MSG_RESULT($cc_support_generic)
+AC_DEFINE_UNQUOTED(_NM_CC_SUPPORT_GENERIC, $cc_support_generic, [Define whether the compiler supports C11 _Generic()])
+
+AC_MSG_CHECKING([CC support gcc __auto_type])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[int foo(void); int foo() { int a = 0; __auto_type b = a; return b + a; }]],
+ [[foo();]])],
+ [cc_support_auto_type=1],
+ [cc_support_auto_type=0])
+AC_MSG_RESULT($cc_support_auto_type)
+AC_DEFINE_UNQUOTED(_NM_CC_SUPPORT_AUTO_TYPE, $cc_support_auto_type, [Define whether the compiler support gcc __auto_type])
+
dnl -------------------------
dnl Vala bindings
dnl -------------------------
diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c
index 7265fdc51e..41ae0993f6 100644
--- a/libnm-core/nm-setting-ip-config.c
+++ b/libnm-core/nm-setting-ip-config.c
@@ -1245,6 +1245,7 @@ static const NMVariantAttributeSpec * const ip_route_attribute_spec[] = {
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a'),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_FROM, G_VARIANT_TYPE_STRING, FALSE, TRUE, 'p'),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, TRUE, FALSE, 0 ),
+ ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_ONLINK, G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_CWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h
index 84ce84657a..96e61bb5c9 100644
--- a/libnm-core/nm-setting-ip-config.h
+++ b/libnm-core/nm-setting-ip-config.h
@@ -146,6 +146,7 @@ gboolean nm_ip_route_attribute_validate (const char *name,
#define NM_IP_ROUTE_ATTRIBUTE_SRC "src"
#define NM_IP_ROUTE_ATTRIBUTE_FROM "from"
#define NM_IP_ROUTE_ATTRIBUTE_TOS "tos"
+#define NM_IP_ROUTE_ATTRIBUTE_ONLINK "onlink"
#define NM_IP_ROUTE_ATTRIBUTE_WINDOW "window"
#define NM_IP_ROUTE_ATTRIBUTE_CWND "cwnd"
#define NM_IP_ROUTE_ATTRIBUTE_INITCWND "initcwnd"
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h
index d07e298ea2..2d62ba7d97 100644
--- a/shared/nm-utils/nm-macros-internal.h
+++ b/shared/nm-utils/nm-macros-internal.h
@@ -263,11 +263,25 @@ NM_G_ERROR_MSG (GError *error)
/*****************************************************************************/
-#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 9 ))) || (defined (__clang__))
+#ifndef _NM_CC_SUPPORT_AUTO_TYPE
+#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9 )))
+#define _NM_CC_SUPPORT_AUTO_TYPE 1
+#else
+#define _NM_CC_SUPPORT_AUTO_TYPE 0
+#endif
+#endif
+
+#ifndef _NM_CC_SUPPORT_GENERIC
+#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9 ))) || (defined (__clang__))
#define _NM_CC_SUPPORT_GENERIC 1
#else
#define _NM_CC_SUPPORT_GENERIC 0
#endif
+#endif
+
+#if _NM_CC_SUPPORT_AUTO_TYPE
+#define _nm_auto_type __auto_type
+#endif
#if _NM_CC_SUPPORT_GENERIC
#define _NM_CONSTCAST_FULL_1(type, obj_expr, obj) \
@@ -372,6 +386,16 @@ NM_G_ERROR_MSG (GError *error)
#define _NM_ENSURE_TYPE(type, value) (value)
#endif
+#if _NM_CC_SUPPORT_GENERIC
+#define NM_PROPAGATE_CONST(test_expr, ptr) \
+ (_Generic ((test_expr), \
+ const typeof (*(test_expr)) *: ((const typeof (*(ptr)) *) (ptr)), \
+ default: (_Generic ((test_expr), \
+ typeof (*(test_expr)) *: (ptr)))))
+#else
+#define NM_PROPAGATE_CONST(test_expr, ptr) (ptr)
+#endif
+
/*****************************************************************************/
#define _NM_IN_SET_EVAL_1( op, _x, y) (_x == (y))
@@ -651,8 +675,17 @@ _notify (obj_type *obj, _PropertyEnums prop) \
/*****************************************************************************/
-#define _NM_GET_PRIVATE( self, type, is_check, ...) (&(NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv))
-#define _NM_GET_PRIVATE_PTR( self, type, is_check, ...) ( (NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv))
+#define _NM_GET_PRIVATE(self, type, is_check, ...) (&(NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv))
+#if _NM_CC_SUPPORT_AUTO_TYPE
+#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) \
+ ({ \
+ _nm_auto_type _self = NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__); \
+ \
+ NM_PROPAGATE_CONST (_self, _self->_priv); \
+ })
+#else
+#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) (NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv)
+#endif
/*****************************************************************************/
diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h
index 96aab5341e..a092a6b780 100644
--- a/shared/nm-utils/nm-shared-utils.h
+++ b/shared/nm-utils/nm-shared-utils.h
@@ -26,23 +26,6 @@
/*****************************************************************************/
-typedef struct {
- union {
- guint8 addr_ptr[1];
- in_addr_t addr4;
- struct in6_addr addr6;
-
- /* NMIPAddr is really a union for IP addresses.
- * However, as ethernet addresses fit in here nicely, use
- * it also for an ethernet MAC address. */
- guint8 addr_eth[6 /*ETH_ALEN*/];
- };
-} NMIPAddr;
-
-extern const NMIPAddr nm_ip_addr_zero;
-
-/*****************************************************************************/
-
static inline char
nm_utils_addr_family_to_char (int addr_family)
{
@@ -68,6 +51,36 @@ nm_utils_addr_family_to_size (int addr_family)
/*****************************************************************************/
+typedef struct {
+ union {
+ guint8 addr_ptr[1];
+ in_addr_t addr4;
+ struct in6_addr addr6;
+
+ /* NMIPAddr is really a union for IP addresses.
+ * However, as ethernet addresses fit in here nicely, use
+ * it also for an ethernet MAC address. */
+ guint8 addr_eth[6 /*ETH_ALEN*/];
+ };
+} NMIPAddr;
+
+extern const NMIPAddr nm_ip_addr_zero;
+
+static inline void
+nm_ip_addr_set (int addr_family, gpointer dst, const NMIPAddr *src)
+{
+ nm_assert_addr_family (addr_family);
+ nm_assert (dst);
+ nm_assert (src);
+
+ if (addr_family != AF_INET6)
+ *((in_addr_t *) dst) = src->addr4;
+ else
+ *((struct in6_addr *) dst) = src->addr6;
+}
+
+/*****************************************************************************/
+
#define NM_CMP_RETURN(c) \
G_STMT_START { \
const int _cc = (c); \
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 010172dc06..1fe6f064da 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -1164,9 +1164,9 @@ nm_device_get_ip_iface (NMDevice *self)
}
int
-nm_device_get_ip_ifindex (NMDevice *self)
+nm_device_get_ip_ifindex (const NMDevice *self)
{
- NMDevicePrivate *priv;
+ const NMDevicePrivate *priv;
g_return_val_if_fail (self != NULL, 0);
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index bd8104b4bf..b0d299e4ea 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -438,7 +438,7 @@ int nm_device_get_ifindex (NMDevice *dev);
gboolean nm_device_is_software (NMDevice *dev);
gboolean nm_device_is_real (NMDevice *dev);
const char * nm_device_get_ip_iface (NMDevice *dev);
-int nm_device_get_ip_ifindex (NMDevice *dev);
+int nm_device_get_ip_ifindex (const NMDevice *dev);
const char * nm_device_get_driver (NMDevice *dev);
const char * nm_device_get_driver_version (NMDevice *dev);
const char * nm_device_get_type_desc (NMDevice *dev);
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index 06137764f5..94f4a28e15 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -806,44 +806,87 @@ nm_ip4_config_commit (const NMIP4Config *self,
return success;
}
-static void
-merge_route_attributes (NMIPRoute *s_route,
- NMPlatformIP4Route *r,
- guint32 route_table)
+void
+_nm_ip_config_merge_route_attributes (int addr_family,
+ NMIPRoute *s_route,
+ NMPlatformIPRoute *r,
+ guint32 route_table)
{
GVariant *variant;
- guint32 u32;
- in_addr_t addr;
-
-#define GET_ATTR(name, field, variant_type, type) \
- variant = nm_ip_route_get_attribute (s_route, name); \
- if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_ ## variant_type)) \
- r->field = g_variant_get_ ## type (variant);
-
- variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_TABLE);
- u32 = variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32)
- ? g_variant_get_uint32 (variant)
- : 0;
- r->table_coerced = nm_platform_route_table_coerce (u32 ?: (route_table ?: RT_TABLE_MAIN));
-
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TOS, tos, BYTE, byte);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, window, UINT32, uint32);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_CWND, cwnd, UINT32, uint32);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, initcwnd, UINT32, uint32);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITRWND, initrwnd, UINT32, uint32);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_MTU, mtu, UINT32, uint32);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, lock_window, BOOLEAN, boolean);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, lock_cwnd, BOOLEAN, boolean);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, lock_initcwnd, BOOLEAN, boolean);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, lock_initrwnd, BOOLEAN, boolean);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, lock_mtu, BOOLEAN, boolean);
+ guint32 table;
+ NMIPAddr addr;
+ NMPlatformIP4Route *r4 = (NMPlatformIP4Route *) r;
+ NMPlatformIP6Route *r6 = (NMPlatformIP6Route *) r;
+ gboolean onlink;
+
+ nm_assert (s_route);
+ nm_assert_addr_family (addr_family);
+ nm_assert (r);
+
+#define GET_ATTR(name, dst, variant_type, type, dflt) \
+ G_STMT_START { \
+ GVariant *_variant = nm_ip_route_get_attribute (s_route, ""name""); \
+ \
+ if ( _variant \
+ && g_variant_is_of_type (_variant, G_VARIANT_TYPE_ ## variant_type)) \
+ (dst) = g_variant_get_ ## type (_variant); \
+ else \
+ (dst) = (dflt); \
+ } G_STMT_END
+
+ GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, table, UINT32, uint32, 0);
+ r->table_coerced = nm_platform_route_table_coerce (table ?: (route_table ?: RT_TABLE_MAIN));
+
+ if (addr_family == AF_INET) {
+ GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TOS, r4->tos, BYTE, byte, 0);
+ GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_ONLINK, onlink, BOOLEAN, boolean, FALSE);
+ } else
+ onlink = FALSE;
+
+ r->r_rtm_flags = 0;
+ if (onlink)
+ r->r_rtm_flags = RTNH_F_ONLINK;
+
+ GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, r->window, UINT32, uint32, 0);
+ GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_CWND, r->cwnd, UINT32, uint32, 0);
+ GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, r->initcwnd, UINT32, uint32, 0);
+ GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITRWND, r->initrwnd, UINT32, uint32, 0);
+ GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_MTU, r->mtu, UINT32, uint32, 0);
+ GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, r->lock_window, BOOLEAN, boolean, FALSE);
+ GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, r->lock_cwnd, BOOLEAN, boolean, FALSE);
+ GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, r->lock_initcwnd, BOOLEAN, boolean, FALSE);
+ GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, r->lock_initrwnd, BOOLEAN, boolean, FALSE);
+ GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, r->lock_mtu, BOOLEAN, boolean, FALSE);
if ( (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_SRC))
&& g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
- if (inet_pton (AF_INET, g_variant_get_string (variant, NULL), &addr) == 1)
- r->pref_src = addr;
+ if (inet_pton (addr_family, g_variant_get_string (variant, NULL), &addr) == 1) {
+ if (addr_family == AF_INET)
+ r4->pref_src = addr.addr4;
+ else
+ r6->pref_src = addr.addr6;
+ }
}
+ if ( addr_family == AF_INET6
+ && (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_FROM))
+ && g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
+ gs_free char *string = NULL;
+ guint8 plen = 128;
+ char *sep;
+
+ string = g_variant_dup_string (variant, NULL);
+ sep = strchr (string, '/');
+ if (sep) {
+ *sep = 0;
+ plen = _nm_utils_ascii_str_to_int64 (sep + 1, 10, 1, 128, 255);
+ }
+ if ( plen <= 128
+ && inet_pton (AF_INET6, string, &addr) == 1) {
+ r6->src = addr.addr6;
+ r6->src_plen = plen;
+ }
+ }
#undef GET_ATTR
}
@@ -939,7 +982,10 @@ nm_ip4_config_merge_setting (NMIP4Config *self,
route.network = nm_utils_ip4_address_clear_host_address (route.network, route.plen);
- merge_route_attributes (s_route, &route, route_table);
+ _nm_ip_config_merge_route_attributes (AF_INET,
+ s_route,
+ NM_PLATFORM_IP_ROUTE_CAST (&route),
+ route_table);
_add_route (self, NULL, &route, NULL);
}
diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h
index e7fb2703eb..7c345d2052 100644
--- a/src/nm-ip4-config.h
+++ b/src/nm-ip4-config.h
@@ -113,6 +113,11 @@ const NMDedupMultiEntry *_nm_ip_config_lookup_ip_route (const NMDedupMultiIndex
const NMPObject *needle,
NMPlatformIPRouteCmpType cmp_type);
+void _nm_ip_config_merge_route_attributes (int addr_family,
+ NMIPRoute *s_route,
+ NMPlatformIPRoute *r,
+ guint32 route_table);
+
/*****************************************************************************/
#define NM_TYPE_IP4_CONFIG (nm_ip4_config_get_type ())
@@ -272,40 +277,56 @@ gboolean nm_ip4_config_equal (const NMIP4Config *a, const NMIP4Config *b);
#include "nm-ip6-config.h"
+static inline gboolean
+NM_IS_IP_CONFIG (gconstpointer config)
+{
+ return NM_IS_IP4_CONFIG (config) || NM_IS_IP6_CONFIG (config);
+}
+
#if _NM_CC_SUPPORT_GENERIC
-#define NM_IP_CONFIG_CAST(config) \
+/* _NM_IS_IP_CONFIG() is a bit unusual. If _Generic() is supported,
+ * it checks whether @config is either NM_IS_IP4_CONFIG() or NM_IS_IP6_CONFIG(),
+ * depending on the pointer type of @config.
+ *
+ * For example, with _Generic() support, the following assertions would fail:
+ * NMIP6Config *ptr = (NMIP6Config *) nm_ip4_config_new(...);
+ * g_assert (_NM_IS_IP_CONFIG (ptr, ptr));
+ * but the following would pass:
+ * NMIP4Config *ptr = nm_ip4_config_new(...);
+ * g_assert (_NM_IS_IP_CONFIG (ptr, ptr));
+ */
+#define _NM_IS_IP_CONFIG(typeexpr, config) \
({ \
const void *const _config = (config); \
- \
- nm_assert (_Generic ((config), \
- const void *: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- void *: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- const NMIPConfig *: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- NMIPConfig *: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- const NMIP4Config *: (NM_IS_IP4_CONFIG (_config)), \
- NMIP4Config *: (NM_IS_IP4_CONFIG (_config)), \
- const NMIP6Config *: (NM_IS_IP6_CONFIG (_config)), \
- NMIP6Config *: (NM_IS_IP6_CONFIG (_config)))); \
- \
- _Generic ((config), \
- const void *: ((const NMIPConfig *) _config), \
- void *: (( NMIPConfig *) _config), \
- const NMIPConfig *: ((const NMIPConfig *) _config), \
- NMIPConfig *: (( NMIPConfig *) _config), \
- const NMIP4Config *: ((const NMIPConfig *) _config), \
- NMIP4Config *: (( NMIPConfig *) _config), \
- const NMIP6Config *: ((const NMIPConfig *) _config), \
- NMIP6Config *: (( NMIPConfig *) _config)); \
+ _Generic ((typeexpr), \
+ const void *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
+ const void * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
+ void *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
+ void * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
+ const NMIPConfig *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
+ const NMIPConfig * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
+ NMIPConfig *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
+ NMIPConfig * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
+ const NMIP4Config *const: (NM_IS_IP4_CONFIG (_config)), \
+ const NMIP4Config * : (NM_IS_IP4_CONFIG (_config)), \
+ NMIP4Config *const: (NM_IS_IP4_CONFIG (_config)), \
+ NMIP4Config * : (NM_IS_IP4_CONFIG (_config)), \
+ const NMIP6Config *const: (NM_IS_IP6_CONFIG (_config)), \
+ const NMIP6Config * : (NM_IS_IP6_CONFIG (_config)), \
+ NMIP6Config *const: (NM_IS_IP6_CONFIG (_config)), \
+ NMIP6Config * : (NM_IS_IP6_CONFIG (_config))); \
})
#else
-#define NM_IP_CONFIG_CAST(config) ((NMIPConfig *) (config))
+#define _NM_IS_IP_CONFIG(typeexpr, config) NM_IS_IP_CONFIG(config)
#endif
-static inline gboolean
-NM_IS_IP_CONFIG (gconstpointer config)
-{
- return NM_IS_IP4_CONFIG (config) || NM_IS_IP6_CONFIG (config);
-}
+#define NM_IP_CONFIG_CAST(config) \
+ ({ \
+ const void *const _configx = (config); \
+ \
+ nm_assert (!_configx || _NM_IS_IP_CONFIG ((config), _configx)); \
+ NM_CONSTCAST_FULL (NMIPConfig, (config), _configx, NMIP4Config, NMIP6Config); \
+ })
static inline int
nm_ip_config_get_addr_family (const NMIPConfig *config)
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index 3f0bbfe75c..28841e3434 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -571,65 +571,6 @@ nm_ip6_config_commit (const NMIP6Config *self,
return success;
}
-static void
-merge_route_attributes (NMIPRoute *s_route,
- NMPlatformIP6Route *r,
- guint32 route_table)
-{
- GVariant *variant;
- guint32 u32;
- struct in6_addr addr;
-
-#define GET_ATTR(name, field, variant_type, type) \
- variant = nm_ip_route_get_attribute (s_route, name); \
- if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_ ## variant_type)) \
- r->field = g_variant_get_ ## type (variant);
-
- variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_TABLE);
- u32 = variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32)
- ? g_variant_get_uint32 (variant)
- : 0;
- r->table_coerced = nm_platform_route_table_coerce (u32 ?: (route_table ?: RT_TABLE_MAIN));
-
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, window, UINT32, uint32);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_CWND, cwnd, UINT32, uint32);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, initcwnd, UINT32, uint32);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITRWND, initrwnd, UINT32, uint32);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_MTU, mtu, UINT32, uint32);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, lock_window, BOOLEAN, boolean);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, lock_cwnd, BOOLEAN, boolean);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, lock_initcwnd, BOOLEAN, boolean);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, lock_initrwnd, BOOLEAN, boolean);
- GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, lock_mtu, BOOLEAN, boolean);
-
-
- if ( (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_SRC))
- && g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
- if (inet_pton (AF_INET6, g_variant_get_string (variant, NULL), &addr) == 1)
- r->pref_src = addr;
- }
-
- if ( (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_FROM))
- && g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
- gs_free char *string = NULL;
- guint8 plen = 128;
- char *sep;
-
- string = g_variant_dup_string (variant, NULL);
- sep = strchr (string, '/');
- if (sep) {
- *sep = 0;
- plen = _nm_utils_ascii_str_to_int64 (sep + 1, 10, 1, 128, 255);
- }
- if ( plen <= 128
- && inet_pton (AF_INET6, string, &addr) == 1) {
- r->src = addr;
- r->src_plen = plen;
- }
- }
-#undef GET_ATTR
-}
-
void
nm_ip6_config_merge_setting (NMIP6Config *self,
NMSettingIPConfig *setting,
@@ -716,7 +657,10 @@ nm_ip6_config_merge_setting (NMIP6Config *self,
nm_utils_ip6_address_clear_host_address (&route.network, &route.network, route.plen);
- merge_route_attributes (s_route, &route, route_table);
+ _nm_ip_config_merge_route_attributes (AF_INET,
+ s_route,
+ NM_PLATFORM_IP_ROUTE_CAST (&route),
+ route_table);
_add_route (self, NULL, &route, NULL);
}
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 9efdd41327..46b7bd209e 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -2291,17 +2291,7 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
obj->ip6_route.rt_pref = nla_get_u8 (tb[RTA_PREF]);
}
- if (NM_FLAGS_HAS (rtm->rtm_flags, RTM_F_CLONED)) {
- /* we must not straight way reject cloned routes, because we might have cached
- * a non-cloned route. If we now receive an update of the route with the route
- * being cloned, we must still return the object, so that we can remove the old
- * one from the cache.
- *
- * This happens, because this route is not nmp_object_is_alive().
- * */
- obj->ip_route.rt_cloned = TRUE;
- }
-
+ obj->ip_route.r_rtm_flags = rtm->rtm_flags;
obj->ip_route.rt_source = nmp_utils_ip_config_source_from_rtprot (rtm->rtm_protocol);
obj_result = obj;
@@ -2700,7 +2690,9 @@ _nl_msg_new_route (int nlmsg_type,
? nm_platform_route_scope_inv (obj->ip4_route.scope_inv)
: RT_SCOPE_NOWHERE,
.rtm_type = RTN_UNICAST,
- .rtm_flags = 0,
+ .rtm_flags = obj->ip_route.r_rtm_flags & (is_v4
+ ? (unsigned) (RTNH_F_ONLINK)
+ : (unsigned) 0),
.rtm_dst_len = obj->ip_route.plen,
.rtm_src_len = is_v4
? 0
@@ -4189,7 +4181,7 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event
gboolean resync_required = FALSE;
gboolean only_dirty = FALSE;
- if (obj->ip_route.rt_cloned) {
+ if (NM_FLAGS_HAS (obj->ip_route.r_rtm_flags, RTM_F_CLONED)) {
/* a cloned route might be a response for RTM_GETROUTE. Check, whether it is. */
nm_assert (!nmp_object_is_alive (obj));
priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index ffc4b3956d..f94d93e257 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -4976,6 +4976,40 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *bu
return buf;
}
+NM_UTILS_FLAGS2STR_DEFINE_STATIC (_rtm_flags_to_string, unsigned,
+ NM_UTILS_FLAGS2STR (RTNH_F_DEAD, "dead"),
+ NM_UTILS_FLAGS2STR (RTNH_F_PERVASIVE, "pervasive"),
+ NM_UTILS_FLAGS2STR (RTNH_F_ONLINK, "onlink"),
+ NM_UTILS_FLAGS2STR (8 /*RTNH_F_OFFLOAD*/, "offload"),
+ NM_UTILS_FLAGS2STR (16 /*RTNH_F_LINKDOWN*/, "linkdown"),
+ NM_UTILS_FLAGS2STR (32 /*RTNH_F_UNRESOLVED*/, "unresolved"),
+
+ NM_UTILS_FLAGS2STR (RTM_F_NOTIFY, "notify"),
+ NM_UTILS_FLAGS2STR (RTM_F_CLONED, "cloned"),
+ NM_UTILS_FLAGS2STR (RTM_F_EQUALIZE, "equalize"),
+ NM_UTILS_FLAGS2STR (RTM_F_PREFIX, "prefix"),
+ NM_UTILS_FLAGS2STR (0x1000 /*RTM_F_LOOKUP_TABLE*/, "lookup-table"),
+ NM_UTILS_FLAGS2STR (0x2000 /*RTM_F_FIB_MATCH*/, "fib-match"),
+);
+
+#define _RTM_FLAGS_TO_STRING_MAXLEN 200
+
+static const char *
+_rtm_flags_to_string_full (char *buf, gsize buf_size, unsigned rtm_flags)
+{
+ const char *buf0 = buf;
+
+ nm_assert (buf_size >= _RTM_FLAGS_TO_STRING_MAXLEN);
+
+ if (!rtm_flags)
+ return "";
+
+ nm_utils_strbuf_append_str (&buf, &buf_size, " rtm_flags ");
+ _rtm_flags_to_string (rtm_flags, buf, buf_size);
+ nm_assert (strlen (buf) < buf_size);
+ return buf0;
+}
+
/**
* nm_platform_ip4_route_to_string:
* @route: pointer to NMPlatformIP4Route route structure
@@ -4997,6 +5031,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
char str_table[30];
char str_scope[30], s_source[50];
char str_tos[32], str_window[32], str_cwnd[32], str_initcwnd[32], str_initrwnd[32], str_mtu[32];
+ char str_rtm_flags[_RTM_FLAGS_TO_STRING_MAXLEN];
if (!nm_utils_to_string_buffer_init_null (route, &buf, &len))
return buf;
@@ -5015,7 +5050,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
" metric %"G_GUINT32_FORMAT
" mss %"G_GUINT32_FORMAT
" rt-src %s" /* protocol */
- "%s" /* cloned */
+ "%s" /* rtm_flags */
"%s%s" /* scope */
"%s%s" /* pref-src */
"%s" /* tos */
@@ -5033,7 +5068,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
route->metric,
route->mss,
nmp_utils_ip_config_source_to_string (route->rt_source, s_source, sizeof (s_source)),
- route->rt_cloned ? " cloned" : "",
+ _rtm_flags_to_string_full (str_rtm_flags, sizeof (str_rtm_flags), route->r_rtm_flags),
route->scope_inv ? " scope " : "",
route->scope_inv ? (nm_platform_route_scope2str (nm_platform_route_scope_inv (route->scope_inv), str_scope, sizeof (str_scope))) : "",
route->pref_src ? " pref-src " : "",
@@ -5069,6 +5104,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
char str_pref2[30];
char str_dev[TO_STRING_DEV_BUF_SIZE], s_source[50];
char str_window[32], str_cwnd[32], str_initcwnd[32], str_initrwnd[32], str_mtu[32];
+ char str_rtm_flags[_RTM_FLAGS_TO_STRING_MAXLEN];
if (!nm_utils_to_string_buffer_init_null (route, &buf, &len))
return buf;
@@ -5092,7 +5128,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
" mss %"G_GUINT32_FORMAT
" rt-src %s" /* protocol */
"%s" /* source */
- "%s" /* cloned */
+ "%s" /* rtm_flags */
"%s%s" /* pref-src */
"%s" /* window */
"%s" /* cwnd */
@@ -5112,7 +5148,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
route->src_plen || !IN6_IS_ADDR_UNSPECIFIED (&route->src)
? nm_sprintf_buf (s_src_all, " src %s/%u", nm_utils_inet6_ntop (&route->src, s_src), (unsigned) route->src_plen)
: "",
- route->rt_cloned ? " cloned" : "",
+ _rtm_flags_to_string_full (str_rtm_flags, sizeof (str_rtm_flags), route->r_rtm_flags),
s_pref_src[0] ? " pref-src " : "",
s_pref_src[0] ? s_pref_src : "",
route->window || route->lock_window ? nm_sprintf_buf (str_window, " window %s%"G_GUINT32_FORMAT, route->lock_window ? "lock " : "", route->window) : "",
@@ -5538,6 +5574,7 @@ nm_platform_ip4_route_hash_update (const NMPlatformIP4Route *obj, NMPlatformIPRo
obj->initcwnd,
obj->initrwnd,
obj->mtu,
+ obj->r_rtm_flags & RTNH_F_ONLINK,
NM_HASH_COMBINE_BOOLS (guint8,
obj->lock_window,
obj->lock_cwnd,
@@ -5563,8 +5600,8 @@ nm_platform_ip4_route_hash_update (const NMPlatformIP4Route *obj, NMPlatformIPRo
obj->initcwnd,
obj->initrwnd,
obj->mtu,
+ obj->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK),
NM_HASH_COMBINE_BOOLS (guint8,
- obj->rt_cloned,
obj->lock_window,
obj->lock_cwnd,
obj->lock_initcwnd,
@@ -5589,8 +5626,8 @@ nm_platform_ip4_route_hash_update (const NMPlatformIP4Route *obj, NMPlatformIPRo
obj->initcwnd,
obj->initrwnd,
obj->mtu,
+ obj->r_rtm_flags,
NM_HASH_COMBINE_BOOLS (guint8,
- obj->rt_cloned,
obj->lock_window,
obj->lock_cwnd,
obj->lock_initcwnd,
@@ -5627,6 +5664,8 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route
NM_CMP_FIELD (a, b, initcwnd);
NM_CMP_FIELD (a, b, initrwnd);
NM_CMP_FIELD (a, b, mtu);
+ NM_CMP_DIRECT (a->r_rtm_flags & RTNH_F_ONLINK,
+ b->r_rtm_flags & RTNH_F_ONLINK);
NM_CMP_FIELD_UNSAFE (a, b, lock_window);
NM_CMP_FIELD_UNSAFE (a, b, lock_cwnd);
NM_CMP_FIELD_UNSAFE (a, b, lock_initcwnd);
@@ -5660,7 +5699,11 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route
}
NM_CMP_FIELD (a, b, mss);
NM_CMP_FIELD (a, b, pref_src);
- NM_CMP_FIELD_UNSAFE (a, b, rt_cloned);
+ if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) {
+ NM_CMP_DIRECT (a->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK),
+ b->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK));
+ } else
+ NM_CMP_FIELD (a, b, r_rtm_flags);
NM_CMP_FIELD (a, b, tos);
NM_CMP_FIELD_UNSAFE (a, b, lock_window);
NM_CMP_FIELD_UNSAFE (a, b, lock_cwnd);
@@ -5717,8 +5760,8 @@ nm_platform_ip6_route_hash_update (const NMPlatformIP6Route *obj, NMPlatformIPRo
obj->src_plen,
nmp_utils_ip_config_source_round_trip_rtprot (obj->rt_source),
obj->mss,
+ obj->r_rtm_flags & RTM_F_CLONED,
NM_HASH_COMBINE_BOOLS (guint8,
- obj->rt_cloned,
obj->lock_window,
obj->lock_cwnd,
obj->lock_initcwnd,
@@ -5744,8 +5787,8 @@ nm_platform_ip6_route_hash_update (const NMPlatformIP6Route *obj, NMPlatformIPRo
obj->src_plen,
obj->rt_source,
obj->mss,
+ obj->r_rtm_flags,
NM_HASH_COMBINE_BOOLS (guint8,
- obj->rt_cloned,
obj->lock_window,
obj->lock_cwnd,
obj->lock_initcwnd,
@@ -5810,7 +5853,11 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
NM_CMP_FIELD (a, b, rt_source);
}
NM_CMP_FIELD (a, b, mss);
- NM_CMP_FIELD_UNSAFE (a, b, rt_cloned);
+ if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) {
+ NM_CMP_DIRECT (a->r_rtm_flags & RTM_F_CLONED,
+ b->r_rtm_flags & RTM_F_CLONED);
+ } else
+ NM_CMP_FIELD (a, b, r_rtm_flags);
NM_CMP_FIELD_UNSAFE (a, b, lock_window);
NM_CMP_FIELD_UNSAFE (a, b, lock_cwnd);
NM_CMP_FIELD_UNSAFE (a, b, lock_initcwnd);
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index d155c1092e..3336642b8b 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -375,13 +375,6 @@ typedef union {
\
guint8 plen; \
\
- /* the route has rtm_flags set to RTM_F_CLONED. Such a route
- * is hidden by platform and does not exist from the point-of-view
- * of platform users. This flag is internal to track those hidden
- * routes. Such a route is not alive, according to nmp_object_is_alive(). */ \
- bool rt_cloned:1; \
- \
- \
/* RTA_METRICS:
*
* For IPv4 routes, these properties are part of their
@@ -401,6 +394,18 @@ typedef union {
bool lock_initrwnd:1; \
bool lock_mtu:1; \
\
+ /* rtnh_flags
+ *
+ * Routes with rtm_flags RTM_F_CLONED are hidden by platform and
+ * do not exist from the point-of-view of platform users.
+ * Such a route is not alive, according to nmp_object_is_alive().
+ *
+ * XXX: currently we ignore all flags except RTM_F_CLONED
+ * and RTNH_F_ONLINK for IPv4.
+ * We also may not properly consider the flags as part of the ID
+ * in route-cmp. */ \
+ unsigned r_rtm_flags; \
+ \
/* RTA_METRICS.RTAX_ADVMSS (iproute2: advmss) */ \
guint32 mss; \
\
@@ -441,23 +446,11 @@ typedef struct {
};
} NMPlatformIPRoute;
-#if _NM_CC_SUPPORT_GENERIC
-#define NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route) \
- (_Generic ((route), \
- const NMPlatformIPRoute *: ((const NMPlatformIPRoute *) (route))->plen, \
- NMPlatformIPRoute *: ((const NMPlatformIPRoute *) (route))->plen, \
- const NMPlatformIPXRoute *: ((const NMPlatformIPRoute *) (route))->plen, \
- NMPlatformIPXRoute *: ((const NMPlatformIPRoute *) (route))->plen, \
- const NMPlatformIP4Route *: ((const NMPlatformIPRoute *) (route))->plen, \
- NMPlatformIP4Route *: ((const NMPlatformIPRoute *) (route))->plen, \
- const NMPlatformIP6Route *: ((const NMPlatformIPRoute *) (route))->plen, \
- NMPlatformIP6Route *: ((const NMPlatformIPRoute *) (route))->plen, \
- const void *: ((const NMPlatformIPRoute *) (route))->plen, \
- void *: ((const NMPlatformIPRoute *) (route))->plen) == 0)
-#else
+#define NM_PLATFORM_IP_ROUTE_CAST(route) \
+ NM_CONSTCAST (NMPlatformIPRoute, (route), NMPlatformIPXRoute, NMPlatformIP4Route, NMPlatformIP6Route)
+
#define NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route) \
- ( ((const NMPlatformIPRoute *) (route))->plen <= 0 )
-#endif
+ (NM_PLATFORM_IP_ROUTE_CAST (route)->plen <= 0)
struct _NMPlatformIP4Route {
__NMPlatformIPRoute_COMMON;
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index a860070545..0c951dd4fc 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -1170,7 +1170,8 @@ _vt_cmd_obj_is_alive_ipx_route (const NMPObject *obj)
* Instead we create a dead object, and nmp_cache_update_netlink()
* will remove the old version of the update.
**/
- return obj->object.ifindex > 0 && !obj->ip_route.rt_cloned;
+ return obj->object.ifindex > 0
+ && !NM_FLAGS_HAS (obj->ip_route.r_rtm_flags, RTM_F_CLONED);
}
gboolean
diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c
index 2c00fadaab..04f4ff494a 100644
--- a/src/platform/tests/test-route.c
+++ b/src/platform/tests/test-route.c
@@ -31,6 +31,42 @@
#define EX NMTSTP_ENV1_EX
static void
+_wait_for_ipv4_addr_device_route (NMPlatform *platform,
+ gint64 timeout_ms,
+ int ifindex,
+ in_addr_t addr,
+ guint8 plen)
+{
+ /* Wait that the addresses gets a device-route. After adding a address,
+ * the device route is not added immediately. It takes a moment... */
+
+ addr = nm_utils_ip4_address_clear_host_address (addr, plen);
+ NMTST_WAIT_ASSERT (400, {
+ NMDedupMultiIter iter;
+ NMPLookup lookup;
+ const NMPObject *o;
+
+ nmp_cache_iter_for_each (&iter,
+ nm_platform_lookup (platform,
+ nmp_lookup_init_addrroute (&lookup,
+ NMP_OBJECT_TYPE_IP4_ROUTE,
+ ifindex)),
+ &o) {
+ const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (o);
+
+ if ( r->plen == plen
+ && addr == nm_utils_ip4_address_clear_host_address (r->network, plen)
+ && r->metric == 0
+ && r->scope_inv == nm_platform_route_scope_inv (RT_SCOPE_LINK)
+ && r->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
+ return;
+ }
+ nmtstp_assert_wait_for_signal (platform,
+ (nmtst_wait_end_us - g_get_monotonic_time ()) / 1000);
+ });
+}
+
+static void
_wait_for_ipv6_addr_non_tentative (NMPlatform *platform,
gint64 timeout_ms,
int ifindex,
@@ -44,7 +80,7 @@ _wait_for_ipv6_addr_non_tentative (NMPlatform *platform,
* small amount of time, which prevents the immediate addition of the route
* with RTA_PREFSRC */
- NMTST_WAIT_ASSERT (400, {
+ NMTST_WAIT_ASSERT (timeout_ms, {
gboolean should_wait = FALSE;
const NMPlatformIP6Address *plt_addr;
@@ -63,7 +99,6 @@ _wait_for_ipv6_addr_non_tentative (NMPlatform *platform,
});
}
-
static void
ip4_route_callback (NMPlatform *platform, int obj_type_i, int ifindex, const NMPlatformIP4Route *received, int change_type_i, SignalData *data)
{
@@ -417,7 +452,7 @@ test_ip_route_get (void)
g_assert (!NMP_OBJECT_IS_STACKINIT (route));
g_assert (route->parent._ref_count == 1);
r = NMP_OBJECT_CAST_IP4_ROUTE (route);
- g_assert (r->rt_cloned);
+ g_assert (NM_FLAGS_HAS (r->r_rtm_flags, RTM_F_CLONED));
g_assert (r->ifindex == ifindex);
g_assert (r->network == a);
g_assert (r->plen == 32);
@@ -448,63 +483,114 @@ test_ip4_zero_gateway (void)
}
static void
-test_ip4_route_options (void)
+test_ip4_route_options (gconstpointer test_data)
{
- int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
- NMPlatformIP4Route route = { };
- in_addr_t network;
- GPtrArray *routes;
- NMPlatformIP4Route rts[1];
+ const int TEST_IDX = GPOINTER_TO_INT (test_data);
+ const int IFINDEX = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
+ gs_unref_ptrarray GPtrArray *routes = NULL;
+#define RTS_MAX 3
+ NMPlatformIP4Route rts_add[RTS_MAX] = { };
+ NMPlatformIP4Route rts_cmp[RTS_MAX] = { };
+ NMPlatformIP4Address addr[1] = { };
+ guint i;
+ guint rts_n = 0;
+ guint addr_n = 0;
- inet_pton (AF_INET, "172.16.1.0", &network);
+ switch (TEST_IDX) {
+ case 1:
+ rts_add[rts_n++] = ((NMPlatformIP4Route) {
+ .ifindex = IFINDEX,
+ .rt_source = NM_IP_CONFIG_SOURCE_USER,
+ .network = nmtst_inet4_from_string ("172.16.1.0"),
+ .plen = 24,
+ .metric = 20,
+ .tos = 0x28,
+ .window = 10000,
+ .cwnd = 16,
+ .initcwnd = 30,
+ .initrwnd = 50,
+ .mtu = 1350,
+ .lock_cwnd = TRUE,
+ });
+ break;
+ case 2:
+ addr[addr_n++] = ((NMPlatformIP4Address) {
+ .ifindex = IFINDEX,
+ .address = nmtst_inet4_from_string ("172.16.1.5"),
+ .peer_address = nmtst_inet4_from_string ("172.16.1.5"),
+ .plen = 24,
+ .lifetime = NM_PLATFORM_LIFETIME_PERMANENT,
+ .preferred = NM_PLATFORM_LIFETIME_PERMANENT,
+ .n_ifa_flags = 0,
+ });
+ rts_add[rts_n++] = ((NMPlatformIP4Route) {
+ .ifindex = IFINDEX,
+ .rt_source = NM_IP_CONFIG_SOURCE_USER,
+ .network = nmtst_inet4_from_string ("172.17.1.0"),
+ .gateway = nmtst_inet4_from_string ("172.16.1.1"),
+ .plen = 24,
+ .metric = 20,
+ });
+ rts_add[rts_n++] = ((NMPlatformIP4Route) {
+ .ifindex = IFINDEX,
+ .rt_source = NM_IP_CONFIG_SOURCE_USER,
+ .network = nmtst_inet4_from_string ("172.19.1.0"),
+ .gateway = nmtst_inet4_from_string ("172.18.1.1"),
+ .r_rtm_flags = RTNH_F_ONLINK,
+ .plen = 24,
+ .metric = 20,
+ });
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ g_assert (rts_n <= G_N_ELEMENTS (rts_add));
+ g_assert (addr_n <= G_N_ELEMENTS (addr));
- route.ifindex = ifindex;
- route.rt_source = NM_IP_CONFIG_SOURCE_USER;
- route.network = network;
- route.plen = 24;
- route.metric = 20;
- route.tos = 0x28;
- route.window = 10000;
- route.cwnd = 16;
- route.initcwnd = 30;
- route.initrwnd = 50;
- route.mtu = 1350;
- route.lock_cwnd = TRUE;
+ for (i = 0; i < addr_n; i++) {
+ const NMPlatformIP4Address *a = &addr[i];
+
+ g_assert (a->ifindex == IFINDEX);
+ g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET,
+ a->ifindex,
+ a->address,
+ a->plen,
+ a->peer_address,
+ a->lifetime,
+ a->preferred,
+ a->n_ifa_flags,
+ a->label));
+ if (a->peer_address == a->address)
+ _wait_for_ipv4_addr_device_route (NM_PLATFORM_GET, 200, a->ifindex, a->address, a->plen);
+ }
- g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &route) == NM_PLATFORM_ERROR_SUCCESS);
+ for (i = 0; i < rts_n; i++)
+ g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &rts_add[i]) == NM_PLATFORM_ERROR_SUCCESS);
- /* Test route listing */
- routes = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, ifindex);
- memset (rts, 0, sizeof (rts));
- rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
- rts[0].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK);
- rts[0].network = network;
- rts[0].plen = 24;
- rts[0].ifindex = ifindex;
- rts[0].metric = 20;
- rts[0].tos = 0x28;
- rts[0].window = 10000;
- rts[0].cwnd = 16;
- rts[0].initcwnd = 30;
- rts[0].initrwnd = 50;
- rts[0].mtu = 1350;
- rts[0].lock_cwnd = TRUE;
- g_assert_cmpint (routes->len, ==, 1);
- nmtst_platform_ip4_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts, routes->len, TRUE);
+ for (i = 0; i < rts_n; i++) {
+ rts_cmp[i] = rts_add[i];
+ nm_platform_ip_route_normalize (AF_INET, NM_PLATFORM_IP_ROUTE_CAST (&rts_cmp[i]));
+ }
- /* Remove route */
- g_assert (nm_platform_ip_route_delete (NM_PLATFORM_GET, routes->pdata[0]));
+ routes = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, IFINDEX);
+ g_assert_cmpint (routes->len, ==, rts_n);
+ nmtst_platform_ip4_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts_cmp, routes->len, TRUE);
- g_ptr_array_unref (routes);
+ for (i = 0; i < rts_n; i++) {
+ g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, IFINDEX,
+ rts_add[i].network, rts_add[i].plen,
+ rts_add[i].metric));
+ }
+#undef RTS_MAX
}
-
static void
test_ip6_route_options (gconstpointer test_data)
{
const int TEST_IDX = GPOINTER_TO_INT (test_data);
const int IFINDEX = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
- GPtrArray *routes;
+ gs_unref_ptrarray GPtrArray *routes = NULL;
#define RTS_MAX 3
NMPlatformIP6Route rts_add[RTS_MAX] = { };
NMPlatformIP6Route rts_cmp[RTS_MAX] = { };
@@ -582,6 +668,8 @@ test_ip6_route_options (gconstpointer test_data)
default:
g_assert_not_reached ();
}
+ g_assert (rts_n <= G_N_ELEMENTS (rts_add));
+ g_assert (addr_n <= G_N_ELEMENTS (addr));
for (i = 0; i < addr_n; i++) {
g_assert (addr[i].ifindex == IFINDEX);
@@ -595,28 +683,19 @@ test_ip6_route_options (gconstpointer test_data)
addr[i].preferred,
addr[i].n_ifa_flags));
}
-
_wait_for_ipv6_addr_non_tentative (NM_PLATFORM_GET, 400, IFINDEX, addr_n, addr_in6);
for (i = 0; i < rts_n; i++)
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &rts_add[i]) == NM_PLATFORM_ERROR_SUCCESS);
- routes = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, IFINDEX);
- switch (TEST_IDX) {
- case 1:
- case 2:
- case 3:
- for (i = 0; i < rts_n; i++) {
- rts_cmp[i] = rts_add[i];
- rts_cmp[i].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
- }
- break;
- default:
- g_assert_not_reached ();
+ for (i = 0; i < rts_n; i++) {
+ rts_cmp[i] = rts_add[i];
+ nm_platform_ip_route_normalize (AF_INET6, NM_PLATFORM_IP_ROUTE_CAST (&rts_cmp[i]));
}
+
+ routes = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, IFINDEX);
g_assert_cmpint (routes->len, ==, rts_n);
nmtst_platform_ip6_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts_cmp, routes->len, TRUE);
- g_ptr_array_unref (routes);
for (i = 0; i < rts_n; i++) {
g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, IFINDEX,
@@ -631,6 +710,7 @@ test_ip6_route_options (gconstpointer test_data)
rts_add[i].network,
rts_add[i].plen);
}
+#undef RTS_MAX
}
/*****************************************************************************/
@@ -771,7 +851,9 @@ _nmtstp_setup_tests (void)
add_test_func ("/route/ip4", test_ip4_route);
add_test_func ("/route/ip6", test_ip6_route);
add_test_func ("/route/ip4_metric0", test_ip4_route_metric0);
- add_test_func ("/route/ip4_options", test_ip4_route_options);
+ add_test_func_data ("/route/ip4_options/1", test_ip4_route_options, GINT_TO_POINTER (1));
+ if (nmtstp_is_root_test ())
+ add_test_func_data ("/route/ip4_options/2", test_ip4_route_options, GINT_TO_POINTER (2));
add_test_func_data ("/route/ip6_options/1", test_ip6_route_options, GINT_TO_POINTER (1));
add_test_func_data ("/route/ip6_options/2", test_ip6_route_options, GINT_TO_POINTER (2));
add_test_func_data ("/route/ip6_options/3", test_ip6_route_options, GINT_TO_POINTER (3));
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
index 66add713b0..b1cf80ad91 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
@@ -512,13 +512,13 @@ typedef struct {
bool int_base_16:1;
- /* the type, one of PARSE_LINE_TYPE_* */
- char type;
-
/* whether the command line option was found, and @v is
* initialized. */
bool has:1;
+ /* the type, one of PARSE_LINE_TYPE_* */
+ char type;
+
union {
guint8 uint8;
guint32 uint32;
@@ -541,6 +541,7 @@ enum {
PARSE_LINE_ATTR_ROUTE_SRC,
PARSE_LINE_ATTR_ROUTE_FROM,
PARSE_LINE_ATTR_ROUTE_TOS,
+ PARSE_LINE_ATTR_ROUTE_ONLINK,
PARSE_LINE_ATTR_ROUTE_WINDOW,
PARSE_LINE_ATTR_ROUTE_CWND,
PARSE_LINE_ATTR_ROUTE_INITCWND,
@@ -562,6 +563,7 @@ enum {
#define PARSE_LINE_TYPE_ADDR 'a'
#define PARSE_LINE_TYPE_ADDR_WITH_PREFIX 'p'
#define PARSE_LINE_TYPE_IFNAME 'i'
+#define PARSE_LINE_TYPE_FLAG 'f'
/**
* parse_route_line:
@@ -601,42 +603,45 @@ parse_route_line (const char *line,
char buf1[256];
char buf2[256];
ParseLineInfo infos[] = {
- [PARSE_LINE_ATTR_ROUTE_TABLE] = { .key = NM_IP_ROUTE_ATTRIBUTE_TABLE,
- .type = PARSE_LINE_TYPE_UINT32, },
- [PARSE_LINE_ATTR_ROUTE_SRC] = { .key = NM_IP_ROUTE_ATTRIBUTE_SRC,
- .type = PARSE_LINE_TYPE_ADDR, },
- [PARSE_LINE_ATTR_ROUTE_FROM] = { .key = NM_IP_ROUTE_ATTRIBUTE_FROM,
- .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX,
- .disabled = (addr_family != AF_INET6), },
- [PARSE_LINE_ATTR_ROUTE_TOS] = { .key = NM_IP_ROUTE_ATTRIBUTE_TOS,
- .type = PARSE_LINE_TYPE_UINT8,
- .int_base_16 = TRUE,
- .ignore = (addr_family != AF_INET), },
- [PARSE_LINE_ATTR_ROUTE_WINDOW] = { .key = NM_IP_ROUTE_ATTRIBUTE_WINDOW,
- .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, },
- [PARSE_LINE_ATTR_ROUTE_CWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_CWND,
- .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, },
- [PARSE_LINE_ATTR_ROUTE_INITCWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_INITCWND,
- .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, },
- [PARSE_LINE_ATTR_ROUTE_INITRWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_INITRWND,
- .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, },
- [PARSE_LINE_ATTR_ROUTE_MTU] = { .key = NM_IP_ROUTE_ATTRIBUTE_MTU,
- .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, },
-
- [PARSE_LINE_ATTR_ROUTE_TO] = { .key = "to",
- .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX,
- .disabled = (options_route != NULL), },
- [PARSE_LINE_ATTR_ROUTE_VIA] = { .key = "via",
- .type = PARSE_LINE_TYPE_ADDR,
- .disabled = (options_route != NULL), },
- [PARSE_LINE_ATTR_ROUTE_METRIC] = { .key = "metric",
- .type = PARSE_LINE_TYPE_UINT32,
- .disabled = (options_route != NULL), },
-
- [PARSE_LINE_ATTR_ROUTE_DEV] = { .key = "dev",
- .type = PARSE_LINE_TYPE_IFNAME,
- .ignore = TRUE,
- .disabled = (options_route != NULL), },
+ [PARSE_LINE_ATTR_ROUTE_TABLE] = { .key = NM_IP_ROUTE_ATTRIBUTE_TABLE,
+ .type = PARSE_LINE_TYPE_UINT32, },
+ [PARSE_LINE_ATTR_ROUTE_SRC] = { .key = NM_IP_ROUTE_ATTRIBUTE_SRC,
+ .type = PARSE_LINE_TYPE_ADDR, },
+ [PARSE_LINE_ATTR_ROUTE_FROM] = { .key = NM_IP_ROUTE_ATTRIBUTE_FROM,
+ .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX,
+ .disabled = (addr_family != AF_INET6), },
+ [PARSE_LINE_ATTR_ROUTE_TOS] = { .key = NM_IP_ROUTE_ATTRIBUTE_TOS,
+ .type = PARSE_LINE_TYPE_UINT8,
+ .int_base_16 = TRUE,
+ .ignore = (addr_family != AF_INET), },
+ [PARSE_LINE_ATTR_ROUTE_ONLINK] = { .key = NM_IP_ROUTE_ATTRIBUTE_ONLINK,
+ .type = PARSE_LINE_TYPE_FLAG,
+ .ignore = (addr_family != AF_INET), },
+ [PARSE_LINE_ATTR_ROUTE_WINDOW] = { .key = NM_IP_ROUTE_ATTRIBUTE_WINDOW,
+ .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, },
+ [PARSE_LINE_ATTR_ROUTE_CWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_CWND,
+ .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, },
+ [PARSE_LINE_ATTR_ROUTE_INITCWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_INITCWND,
+ .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, },
+ [PARSE_LINE_ATTR_ROUTE_INITRWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_INITRWND,
+ .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, },
+ [PARSE_LINE_ATTR_ROUTE_MTU] = { .key = NM_IP_ROUTE_ATTRIBUTE_MTU,
+ .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, },
+
+ [PARSE_LINE_ATTR_ROUTE_TO] = { .key = "to",
+ .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX,
+ .disabled = (options_route != NULL), },
+ [PARSE_LINE_ATTR_ROUTE_VIA] = { .key = "via",
+ .type = PARSE_LINE_TYPE_ADDR,
+ .disabled = (options_route != NULL), },
+ [PARSE_LINE_ATTR_ROUTE_METRIC] = { .key = "metric",
+ .type = PARSE_LINE_TYPE_UINT32,
+ .disabled = (options_route != NULL), },
+
+ [PARSE_LINE_ATTR_ROUTE_DEV] = { .key = "dev",
+ .type = PARSE_LINE_TYPE_IFNAME,
+ .ignore = TRUE,
+ .disabled = (options_route != NULL), },
};
nm_assert (line);
@@ -705,6 +710,9 @@ parse_route_line (const char *line,
case PARSE_LINE_TYPE_IFNAME:
i_words++;
goto parse_line_type_ifname;
+ case PARSE_LINE_TYPE_FLAG:
+ i_words++;
+ goto next;
default:
nm_assert_not_reached ();
}
@@ -913,6 +921,15 @@ next:
? nm_sprintf_buf (buf2, "/%u", (unsigned) info->v.addr.plen)
: ""));
break;
+ case PARSE_LINE_TYPE_FLAG:
+ /* XXX: the flag (for "onlink") only allows to explictly set "TRUE".
+ * There is no way to express an explicit "FALSE" setting
+ * of this attribute, hence, the file format cannot encode
+ * that configuration. */
+ nm_ip_route_set_attribute (route,
+ info->key,
+ g_variant_new_boolean (TRUE));
+ break;
default:
nm_assert_not_reached ();
break;
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
index 5c8de7d12a..e413da1ef4 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
@@ -1928,8 +1928,11 @@ get_route_attributes_string (NMIPRoute *route, int family)
g_string_append_printf (str, "%s 0x%02x", names[i], (unsigned) g_variant_get_byte (attr));
} else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_TABLE)) {
g_string_append_printf (str, "%s %u", names[i], (unsigned) g_variant_get_uint32 (attr));
- } else if ( nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC)
- || nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_FROM)) {
+ } else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_ONLINK)) {
+ if (g_variant_get_boolean (attr))
+ g_string_append (str, "onlink");
+ } else if (NM_IN_STRSET (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC,
+ NM_IP_ROUTE_ATTRIBUTE_FROM)) {
char *arg = nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC) ? "src" : "from";
g_string_append_printf (str, "%s %s", arg, g_variant_get_string (attr, NULL));
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected
new file mode 100644
index 0000000000..c0e47c48d8
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected
@@ -0,0 +1,20 @@
+HWADDR=31:33:33:37:BE:CD
+MTU=1492
+TYPE=Ethernet
+PROXY_METHOD=none
+BROWSER_ONLY=no
+BOOTPROTO=none
+IPADDR=1.1.1.3
+PREFIX=24
+IPADDR1=1.1.1.5
+PREFIX1=24
+GATEWAY=1.1.1.1
+DNS1=4.2.2.1
+DNS2=4.2.2.2
+DOMAIN="foobar.com lab.foobar.com"
+DEFROUTE=yes
+IPV4_FAILURE_FATAL=no
+IPV6INIT=no
+NAME="Test Write Wired Static Routes"
+UUID=${UUID}
+ONBOOT=yes
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes
index 10a63b674f..8d6aaac2f6 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes
@@ -7,3 +7,9 @@ NETMASK1=255.255.255.255
GATEWAY1=192.168.1.7
METRIC1=3
OPTIONS1="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 window 30000 initcwnd lock 13 initrwnd 14"
+
+ADDRESS2=44.55.66.78
+NETMASK2=255.255.255.255
+GATEWAY2=192.168.1.8
+METRIC2=3
+OPTIONS2="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 onlink window 30000 initcwnd lock 13 initrwnd 14"
diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
index 5044a2d7d8..17b6ca4940 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -1318,7 +1318,7 @@ test_read_wired_static_routes (void)
g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
/* Routes */
- g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 2);
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 3);
ip4_route = nm_setting_ip_config_get_route (s_ip4, 0);
g_assert (ip4_route);
@@ -1343,6 +1343,23 @@ test_read_wired_static_routes (void)
nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, TRUE);
nmtst_assert_route_attribute_string (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SRC, "1.1.1.1");
+ ip4_route = nm_setting_ip_config_get_route (s_ip4, 2);
+ g_assert (ip4_route);
+ g_assert_cmpstr (nm_ip_route_get_dest (ip4_route), ==, "44.55.66.78");
+ g_assert_cmpint (nm_ip_route_get_prefix (ip4_route), ==, 32);
+ g_assert_cmpstr (nm_ip_route_get_next_hop (ip4_route), ==, "192.168.1.8");
+ g_assert_cmpint (nm_ip_route_get_metric (ip4_route), ==, 3);
+ nmtst_assert_route_attribute_byte (ip4_route, NM_IP_ROUTE_ATTRIBUTE_TOS, 0x28);
+ nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_WINDOW, 30000);
+ nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_CWND, 12);
+ nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_INITCWND, 13);
+ nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_INITRWND, 14);
+ nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_MTU, 9000);
+ nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, TRUE);
+ nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, TRUE);
+ nmtst_assert_route_attribute_string (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SRC, "1.1.1.1");
+ nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, TRUE);
+
g_object_unref (connection);
}
@@ -4748,6 +4765,7 @@ test_write_wired_static_routes (void)
NMIPAddress *addr;
NMIPRoute *route;
GError *error = NULL;
+ gboolean reread_same = FALSE;
connection = nm_simple_connection_new ();
@@ -4792,11 +4810,15 @@ test_write_wired_static_routes (void)
/* Write out routes */
route = nm_ip_route_new (AF_INET, "1.2.3.0", 24, "222.173.190.239", 0, &error);
+ nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_WINDOW, g_variant_new_uint32 (3455));
+ nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, g_variant_new_boolean (TRUE));
g_assert_no_error (error);
nm_setting_ip_config_add_route (s_ip4, route);
nm_ip_route_unref (route);
route = nm_ip_route_new (AF_INET, "3.2.1.0", 24, "202.254.186.190", 77, &error);
+ nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_WINDOW, g_variant_new_uint32 (30000));
+ nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, g_variant_new_boolean (FALSE));
g_assert_no_error (error);
nm_setting_ip_config_add_route (s_ip4, route);
nm_ip_route_unref (route);
@@ -4818,15 +4840,28 @@ test_write_wired_static_routes (void)
nmtst_assert_connection_verifies (connection);
- _writer_new_connection (connection,
- TEST_SCRATCH_DIR "/network-scripts/",
- &testfile);
+ _writer_new_connection_reread (connection,
+ TEST_SCRATCH_DIR "/network-scripts/",
+ &testfile,
+ TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected",
+ &reread,
+ &reread_same);
+ /* ifcfg does not support setting onlink=0. It gets lost during write+re-read.
+ * Assert that it's missing, and patch it to check whether the rest of the
+ * connection equals. */
+ g_assert (!reread_same);
+ nmtst_assert_connection_verifies_without_normalization (reread);
+ s_ip4 = nm_connection_get_setting_ip4_config (reread);
+ g_assert (s_ip4);
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 2);
+ route = nm_setting_ip_config_get_route (s_ip4, 1);
+ g_assert (route);
+ g_assert (!nm_ip_route_get_attribute (route, NM_IP_ROUTE_ATTRIBUTE_ONLINK));
+ nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, g_variant_new_boolean (FALSE));
- reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
+ nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
routefile = utils_get_route_path (testfile);
-
- nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
}
static void
diff --git a/src/tests/test-ip4-config.c b/src/tests/test-ip4-config.c
index 649b443f2a..4c3c344e46 100644
--- a/src/tests/test-ip4-config.c
+++ b/src/tests/test-ip4-config.c
@@ -38,6 +38,8 @@ build_test_config (void)
/* Build up the config to subtract */
config = nmtst_ip4_config_new (1);
+ nm_assert (NM_IP_CONFIG_CAST (config));
+
addr = *nmtst_platform_ip4_address ("192.168.1.10", "1.2.3.4", 24);
nm_ip4_config_add_address (config, &addr);