mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-15 20:45:32 +00:00
libnm-core: define known route attribute names and validation function
This adds definition of a set of known route option attributes to libnm-core and helper functions. nm_ip_route_attribute_validate() performs the validation of the attribute type and, in case of a formatted string attribute, of its content. nm_ip_route_get_variant_attribute_spec() returns the attribute format specifier to be passed to nm_utils_parse_variant_attributes(). Since at the moment NMIPRoute is the only user of NMVariantAttributeSpec and the type is opaque to users of the library, the struct is extended to carry some other data useful for validation.
This commit is contained in:
parent
93b3a478bb
commit
54e58eb96b
|
@ -1182,6 +1182,157 @@ nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value)
|
|||
g_hash_table_remove (route->attributes, name);
|
||||
}
|
||||
|
||||
#define ATTR_SPEC_PTR(name, type, v4, v6, str_type) \
|
||||
&(NMVariantAttributeSpec) { name, type, v4, v6, str_type }
|
||||
|
||||
static const NMVariantAttributeSpec * const ip_route_attribute_spec[] = {
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_PREF_SRC, G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a'),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, FALSE, TRUE, 'p'),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, TRUE, TRUE, 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 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_INITRWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_MTU, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ),
|
||||
NULL,
|
||||
};
|
||||
|
||||
/**
|
||||
* nm_ip_route_get_variant_attribute_spec:
|
||||
*
|
||||
* Returns: the specifiers for route attributes
|
||||
*
|
||||
* Since: 1.8
|
||||
*/
|
||||
const NMVariantAttributeSpec *const *
|
||||
nm_ip_route_get_variant_attribute_spec (void)
|
||||
{
|
||||
return ip_route_attribute_spec;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_ip_route_attribute_validate:
|
||||
* @name: the attribute name
|
||||
* @value: the attribute value
|
||||
* @family: IP address family of the route
|
||||
* @known: (out): on return, whether the attribute name is a known one
|
||||
* @error: (allow-none): return location for a #GError, or %NULL
|
||||
*
|
||||
* Validates a route attribute, i.e. checks that the attribute is a known one
|
||||
* and the value is of the correct type and well-formed.
|
||||
*
|
||||
* Returns: %TRUE if the attribute is valid, %FALSE otherwise
|
||||
*
|
||||
* Since: 1.8
|
||||
*/
|
||||
gboolean
|
||||
nm_ip_route_attribute_validate (const char *name,
|
||||
GVariant *value,
|
||||
int family,
|
||||
gboolean *known,
|
||||
GError **error)
|
||||
{
|
||||
const NMVariantAttributeSpec *const *iter;
|
||||
const NMVariantAttributeSpec *spec = NULL;
|
||||
|
||||
g_return_val_if_fail (name, FALSE);
|
||||
g_return_val_if_fail (value, FALSE);
|
||||
g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE);
|
||||
g_return_val_if_fail (!error || !*error, FALSE);
|
||||
|
||||
for (iter = ip_route_attribute_spec; *iter; iter++) {
|
||||
if (nm_streq (name, (*iter)->name)) {
|
||||
spec = *iter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!spec) {
|
||||
NM_SET_OUT (known, FALSE);
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_FAILED,
|
||||
_("unknown attribute"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NM_SET_OUT (known, TRUE);
|
||||
|
||||
if (!g_variant_is_of_type (value, spec->type)) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_FAILED,
|
||||
_("invalid attribute type'%s'"),
|
||||
g_variant_get_type_string (value));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( (family == AF_INET && !spec->v4)
|
||||
|| (family == AF_INET6 && !spec->v6)) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_FAILED,
|
||||
family == AF_INET ?
|
||||
_("attribute is not valid for a IPv4 route") :
|
||||
_("attribute is not valid for a IPv6 route"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (spec->type == G_VARIANT_TYPE_STRING) {
|
||||
const char *string = g_variant_get_string (value, NULL);
|
||||
gs_free char *string_free = NULL;
|
||||
char *sep;
|
||||
|
||||
switch (spec->str_type) {
|
||||
case 'a': /* IP address */
|
||||
if (!nm_utils_ipaddr_valid (family, string)) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_FAILED,
|
||||
family == AF_INET ?
|
||||
_("'%s' is not a valid IPv4 address") :
|
||||
_("'%s' is not a valid IPv6 address"),
|
||||
string);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case 'p': /* IP address + optional prefix */
|
||||
string_free = g_strdup (string);
|
||||
sep = strchr (string_free, '/');
|
||||
if (sep) {
|
||||
*sep = 0;
|
||||
if (_nm_utils_ascii_str_to_int64 (sep + 1, 10, 1, family == AF_INET ? 32 : 128, -1) < 0) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_FAILED,
|
||||
_("invalid prefix %s"), sep + 1);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (!nm_utils_ipaddr_valid (family, string_free)) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_FAILED,
|
||||
family == AF_INET ?
|
||||
_("'%s' is not a valid IPv4 address") :
|
||||
_("'%s' is not a valid IPv6 address"),
|
||||
string_free);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (NMSettingIPConfig, nm_setting_ip_config, NM_TYPE_SETTING)
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#endif
|
||||
|
||||
#include "nm-setting.h"
|
||||
#include "nm-utils.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -121,7 +122,28 @@ GVariant *nm_ip_route_get_attribute (NMIPRoute *route,
|
|||
void nm_ip_route_set_attribute (NMIPRoute *route,
|
||||
const char *name,
|
||||
GVariant *value);
|
||||
NM_AVAILABLE_IN_1_8
|
||||
const NMVariantAttributeSpec *const *nm_ip_route_get_variant_attribute_spec (void);
|
||||
NM_AVAILABLE_IN_1_8
|
||||
gboolean nm_ip_route_attribute_validate (const char *name,
|
||||
GVariant *value,
|
||||
int family,
|
||||
gboolean *known,
|
||||
GError **error);
|
||||
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_PREF_SRC "pref-src"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_SRC "src"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_TOS "tos"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_WINDOW "window"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_CWND "cwnd"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_INITCWND "initcwnd"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_INITRWND "initrwnd"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_MTU "mtu"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW "lock-window"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND "lock-cwnd"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND "lock-initcwnd"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND "lock-initrwnd"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU "lock-mtu"
|
||||
|
||||
#define NM_TYPE_SETTING_IP_CONFIG (nm_setting_ip_config_get_type ())
|
||||
#define NM_SETTING_IP_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_IP_CONFIG, NMSettingIPConfig))
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
struct _NMVariantAttributeSpec {
|
||||
char *name;
|
||||
const GVariantType *type;
|
||||
bool v4:1;
|
||||
bool v6:1;
|
||||
char str_type;
|
||||
};
|
||||
|
||||
gboolean _nm_utils_string_slist_validate (GSList *list,
|
||||
|
|
|
@ -642,6 +642,47 @@ test_setting_ip4_config_address_data (void)
|
|||
g_object_unref (conn);
|
||||
}
|
||||
|
||||
static void
|
||||
test_setting_ip_route_attributes (void)
|
||||
{
|
||||
GVariant *variant;
|
||||
gboolean res, known;
|
||||
|
||||
#define TEST_ATTR(name, type, value, family, exp_res, exp_known) \
|
||||
variant = g_variant_new_ ## type (value); \
|
||||
res = nm_ip_route_attribute_validate (name, variant, family, &known, NULL); \
|
||||
g_assert (res == exp_res); \
|
||||
g_assert (known == exp_known); \
|
||||
g_variant_unref (variant);
|
||||
|
||||
TEST_ATTR ("foo", uint32, 12, AF_INET, FALSE, FALSE);
|
||||
|
||||
TEST_ATTR ("tos", byte, 127, AF_INET, TRUE, TRUE);
|
||||
TEST_ATTR ("tos", string, "0x28", AF_INET, FALSE, TRUE);
|
||||
|
||||
TEST_ATTR ("cwnd", uint32, 10, AF_INET, TRUE, TRUE);
|
||||
TEST_ATTR ("cwnd", string, "11", AF_INET, FALSE, TRUE);
|
||||
|
||||
TEST_ATTR ("lock-mtu", boolean, TRUE, AF_INET, TRUE, TRUE);
|
||||
TEST_ATTR ("lock-mtu", uint32, 1, AF_INET, FALSE, TRUE);
|
||||
|
||||
TEST_ATTR ("src", string, "fd01::1", AF_INET6, TRUE, TRUE);
|
||||
TEST_ATTR ("src", string, "fd01::1/64", AF_INET6, TRUE, TRUE);
|
||||
TEST_ATTR ("src", string, "fd01::1/128", AF_INET6, TRUE, TRUE);
|
||||
TEST_ATTR ("src", string, "fd01::1/129", AF_INET6, FALSE, TRUE);
|
||||
TEST_ATTR ("src", string, "fd01::1/a", AF_INET6, FALSE, TRUE);
|
||||
TEST_ATTR ("src", string, "abc/64", AF_INET6, FALSE, TRUE);
|
||||
TEST_ATTR ("src", string, "1.2.3.4", AF_INET, FALSE, TRUE);
|
||||
TEST_ATTR ("src", string, "1.2.3.4", AF_INET6, FALSE, TRUE);
|
||||
|
||||
TEST_ATTR ("pref-src", string, "1.2.3.4", AF_INET, TRUE, TRUE);
|
||||
TEST_ATTR ("pref-src", string, "1.2.3.4", AF_INET6, FALSE, TRUE);
|
||||
TEST_ATTR ("pref-src", string, "1.2.3.0/24", AF_INET, FALSE, TRUE);
|
||||
TEST_ATTR ("pref-src", string, "fd01::12", AF_INET6, TRUE, TRUE);
|
||||
|
||||
#undef TEST_ATTR
|
||||
}
|
||||
|
||||
static void
|
||||
test_setting_gsm_apn_spaces (void)
|
||||
{
|
||||
|
@ -5412,6 +5453,97 @@ test_nm_in_strset (void)
|
|||
#undef _ASSERT
|
||||
}
|
||||
|
||||
static void
|
||||
test_route_attributes_parse (void)
|
||||
{
|
||||
GHashTable *ht;
|
||||
GError *error = NULL;
|
||||
GVariant *variant;
|
||||
|
||||
ht = nm_utils_parse_variant_attributes ("mtu=1400 pref-src=1.2.3.4 cwnd=14",
|
||||
' ', '=', FALSE,
|
||||
nm_ip_route_get_variant_attribute_spec (),
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (ht);
|
||||
g_hash_table_unref (ht);
|
||||
|
||||
ht = nm_utils_parse_variant_attributes ("mtu=1400 pref-src=1.2.3.4 cwnd=14 \\",
|
||||
' ', '=', FALSE,
|
||||
nm_ip_route_get_variant_attribute_spec (),
|
||||
&error);
|
||||
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED);
|
||||
g_assert (!ht);
|
||||
g_clear_error (&error);
|
||||
|
||||
ht = nm_utils_parse_variant_attributes ("mtu.1400 pref-src.1\\.2\\.3\\.4 ",
|
||||
' ', '.', FALSE,
|
||||
nm_ip_route_get_variant_attribute_spec (),
|
||||
&error);
|
||||
g_assert (ht);
|
||||
g_assert_no_error (error);
|
||||
variant = g_hash_table_lookup (ht, NM_IP_ROUTE_ATTRIBUTE_MTU);
|
||||
g_assert (variant);
|
||||
g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32));
|
||||
g_assert_cmpuint (g_variant_get_uint32 (variant), ==, 1400);
|
||||
|
||||
variant = g_hash_table_lookup (ht, NM_IP_ROUTE_ATTRIBUTE_PREF_SRC);
|
||||
g_assert (variant);
|
||||
g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING));
|
||||
g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "1.2.3.4");
|
||||
g_hash_table_unref (ht);
|
||||
|
||||
ht = nm_utils_parse_variant_attributes ("src:fd01\\:\\:42\\/64/initrwnd:21",
|
||||
'/', ':', FALSE,
|
||||
nm_ip_route_get_variant_attribute_spec (),
|
||||
&error);
|
||||
g_assert (ht);
|
||||
g_assert_no_error (error);
|
||||
variant = g_hash_table_lookup (ht, NM_IP_ROUTE_ATTRIBUTE_INITRWND);
|
||||
g_assert (variant);
|
||||
g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32));
|
||||
g_assert_cmpuint (g_variant_get_uint32 (variant), ==, 21);
|
||||
|
||||
variant = g_hash_table_lookup (ht, NM_IP_ROUTE_ATTRIBUTE_SRC);
|
||||
g_assert (variant);
|
||||
g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING));
|
||||
g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "fd01::42/64");
|
||||
g_hash_table_unref (ht);
|
||||
}
|
||||
|
||||
static void
|
||||
test_route_attributes_format (void)
|
||||
{
|
||||
gs_unref_hashtable GHashTable *ht = NULL;
|
||||
char *str;
|
||||
|
||||
ht = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
NULL, (GDestroyNotify) g_variant_unref);
|
||||
|
||||
str = nm_utils_format_variant_attributes (NULL, ' ', '=');
|
||||
g_assert_cmpstr (str, ==, NULL);
|
||||
|
||||
str = nm_utils_format_variant_attributes (ht, ' ', '=');
|
||||
g_assert_cmpstr (str, ==, NULL);
|
||||
|
||||
g_hash_table_insert (ht, NM_IP_ROUTE_ATTRIBUTE_MTU, g_variant_new_uint32 (5000));
|
||||
g_hash_table_insert (ht, NM_IP_ROUTE_ATTRIBUTE_INITRWND, g_variant_new_uint32 (20));
|
||||
g_hash_table_insert (ht, NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, g_variant_new_boolean (TRUE));
|
||||
g_hash_table_insert (ht, NM_IP_ROUTE_ATTRIBUTE_PREF_SRC, g_variant_new_string ("aaaa:bbbb::1"));
|
||||
str = nm_utils_format_variant_attributes (ht, ' ', '=');
|
||||
g_assert_cmpstr (str, ==, "initrwnd=20 lock-mtu=true mtu=5000 pref-src=aaaa:bbbb::1");
|
||||
g_hash_table_remove_all (ht);
|
||||
g_free (str);
|
||||
|
||||
g_hash_table_insert (ht, NM_IP_ROUTE_ATTRIBUTE_WINDOW, g_variant_new_uint32 (30000));
|
||||
g_hash_table_insert (ht, NM_IP_ROUTE_ATTRIBUTE_INITCWND, g_variant_new_uint32 (21));
|
||||
g_hash_table_insert (ht, NM_IP_ROUTE_ATTRIBUTE_SRC, g_variant_new_string ("aaaa:bbbb:cccc:dddd::/64"));
|
||||
str = nm_utils_format_variant_attributes (ht, '/', ':');
|
||||
g_assert_cmpstr (str, ==, "initcwnd:21/src:aaaa\\:bbbb\\:cccc\\:dddd\\:\\:\\/64/window:30000");
|
||||
g_hash_table_remove_all (ht);
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
|
@ -5467,6 +5599,7 @@ int main (int argc, char **argv)
|
|||
g_test_add_func ("/core/general/test_setting_vpn_modify_during_foreach", test_setting_vpn_modify_during_foreach);
|
||||
g_test_add_func ("/core/general/test_setting_ip4_config_labels", test_setting_ip4_config_labels);
|
||||
g_test_add_func ("/core/general/test_setting_ip4_config_address_data", test_setting_ip4_config_address_data);
|
||||
g_test_add_func ("/core/general/test_setting_ip_route_attributes", test_setting_ip_route_attributes);
|
||||
g_test_add_func ("/core/general/test_setting_gsm_apn_spaces", test_setting_gsm_apn_spaces);
|
||||
g_test_add_func ("/core/general/test_setting_gsm_apn_bad_chars", test_setting_gsm_apn_bad_chars);
|
||||
g_test_add_func ("/core/general/test_setting_gsm_apn_underscore", test_setting_gsm_apn_underscore);
|
||||
|
@ -5576,6 +5709,8 @@ int main (int argc, char **argv)
|
|||
g_test_add_func ("/core/general/_nm_utils_team_config_equal", test_nm_utils_team_config_equal);
|
||||
g_test_add_func ("/core/general/test_nm_utils_enum", test_nm_utils_enum);
|
||||
g_test_add_func ("/core/general/nm-set-out", test_nm_set_out);
|
||||
g_test_add_func ("/core/general/route_attributes/parse", test_route_attributes_parse);
|
||||
g_test_add_func ("/core/general/route_attributes/format", test_route_attributes_format);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
@ -1148,6 +1148,8 @@ libnm_1_8_0 {
|
|||
global:
|
||||
nm_connection_get_setting_dummy;
|
||||
nm_device_dummy_get_type;
|
||||
nm_ip_route_get_variant_attribute_spec;
|
||||
nm_ip_route_attribute_validate;
|
||||
nm_setting_802_1x_auth_flags_get_type;
|
||||
nm_setting_802_1x_get_auth_timeout;
|
||||
nm_setting_802_1x_get_ca_cert_password;
|
||||
|
|
Loading…
Reference in a new issue