all: merge branch 'th/platform-routes-onlink-rh1428334'

https://bugzilla.redhat.com/show_bug.cgi?id=1428334
This commit is contained in:
Thomas Haller 2017-11-13 11:50:44 +01:00
commit d44a3eb80c
22 changed files with 570 additions and 296 deletions

View file

@ -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 \

View file

@ -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 -------------------------

View file

@ -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 ),

View file

@ -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"

View file

@ -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
/*****************************************************************************/

View file

@ -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); \

View file

@ -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);

View file

@ -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);

View file

@ -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;
guint32 table;
NMIPAddr addr;
NMPlatformIP4Route *r4 = (NMPlatformIP4Route *) r;
NMPlatformIP6Route *r6 = (NMPlatformIP6Route *) r;
gboolean onlink;
#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);
nm_assert (s_route);
nm_assert_addr_family (addr_family);
nm_assert (r);
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));
#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_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);
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);
}

View file

@ -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,41 +277,57 @@ gboolean nm_ip4_config_equal (const NMIP4Config *a, const NMIP4Config *b);
#include "nm-ip6-config.h"
#if _NM_CC_SUPPORT_GENERIC
#define NM_IP_CONFIG_CAST(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)); \
})
#else
#define NM_IP_CONFIG_CAST(config) ((NMIPConfig *) (config))
#endif
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
/* _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); \
_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_IS_IP_CONFIG(typeexpr, config) NM_IS_IP_CONFIG(config)
#endif
#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)
{

View file

@ -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);
}

View file

@ -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);

View file

@ -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);

View file

@ -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_CAST(route) \
NM_CONSTCAST (NMPlatformIPRoute, (route), NMPlatformIPXRoute, NMPlatformIP4Route, NMPlatformIP6Route)
#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_IS_DEFAULT(route) \
( ((const NMPlatformIPRoute *) (route))->plen <= 0 )
#endif
(NM_PLATFORM_IP_ROUTE_CAST (route)->plen <= 0)
struct _NMPlatformIP4Route {
__NMPlatformIPRoute_COMMON;

View file

@ -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

View file

@ -30,6 +30,42 @@
#define DEVICE_IFINDEX NMTSTP_ENV1_IFINDEX
#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,
@ -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 (nm_platform_ip4_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &route) == NM_PLATFORM_ERROR_SUCCESS);
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);
}
/* 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++)
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &rts_add[i]) == NM_PLATFORM_ERROR_SUCCESS);
/* Remove route */
g_assert (nm_platform_ip_route_delete (NM_PLATFORM_GET, routes->pdata[0]));
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]));
}
g_ptr_array_unref (routes);
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);
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));

View file

@ -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_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_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_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;

View file

@ -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));

View file

@ -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

View file

@ -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"

View file

@ -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);
reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
routefile = utils_get_route_path (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));
nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
routefile = utils_get_route_path (testfile);
}
static void

View file

@ -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);