mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-11 00:10:33 +01:00
merge: branch 'bg/route-options-rh1373698'
https://bugzilla.redhat.com/show_bug.cgi?id=1373698
This commit is contained in:
commit
468127ca69
36 changed files with 1819 additions and 394 deletions
|
|
@ -395,26 +395,20 @@ finish:
|
|||
/*
|
||||
* nmc_parse_and_build_route:
|
||||
* @family: AF_INET or AF_INET6
|
||||
* @first: the route destination in the form of "address/prefix"
|
||||
(/prefix is optional)
|
||||
* @second: (allow-none): next hop address, if third is not NULL. Otherwise it could be
|
||||
either next hop address or metric. (It can be NULL when @third is NULL).
|
||||
* @third: (allow-none): route metric
|
||||
* @str: route string to be parsed
|
||||
* @error: location to store GError
|
||||
*
|
||||
* Parse route from strings and return an #NMIPRoute
|
||||
* Parse route from string and return an #NMIPRoute
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE on failure
|
||||
* Returns: a new #NMIPRoute or %NULL on error
|
||||
*/
|
||||
NMIPRoute *
|
||||
nmc_parse_and_build_route (int family,
|
||||
const char *first,
|
||||
const char *second,
|
||||
const char *third,
|
||||
const char *str,
|
||||
GError **error)
|
||||
{
|
||||
int max_prefix = (family == AF_INET) ? 32 : 128;
|
||||
char *dest = NULL, *plen = NULL;
|
||||
char *plen = NULL;
|
||||
const char *next_hop = NULL;
|
||||
const char *canon_dest;
|
||||
long int prefix = max_prefix;
|
||||
|
|
@ -423,13 +417,27 @@ nmc_parse_and_build_route (int family,
|
|||
gboolean success = FALSE;
|
||||
GError *local = NULL;
|
||||
gint64 metric = -1;
|
||||
guint i, len;
|
||||
gs_strfreev char **routev = NULL;
|
||||
gs_free char *value = NULL;
|
||||
gs_free char *dest = NULL;
|
||||
gs_unref_hashtable GHashTable *attrs = NULL;
|
||||
GHashTable *tmp_attrs;
|
||||
|
||||
g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE);
|
||||
g_return_val_if_fail (first != NULL, FALSE);
|
||||
g_return_val_if_fail (second || !third, FALSE);
|
||||
g_return_val_if_fail (str, FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
dest = g_strdup (first);
|
||||
value = g_strdup (str);
|
||||
routev = nmc_strsplit_set (g_strstrip (value), " \t", 0);
|
||||
len = g_strv_length (routev);
|
||||
if (len < 1) {
|
||||
g_set_error (error, 1, 0, _("'%s' is not valid (the format is: ip[/prefix] [next-hop] [metric] [attr=val] [attr=val])"),
|
||||
str);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
dest = g_strdup (routev[0]);
|
||||
plen = strchr (dest, '/'); /* prefix delimiter */
|
||||
if (plen)
|
||||
*plen++ = '\0';
|
||||
|
|
@ -443,26 +451,50 @@ nmc_parse_and_build_route (int family,
|
|||
}
|
||||
}
|
||||
|
||||
if (second) {
|
||||
if (third || nm_utils_ipaddr_valid (family, second))
|
||||
next_hop = second;
|
||||
else {
|
||||
/* 'second' can be a metric */
|
||||
if (!nmc_string_to_uint (second, TRUE, 0, G_MAXUINT32, &tmp_ulong)) {
|
||||
g_set_error (error, 1, 0, _("the second component of route ('%s') is neither "
|
||||
"a next hop address nor a metric"), second);
|
||||
for (i = 1; i < len; i++) {
|
||||
if (nm_utils_ipaddr_valid (family, routev[i])) {
|
||||
if (metric != -1 || attrs) {
|
||||
g_set_error (error, 1, 0, _("the next hop ('%s') must be first"), routev[i]);
|
||||
goto finish;
|
||||
}
|
||||
next_hop = routev[i];
|
||||
} else if (nmc_string_to_uint (routev[i], TRUE, 0, G_MAXUINT32, &tmp_ulong)) {
|
||||
if (attrs) {
|
||||
g_set_error (error, 1, 0, _("the metric ('%s') must be before attributes"), routev[i]);
|
||||
goto finish;
|
||||
}
|
||||
metric = tmp_ulong;
|
||||
}
|
||||
}
|
||||
} else if (strchr (routev[i], '=')) {
|
||||
GHashTableIter iter;
|
||||
char *iter_key;
|
||||
GVariant *iter_value;
|
||||
|
||||
if (third) {
|
||||
if (!nmc_string_to_uint (third, TRUE, 0, G_MAXUINT32, &tmp_ulong)) {
|
||||
g_set_error (error, 1, 0, _("invalid metric '%s'"), third);
|
||||
tmp_attrs = nm_utils_parse_variant_attributes (routev[i], ' ', '=', FALSE,
|
||||
nm_ip_route_get_variant_attribute_spec(),
|
||||
error);
|
||||
if (!tmp_attrs) {
|
||||
g_prefix_error (error, "invalid option '%s': ", routev[i]);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!attrs)
|
||||
attrs = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
g_hash_table_iter_init (&iter, tmp_attrs);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &iter_key, (gpointer *) &iter_value)) {
|
||||
if (!nm_ip_route_attribute_validate (iter_key, iter_value, family, NULL, error)) {
|
||||
g_prefix_error (error, "%s: ", iter_key);
|
||||
g_hash_table_unref (tmp_attrs);
|
||||
goto finish;
|
||||
}
|
||||
g_hash_table_insert (attrs, iter_key, iter_value);
|
||||
g_hash_table_iter_steal (&iter);
|
||||
}
|
||||
g_hash_table_unref (tmp_attrs);
|
||||
} else {
|
||||
g_set_error (error, 1, 0, _("unrecognized option '%s'"), routev[i]);
|
||||
goto finish;
|
||||
}
|
||||
metric = tmp_ulong;
|
||||
}
|
||||
|
||||
route = nm_ip_route_new (family, dest, prefix, next_hop, metric, &local);
|
||||
|
|
@ -485,10 +517,19 @@ nmc_parse_and_build_route (int family,
|
|||
goto finish;
|
||||
}
|
||||
|
||||
if (attrs) {
|
||||
GHashTableIter iter;
|
||||
char *name;
|
||||
GVariant *variant;
|
||||
|
||||
g_hash_table_iter_init (&iter, attrs);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant))
|
||||
nm_ip_route_set_attribute (route, name, variant);
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
finish:
|
||||
g_free (dest);
|
||||
return route;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ gboolean print_dhcp4_config (NMDhcpConfig *dhcp4, NmCli *nmc, const char *group_
|
|||
gboolean print_dhcp6_config (NMDhcpConfig *dhcp6, NmCli *nmc, const char *group_prefix, const char *one_field);
|
||||
|
||||
NMIPAddress *nmc_parse_and_build_address (int family, const char *ip_str, GError **error);
|
||||
NMIPRoute *nmc_parse_and_build_route (int family, const char *first, const char *second, const char *third, GError **error);
|
||||
NMIPRoute *nmc_parse_and_build_route (int family, const char *str, GError **error);
|
||||
|
||||
const char * nmc_device_state_to_string (NMDeviceState state);
|
||||
const char * nmc_device_reason_to_string (NMDeviceStateReason reason);
|
||||
|
|
|
|||
|
|
@ -3470,29 +3470,6 @@ _parse_ip_address (int family, const char *address, GError **error)
|
|||
return ipaddr;
|
||||
}
|
||||
|
||||
static NMIPRoute *
|
||||
_parse_ip_route (int family, const char *route, GError **error)
|
||||
{
|
||||
char *value = g_strdup (route);
|
||||
char **routev;
|
||||
guint len;
|
||||
NMIPRoute *iproute = NULL;
|
||||
|
||||
routev = nmc_strsplit_set (g_strstrip (value), " \t", 0);
|
||||
len = g_strv_length (routev);
|
||||
if (len < 1 || len > 3) {
|
||||
g_set_error (error, 1, 0, _("'%s' is not valid (the format is: ip[/prefix] [next-hop] [metric])"),
|
||||
route);
|
||||
goto finish;
|
||||
}
|
||||
iproute = nmc_parse_and_build_route (family, routev[0], routev[1], len >= 2 ? routev[2] : NULL, error);
|
||||
|
||||
finish:
|
||||
g_free (value);
|
||||
g_strfreev (routev);
|
||||
return iproute;
|
||||
}
|
||||
|
||||
DEFINE_GETTER (nmc_property_ipv4_get_method, NM_SETTING_IP_CONFIG_METHOD)
|
||||
DEFINE_GETTER (nmc_property_ipv4_get_dns, NM_SETTING_IP_CONFIG_DNS)
|
||||
DEFINE_GETTER (nmc_property_ipv4_get_dns_search, NM_SETTING_IP_CONFIG_DNS_SEARCH)
|
||||
|
|
@ -3536,8 +3513,21 @@ nmc_property_ipvx_get_routes (NMSetting *setting, NmcPropertyGetType get_type)
|
|||
|
||||
num_routes = nm_setting_ip_config_get_num_routes (s_ip);
|
||||
for (i = 0; i < num_routes; i++) {
|
||||
gs_free char *attr_str = NULL;
|
||||
gs_strfreev char **attr_names = NULL;
|
||||
gs_unref_hashtable GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
int j;
|
||||
|
||||
route = nm_setting_ip_config_get_route (s_ip, i);
|
||||
|
||||
attr_names = nm_ip_route_get_attribute_names (route);
|
||||
for (j = 0; attr_names && attr_names[j]; j++) {
|
||||
g_hash_table_insert (hash, attr_names[j],
|
||||
nm_ip_route_get_attribute (route, attr_names[j]));
|
||||
}
|
||||
|
||||
attr_str = nm_utils_format_variant_attributes (hash, ' ', '=');
|
||||
|
||||
if (get_type == NMC_PROPERTY_GET_PARSABLE) {
|
||||
if (printable->len > 0)
|
||||
g_string_append (printable, ", ");
|
||||
|
|
@ -3550,7 +3540,10 @@ nmc_property_ipvx_get_routes (NMSetting *setting, NmcPropertyGetType get_type)
|
|||
g_string_append_printf (printable, " %s", nm_ip_route_get_next_hop (route));
|
||||
if (nm_ip_route_get_metric (route) != -1)
|
||||
g_string_append_printf (printable, " %u", (guint32) nm_ip_route_get_metric (route));
|
||||
if (attr_str)
|
||||
g_string_append_printf (printable, " %s", attr_str);
|
||||
} else {
|
||||
|
||||
if (printable->len > 0)
|
||||
g_string_append (printable, "; ");
|
||||
|
||||
|
|
@ -3567,6 +3560,8 @@ nmc_property_ipvx_get_routes (NMSetting *setting, NmcPropertyGetType get_type)
|
|||
|
||||
if (nm_ip_route_get_metric (route) != -1)
|
||||
g_string_append_printf (printable, ", mt = %u", (guint32) nm_ip_route_get_metric (route));
|
||||
if (attr_str)
|
||||
g_string_append_printf (printable, " %s", attr_str);
|
||||
|
||||
g_string_append (printable, " }");
|
||||
}
|
||||
|
|
@ -3858,7 +3853,7 @@ nmc_property_ipv4_set_gateway (NMSetting *setting, const char *prop, const char
|
|||
static NMIPRoute *
|
||||
_parse_ipv4_route (const char *route, GError **error)
|
||||
{
|
||||
return _parse_ip_route (AF_INET, route, error);
|
||||
return nmc_parse_and_build_route (AF_INET, route, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -4201,7 +4196,7 @@ nmc_property_ipv6_set_gateway (NMSetting *setting, const char *prop, const char
|
|||
static NMIPRoute *
|
||||
_parse_ipv6_route (const char *route, GError **error)
|
||||
{
|
||||
return _parse_ip_route (AF_INET6, route, error);
|
||||
return nmc_parse_and_build_route (AF_INET6, route, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
|||
|
|
@ -428,6 +428,31 @@ read_one_ip_address_or_route (KeyfileReaderInfo *info,
|
|||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
fill_route_attributes (GKeyFile *kf, NMIPRoute *route, const char *setting, const char *key, int family)
|
||||
{
|
||||
gs_free char *value = NULL;
|
||||
gs_unref_hashtable GHashTable *hash = NULL;
|
||||
GHashTableIter iter;
|
||||
char *name;
|
||||
GVariant *variant;
|
||||
|
||||
value = nm_keyfile_plugin_kf_get_string (kf, setting, key, NULL);
|
||||
if (!value || !value[0])
|
||||
return;
|
||||
|
||||
hash = nm_utils_parse_variant_attributes (value, ',', '=', TRUE,
|
||||
nm_ip_route_get_variant_attribute_spec (),
|
||||
NULL);
|
||||
if (hash) {
|
||||
g_hash_table_iter_init (&iter, hash);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant)) {
|
||||
if (nm_ip_route_attribute_validate (name, variant, family, NULL, NULL))
|
||||
nm_ip_route_set_attribute (route, name, g_variant_ref (variant));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ip_address_or_route_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
|
||||
{
|
||||
|
|
@ -454,6 +479,7 @@ ip_address_or_route_parser (KeyfileReaderInfo *info, NMSetting *setting, const c
|
|||
for (key_basename = key_names; *key_basename; key_basename++) {
|
||||
char *key_name;
|
||||
gpointer item;
|
||||
char options_key[128];
|
||||
|
||||
/* -1 means no suffix */
|
||||
if (i >= 0)
|
||||
|
|
@ -463,6 +489,11 @@ ip_address_or_route_parser (KeyfileReaderInfo *info, NMSetting *setting, const c
|
|||
|
||||
item = read_one_ip_address_or_route (info, key, setting_name, key_name, ipv6, routes,
|
||||
gateway ? NULL : &gateway, setting);
|
||||
if (item && routes) {
|
||||
nm_sprintf_buf (options_key, "%s_options", key_name);
|
||||
fill_route_attributes (info->keyfile, item, setting_name, options_key, ipv6 ? AF_INET6 : AF_INET);
|
||||
}
|
||||
|
||||
g_free (key_name);
|
||||
|
||||
if (info->error) {
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ write_ip_values (GKeyFile *file,
|
|||
int family, i;
|
||||
const char *addr, *gw;
|
||||
guint32 plen, metric;
|
||||
char key_name[30], *key_name_idx;
|
||||
char key_name[64], *key_name_idx;
|
||||
|
||||
if (!array->len)
|
||||
return;
|
||||
|
|
@ -188,6 +188,23 @@ write_ip_values (GKeyFile *file,
|
|||
|
||||
sprintf (key_name_idx, "%d", i + 1);
|
||||
nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, output->str);
|
||||
|
||||
if (is_route) {
|
||||
gs_free char *attributes = NULL;
|
||||
gs_strfreev char **names = NULL;
|
||||
gs_unref_hashtable GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
int j;
|
||||
|
||||
names = nm_ip_route_get_attribute_names (array->pdata[i]);
|
||||
for (j = 0; names && names[j]; j++)
|
||||
g_hash_table_insert (hash, names[j], nm_ip_route_get_attribute (array->pdata[i], names[j]));
|
||||
|
||||
attributes = nm_utils_format_variant_attributes (hash, ',', '=');
|
||||
if (attributes) {
|
||||
g_strlcat (key_name, "_options", sizeof (key_name));
|
||||
nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, attributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
g_string_free (output, TRUE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -615,7 +615,7 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class)
|
|||
* ---end---
|
||||
* ---ifcfg-rh---
|
||||
* property: routes
|
||||
* variable: ADDRESS1, NETMASK1, GATEWAY1, METRIC1, ...
|
||||
* variable: ADDRESS1, NETMASK1, GATEWAY1, METRIC1, OPTIONS1, ...
|
||||
* description: List of static routes. They are not stored in ifcfg-* file,
|
||||
* but in route-* file instead.
|
||||
* ---end---
|
||||
|
|
|
|||
|
|
@ -28,6 +28,14 @@
|
|||
#include "nm-setting-private.h"
|
||||
#include "nm-setting-ip-config.h"
|
||||
|
||||
struct _NMVariantAttributeSpec {
|
||||
char *name;
|
||||
const GVariantType *type;
|
||||
bool v4:1;
|
||||
bool v6:1;
|
||||
char str_type;
|
||||
};
|
||||
|
||||
gboolean _nm_utils_string_slist_validate (GSList *list,
|
||||
const char **valid_values);
|
||||
|
||||
|
|
|
|||
|
|
@ -4697,6 +4697,261 @@ _nm_utils_team_config_equal (const char *conf1,
|
|||
}
|
||||
#endif
|
||||
|
||||
static char *
|
||||
attribute_escape (const char *src, char c1, char c2)
|
||||
{
|
||||
char *ret, *dest;
|
||||
|
||||
dest = ret = malloc (strlen (src) * 2 + 1);
|
||||
|
||||
while (*src) {
|
||||
if (*src == c1 || *src == c2 || *src == '\\')
|
||||
*dest++ = '\\';
|
||||
*dest++ = *src++;
|
||||
}
|
||||
*dest++ = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *
|
||||
attribute_unescape (const char *start, const char *end)
|
||||
{
|
||||
char *ret, *dest;
|
||||
|
||||
nm_assert (start <= end);
|
||||
dest = ret = g_malloc (end - start + 1);
|
||||
|
||||
for (; start < end && *start; start++) {
|
||||
if (*start == '\\') {
|
||||
start++;
|
||||
if (!*start)
|
||||
break;
|
||||
}
|
||||
*dest++ = *start;
|
||||
}
|
||||
*dest = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_utils_parse_variant_attributes:
|
||||
* @string: the input string
|
||||
* @attr_separator: the attribute separator character
|
||||
* @key_value_separator: character separating key and values
|
||||
* @ignore_unknown: whether unknown attributes should be ignored
|
||||
* @spec: the attribute format specifiers
|
||||
* @error: (out) (allow-none): location to store the error on failure
|
||||
*
|
||||
* Parse attributes from a string.
|
||||
*
|
||||
* Returns: (transfer full): a #GHashTable mapping attribute names to #GVariant values.
|
||||
*
|
||||
* Since: 1.8
|
||||
*/
|
||||
GHashTable *
|
||||
nm_utils_parse_variant_attributes (const char *string,
|
||||
char attr_separator,
|
||||
char key_value_separator,
|
||||
gboolean ignore_unknown,
|
||||
const NMVariantAttributeSpec *const *spec,
|
||||
GError **error)
|
||||
{
|
||||
gs_unref_hashtable GHashTable *ht = NULL;
|
||||
const char *ptr = string, *start = NULL, *sep;
|
||||
GVariant *variant;
|
||||
const NMVariantAttributeSpec * const *s;
|
||||
|
||||
g_return_val_if_fail (string, NULL);
|
||||
g_return_val_if_fail (attr_separator, NULL);
|
||||
g_return_val_if_fail (key_value_separator, NULL);
|
||||
g_return_val_if_fail (!error || !*error, NULL);
|
||||
|
||||
ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
|
||||
|
||||
while (TRUE) {
|
||||
gs_free char *name = NULL, *value = NULL;
|
||||
|
||||
if (!start)
|
||||
start = ptr;
|
||||
if (*ptr == '\\') {
|
||||
ptr++;
|
||||
if (!*ptr) {
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED,
|
||||
_("unterminated escape sequence"));
|
||||
return NULL;
|
||||
}
|
||||
goto next;
|
||||
}
|
||||
if (*ptr == attr_separator || *ptr == '\0') {
|
||||
if (ptr == start) {
|
||||
/* multiple separators */
|
||||
start = NULL;
|
||||
goto next;
|
||||
}
|
||||
|
||||
/* Find the key-value separator */
|
||||
for (sep = start; sep != ptr; sep++) {
|
||||
if (*sep == '\\') {
|
||||
sep++;
|
||||
if (!*sep) {
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED,
|
||||
_("unterminated escape sequence"));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (*sep == key_value_separator)
|
||||
break;
|
||||
}
|
||||
|
||||
if (*sep != key_value_separator) {
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED,
|
||||
_("missing key-value separator '%c'"), key_value_separator);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
name = attribute_unescape (start, sep);
|
||||
value = attribute_unescape (sep + 1, ptr);
|
||||
|
||||
for (s = spec; *s; s++) {
|
||||
if (nm_streq (name, (*s)->name))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!*s) {
|
||||
if (ignore_unknown)
|
||||
goto next;
|
||||
else {
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED,
|
||||
_("unknown attribute '%s'"), name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_variant_type_equal ((*s)->type, G_VARIANT_TYPE_UINT32)) {
|
||||
gint64 num = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, -1);
|
||||
|
||||
if (num == -1) {
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED,
|
||||
_("invalid uint32 value '%s' for attribute '%s'"), value, name);
|
||||
return NULL;
|
||||
}
|
||||
variant = g_variant_new_uint32 (num);
|
||||
} else if (g_variant_type_equal ((*s)->type, G_VARIANT_TYPE_BYTE)) {
|
||||
gint64 num = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT8, -1);
|
||||
|
||||
if (num == -1) {
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED,
|
||||
_("invalid uint8 value '%s' for attribute '%s'"), value, name);
|
||||
return NULL;
|
||||
}
|
||||
variant = g_variant_new_byte ((guchar) num);
|
||||
} else if (g_variant_type_equal ((*s)->type, G_VARIANT_TYPE_BOOLEAN)) {
|
||||
gboolean b;
|
||||
|
||||
if (nm_streq (value, "true"))
|
||||
b = TRUE;
|
||||
else if (nm_streq (value, "false"))
|
||||
b = FALSE;
|
||||
else {
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED,
|
||||
_("invalid boolean value '%s' for attribute '%s'"), value, name);
|
||||
return NULL;
|
||||
}
|
||||
variant = g_variant_new_boolean (b);
|
||||
} else if (g_variant_type_equal ((*s)->type, G_VARIANT_TYPE_STRING)) {
|
||||
variant = g_variant_new_take_string (g_steal_pointer (&value));
|
||||
} else {
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED,
|
||||
_("unsupported attribute '%s' of type '%s'"), name,
|
||||
(char *) (*s)->type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_hash_table_insert (ht, g_steal_pointer (&name), variant);
|
||||
start = NULL;
|
||||
}
|
||||
next:
|
||||
if (*ptr == '\0')
|
||||
break;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return g_steal_pointer (&ht);
|
||||
}
|
||||
|
||||
/*
|
||||
* nm_utils_format_variant_attributes:
|
||||
* @attributes: a #GHashTable mapping attribute names to #GVariant values
|
||||
* @attr_separator: the attribute separator character
|
||||
* @key_value_separator: character separating key and values
|
||||
*
|
||||
* Format attributes to a string.
|
||||
*
|
||||
* Returns: (transfer full): the string representing attributes, or %NULL
|
||||
* in case there are no attributes
|
||||
*
|
||||
* Since: 1.8
|
||||
*/
|
||||
char *
|
||||
nm_utils_format_variant_attributes (GHashTable *attributes,
|
||||
char attr_separator,
|
||||
char key_value_separator)
|
||||
{
|
||||
GString *str = NULL;
|
||||
GVariant *variant;
|
||||
char sep = 0;
|
||||
const char *name, *value;
|
||||
char *escaped;
|
||||
char buf[64];
|
||||
gs_free_list GList *keys = NULL;
|
||||
GList *iter;
|
||||
|
||||
g_return_val_if_fail (attr_separator, NULL);
|
||||
g_return_val_if_fail (key_value_separator, NULL);
|
||||
|
||||
if (!attributes || !g_hash_table_size (attributes))
|
||||
return NULL;
|
||||
|
||||
keys = g_list_sort (g_hash_table_get_keys (attributes), (GCompareFunc) g_strcmp0);
|
||||
str = g_string_new ("");
|
||||
|
||||
for (iter = keys; iter; iter = g_list_next (iter)) {
|
||||
name = iter->data;
|
||||
variant = g_hash_table_lookup (attributes, name);
|
||||
value = NULL;
|
||||
|
||||
if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32))
|
||||
value = nm_sprintf_buf (buf, "%u", g_variant_get_uint32 (variant));
|
||||
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BYTE))
|
||||
value = nm_sprintf_buf (buf, "%hhu", g_variant_get_byte (variant));
|
||||
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN))
|
||||
value = g_variant_get_boolean (variant) ? "true" : "false";
|
||||
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING))
|
||||
value = g_variant_get_string (variant, NULL);
|
||||
else
|
||||
continue;
|
||||
|
||||
if (sep)
|
||||
g_string_append_c (str, sep);
|
||||
|
||||
escaped = attribute_escape (name, attr_separator, key_value_separator);
|
||||
g_string_append (str, escaped);
|
||||
g_free (escaped);
|
||||
|
||||
g_string_append_c (str, key_value_separator);
|
||||
|
||||
escaped = attribute_escape (value, attr_separator, key_value_separator);
|
||||
g_string_append (str, escaped);
|
||||
g_free (escaped);
|
||||
|
||||
sep = attr_separator;
|
||||
}
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _NMVariantAttributeSpec NMVariantAttributeSpec;
|
||||
|
||||
/* SSID helpers */
|
||||
gboolean nm_utils_is_empty_ssid (const guint8 *ssid, gsize len);
|
||||
const char *nm_utils_escape_ssid (const guint8 *ssid, gsize len);
|
||||
|
|
@ -215,6 +217,19 @@ const char **nm_utils_enum_get_values (GType type, gint from, gint to);
|
|||
NM_AVAILABLE_IN_1_6
|
||||
guint nm_utils_version (void);
|
||||
|
||||
NM_AVAILABLE_IN_1_8
|
||||
GHashTable * nm_utils_parse_variant_attributes (const char *string,
|
||||
char attr_separator,
|
||||
char key_value_separator,
|
||||
gboolean ignore_unknown,
|
||||
const NMVariantAttributeSpec *const *spec,
|
||||
GError **error);
|
||||
|
||||
NM_AVAILABLE_IN_1_8
|
||||
char * nm_utils_format_variant_attributes (GHashTable *attributes,
|
||||
char attr_separator,
|
||||
char key_value_separator);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __NM_UTILS_H__ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -1163,4 +1165,6 @@ global:
|
|||
nm_setting_dummy_get_type;
|
||||
nm_setting_dummy_new;
|
||||
nm_setting_gsm_get_mtu;
|
||||
nm_utils_format_variant_attributes;
|
||||
nm_utils_parse_variant_attributes;
|
||||
} libnm_1_6_0;
|
||||
|
|
|
|||
|
|
@ -1291,6 +1291,50 @@ nmtst_setting_ip_config_add_route (NMSettingIPConfig *s_ip,
|
|||
g_assert (nm_setting_ip_config_add_route (s_ip, route));
|
||||
nm_ip_route_unref (route);
|
||||
}
|
||||
|
||||
inline static void
|
||||
nmtst_assert_route_attribute_string (NMIPRoute *route, const char *name, const char *value)
|
||||
{
|
||||
GVariant *variant;
|
||||
|
||||
variant = nm_ip_route_get_attribute (route, name);
|
||||
g_assert (variant);
|
||||
g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING));
|
||||
g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, value);
|
||||
}
|
||||
|
||||
inline static void
|
||||
nmtst_assert_route_attribute_byte (NMIPRoute *route, const char *name, guchar value)
|
||||
{
|
||||
GVariant *variant;
|
||||
|
||||
variant = nm_ip_route_get_attribute (route, name);
|
||||
g_assert (variant);
|
||||
g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_BYTE));
|
||||
g_assert_cmpint (g_variant_get_byte (variant), ==, value);
|
||||
}
|
||||
|
||||
inline static void
|
||||
nmtst_assert_route_attribute_uint32 (NMIPRoute *route, const char *name, guint32 value)
|
||||
{
|
||||
GVariant *variant;
|
||||
|
||||
variant = nm_ip_route_get_attribute (route, name);
|
||||
g_assert (variant);
|
||||
g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32));
|
||||
g_assert_cmpint (g_variant_get_uint32 (variant), ==, value);
|
||||
}
|
||||
|
||||
inline static void
|
||||
nmtst_assert_route_attribute_boolean (NMIPRoute *route, const char *name, gboolean value)
|
||||
{
|
||||
GVariant *variant;
|
||||
|
||||
variant = nm_ip_route_get_attribute (route, name);
|
||||
g_assert (variant);
|
||||
g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN));
|
||||
g_assert_cmpint (g_variant_get_boolean (variant), ==, value);
|
||||
}
|
||||
#endif /* NM_SETTING_IP_CONFIG_H */
|
||||
|
||||
#if (defined(__NM_SIMPLE_CONNECTION_H__) && defined(__NM_SETTING_CONNECTION_H__)) || (defined(NM_CONNECTION_H))
|
||||
|
|
@ -1661,6 +1705,7 @@ nmtst_assert_hwaddr_equals (gconstpointer hwaddr1, gssize hwaddr1_len, const cha
|
|||
nmtst_assert_hwaddr_equals (hwaddr1, hwaddr1_len, expected, __FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__NM_SIMPLE_CONNECTION_H__) && defined(__NM_SETTING_CONNECTION_H__) && defined(__NM_KEYFILE_INTERNAL_H__)
|
||||
|
||||
static inline NMConnection *
|
||||
|
|
|
|||
|
|
@ -301,24 +301,21 @@ _platform_route_sync_add (const VTableIP *vtable, NMDefaultRouteManager *self, g
|
|||
return FALSE;
|
||||
|
||||
if (vtable->vt->is_ip4) {
|
||||
success = nm_platform_ip4_route_add (priv->platform,
|
||||
entry->route.rx.ifindex,
|
||||
entry->route.rx.rt_source,
|
||||
0,
|
||||
0,
|
||||
entry->route.r4.gateway,
|
||||
0,
|
||||
entry->effective_metric,
|
||||
entry->route.rx.mss);
|
||||
NMPlatformIP4Route rt = entry->route.r4;
|
||||
|
||||
rt.network = 0;
|
||||
rt.plen = 0;
|
||||
rt.metric = entry->effective_metric;
|
||||
|
||||
success = nm_platform_ip4_route_add (priv->platform, &rt);
|
||||
} else {
|
||||
success = nm_platform_ip6_route_add (priv->platform,
|
||||
entry->route.rx.ifindex,
|
||||
entry->route.rx.rt_source,
|
||||
in6addr_any,
|
||||
0,
|
||||
entry->route.r6.gateway,
|
||||
entry->effective_metric,
|
||||
entry->route.rx.mss);
|
||||
NMPlatformIP6Route rt = entry->route.r6;
|
||||
|
||||
rt.network = in6addr_any;
|
||||
rt.plen = 0;
|
||||
rt.metric = entry->effective_metric;
|
||||
|
||||
success = nm_platform_ip6_route_add (priv->platform, &rt);
|
||||
}
|
||||
if (!success) {
|
||||
_LOGW (vtable->vt->addr_family, "failed to add default route %s with effective metric %u",
|
||||
|
|
|
|||
|
|
@ -412,6 +412,38 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_fu
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
merge_route_attributes (NMIPRoute *s_route, NMPlatformIP4Route *r)
|
||||
{
|
||||
GVariant *variant;
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
if ( (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_PREF_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;
|
||||
}
|
||||
|
||||
#undef GET_ATTR
|
||||
}
|
||||
|
||||
void
|
||||
nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, guint32 default_route_metric)
|
||||
{
|
||||
|
|
@ -492,6 +524,7 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu
|
|||
route.metric = nm_ip_route_get_metric (s_route);
|
||||
route.rt_source = NM_IP_CONFIG_SOURCE_USER;
|
||||
|
||||
merge_route_attributes (s_route, &route);
|
||||
nm_ip4_config_add_route (config, &route);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -416,6 +416,57 @@ nm_ip6_config_commit (const NMIP6Config *config, int ifindex, gboolean routes_fu
|
|||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
merge_route_attributes (NMIPRoute *s_route, NMPlatformIP6Route *r)
|
||||
{
|
||||
GVariant *variant;
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
if ( (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_PREF_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_SRC))
|
||||
&& 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 *config, NMSettingIPConfig *setting, guint32 default_route_metric)
|
||||
{
|
||||
|
|
@ -492,6 +543,7 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu
|
|||
route.metric = nm_ip_route_get_metric (s_route);
|
||||
route.rt_source = NM_IP_CONFIG_SOURCE_USER;
|
||||
|
||||
merge_route_attributes (s_route, &route);
|
||||
nm_ip6_config_add_route (config, &route);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ nmtst_platform_ip4_route_full (const char *network, guint plen, const char *gate
|
|||
}
|
||||
|
||||
static inline NMPlatformIP6Route *
|
||||
nmtst_platform_ip6_route (const char *network, guint plen, const char *gateway)
|
||||
nmtst_platform_ip6_route (const char *network, guint plen, const char *gateway, const char *pref_src)
|
||||
{
|
||||
static NMPlatformIP6Route route;
|
||||
|
||||
|
|
@ -172,6 +172,7 @@ nmtst_platform_ip6_route (const char *network, guint plen, const char *gateway)
|
|||
route.network = *nmtst_inet6_from_string (network);
|
||||
route.plen = plen;
|
||||
route.gateway = *nmtst_inet6_from_string (gateway);
|
||||
route.pref_src = *nmtst_inet6_from_string (pref_src);
|
||||
|
||||
return &route;
|
||||
}
|
||||
|
|
@ -181,7 +182,7 @@ nmtst_platform_ip6_route_full (const char *network, guint plen, const char *gate
|
|||
int ifindex, NMIPConfigSource source,
|
||||
guint metric, guint mss)
|
||||
{
|
||||
NMPlatformIP6Route *route = nmtst_platform_ip6_route (network, plen, gateway);
|
||||
NMPlatformIP6Route *route = nmtst_platform_ip6_route (network, plen, gateway, NULL);
|
||||
|
||||
route->ifindex = ifindex;
|
||||
route->rt_source = source;
|
||||
|
|
|
|||
|
|
@ -1225,42 +1225,29 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, gu
|
|||
}
|
||||
|
||||
static gboolean
|
||||
ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
||||
in_addr_t network, guint8 plen, in_addr_t gateway,
|
||||
in_addr_t pref_src, guint32 metric, guint32 mss)
|
||||
ip4_route_add (NMPlatform *platform, const NMPlatformIP4Route *route)
|
||||
{
|
||||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
|
||||
NMPlatformIP4Route route;
|
||||
NMPlatformIP4Route rt = *route;
|
||||
guint i;
|
||||
guint8 scope;
|
||||
|
||||
g_assert (plen <= 32);
|
||||
rt.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (rt.rt_source);
|
||||
rt.network = nm_utils_ip4_address_clear_host_address (rt.network, rt.plen);
|
||||
rt.scope_inv = nm_platform_route_scope_inv (rt.gateway ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK);
|
||||
|
||||
scope = gateway == 0 ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
|
||||
|
||||
memset (&route, 0, sizeof (route));
|
||||
route.ifindex = ifindex;
|
||||
route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (source);
|
||||
route.network = nm_utils_ip4_address_clear_host_address (network, plen);
|
||||
route.plen = plen;
|
||||
route.gateway = gateway;
|
||||
route.metric = metric;
|
||||
route.mss = mss;
|
||||
route.scope_inv = nm_platform_route_scope_inv (scope);
|
||||
|
||||
if (gateway) {
|
||||
if (rt.gateway) {
|
||||
for (i = 0; i < priv->ip4_routes->len; i++) {
|
||||
NMPlatformIP4Route *item = &g_array_index (priv->ip4_routes,
|
||||
NMPlatformIP4Route, i);
|
||||
guint32 gate = ntohl (item->network) >> (32 - item->plen);
|
||||
guint32 host = ntohl (gateway) >> (32 - item->plen);
|
||||
guint32 host = ntohl (rt.gateway) >> (32 - item->plen);
|
||||
|
||||
if (ifindex == item->ifindex && gate == host)
|
||||
if (rt.ifindex == item->ifindex && gate == host)
|
||||
break;
|
||||
}
|
||||
if (i == priv->ip4_routes->len) {
|
||||
nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip4-route '%d: %s/%d %d': Network Unreachable",
|
||||
route.ifindex, nm_utils_inet4_ntop (route.network, NULL), route.plen, route.metric);
|
||||
rt.ifindex, nm_utils_inet4_ntop (rt.network, NULL), rt.plen, rt.metric);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1268,65 +1255,58 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
|||
for (i = 0; i < priv->ip4_routes->len; i++) {
|
||||
NMPlatformIP4Route *item = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
|
||||
|
||||
if (item->network != route.network)
|
||||
if (item->network != rt.network)
|
||||
continue;
|
||||
if (item->plen != route.plen)
|
||||
if (item->plen != rt.plen)
|
||||
continue;
|
||||
if (item->metric != metric)
|
||||
if (item->metric != rt.metric)
|
||||
continue;
|
||||
|
||||
if (item->ifindex != route.ifindex) {
|
||||
if (item->ifindex != rt.ifindex) {
|
||||
ip4_route_delete (platform, item->ifindex, item->network, item->plen, item->metric);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy (item, &route, sizeof (route));
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, (int) NMP_OBJECT_TYPE_IP4_ROUTE, ifindex, &route, (int) NM_PLATFORM_SIGNAL_CHANGED);
|
||||
memcpy (item, &rt, sizeof (rt));
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, (int) NMP_OBJECT_TYPE_IP4_ROUTE,
|
||||
rt.ifindex, &rt, (int) NM_PLATFORM_SIGNAL_CHANGED);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_array_append_val (priv->ip4_routes, route);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, (int) NMP_OBJECT_TYPE_IP4_ROUTE, ifindex, &route, (int) NM_PLATFORM_SIGNAL_ADDED);
|
||||
g_array_append_val (priv->ip4_routes, rt);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, (int) NMP_OBJECT_TYPE_IP4_ROUTE,
|
||||
rt.ifindex, &rt, (int) NM_PLATFORM_SIGNAL_ADDED);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
||||
struct in6_addr network, guint8 plen, struct in6_addr gateway,
|
||||
guint32 metric, guint32 mss)
|
||||
ip6_route_add (NMPlatform *platform, const NMPlatformIP6Route *route)
|
||||
{
|
||||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
|
||||
NMPlatformIP6Route route;
|
||||
NMPlatformIP6Route rt = *route;
|
||||
guint i;
|
||||
|
||||
metric = nm_utils_ip6_route_metric_normalize (metric);
|
||||
rt.metric = nm_utils_ip6_route_metric_normalize (rt.metric);
|
||||
rt.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (rt.rt_source);
|
||||
nm_utils_ip6_address_clear_host_address (&rt.network, &rt.network, rt.plen);
|
||||
|
||||
memset (&route, 0, sizeof (route));
|
||||
route.ifindex = ifindex;
|
||||
route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (source);
|
||||
nm_utils_ip6_address_clear_host_address (&route.network, &network, plen);
|
||||
route.plen = plen;
|
||||
route.gateway = gateway;
|
||||
route.metric = metric;
|
||||
route.mss = mss;
|
||||
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&gateway)) {
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED (&rt.gateway)) {
|
||||
for (i = 0; i < priv->ip6_routes->len; i++) {
|
||||
NMPlatformIP6Route *item = &g_array_index (priv->ip6_routes,
|
||||
NMPlatformIP6Route, i);
|
||||
guint8 gate_bits = gateway.s6_addr[item->plen / 8] >> (8 - item->plen % 8);
|
||||
guint8 gate_bits = rt.gateway.s6_addr[item->plen / 8] >> (8 - item->plen % 8);
|
||||
guint8 host_bits = item->network.s6_addr[item->plen / 8] >> (8 - item->plen % 8);
|
||||
|
||||
if ( ifindex == item->ifindex
|
||||
&& memcmp (&gateway, &item->network, item->plen / 8) == 0
|
||||
if ( rt.ifindex == item->ifindex
|
||||
&& memcmp (&rt.gateway, &item->network, item->plen / 8) == 0
|
||||
&& gate_bits == host_bits)
|
||||
break;
|
||||
}
|
||||
if (i == priv->ip6_routes->len) {
|
||||
nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip6-route '%d: %s/%d %d': Network Unreachable",
|
||||
route.ifindex, nm_utils_inet6_ntop (&route.network, NULL), route.plen, route.metric);
|
||||
rt.ifindex, nm_utils_inet6_ntop (&rt.network, NULL), rt.plen, rt.metric);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1334,26 +1314,28 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
|||
for (i = 0; i < priv->ip6_routes->len; i++) {
|
||||
NMPlatformIP6Route *item = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i);
|
||||
|
||||
if (!IN6_ARE_ADDR_EQUAL (&item->network, &route.network))
|
||||
if (!IN6_ARE_ADDR_EQUAL (&item->network, &rt.network))
|
||||
continue;
|
||||
if (item->plen != route.plen)
|
||||
if (item->plen != rt.plen)
|
||||
continue;
|
||||
if (item->metric != metric)
|
||||
if (item->metric != rt.metric)
|
||||
continue;
|
||||
|
||||
if (item->ifindex != route.ifindex) {
|
||||
if (item->ifindex != rt.ifindex) {
|
||||
ip6_route_delete (platform, item->ifindex, item->network, item->plen, item->metric);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy (item, &route, sizeof (route));
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, (int) NMP_OBJECT_TYPE_IP6_ROUTE, ifindex, &route, (int) NM_PLATFORM_SIGNAL_CHANGED);
|
||||
memcpy (item, &rt, sizeof (rt));
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, (int) NMP_OBJECT_TYPE_IP6_ROUTE,
|
||||
rt.ifindex, &rt, (int) NM_PLATFORM_SIGNAL_CHANGED);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_array_append_val (priv->ip6_routes, route);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, (int) NMP_OBJECT_TYPE_IP6_ROUTE, ifindex, &route, (int) NM_PLATFORM_SIGNAL_ADDED);
|
||||
g_array_append_val (priv->ip6_routes, rt);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, (int) NMP_OBJECT_TYPE_IP6_ROUTE,
|
||||
rt.ifindex, &rt, (int) NM_PLATFORM_SIGNAL_ADDED);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1833,6 +1833,7 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
|
|||
NMIPAddr gateway;
|
||||
} nh;
|
||||
guint32 mss;
|
||||
guint32 window = 0, cwnd = 0, initcwnd = 0, initrwnd = 0, mtu = 0, lock = 0;
|
||||
guint32 table;
|
||||
|
||||
if (!nlmsg_valid_hdr (nlh, sizeof (*rtm)))
|
||||
|
|
@ -1846,8 +1847,7 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
|
|||
if (!NM_IN_SET (rtm->rtm_family, AF_INET, AF_INET6))
|
||||
goto errout;
|
||||
|
||||
if ( rtm->rtm_type != RTN_UNICAST
|
||||
|| rtm->rtm_tos != 0)
|
||||
if (rtm->rtm_type != RTN_UNICAST)
|
||||
goto errout;
|
||||
|
||||
err = nlmsg_parse (nlh, sizeof (struct rtmsg), tb, RTA_MAX, policy);
|
||||
|
|
@ -1941,21 +1941,34 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
|
|||
mss = 0;
|
||||
if (tb[RTA_METRICS]) {
|
||||
struct nlattr *mtb[RTAX_MAX + 1];
|
||||
int i;
|
||||
static struct nla_policy rtax_policy[RTAX_MAX + 1] = {
|
||||
[RTAX_LOCK] = { .type = NLA_U32 },
|
||||
[RTAX_ADVMSS] = { .type = NLA_U32 },
|
||||
[RTAX_WINDOW] = { .type = NLA_U32 },
|
||||
[RTAX_CWND] = { .type = NLA_U32 },
|
||||
[RTAX_INITCWND] = { .type = NLA_U32 },
|
||||
[RTAX_INITRWND] = { .type = NLA_U32 },
|
||||
[RTAX_MTU] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
err = nla_parse_nested(mtb, RTAX_MAX, tb[RTA_METRICS], NULL);
|
||||
err = nla_parse_nested (mtb, RTAX_MAX, tb[RTA_METRICS], rtax_policy);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
for (i = 1; i <= RTAX_MAX; i++) {
|
||||
if (mtb[i]) {
|
||||
if (i == RTAX_ADVMSS) {
|
||||
if (nla_len (mtb[i]) >= sizeof (uint32_t))
|
||||
mss = nla_get_u32(mtb[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mtb[RTAX_LOCK])
|
||||
lock = nla_get_u32 (mtb[RTAX_LOCK]);
|
||||
if (mtb[RTAX_ADVMSS])
|
||||
mss = nla_get_u32 (mtb[RTAX_ADVMSS]);
|
||||
if (mtb[RTAX_WINDOW])
|
||||
window = nla_get_u32 (mtb[RTAX_WINDOW]);
|
||||
if (mtb[RTAX_CWND])
|
||||
cwnd = nla_get_u32 (mtb[RTAX_CWND]);
|
||||
if (mtb[RTAX_INITCWND])
|
||||
initcwnd = nla_get_u32 (mtb[RTAX_INITCWND]);
|
||||
if (mtb[RTAX_INITRWND])
|
||||
initrwnd = nla_get_u32 (mtb[RTAX_INITRWND]);
|
||||
if (mtb[RTAX_MTU])
|
||||
mtu = nla_get_u32 (mtb[RTAX_MTU]);
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
|
|
@ -1980,12 +1993,31 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
|
|||
if (is_v4)
|
||||
obj->ip4_route.scope_inv = nm_platform_route_scope_inv (rtm->rtm_scope);
|
||||
|
||||
if (is_v4) {
|
||||
if (_check_addr_or_errout (tb, RTA_PREFSRC, addr_len))
|
||||
if (_check_addr_or_errout (tb, RTA_PREFSRC, addr_len)) {
|
||||
if (is_v4)
|
||||
memcpy (&obj->ip4_route.pref_src, nla_data (tb[RTA_PREFSRC]), addr_len);
|
||||
else
|
||||
memcpy (&obj->ip6_route.pref_src, nla_data (tb[RTA_PREFSRC]), addr_len);
|
||||
}
|
||||
|
||||
if (!is_v4 && tb[RTA_SRC]) {
|
||||
_check_addr_or_errout (tb, RTA_SRC, addr_len);
|
||||
memcpy (&obj->ip6_route.src, nla_data (tb[RTA_SRC]), addr_len);
|
||||
obj->ip6_route.src_plen = rtm->rtm_src_len;
|
||||
}
|
||||
|
||||
obj->ip_route.mss = mss;
|
||||
obj->ip_route.window = window;
|
||||
obj->ip_route.cwnd = cwnd;
|
||||
obj->ip_route.initcwnd = initcwnd;
|
||||
obj->ip_route.initrwnd = initrwnd;
|
||||
obj->ip_route.mtu = mtu;
|
||||
obj->ip_route.tos = rtm->rtm_tos;
|
||||
obj->ip_route.lock_window = NM_FLAGS_HAS (lock, 1 << RTAX_WINDOW);
|
||||
obj->ip_route.lock_cwnd = NM_FLAGS_HAS (lock, 1 << RTAX_CWND);
|
||||
obj->ip_route.lock_initcwnd = NM_FLAGS_HAS (lock, 1 << RTAX_INITCWND);
|
||||
obj->ip_route.lock_initrwnd = NM_FLAGS_HAS (lock, 1 << RTAX_INITRWND);
|
||||
obj->ip_route.lock_mtu = NM_FLAGS_HAS (lock, 1 << RTAX_MTU);
|
||||
|
||||
if (NM_FLAGS_HAS (rtm->rtm_flags, RTM_F_CLONED)) {
|
||||
/* we must not straight way reject cloned routes, because we might have cached
|
||||
|
|
@ -2360,19 +2392,28 @@ _nl_msg_new_route (int nlmsg_type,
|
|||
gconstpointer gateway,
|
||||
guint32 metric,
|
||||
guint32 mss,
|
||||
gconstpointer pref_src)
|
||||
gconstpointer pref_src,
|
||||
gconstpointer src,
|
||||
guint8 src_plen,
|
||||
guint8 tos,
|
||||
guint32 window,
|
||||
guint32 cwnd,
|
||||
guint32 initcwnd,
|
||||
guint32 initrwnd,
|
||||
guint32 mtu,
|
||||
guint32 lock)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
struct rtmsg rtmsg = {
|
||||
.rtm_family = family,
|
||||
.rtm_tos = 0,
|
||||
.rtm_tos = tos,
|
||||
.rtm_table = RT_TABLE_MAIN, /* omit setting RTA_TABLE attribute */
|
||||
.rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot (source),
|
||||
.rtm_scope = scope,
|
||||
.rtm_type = RTN_UNICAST,
|
||||
.rtm_flags = 0,
|
||||
.rtm_dst_len = plen,
|
||||
.rtm_src_len = 0,
|
||||
.rtm_src_len = src ? src_plen : 0,
|
||||
};
|
||||
NMIPAddr network_clean;
|
||||
|
||||
|
|
@ -2394,19 +2435,35 @@ _nl_msg_new_route (int nlmsg_type,
|
|||
nm_utils_ipx_address_clear_host_address (family, &network_clean, network, plen);
|
||||
NLA_PUT (msg, RTA_DST, addr_len, &network_clean);
|
||||
|
||||
if (src)
|
||||
NLA_PUT (msg, RTA_SRC, addr_len, src);
|
||||
|
||||
NLA_PUT_U32 (msg, RTA_PRIORITY, metric);
|
||||
|
||||
if (pref_src)
|
||||
NLA_PUT (msg, RTA_PREFSRC, addr_len, pref_src);
|
||||
|
||||
if (mss > 0) {
|
||||
if (mss || window || cwnd || initcwnd || initrwnd || mtu || lock) {
|
||||
struct nlattr *metrics;
|
||||
|
||||
metrics = nla_nest_start (msg, RTA_METRICS);
|
||||
if (!metrics)
|
||||
goto nla_put_failure;
|
||||
|
||||
NLA_PUT_U32 (msg, RTAX_ADVMSS, mss);
|
||||
if (mss)
|
||||
NLA_PUT_U32 (msg, RTAX_ADVMSS, mss);
|
||||
if (window)
|
||||
NLA_PUT_U32 (msg, RTAX_WINDOW, window);
|
||||
if (cwnd)
|
||||
NLA_PUT_U32 (msg, RTAX_CWND, cwnd);
|
||||
if (initcwnd)
|
||||
NLA_PUT_U32 (msg, RTAX_INITCWND, initcwnd);
|
||||
if (initrwnd)
|
||||
NLA_PUT_U32 (msg, RTAX_INITRWND, initrwnd);
|
||||
if (mtu)
|
||||
NLA_PUT_U32 (msg, RTAX_MTU, mtu);
|
||||
if (lock)
|
||||
NLA_PUT_U32 (msg, RTAX_LOCK, lock);
|
||||
|
||||
nla_nest_end(msg, metrics);
|
||||
}
|
||||
|
|
@ -5901,53 +5958,85 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags fl
|
|||
return ipx_route_get_all (platform, ifindex, NMP_OBJECT_TYPE_IP6_ROUTE, flags);
|
||||
}
|
||||
|
||||
static guint32
|
||||
ip_route_get_lock_flag (NMPlatformIPRoute *route)
|
||||
{
|
||||
return (((guint32) route->lock_window) << RTAX_WINDOW)
|
||||
| (((guint32) route->lock_cwnd) << RTAX_CWND)
|
||||
| (((guint32) route->lock_initcwnd) << RTAX_INITCWND)
|
||||
| (((guint32) route->lock_initrwnd) << RTAX_INITRWND)
|
||||
| (((guint32) route->lock_mtu) << RTAX_MTU);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
||||
in_addr_t network, guint8 plen, in_addr_t gateway,
|
||||
in_addr_t pref_src, guint32 metric, guint32 mss)
|
||||
ip4_route_add (NMPlatform *platform, const NMPlatformIP4Route *route)
|
||||
{
|
||||
NMPObject obj_id;
|
||||
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
|
||||
in_addr_t network;
|
||||
|
||||
network = nm_utils_ip4_address_clear_host_address (route->network, route->plen);
|
||||
|
||||
/* FIXME: take the scope from route into account */
|
||||
nlmsg = _nl_msg_new_route (RTM_NEWROUTE,
|
||||
NLM_F_CREATE | NLM_F_REPLACE,
|
||||
AF_INET,
|
||||
ifindex,
|
||||
source,
|
||||
gateway ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK,
|
||||
route->ifindex,
|
||||
route->rt_source,
|
||||
route->gateway ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK,
|
||||
&network,
|
||||
plen,
|
||||
&gateway,
|
||||
metric,
|
||||
mss,
|
||||
pref_src ? &pref_src : NULL);
|
||||
route->plen,
|
||||
&route->gateway,
|
||||
route->metric,
|
||||
route->mss,
|
||||
route->pref_src ? &route->pref_src : NULL,
|
||||
NULL,
|
||||
0,
|
||||
route->tos,
|
||||
route->window,
|
||||
route->cwnd,
|
||||
route->initcwnd,
|
||||
route->initrwnd,
|
||||
route->mtu,
|
||||
ip_route_get_lock_flag ((NMPlatformIPRoute *) route));
|
||||
|
||||
nmp_object_stackinit_id_ip4_route (&obj_id, ifindex, network, plen, metric);
|
||||
nmp_object_stackinit_id_ip4_route (&obj_id, route->ifindex, network, route->plen, route->metric);
|
||||
return do_add_addrroute (platform, &obj_id, nlmsg);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
||||
struct in6_addr network, guint8 plen, struct in6_addr gateway,
|
||||
guint32 metric, guint32 mss)
|
||||
ip6_route_add (NMPlatform *platform, const NMPlatformIP6Route *route)
|
||||
{
|
||||
NMPObject obj_id;
|
||||
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
|
||||
struct in6_addr network;
|
||||
|
||||
nm_utils_ip6_address_clear_host_address (&network, &route->network, route->plen);
|
||||
|
||||
/* FIXME: take the scope from route into account */
|
||||
nlmsg = _nl_msg_new_route (RTM_NEWROUTE,
|
||||
NLM_F_CREATE | NLM_F_REPLACE,
|
||||
AF_INET6,
|
||||
ifindex,
|
||||
source,
|
||||
!IN6_IS_ADDR_UNSPECIFIED (&gateway) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK,
|
||||
route->ifindex,
|
||||
route->rt_source,
|
||||
IN6_IS_ADDR_UNSPECIFIED (&route->gateway) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE,
|
||||
&network,
|
||||
plen,
|
||||
&gateway,
|
||||
metric,
|
||||
mss,
|
||||
NULL);
|
||||
route->plen,
|
||||
&route->gateway,
|
||||
route->metric,
|
||||
route->mss,
|
||||
!IN6_IS_ADDR_UNSPECIFIED (&route->pref_src) ? &route->pref_src : NULL,
|
||||
!IN6_IS_ADDR_UNSPECIFIED (&route->src) ? &route->src : NULL,
|
||||
route->src_plen,
|
||||
route->tos,
|
||||
route->window,
|
||||
route->cwnd,
|
||||
route->initcwnd,
|
||||
route->initrwnd,
|
||||
route->mtu,
|
||||
ip_route_get_lock_flag ((NMPlatformIPRoute *) route));
|
||||
|
||||
nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric);
|
||||
nmp_object_stackinit_id_ip6_route (&obj_id, route->ifindex, &network, route->plen, route->metric);
|
||||
return do_add_addrroute (platform, &obj_id, nlmsg);
|
||||
}
|
||||
|
||||
|
|
@ -6000,7 +6089,16 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 p
|
|||
NULL,
|
||||
metric,
|
||||
0,
|
||||
NULL);
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
if (!nlmsg)
|
||||
return FALSE;
|
||||
|
||||
|
|
@ -6026,7 +6124,16 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, gu
|
|||
NULL,
|
||||
metric,
|
||||
0,
|
||||
NULL);
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
if (!nlmsg)
|
||||
return FALSE;
|
||||
|
||||
|
|
|
|||
|
|
@ -3109,14 +3109,7 @@ nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRoute
|
|||
/**
|
||||
* nm_platform_ip4_route_add:
|
||||
* @self:
|
||||
* @ifindex:
|
||||
* @source:
|
||||
* network:
|
||||
* plen:
|
||||
* gateway:
|
||||
* pref_src:
|
||||
* metric:
|
||||
* mss:
|
||||
* @route:
|
||||
*
|
||||
* For kernel, a gateway can be either explicitly set or left
|
||||
* at zero (0.0.0.0). In addition, there is the scope of the IPv4
|
||||
|
|
@ -3137,57 +3130,29 @@ nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRoute
|
|||
* Returns: %TRUE in case of success.
|
||||
*/
|
||||
gboolean
|
||||
nm_platform_ip4_route_add (NMPlatform *self,
|
||||
int ifindex, NMIPConfigSource source,
|
||||
in_addr_t network, guint8 plen,
|
||||
in_addr_t gateway, in_addr_t pref_src,
|
||||
guint32 metric, guint32 mss)
|
||||
nm_platform_ip4_route_add (NMPlatform *self, const NMPlatformIP4Route *route)
|
||||
{
|
||||
_CHECK_SELF (self, klass, FALSE);
|
||||
|
||||
g_return_val_if_fail (plen <= 32, FALSE);
|
||||
g_return_val_if_fail (route, FALSE);
|
||||
g_return_val_if_fail (route->plen <= 32, FALSE);
|
||||
|
||||
if (_LOGD_ENABLED ()) {
|
||||
NMPlatformIP4Route route = { 0 };
|
||||
_LOGD ("route: adding or updating IPv4 route: %s", nm_platform_ip4_route_to_string (route, NULL, 0));
|
||||
|
||||
route.ifindex = ifindex;
|
||||
route.rt_source = source;
|
||||
route.network = network;
|
||||
route.plen = plen;
|
||||
route.gateway = gateway;
|
||||
route.metric = metric;
|
||||
route.mss = mss;
|
||||
route.pref_src = pref_src;
|
||||
|
||||
_LOGD ("route: adding or updating IPv4 route: %s", nm_platform_ip4_route_to_string (&route, NULL, 0));
|
||||
}
|
||||
return klass->ip4_route_add (self, ifindex, source, network, plen, gateway, pref_src, metric, mss);
|
||||
return klass->ip4_route_add (self, route);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_platform_ip6_route_add (NMPlatform *self,
|
||||
int ifindex, NMIPConfigSource source,
|
||||
struct in6_addr network, guint8 plen, struct in6_addr gateway,
|
||||
guint32 metric, guint32 mss)
|
||||
nm_platform_ip6_route_add (NMPlatform *self, const NMPlatformIP6Route *route)
|
||||
{
|
||||
_CHECK_SELF (self, klass, FALSE);
|
||||
|
||||
g_return_val_if_fail (plen <= 128, FALSE);
|
||||
g_return_val_if_fail (route, FALSE);
|
||||
g_return_val_if_fail (route->plen <= 128, FALSE);
|
||||
|
||||
if (_LOGD_ENABLED ()) {
|
||||
NMPlatformIP6Route route = { 0 };
|
||||
_LOGD ("route: adding or updating IPv6 route: %s", nm_platform_ip6_route_to_string (route, NULL, 0));
|
||||
|
||||
route.ifindex = ifindex;
|
||||
route.rt_source = source;
|
||||
route.network = network;
|
||||
route.plen = plen;
|
||||
route.gateway = gateway;
|
||||
route.metric = metric;
|
||||
route.mss = mss;
|
||||
|
||||
_LOGD ("route: adding or updating IPv6 route: %s", nm_platform_ip6_route_to_string (&route, NULL, 0));
|
||||
}
|
||||
return klass->ip6_route_add (self, ifindex, source, network, plen, gateway, metric, mss);
|
||||
return klass->ip6_route_add (self, route);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
@ -3900,6 +3865,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
|
|||
char s_pref_src[INET_ADDRSTRLEN];
|
||||
char str_dev[TO_STRING_DEV_BUF_SIZE];
|
||||
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];
|
||||
|
||||
if (!nm_utils_to_string_buffer_init_null (route, &buf, &len))
|
||||
return buf;
|
||||
|
|
@ -3909,16 +3875,35 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
|
|||
|
||||
_to_string_dev (NULL, route->ifindex, str_dev, sizeof (str_dev));
|
||||
|
||||
if (route->tos)
|
||||
nm_sprintf_buf (str_tos, " tos 0x%x", (unsigned) route->tos);
|
||||
if (route->window)
|
||||
nm_sprintf_buf (str_window, " window %s%"G_GUINT32_FORMAT, route->lock_window ? "lock " : "", route->window);
|
||||
if (route->cwnd)
|
||||
nm_sprintf_buf (str_cwnd, " cwnd %s%"G_GUINT32_FORMAT, route->lock_cwnd ? "lock " : "", route->cwnd);
|
||||
if (route->initcwnd)
|
||||
nm_sprintf_buf (str_initcwnd, " initcwnd %s%"G_GUINT32_FORMAT, route->lock_initcwnd ? "lock " : "", route->initcwnd);
|
||||
if (route->initrwnd)
|
||||
nm_sprintf_buf (str_initrwnd, " initrwnd %s%"G_GUINT32_FORMAT, route->lock_initrwnd ? "lock " : "", route->initrwnd);
|
||||
if (route->mtu)
|
||||
nm_sprintf_buf (str_mtu, " mtu %s%"G_GUINT32_FORMAT, route->lock_mtu ? "lock " : "", route->mtu);
|
||||
|
||||
g_snprintf (buf, len,
|
||||
"%s/%d"
|
||||
" via %s"
|
||||
"%s"
|
||||
" metric %"G_GUINT32_FORMAT
|
||||
" mss %"G_GUINT32_FORMAT
|
||||
" src %s" /* source */
|
||||
" rt-src %s" /* protocol */
|
||||
"%s" /* cloned */
|
||||
"%s%s" /* scope */
|
||||
"%s%s" /* pref-src */
|
||||
"%s" /* tos */
|
||||
"%s" /* window */
|
||||
"%s" /* cwnd */
|
||||
"%s" /* initcwnd */
|
||||
"%s" /* initrwnd */
|
||||
"%s" /* mtu */
|
||||
"",
|
||||
s_network,
|
||||
route->plen,
|
||||
|
|
@ -3931,7 +3916,13 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
|
|||
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 " : "",
|
||||
route->pref_src ? inet_ntop (AF_INET, &route->pref_src, s_pref_src, sizeof(s_pref_src)) : "");
|
||||
route->pref_src ? inet_ntop (AF_INET, &route->pref_src, s_pref_src, sizeof(s_pref_src)) : "",
|
||||
route->tos ? str_tos : "",
|
||||
route->window ? str_window : "",
|
||||
route->cwnd ? str_cwnd : "",
|
||||
route->initcwnd ? str_initcwnd : "",
|
||||
route->initrwnd ? str_initrwnd : "",
|
||||
route->mtu ? str_mtu : "");
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
|
@ -3950,25 +3941,54 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
|
|||
const char *
|
||||
nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsize len)
|
||||
{
|
||||
char s_network[INET6_ADDRSTRLEN], s_gateway[INET6_ADDRSTRLEN];
|
||||
char s_network[INET6_ADDRSTRLEN], s_gateway[INET6_ADDRSTRLEN], s_pref_src[INET6_ADDRSTRLEN];
|
||||
char s_src[INET6_ADDRSTRLEN];
|
||||
char str_dev[TO_STRING_DEV_BUF_SIZE], s_source[50];
|
||||
char str_tos[32], str_window[32], str_cwnd[32], str_initcwnd[32], str_initrwnd[32], str_mtu[32];
|
||||
|
||||
if (!nm_utils_to_string_buffer_init_null (route, &buf, &len))
|
||||
return buf;
|
||||
|
||||
inet_ntop (AF_INET6, &route->network, s_network, sizeof(s_network));
|
||||
inet_ntop (AF_INET6, &route->gateway, s_gateway, sizeof(s_gateway));
|
||||
inet_ntop (AF_INET6, &route->network, s_network, sizeof (s_network));
|
||||
inet_ntop (AF_INET6, &route->gateway, s_gateway, sizeof (s_gateway));
|
||||
inet_ntop (AF_INET6, &route->src, s_src, sizeof (s_src));
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED (&route->pref_src))
|
||||
s_pref_src[0] = 0;
|
||||
else
|
||||
inet_ntop (AF_INET6, &route->pref_src, s_pref_src, sizeof (s_pref_src));
|
||||
|
||||
_to_string_dev (NULL, route->ifindex, str_dev, sizeof (str_dev));
|
||||
|
||||
if (route->tos)
|
||||
nm_sprintf_buf (str_tos, " tos 0x%x", (unsigned) route->tos);
|
||||
if (route->window)
|
||||
nm_sprintf_buf (str_window, " window %s%"G_GUINT32_FORMAT, route->lock_window ? "lock " : "", route->window);
|
||||
if (route->cwnd)
|
||||
nm_sprintf_buf (str_cwnd, " cwnd %s%"G_GUINT32_FORMAT, route->lock_cwnd ? "lock " : "", route->cwnd);
|
||||
if (route->initcwnd)
|
||||
nm_sprintf_buf (str_initcwnd, " initcwnd %s%"G_GUINT32_FORMAT, route->lock_initcwnd ? "lock " : "", route->initcwnd);
|
||||
if (route->initrwnd)
|
||||
nm_sprintf_buf (str_initrwnd, " initrwnd %s%"G_GUINT32_FORMAT, route->lock_initrwnd ? "lock " : "", route->initrwnd);
|
||||
if (route->mtu)
|
||||
nm_sprintf_buf (str_mtu, " mtu %s%"G_GUINT32_FORMAT, route->lock_mtu ? "lock " : "", route->mtu);
|
||||
|
||||
g_snprintf (buf, len,
|
||||
"%s/%d"
|
||||
" via %s"
|
||||
"%s"
|
||||
" metric %"G_GUINT32_FORMAT
|
||||
" mss %"G_GUINT32_FORMAT
|
||||
" src %s" /* source */
|
||||
" rt-src %s" /* protocol */
|
||||
" src %s/%u" /* source */
|
||||
"%s" /* cloned */
|
||||
"%s%s" /* pref-src */
|
||||
"%s" /* tos */
|
||||
"%s" /* window */
|
||||
"%s" /* cwnd */
|
||||
"%s" /* initcwnd */
|
||||
"%s" /* initrwnd */
|
||||
"%s" /* mtu */
|
||||
"",
|
||||
s_network,
|
||||
route->plen,
|
||||
|
|
@ -3977,7 +3997,17 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *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" : "");
|
||||
s_src, route->src_plen,
|
||||
route->rt_cloned ? " cloned" : "",
|
||||
s_pref_src[0] ? " pref-src " : "",
|
||||
s_pref_src[0] ? s_pref_src : "",
|
||||
route->tos ? str_tos : "",
|
||||
route->window ? str_window : "",
|
||||
route->cwnd ? str_cwnd : "",
|
||||
route->initcwnd ? str_initcwnd : "",
|
||||
route->initrwnd ? str_initrwnd : "",
|
||||
route->mtu ? str_mtu : "");
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
|
@ -4266,6 +4296,17 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route
|
|||
_CMP_FIELD (a, b, scope_inv);
|
||||
_CMP_FIELD (a, b, pref_src);
|
||||
_CMP_FIELD (a, b, rt_cloned);
|
||||
_CMP_FIELD (a, b, tos);
|
||||
_CMP_FIELD (a, b, lock_window);
|
||||
_CMP_FIELD (a, b, lock_cwnd);
|
||||
_CMP_FIELD (a, b, lock_initcwnd);
|
||||
_CMP_FIELD (a, b, lock_initrwnd);
|
||||
_CMP_FIELD (a, b, lock_mtu);
|
||||
_CMP_FIELD (a, b, window);
|
||||
_CMP_FIELD (a, b, cwnd);
|
||||
_CMP_FIELD (a, b, initcwnd);
|
||||
_CMP_FIELD (a, b, initrwnd);
|
||||
_CMP_FIELD (a, b, mtu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -4278,9 +4319,23 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
|
|||
_CMP_FIELD (a, b, plen);
|
||||
_CMP_FIELD (a, b, metric);
|
||||
_CMP_FIELD_MEMCMP (a, b, gateway);
|
||||
_CMP_FIELD_MEMCMP (a, b, pref_src);
|
||||
_CMP_FIELD_MEMCMP (a, b, src);
|
||||
_CMP_FIELD (a, b, src_plen);
|
||||
_CMP_FIELD (a, b, rt_source);
|
||||
_CMP_FIELD (a, b, mss);
|
||||
_CMP_FIELD (a, b, rt_cloned);
|
||||
_CMP_FIELD (a, b, tos);
|
||||
_CMP_FIELD (a, b, lock_window);
|
||||
_CMP_FIELD (a, b, lock_cwnd);
|
||||
_CMP_FIELD (a, b, lock_initcwnd);
|
||||
_CMP_FIELD (a, b, lock_initrwnd);
|
||||
_CMP_FIELD (a, b, lock_mtu);
|
||||
_CMP_FIELD (a, b, window);
|
||||
_CMP_FIELD (a, b, cwnd);
|
||||
_CMP_FIELD (a, b, initcwnd);
|
||||
_CMP_FIELD (a, b, initrwnd);
|
||||
_CMP_FIELD (a, b, mtu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -4411,28 +4466,27 @@ nm_platform_netns_push (NMPlatform *platform, NMPNetns **netns)
|
|||
static gboolean
|
||||
_vtr_v4_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route, gint64 metric)
|
||||
{
|
||||
return nm_platform_ip4_route_add (self,
|
||||
ifindex > 0 ? ifindex : route->rx.ifindex,
|
||||
route->rx.rt_source,
|
||||
route->r4.network,
|
||||
route->rx.plen,
|
||||
route->r4.gateway,
|
||||
route->r4.pref_src,
|
||||
metric >= 0 ? (guint32) metric : route->rx.metric,
|
||||
route->rx.mss);
|
||||
NMPlatformIP4Route rt = route->r4;
|
||||
|
||||
if (ifindex > 0)
|
||||
rt.ifindex = ifindex;
|
||||
if (metric >= 0)
|
||||
rt.metric = metric;
|
||||
|
||||
return nm_platform_ip4_route_add (self, &rt);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_vtr_v6_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route, gint64 metric)
|
||||
{
|
||||
return nm_platform_ip6_route_add (self,
|
||||
ifindex > 0 ? ifindex : route->rx.ifindex,
|
||||
route->rx.rt_source,
|
||||
route->r6.network,
|
||||
route->rx.plen,
|
||||
route->r6.gateway,
|
||||
metric >= 0 ? (guint32) metric : route->rx.metric,
|
||||
route->rx.mss);
|
||||
NMPlatformIP6Route rt = route->r6;
|
||||
|
||||
if (ifindex > 0)
|
||||
rt.ifindex = ifindex;
|
||||
if (metric >= 0)
|
||||
rt.metric = metric;
|
||||
|
||||
return nm_platform_ip6_route_add (self, &rt);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
|||
|
|
@ -324,9 +324,20 @@ typedef union {
|
|||
* 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; \
|
||||
bool lock_window:1; \
|
||||
bool lock_cwnd:1; \
|
||||
bool lock_initcwnd:1; \
|
||||
bool lock_initrwnd:1; \
|
||||
bool lock_mtu:1; \
|
||||
\
|
||||
guint32 metric; \
|
||||
guint32 mss; \
|
||||
guint32 tos; \
|
||||
guint32 window; \
|
||||
guint32 cwnd; \
|
||||
guint32 initcwnd; \
|
||||
guint32 initrwnd; \
|
||||
guint32 mtu; \
|
||||
;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -358,6 +369,9 @@ struct _NMPlatformIP6Route {
|
|||
__NMPlatformIPRoute_COMMON;
|
||||
struct in6_addr network;
|
||||
struct in6_addr gateway;
|
||||
struct in6_addr pref_src;
|
||||
struct in6_addr src;
|
||||
guint8 src_plen;
|
||||
};
|
||||
|
||||
typedef union {
|
||||
|
|
@ -667,12 +681,8 @@ typedef struct {
|
|||
|
||||
GArray * (*ip4_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteFlags flags);
|
||||
GArray * (*ip6_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteFlags flags);
|
||||
gboolean (*ip4_route_add) (NMPlatform *, int ifindex, NMIPConfigSource source,
|
||||
in_addr_t network, guint8 plen, in_addr_t gateway,
|
||||
in_addr_t pref_src, guint32 metric, guint32 mss);
|
||||
gboolean (*ip6_route_add) (NMPlatform *, int ifindex, NMIPConfigSource source,
|
||||
struct in6_addr network, guint8 plen, struct in6_addr gateway,
|
||||
guint32 metric, guint32 mss);
|
||||
gboolean (*ip4_route_add) (NMPlatform *, const NMPlatformIP4Route *route);
|
||||
gboolean (*ip6_route_add) (NMPlatform *, const NMPlatformIP6Route *route);
|
||||
gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
|
||||
gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
|
||||
const NMPlatformIP4Route *(*ip4_route_get) (NMPlatform *, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
|
||||
|
|
@ -969,12 +979,8 @@ const NMPlatformIP4Route *nm_platform_ip4_route_get (NMPlatform *self, int ifind
|
|||
const NMPlatformIP6Route *nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
|
||||
GArray *nm_platform_ip4_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags);
|
||||
GArray *nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags);
|
||||
gboolean nm_platform_ip4_route_add (NMPlatform *self, int ifindex, NMIPConfigSource source,
|
||||
in_addr_t network, guint8 plen, in_addr_t gateway,
|
||||
in_addr_t pref_src, guint32 metric, guint32 mss);
|
||||
gboolean nm_platform_ip6_route_add (NMPlatform *self, int ifindex, NMIPConfigSource source,
|
||||
struct in6_addr network, guint8 plen, struct in6_addr gateway,
|
||||
guint32 metric, guint32 mss);
|
||||
gboolean nm_platform_ip4_route_add (NMPlatform *self, const NMPlatformIP4Route *route);
|
||||
gboolean nm_platform_ip6_route_add (NMPlatform *self, const NMPlatformIP6Route *route);
|
||||
gboolean nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
|
||||
gboolean nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
|
||||
|
||||
|
|
|
|||
|
|
@ -65,12 +65,12 @@ test_cleanup_internal (void)
|
|||
/* Add routes and addresses */
|
||||
g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr4, plen4, addr4, lifetime, preferred, 0, NULL));
|
||||
g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr6, plen6, in6addr_any, lifetime, preferred, flags));
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway4, 32, INADDR_ANY, 0, metric, mss));
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network4, plen4, gateway4, 0, metric, mss));
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway4, 0, metric, mss));
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway6, 128, in6addr_any, metric, mss));
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network6, plen6, gateway6, metric, mss));
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway6, metric, mss));
|
||||
nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway4, 32, INADDR_ANY, 0, metric, mss);
|
||||
nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network4, plen4, gateway4, 0, metric, mss);
|
||||
nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway4, 0, metric, mss);
|
||||
nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway6, 128, in6addr_any, in6addr_any, metric, mss);
|
||||
nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network6, plen6, gateway6, in6addr_any, metric, mss);
|
||||
nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway6, in6addr_any, metric, mss);
|
||||
|
||||
addresses4 = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
|
||||
addresses6 = nm_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex);
|
||||
|
|
|
|||
|
|
@ -783,6 +783,54 @@ nmtstp_ip6_address_add (NMPlatform *platform,
|
|||
NULL);
|
||||
}
|
||||
|
||||
void nmtstp_ip4_route_add (NMPlatform *platform,
|
||||
int ifindex,
|
||||
NMIPConfigSource source,
|
||||
in_addr_t network,
|
||||
guint8 plen,
|
||||
in_addr_t gateway,
|
||||
in_addr_t pref_src,
|
||||
guint32 metric,
|
||||
guint32 mss)
|
||||
{
|
||||
NMPlatformIP4Route route = { };
|
||||
|
||||
route.ifindex = ifindex;
|
||||
route.rt_source = source;
|
||||
route.network = network;
|
||||
route.plen = plen;
|
||||
route.gateway = gateway;
|
||||
route.pref_src = pref_src;
|
||||
route.metric = metric;
|
||||
route.mss = mss;
|
||||
|
||||
g_assert (nm_platform_ip4_route_add (platform, &route));
|
||||
}
|
||||
|
||||
void nmtstp_ip6_route_add (NMPlatform *platform,
|
||||
int ifindex,
|
||||
NMIPConfigSource source,
|
||||
struct in6_addr network,
|
||||
guint8 plen,
|
||||
struct in6_addr gateway,
|
||||
struct in6_addr pref_src,
|
||||
guint32 metric,
|
||||
guint32 mss)
|
||||
{
|
||||
NMPlatformIP6Route route = { };
|
||||
|
||||
route.ifindex = ifindex;
|
||||
route.rt_source = source;
|
||||
route.network = network;
|
||||
route.plen = plen;
|
||||
route.gateway = gateway;
|
||||
route.pref_src = pref_src;
|
||||
route.metric = metric;
|
||||
route.mss = mss;
|
||||
|
||||
g_assert (nm_platform_ip6_route_add (platform, &route));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -167,6 +167,26 @@ void nmtstp_ip6_address_del (NMPlatform *platform,
|
|||
struct in6_addr address,
|
||||
int plen);
|
||||
|
||||
void nmtstp_ip4_route_add (NMPlatform *platform,
|
||||
int ifindex,
|
||||
NMIPConfigSource source,
|
||||
in_addr_t network,
|
||||
guint8 plen,
|
||||
in_addr_t gateway,
|
||||
in_addr_t pref_src,
|
||||
guint32 metric,
|
||||
guint32 mss);
|
||||
|
||||
void nmtstp_ip6_route_add (NMPlatform *platform,
|
||||
int ifindex,
|
||||
NMIPConfigSource source,
|
||||
struct in6_addr network,
|
||||
guint8 plen,
|
||||
struct in6_addr gateway,
|
||||
struct in6_addr pref_src,
|
||||
guint32 metric,
|
||||
guint32 mss);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const NMPlatformLink *nmtstp_link_get_typed (NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type);
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ test_ip4_route_metric0 (void)
|
|||
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric);
|
||||
|
||||
/* add the first route */
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, metric, mss));
|
||||
nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, metric, mss);
|
||||
accept_signal (route_added);
|
||||
|
||||
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
|
||||
|
|
@ -108,7 +108,7 @@ test_ip4_route_metric0 (void)
|
|||
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
|
||||
|
||||
/* add the second route */
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, 0, mss));
|
||||
nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, 0, mss);
|
||||
accept_signal (route_added);
|
||||
|
||||
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, 0);
|
||||
|
|
@ -160,27 +160,27 @@ test_ip4_route (void)
|
|||
inet_pton (AF_INET, "198.51.100.1", &gateway);
|
||||
|
||||
/* Add route to gateway */
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 32, INADDR_ANY, 0, metric, mss));
|
||||
nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 32, INADDR_ANY, 0, metric, mss);
|
||||
accept_signal (route_added);
|
||||
|
||||
/* Add route */
|
||||
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric);
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss));
|
||||
nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss);
|
||||
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
|
||||
accept_signal (route_added);
|
||||
|
||||
/* Add route again */
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss));
|
||||
nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss);
|
||||
accept_signals (route_changed, 0, 1);
|
||||
|
||||
/* Add default route */
|
||||
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, 0, 0, metric);
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss));
|
||||
nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss);
|
||||
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, 0, 0, metric);
|
||||
accept_signal (route_added);
|
||||
|
||||
/* Add default route again */
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss));
|
||||
nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss);
|
||||
accept_signals (route_changed, 0, 1);
|
||||
|
||||
/* Test route listing */
|
||||
|
|
@ -222,6 +222,14 @@ test_ip4_route (void)
|
|||
/* Remove route again */
|
||||
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
|
||||
|
||||
/* Remove default route */
|
||||
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, 0, 0, metric));
|
||||
accept_signal (route_removed);
|
||||
|
||||
/* Remove route to gateway */
|
||||
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, gateway, 32, metric));
|
||||
accept_signal (route_removed);
|
||||
|
||||
free_signal (route_added);
|
||||
free_signal (route_changed);
|
||||
free_signal (route_removed);
|
||||
|
|
@ -238,36 +246,41 @@ test_ip6_route (void)
|
|||
NMPlatformIP6Route rts[3];
|
||||
struct in6_addr network;
|
||||
guint8 plen = 64;
|
||||
struct in6_addr gateway;
|
||||
struct in6_addr gateway, pref_src;
|
||||
/* Choose a high metric so that we hopefully don't conflict. */
|
||||
int metric = 22987;
|
||||
int mss = 1000;
|
||||
|
||||
inet_pton (AF_INET6, "2001:db8:a:b:0:0:0:0", &network);
|
||||
inet_pton (AF_INET6, "2001:db8:c:d:1:2:3:4", &gateway);
|
||||
inet_pton (AF_INET6, "::42", &pref_src);
|
||||
|
||||
g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, pref_src, 128, in6addr_any,
|
||||
NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, 0));
|
||||
accept_signals (route_added, 0, 1);
|
||||
|
||||
/* Add route to gateway */
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 128, in6addr_any, metric, mss));
|
||||
nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 128, in6addr_any, in6addr_any, metric, mss);
|
||||
accept_signal (route_added);
|
||||
|
||||
/* Add route */
|
||||
g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric));
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, metric, mss));
|
||||
nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, pref_src, metric, mss);
|
||||
g_assert (nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric));
|
||||
accept_signal (route_added);
|
||||
|
||||
/* Add route again */
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, metric, mss));
|
||||
nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, pref_src, metric, mss);
|
||||
accept_signals (route_changed, 0, 1);
|
||||
|
||||
/* Add default route */
|
||||
g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric));
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway, metric, mss));
|
||||
nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway, in6addr_any, metric, mss);
|
||||
g_assert (nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric));
|
||||
accept_signal (route_added);
|
||||
|
||||
/* Add default route again */
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway, metric, mss));
|
||||
nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway, in6addr_any, metric, mss);
|
||||
accept_signals (route_changed, 0, 1);
|
||||
|
||||
/* Test route listing */
|
||||
|
|
@ -278,6 +291,7 @@ test_ip6_route (void)
|
|||
rts[0].plen = 128;
|
||||
rts[0].ifindex = ifindex;
|
||||
rts[0].gateway = in6addr_any;
|
||||
rts[0].pref_src = in6addr_any;
|
||||
rts[0].metric = nm_utils_ip6_route_metric_normalize (metric);
|
||||
rts[0].mss = mss;
|
||||
rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
|
||||
|
|
@ -285,6 +299,7 @@ test_ip6_route (void)
|
|||
rts[1].plen = plen;
|
||||
rts[1].ifindex = ifindex;
|
||||
rts[1].gateway = gateway;
|
||||
rts[1].pref_src = pref_src;
|
||||
rts[1].metric = nm_utils_ip6_route_metric_normalize (metric);
|
||||
rts[1].mss = mss;
|
||||
rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
|
||||
|
|
@ -292,6 +307,7 @@ test_ip6_route (void)
|
|||
rts[2].plen = 0;
|
||||
rts[2].ifindex = ifindex;
|
||||
rts[2].gateway = gateway;
|
||||
rts[2].pref_src = in6addr_any;
|
||||
rts[2].metric = nm_utils_ip6_route_metric_normalize (metric);
|
||||
rts[2].mss = mss;
|
||||
g_assert_cmpint (routes->len, ==, 3);
|
||||
|
|
@ -306,6 +322,14 @@ test_ip6_route (void)
|
|||
/* Remove route again */
|
||||
g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
|
||||
|
||||
/* Remove default route */
|
||||
g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric));
|
||||
accept_signal (route_removed);
|
||||
|
||||
/* Remove route to gateway */
|
||||
g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, gateway, 128, metric));
|
||||
accept_signal (route_removed);
|
||||
|
||||
free_signal (route_added);
|
||||
free_signal (route_changed);
|
||||
free_signal (route_removed);
|
||||
|
|
@ -334,6 +358,119 @@ test_ip4_zero_gateway (void)
|
|||
nm_platform_process_events (NM_PLATFORM_GET);
|
||||
}
|
||||
|
||||
static void
|
||||
test_ip4_route_options (void)
|
||||
{
|
||||
int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
|
||||
NMPlatformIP4Route route = { };
|
||||
in_addr_t network;
|
||||
GArray *routes;
|
||||
NMPlatformIP4Route rts[1];
|
||||
|
||||
inet_pton (AF_INET, "172.16.1.0", &network);
|
||||
|
||||
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;
|
||||
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, &route));
|
||||
|
||||
/* Test route listing */
|
||||
routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex,
|
||||
NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT |
|
||||
NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
|
||||
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 ((NMPlatformIP4Route *) routes->data, rts, routes->len, TRUE);
|
||||
|
||||
/* Remove route */
|
||||
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, 24, 20));
|
||||
|
||||
g_array_unref (routes);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_ip6_route_options (void)
|
||||
{
|
||||
int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
|
||||
NMPlatformIP6Route route = { };
|
||||
struct in6_addr network, src;
|
||||
GArray *routes;
|
||||
NMPlatformIP6Route rts[3];
|
||||
|
||||
inet_pton (AF_INET6, "2001:db8:a:b:0:0:0:0", &network);
|
||||
inet_pton (AF_INET6, "2001:db8:e:0:0:0:0:0", &src);
|
||||
|
||||
route.ifindex = ifindex;
|
||||
route.rt_source = NM_IP_CONFIG_SOURCE_USER;
|
||||
route.network = network;
|
||||
route.plen = 64;
|
||||
route.gateway = in6addr_any;
|
||||
route.src = src;
|
||||
route.src_plen = 48;
|
||||
route.metric = 1024;
|
||||
route.window = 20000;
|
||||
route.cwnd = 8;
|
||||
route.initcwnd = 22;
|
||||
route.initrwnd = 33;
|
||||
route.mtu = 1300;
|
||||
route.lock_mtu = TRUE;
|
||||
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, &route));
|
||||
|
||||
/* Test route listing */
|
||||
routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex,
|
||||
NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT |
|
||||
NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
|
||||
memset (rts, 0, sizeof (rts));
|
||||
rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
|
||||
rts[0].network = network;
|
||||
rts[0].plen = 64;
|
||||
rts[0].ifindex = ifindex;
|
||||
rts[0].gateway = in6addr_any;
|
||||
rts[0].src = src;
|
||||
rts[0].src_plen = 48;
|
||||
rts[0].metric = 1024;
|
||||
rts[0].window = 20000;
|
||||
rts[0].cwnd = 8;
|
||||
rts[0].initcwnd = 22;
|
||||
rts[0].initrwnd = 33;
|
||||
rts[0].mtu = 1300;
|
||||
rts[0].lock_mtu = TRUE;
|
||||
|
||||
g_assert_cmpint (routes->len, ==, 1);
|
||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, rts, routes->len, TRUE);
|
||||
|
||||
/* Remove route */
|
||||
g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, 64, 1024));
|
||||
|
||||
g_array_unref (routes);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP;
|
||||
|
|
@ -360,6 +497,8 @@ _nmtstp_setup_tests (void)
|
|||
g_test_add_func ("/route/ip4", test_ip4_route);
|
||||
g_test_add_func ("/route/ip6", test_ip6_route);
|
||||
g_test_add_func ("/route/ip4_metric0", test_ip4_route_metric0);
|
||||
g_test_add_func ("/route/ip4_options", test_ip4_route_options);
|
||||
g_test_add_func ("/route/ip6_options", test_ip6_route_options);
|
||||
|
||||
if (nmtstp_is_root_test ())
|
||||
g_test_add_func ("/route/ip4_zero_gateway", test_ip4_zero_gateway);
|
||||
|
|
|
|||
|
|
@ -435,6 +435,134 @@ read_full_ip4_address (shvarFile *ifcfg,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use looser syntax to comprise all the possibilities.
|
||||
* The validity must be checked after the match.
|
||||
*/
|
||||
#define IPV4_ADDR_REGEX "(?:[0-9]{1,3}\\.){3}[0-9]{1,3}"
|
||||
#define IPV6_ADDR_REGEX "[0-9A-Fa-f:.]+"
|
||||
|
||||
/*
|
||||
* NOTE: The regexes below don't describe all variants allowed by 'ip route add',
|
||||
* namely destination IP without 'to' keyword is recognized just at line start.
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
parse_route_options (NMIPRoute *route, int family, const char *line, GError **error)
|
||||
{
|
||||
GRegex *regex = NULL;
|
||||
GMatchInfo *match_info = NULL;
|
||||
gboolean success = FALSE;
|
||||
char *metrics[] = { NM_IP_ROUTE_ATTRIBUTE_WINDOW, NM_IP_ROUTE_ATTRIBUTE_CWND,
|
||||
NM_IP_ROUTE_ATTRIBUTE_INITCWND , NM_IP_ROUTE_ATTRIBUTE_INITRWND,
|
||||
NM_IP_ROUTE_ATTRIBUTE_MTU , NULL };
|
||||
char buffer[1024];
|
||||
int i;
|
||||
|
||||
g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE);
|
||||
|
||||
for (i = 0; metrics[i]; i++) {
|
||||
nm_sprintf_buf (buffer, "(?:\\s|^)%s\\s+(lock\\s+)?(\\d+)(?:$|\\s)", metrics[i]);
|
||||
regex = g_regex_new (buffer, 0, 0, NULL);
|
||||
g_regex_match (regex, line, 0, &match_info);
|
||||
if (g_match_info_matches (match_info)) {
|
||||
gs_free char *lock = g_match_info_fetch (match_info, 1);
|
||||
gs_free char *str = g_match_info_fetch (match_info, 2);
|
||||
gint64 num = _nm_utils_ascii_str_to_int64 (str, 10, 0, G_MAXUINT32, -1);
|
||||
|
||||
if (num == -1) {
|
||||
g_match_info_free (match_info);
|
||||
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||
"Invalid route %s '%s'", metrics[i], str);
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_ip_route_set_attribute (route, metrics[i],
|
||||
g_variant_new_uint32 (num));
|
||||
if (lock && lock[0]) {
|
||||
nm_sprintf_buf (buffer, "lock-%s", metrics[i]);
|
||||
nm_ip_route_set_attribute (route, buffer,
|
||||
g_variant_new_boolean (TRUE));
|
||||
}
|
||||
}
|
||||
g_clear_pointer (®ex, g_regex_unref);
|
||||
g_clear_pointer (&match_info, g_match_info_free);
|
||||
}
|
||||
|
||||
/* tos */
|
||||
regex = g_regex_new ("(?:\\s|^)tos\\s+(\\S+)(?:$|\\s)", 0, 0, NULL);
|
||||
g_regex_match (regex, line, 0, &match_info);
|
||||
if (g_match_info_matches (match_info)) {
|
||||
gs_free char *str = g_match_info_fetch (match_info, 1);
|
||||
gs_free_error GError *local_error = NULL;
|
||||
gint64 num = _nm_utils_ascii_str_to_int64 (str, 0, 0, G_MAXUINT8, -1);
|
||||
|
||||
if (num == -1) {
|
||||
g_match_info_free (match_info);
|
||||
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||
"Invalid route %s '%s'", "tos", str);
|
||||
goto out;
|
||||
}
|
||||
nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_TOS,
|
||||
g_variant_new_byte ((guchar) num));
|
||||
}
|
||||
g_clear_pointer (®ex, g_regex_unref);
|
||||
g_clear_pointer (&match_info, g_match_info_free);
|
||||
|
||||
/* from */
|
||||
if (family == AF_INET6) {
|
||||
regex = g_regex_new ("(?:\\s|^)from\\s+(" IPV6_ADDR_REGEX "(?:/\\d{1,3})?)(?:$|\\s)", 0, 0, NULL);
|
||||
g_regex_match (regex, line, 0, &match_info);
|
||||
if (g_match_info_matches (match_info)) {
|
||||
gs_free char *str = g_match_info_fetch (match_info, 1);
|
||||
gs_free_error GError *local_error = NULL;
|
||||
GVariant *variant = g_variant_new_string (str);
|
||||
|
||||
if (!nm_ip_route_attribute_validate (NM_IP_ROUTE_ATTRIBUTE_SRC, variant, family, NULL, &local_error)) {
|
||||
g_match_info_free (match_info);
|
||||
g_variant_unref (variant);
|
||||
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||
"Invalid route from '%s': %s", str, local_error->message);
|
||||
goto out;
|
||||
}
|
||||
nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_SRC, variant);
|
||||
}
|
||||
g_clear_pointer (®ex, g_regex_unref);
|
||||
g_clear_pointer (&match_info, g_match_info_free);
|
||||
}
|
||||
|
||||
if (family == AF_INET)
|
||||
regex = g_regex_new ("(?:\\s|^)src\\s+(" IPV4_ADDR_REGEX ")(?:$|\\s)", 0, 0, NULL);
|
||||
else
|
||||
regex = g_regex_new ("(?:\\s|^)src\\s+(" IPV6_ADDR_REGEX ")(?:$|\\s)", 0, 0, NULL);
|
||||
g_regex_match (regex, line, 0, &match_info);
|
||||
if (g_match_info_matches (match_info)) {
|
||||
gs_free char *str = g_match_info_fetch (match_info, 1);
|
||||
gs_free_error GError *local_error = NULL;
|
||||
GVariant *variant = g_variant_new_string (str);
|
||||
|
||||
if (!nm_ip_route_attribute_validate (NM_IP_ROUTE_ATTRIBUTE_PREF_SRC, variant, family,
|
||||
NULL, &local_error)) {
|
||||
g_match_info_free (match_info);
|
||||
g_variant_unref (variant);
|
||||
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||
"Invalid route src '%s': %s", str, local_error->message);
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_PREF_SRC, variant);
|
||||
}
|
||||
success = TRUE;
|
||||
|
||||
out:
|
||||
if (regex)
|
||||
g_regex_unref (regex);
|
||||
if (match_info)
|
||||
g_match_info_free (match_info);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/* Returns TRUE on missing route or valid route */
|
||||
static gboolean
|
||||
read_one_ip4_route (shvarFile *ifcfg,
|
||||
|
|
@ -507,10 +635,20 @@ read_one_ip4_route (shvarFile *ifcfg,
|
|||
metric = -1;
|
||||
|
||||
*out_route = nm_ip_route_new_binary (AF_INET, &dest, prefix, &next_hop, metric, error);
|
||||
if (*out_route)
|
||||
return TRUE;
|
||||
if (!*out_route)
|
||||
return FALSE;
|
||||
|
||||
return FALSE;
|
||||
/* Options */
|
||||
nm_clear_g_free (&value);
|
||||
value = svGetValueStr_cp (ifcfg, numbered_tag (tag, "OPTIONS", which));
|
||||
if (value) {
|
||||
if (!parse_route_options (*out_route, AF_INET, value, error)) {
|
||||
g_clear_pointer (out_route, nm_ip_route_unref);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -636,6 +774,12 @@ read_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError *
|
|||
route = nm_ip_route_new (AF_INET, dest, prefix_int, next_hop, metric_int, error);
|
||||
if (!route)
|
||||
goto error;
|
||||
|
||||
if (!parse_route_options (route, AF_INET, *iter, error)) {
|
||||
nm_ip_route_unref (route);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!nm_setting_ip_config_add_route (s_ip4, route))
|
||||
PARSE_WARNING ("duplicate IP4 route");
|
||||
nm_ip_route_unref (route);
|
||||
|
|
@ -729,13 +873,6 @@ error:
|
|||
return success;
|
||||
}
|
||||
|
||||
/* IPv6 address is very complex to describe completely by a regular expression,
|
||||
* so don't try to, rather use looser syntax to comprise all possibilities
|
||||
* NOTE: The regexes below don't describe all variants allowed by 'ip route add',
|
||||
* namely destination IP without 'to' keyword is recognized just at line start.
|
||||
*/
|
||||
#define IPV6_ADDR_REGEX "[0-9A-Fa-f:.]+"
|
||||
|
||||
static gboolean
|
||||
read_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error)
|
||||
{
|
||||
|
|
@ -757,6 +894,7 @@ read_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error
|
|||
const char *pattern_via = "via\\s+(" IPV6_ADDR_REGEX ")"; /* IPv6 of gateway */
|
||||
const char *pattern_metric = "metric\\s+(\\d+)"; /* metric */
|
||||
|
||||
|
||||
g_return_val_if_fail (filename != NULL, FALSE);
|
||||
g_return_val_if_fail (s_ip6 != NULL, FALSE);
|
||||
g_return_val_if_fail (!error || !*error, FALSE);
|
||||
|
|
@ -862,6 +1000,12 @@ read_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error
|
|||
g_free (next_hop);
|
||||
if (!route)
|
||||
goto error;
|
||||
|
||||
if (!parse_route_options (route, AF_INET6, *iter, error)) {
|
||||
nm_ip_route_unref (route);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!nm_setting_ip_config_add_route (s_ip6, route))
|
||||
PARSE_WARNING ("duplicate IP6 route");
|
||||
nm_ip_route_unref (route);
|
||||
|
|
|
|||
|
|
@ -1867,6 +1867,61 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg)
|
|||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
get_route_attributes_string (NMIPRoute *route, int family)
|
||||
{
|
||||
gs_strfreev char **names = NULL;
|
||||
GVariant *attr, *lock;
|
||||
GString *str;
|
||||
int i;
|
||||
|
||||
names = nm_ip_route_get_attribute_names (route);
|
||||
if (!names || !names[0])
|
||||
return NULL;
|
||||
|
||||
str = g_string_new ("");
|
||||
|
||||
for (i = 0; names[i]; i++) {
|
||||
attr = nm_ip_route_get_attribute (route, names[i]);
|
||||
|
||||
if (!nm_ip_route_attribute_validate (names[i], attr, family, NULL, NULL))
|
||||
continue;
|
||||
|
||||
if (NM_IN_STRSET (names[i], NM_IP_ROUTE_ATTRIBUTE_WINDOW,
|
||||
NM_IP_ROUTE_ATTRIBUTE_CWND,
|
||||
NM_IP_ROUTE_ATTRIBUTE_INITCWND,
|
||||
NM_IP_ROUTE_ATTRIBUTE_INITRWND,
|
||||
NM_IP_ROUTE_ATTRIBUTE_MTU)) {
|
||||
char lock_name[256];
|
||||
|
||||
nm_sprintf_buf (lock_name, "lock-%s", names[i]);
|
||||
lock = nm_ip_route_get_attribute (route, lock_name);
|
||||
|
||||
g_string_append_printf (str,
|
||||
"%s %s%u",
|
||||
names[i],
|
||||
(lock && g_variant_get_boolean (lock)) ? "lock " : "",
|
||||
g_variant_get_uint32 (attr));
|
||||
} else if (strstr (names[i], "lock-")) {
|
||||
/* handled above */
|
||||
} else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_TOS)) {
|
||||
g_string_append_printf (str, "%s %u", names[i], (unsigned) g_variant_get_byte (attr));
|
||||
} else if ( nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_PREF_SRC)
|
||||
|| nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC)) {
|
||||
char *arg = nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_PREF_SRC) ? "src" : "from";
|
||||
|
||||
g_string_append_printf (str, "%s %s", arg, g_variant_get_string (attr, NULL));
|
||||
} else {
|
||||
_LOGW ("unknown route option '%s'", names[i]);
|
||||
continue;
|
||||
}
|
||||
if (names[i + 1])
|
||||
g_string_append_c (str, ' ');
|
||||
}
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
write_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError **error)
|
||||
{
|
||||
|
|
@ -1891,6 +1946,8 @@ write_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError
|
|||
|
||||
route_items = g_malloc0 (sizeof (char*) * (num + 1));
|
||||
for (i = 0; i < num; i++) {
|
||||
gs_free char *options = NULL;
|
||||
|
||||
route = nm_setting_ip_config_get_route (s_ip4, i);
|
||||
|
||||
dest = nm_ip_route_get_dest (route);
|
||||
|
|
@ -1898,10 +1955,19 @@ write_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError
|
|||
next_hop = nm_ip_route_get_next_hop (route);
|
||||
metric = nm_ip_route_get_metric (route);
|
||||
|
||||
if (metric == -1)
|
||||
route_items[i] = g_strdup_printf ("%s/%u via %s\n", dest, prefix, next_hop);
|
||||
else
|
||||
route_items[i] = g_strdup_printf ("%s/%u via %s metric %u\n", dest, prefix, next_hop, (guint32) metric);
|
||||
options = get_route_attributes_string (route, AF_INET);
|
||||
|
||||
if (metric == -1) {
|
||||
route_items[i] = g_strdup_printf ("%s/%u via %s%s%s\n",
|
||||
dest, prefix, next_hop,
|
||||
options ? " " : "",
|
||||
options ?: "");
|
||||
} else {
|
||||
route_items[i] = g_strdup_printf ("%s/%u via %s metric %u%s%s\n",
|
||||
dest, prefix, next_hop, (guint32) metric,
|
||||
options ? " " : "",
|
||||
options ?: "");
|
||||
}
|
||||
}
|
||||
route_items[num] = NULL;
|
||||
route_contents = g_strjoinv (NULL, route_items);
|
||||
|
|
@ -1960,10 +2026,14 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
{
|
||||
NMSettingIPConfig *s_ip4;
|
||||
const char *value;
|
||||
char *addr_key, *prefix_key, *netmask_key, *gw_key, *metric_key, *tmp;
|
||||
char *tmp;
|
||||
char addr_key[64];
|
||||
char prefix_key[64];
|
||||
char netmask_key[64];
|
||||
char gw_key[64];
|
||||
char *route_path = NULL;
|
||||
gint32 j;
|
||||
guint32 i, n, num;
|
||||
gint j;
|
||||
guint i, num, n;
|
||||
gint64 route_metric;
|
||||
gint priority;
|
||||
int timeout;
|
||||
|
|
@ -2003,26 +2073,21 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
svUnsetValue (ifcfg, "BOOTPROTO");
|
||||
for (j = -1; j < 256; j++) {
|
||||
if (j == -1) {
|
||||
addr_key = g_strdup ("IPADDR");
|
||||
prefix_key = g_strdup ("PREFIX");
|
||||
netmask_key = g_strdup ("NETMASK");
|
||||
gw_key = g_strdup ("GATEWAY");
|
||||
nm_sprintf_buf (addr_key, "IPADDR");
|
||||
nm_sprintf_buf (prefix_key, "PREFIX");
|
||||
nm_sprintf_buf (netmask_key, "NETMASK");
|
||||
nm_sprintf_buf (gw_key, "GATEWAY");
|
||||
} else {
|
||||
addr_key = g_strdup_printf ("IPADDR%d", j);
|
||||
prefix_key = g_strdup_printf ("PREFIX%d", j);
|
||||
netmask_key = g_strdup_printf ("NETMASK%d", j);
|
||||
gw_key = g_strdup_printf ("GATEWAY%d", j);
|
||||
nm_sprintf_buf (addr_key, "IPADDR%d", (guint) j);
|
||||
nm_sprintf_buf (prefix_key, "PREFIX%u", (guint) j);
|
||||
nm_sprintf_buf (netmask_key, "NETMASK%u", (guint) j);
|
||||
nm_sprintf_buf (gw_key, "GATEWAY%u", (guint) j);
|
||||
}
|
||||
|
||||
svUnsetValue (ifcfg, addr_key);
|
||||
svUnsetValue (ifcfg, prefix_key);
|
||||
svUnsetValue (ifcfg, netmask_key);
|
||||
svUnsetValue (ifcfg, gw_key);
|
||||
|
||||
g_free (addr_key);
|
||||
g_free (prefix_key);
|
||||
g_free (netmask_key);
|
||||
g_free (gw_key);
|
||||
}
|
||||
|
||||
route_path = utils_get_route_path (svFileGetName (ifcfg));
|
||||
|
|
@ -2074,15 +2139,15 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
* See https://bugzilla.redhat.com/show_bug.cgi?id=771673
|
||||
* and https://bugzilla.redhat.com/show_bug.cgi?id=1105770
|
||||
*/
|
||||
addr_key = g_strdup ("IPADDR");
|
||||
prefix_key = g_strdup ("PREFIX");
|
||||
netmask_key = g_strdup ("NETMASK");
|
||||
gw_key = g_strdup ("GATEWAY");
|
||||
nm_sprintf_buf (addr_key, "IPADDR");
|
||||
nm_sprintf_buf (prefix_key, "PREFIX");
|
||||
nm_sprintf_buf (netmask_key, "NETMASK");
|
||||
nm_sprintf_buf (gw_key, "GATEWAY");
|
||||
} else {
|
||||
addr_key = g_strdup_printf ("IPADDR%d", n);
|
||||
prefix_key = g_strdup_printf ("PREFIX%d", n);
|
||||
netmask_key = g_strdup_printf ("NETMASK%d", n);
|
||||
gw_key = g_strdup_printf ("GATEWAY%d", n);
|
||||
nm_sprintf_buf (addr_key, "IPADDR%u", n);
|
||||
nm_sprintf_buf (prefix_key, "PREFIX%u", n);
|
||||
nm_sprintf_buf (netmask_key, "NETMASK%u", n);
|
||||
nm_sprintf_buf (gw_key, "GATEWAY%u", n);
|
||||
}
|
||||
|
||||
svSetValueStr (ifcfg, addr_key, nm_ip_address_get_address (addr));
|
||||
|
|
@ -2093,30 +2158,20 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
|
||||
svUnsetValue (ifcfg, netmask_key);
|
||||
svUnsetValue (ifcfg, gw_key);
|
||||
|
||||
g_free (addr_key);
|
||||
g_free (prefix_key);
|
||||
g_free (netmask_key);
|
||||
g_free (gw_key);
|
||||
n++;
|
||||
}
|
||||
|
||||
/* Clear remaining IPADDR<n..255>, etc */
|
||||
for (; n < 256; n++) {
|
||||
addr_key = g_strdup_printf ("IPADDR%d", n);
|
||||
prefix_key = g_strdup_printf ("PREFIX%d", n);
|
||||
netmask_key = g_strdup_printf ("NETMASK%d", n);
|
||||
gw_key = g_strdup_printf ("GATEWAY%d", n);
|
||||
for (i = n; i < 256; i++) {
|
||||
nm_sprintf_buf (addr_key, "IPADDR%u", i);
|
||||
nm_sprintf_buf (prefix_key, "PREFIX%u", i);
|
||||
nm_sprintf_buf (netmask_key, "NETMASK%u", i);
|
||||
nm_sprintf_buf (gw_key, "GATEWAY%u", i);
|
||||
|
||||
svUnsetValue (ifcfg, addr_key);
|
||||
svUnsetValue (ifcfg, prefix_key);
|
||||
svUnsetValue (ifcfg, netmask_key);
|
||||
svUnsetValue (ifcfg, gw_key);
|
||||
|
||||
g_free (addr_key);
|
||||
g_free (prefix_key);
|
||||
g_free (netmask_key);
|
||||
g_free (gw_key);
|
||||
}
|
||||
|
||||
svSetValueStr (ifcfg, "GATEWAY", nm_setting_ip_config_get_gateway (s_ip4));
|
||||
|
|
@ -2125,15 +2180,13 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
for (i = 0; i < 254; i++) {
|
||||
const char *dns;
|
||||
|
||||
addr_key = g_strdup_printf ("DNS%d", i + 1);
|
||||
|
||||
nm_sprintf_buf (addr_key, "DNS%u", i + 1);
|
||||
if (i >= num)
|
||||
svUnsetValue (ifcfg, addr_key);
|
||||
else {
|
||||
dns = nm_setting_ip_config_get_dns (s_ip4, i);
|
||||
svSetValueStr (ifcfg, addr_key, dns);
|
||||
}
|
||||
g_free (addr_key);
|
||||
}
|
||||
|
||||
num = nm_setting_ip_config_get_num_dns_searches (s_ip4);
|
||||
|
|
@ -2212,18 +2265,24 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
NMIPRoute *route;
|
||||
guint32 netmask;
|
||||
gint64 metric;
|
||||
char metric_key[64];
|
||||
char options_key[64];
|
||||
|
||||
addr_key = g_strdup_printf ("ADDRESS%d", i);
|
||||
netmask_key = g_strdup_printf ("NETMASK%d", i);
|
||||
gw_key = g_strdup_printf ("GATEWAY%d", i);
|
||||
metric_key = g_strdup_printf ("METRIC%d", i);
|
||||
nm_sprintf_buf (addr_key, "ADDRESS%u", i);
|
||||
nm_sprintf_buf (netmask_key, "NETMASK%u", i);
|
||||
nm_sprintf_buf (gw_key, "GATEWAY%u", i);
|
||||
nm_sprintf_buf (metric_key, "METRIC%u", i);
|
||||
nm_sprintf_buf (options_key, "OPTIONS%u", i);
|
||||
|
||||
if (i >= num) {
|
||||
svUnsetValue (routefile, addr_key);
|
||||
svUnsetValue (routefile, netmask_key);
|
||||
svUnsetValue (routefile, gw_key);
|
||||
svUnsetValue (routefile, metric_key);
|
||||
svUnsetValue (routefile, options_key);
|
||||
} else {
|
||||
gs_free char *options = NULL;
|
||||
|
||||
route = nm_setting_ip_config_get_route (s_ip4, i);
|
||||
|
||||
svSetValueStr (routefile, addr_key, nm_ip_route_get_dest (route));
|
||||
|
|
@ -2244,12 +2303,11 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
svSetValueStr (routefile, metric_key, tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (addr_key);
|
||||
g_free (netmask_key);
|
||||
g_free (gw_key);
|
||||
g_free (metric_key);
|
||||
options = get_route_attributes_string (route, AF_INET);
|
||||
if (options)
|
||||
svSetValueStr (routefile, options_key, options);
|
||||
}
|
||||
}
|
||||
if (!svWriteFile (routefile, 0644, error)) {
|
||||
svCloseFile (routefile);
|
||||
|
|
@ -2371,15 +2429,13 @@ write_ip4_aliases (NMConnection *connection, char *base_ifcfg_path)
|
|||
static gboolean
|
||||
write_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error)
|
||||
{
|
||||
char **route_items;
|
||||
gs_free char *route_contents = NULL;
|
||||
nm_auto_free_gstring GString *contents = NULL;
|
||||
NMIPRoute *route;
|
||||
guint32 i, num;
|
||||
|
||||
g_return_val_if_fail (filename != NULL, FALSE);
|
||||
g_return_val_if_fail (s_ip6 != NULL, FALSE);
|
||||
g_return_val_if_fail (error != NULL, FALSE);
|
||||
g_return_val_if_fail (*error == NULL, FALSE);
|
||||
g_return_val_if_fail (filename, FALSE);
|
||||
g_return_val_if_fail (s_ip6, FALSE);
|
||||
g_return_val_if_fail (!error || !*error, FALSE);
|
||||
|
||||
num = nm_setting_ip_config_get_num_routes (s_ip6);
|
||||
if (num == 0) {
|
||||
|
|
@ -2387,28 +2443,33 @@ write_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **erro
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
route_items = g_malloc0 (sizeof (char*) * (num + 1));
|
||||
contents = g_string_new ("");
|
||||
for (i = 0; i < num; i++) {
|
||||
gs_free char *options = NULL;
|
||||
|
||||
route = nm_setting_ip_config_get_route (s_ip6, i);
|
||||
options = get_route_attributes_string (route, AF_INET6);
|
||||
|
||||
if (nm_ip_route_get_metric (route) == -1) {
|
||||
route_items[i] = g_strdup_printf ("%s/%u via %s\n",
|
||||
nm_ip_route_get_dest (route),
|
||||
nm_ip_route_get_prefix (route),
|
||||
nm_ip_route_get_next_hop (route));
|
||||
} else {
|
||||
route_items[i] = g_strdup_printf ("%s/%u via %s metric %u\n",
|
||||
g_string_append_printf (contents, "%s/%u via %s%s%s",
|
||||
nm_ip_route_get_dest (route),
|
||||
nm_ip_route_get_prefix (route),
|
||||
nm_ip_route_get_next_hop (route),
|
||||
(guint32) nm_ip_route_get_metric (route));
|
||||
options ? " " : "",
|
||||
options ?: "");
|
||||
} else {
|
||||
g_string_append_printf (contents, "%s/%u via %s metric %u%s%s",
|
||||
nm_ip_route_get_dest (route),
|
||||
nm_ip_route_get_prefix (route),
|
||||
nm_ip_route_get_next_hop (route),
|
||||
(unsigned) nm_ip_route_get_metric (route),
|
||||
options ? " " : "",
|
||||
options ?: "");
|
||||
}
|
||||
g_string_append (contents, "\n");
|
||||
}
|
||||
route_items[num] = NULL;
|
||||
route_contents = g_strjoinv (NULL, route_items);
|
||||
g_strfreev (route_items);
|
||||
|
||||
if (!g_file_set_contents (filename, route_contents, -1, NULL)) {
|
||||
if (!g_file_set_contents (filename, contents->str, -1, NULL)) {
|
||||
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
|
||||
"Writing route6 file '%s' failed", filename);
|
||||
return FALSE;
|
||||
|
|
@ -2440,9 +2501,8 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
NMSettingIPConfig *s_ip6;
|
||||
NMSettingIPConfig *s_ip4;
|
||||
const char *value;
|
||||
char *addr_key;
|
||||
char *tmp;
|
||||
guint32 i, num, num4;
|
||||
guint i, num, num4;
|
||||
gint priority;
|
||||
NMIPAddress *addr;
|
||||
const char *dns;
|
||||
|
|
@ -2530,7 +2590,9 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
num4 = s_ip4 ? nm_setting_ip_config_get_num_dns (s_ip4) : 0; /* from where to start with IPv6 entries */
|
||||
num = nm_setting_ip_config_get_num_dns (s_ip6);
|
||||
for (i = 0; i < 254; i++) {
|
||||
addr_key = g_strdup_printf ("DNS%d", i + num4 + 1);
|
||||
char addr_key[64];
|
||||
|
||||
nm_sprintf_buf (addr_key, "DNS%u", i + num4 + 1);
|
||||
|
||||
if (i >= num)
|
||||
svUnsetValue (ifcfg, addr_key);
|
||||
|
|
@ -2538,7 +2600,6 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
dns = nm_setting_ip_config_get_dns (s_ip6, i);
|
||||
svSetValueStr (ifcfg, addr_key, dns);
|
||||
}
|
||||
g_free (addr_key);
|
||||
}
|
||||
|
||||
/* Write out DNS domains - 'DOMAIN' key is shared for both IPv4 and IPv6 domains */
|
||||
|
|
|
|||
|
|
@ -6,3 +6,4 @@ ADDRESS1=44.55.66.77
|
|||
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"
|
||||
|
|
|
|||
|
|
@ -3,5 +3,5 @@
|
|||
|
||||
21.31.41.0/24 via 9.9.9.9 metric 1
|
||||
via 8.8.8.8 to 32.42.52.62
|
||||
43.53.0.0/16 metric 3 via 7.7.7.7 dev eth2
|
||||
43.53.0.0/16 metric 3 via 7.7.7.7 dev eth2 cwnd 14 mtu lock 9000 initrwnd 20 window lock 10000 initcwnd lock 42 src 1.2.3.4
|
||||
|
||||
|
|
|
|||
|
|
@ -5,3 +5,5 @@ default via dead::beaf
|
|||
|
||||
# routes without "via" are valid
|
||||
abbe::cafe/64 metric 777
|
||||
|
||||
aaaa::cccc/64 from 1111::2222/48 via 3333::4444 src 5555::6666 mtu lock 1450 cwnd 13
|
||||
|
|
|
|||
|
|
@ -1127,6 +1127,15 @@ test_read_wired_static_routes (void)
|
|||
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.7");
|
||||
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_PREF_SRC, "1.1.1.1");
|
||||
|
||||
g_object_unref (connection);
|
||||
}
|
||||
|
|
@ -1188,6 +1197,14 @@ test_read_wired_static_routes_legacy (void)
|
|||
g_assert_cmpint (nm_ip_route_get_prefix (ip4_route), ==, 16);
|
||||
g_assert_cmpstr (nm_ip_route_get_next_hop (ip4_route), ==, "7.7.7.7");
|
||||
g_assert_cmpint (nm_ip_route_get_metric (ip4_route), ==, 3);
|
||||
nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_WINDOW, 10000);
|
||||
nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_CWND, 14);
|
||||
nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_INITCWND, 42);
|
||||
nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_INITRWND, 20);
|
||||
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_WINDOW, TRUE);
|
||||
nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, TRUE);
|
||||
nmtst_assert_route_attribute_string (ip4_route, NM_IP_ROUTE_ATTRIBUTE_PREF_SRC, "1.2.3.4");
|
||||
|
||||
g_object_unref (connection);
|
||||
}
|
||||
|
|
@ -1328,7 +1345,7 @@ test_read_wired_ipv6_manual (void)
|
|||
g_assert_cmpint (nm_ip_address_get_prefix (ip6_addr), ==, 96);
|
||||
|
||||
/* Routes */
|
||||
g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 2);
|
||||
g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 3);
|
||||
/* Route #1 */
|
||||
ip6_route = nm_setting_ip_config_get_route (s_ip6, 0);
|
||||
g_assert (ip6_route);
|
||||
|
|
@ -1343,6 +1360,17 @@ test_read_wired_ipv6_manual (void)
|
|||
g_assert_cmpint (nm_ip_route_get_prefix (ip6_route), ==, 64);
|
||||
g_assert_cmpstr (nm_ip_route_get_next_hop (ip6_route), ==, NULL);
|
||||
g_assert_cmpint (nm_ip_route_get_metric (ip6_route), ==, 777);
|
||||
/* Route #3 */
|
||||
ip6_route = nm_setting_ip_config_get_route (s_ip6, 2);
|
||||
g_assert (ip6_route);
|
||||
g_assert_cmpstr (nm_ip_route_get_dest (ip6_route), ==, "aaaa::cccc");
|
||||
g_assert_cmpint (nm_ip_route_get_prefix (ip6_route), ==, 64);
|
||||
g_assert_cmpstr (nm_ip_route_get_next_hop (ip6_route), ==, "3333::4444");
|
||||
nmtst_assert_route_attribute_uint32 (ip6_route, NM_IP_ROUTE_ATTRIBUTE_CWND, 13);
|
||||
nmtst_assert_route_attribute_uint32 (ip6_route, NM_IP_ROUTE_ATTRIBUTE_MTU, 1450);
|
||||
nmtst_assert_route_attribute_boolean (ip6_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, TRUE);
|
||||
nmtst_assert_route_attribute_string (ip6_route, NM_IP_ROUTE_ATTRIBUTE_SRC, "1111::2222/48");
|
||||
nmtst_assert_route_attribute_string (ip6_route, NM_IP_ROUTE_ATTRIBUTE_PREF_SRC, "5555::6666");
|
||||
|
||||
/* DNS Addresses */
|
||||
g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 2);
|
||||
|
|
@ -3867,6 +3895,12 @@ test_write_wired_static (void)
|
|||
|
||||
route6 = nm_ip_route_new (AF_INET6, "::", 128, "2222:aaaa::9999", 1, &error);
|
||||
g_assert_no_error (error);
|
||||
nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_TOS, g_variant_new_byte (0xb8));
|
||||
nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_CWND, g_variant_new_uint32 (100));
|
||||
nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_MTU, g_variant_new_uint32 (1280));
|
||||
nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, g_variant_new_boolean (TRUE));
|
||||
nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_SRC, g_variant_new_string ("2222::bbbb/32"));
|
||||
nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_PREF_SRC, g_variant_new_string ("::42"));
|
||||
nm_setting_ip_config_add_route (s_ip6, route6);
|
||||
nm_ip_route_unref (route6);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ routes8=1.1.1.8/18,0.0.0.0,
|
|||
routes9=1.1.1.9/19,0.0.0.0,0
|
||||
routes10=1.1.1.10/20,,0
|
||||
routes11=1.1.1.11/21,,21
|
||||
routes11_options=cwnd=10,lock-cwnd=true,mtu=1430,pref-src=7.7.7.7
|
||||
ignore-auto-routes=false
|
||||
ignore-auto-dns=false
|
||||
|
||||
|
|
@ -58,5 +59,6 @@ route3=6:7:8:9:0:1:2:3/126,,1
|
|||
route4=7:8:9:0:1:2:3:4/125/::,5
|
||||
route5=8:9:0:1:2:3:4:5/124,6
|
||||
route6=8:9:0:1:2:3:4:6/123,,
|
||||
route6_options=src=abce::/63
|
||||
ignore-auto-routes=false
|
||||
ignore-auto-dns=false
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ test_read_valid_wired_connection (void)
|
|||
NMSettingWired *s_wired;
|
||||
NMSettingIPConfig *s_ip4;
|
||||
NMSettingIPConfig *s_ip6;
|
||||
NMIPRoute *route;
|
||||
gs_free_error GError *error = NULL;
|
||||
const char *mac;
|
||||
char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
|
||||
|
|
@ -318,6 +319,15 @@ test_read_valid_wired_connection (void)
|
|||
check_ip_route (s_ip4, 10, "1.1.1.10", 20, NULL, -1);
|
||||
check_ip_route (s_ip4, 11, "1.1.1.11", 21, NULL, 21);
|
||||
|
||||
/* Route attributes */
|
||||
route = nm_setting_ip_config_get_route (s_ip4, 11);
|
||||
g_assert (route);
|
||||
|
||||
nmtst_assert_route_attribute_uint32 (route, NM_IP_ROUTE_ATTRIBUTE_CWND, 10);
|
||||
nmtst_assert_route_attribute_uint32 (route, NM_IP_ROUTE_ATTRIBUTE_MTU, 1430);
|
||||
nmtst_assert_route_attribute_boolean (route, NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, TRUE);
|
||||
nmtst_assert_route_attribute_string (route, NM_IP_ROUTE_ATTRIBUTE_PREF_SRC, "7.7.7.7");
|
||||
|
||||
/* ===== IPv6 SETTING ===== */
|
||||
s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
||||
g_assert (s_ip6);
|
||||
|
|
@ -357,6 +367,11 @@ test_read_valid_wired_connection (void)
|
|||
check_ip_route (s_ip6, 4, "7:8:9:0:1:2:3:4", 125, NULL, 5);
|
||||
check_ip_route (s_ip6, 5, "8:9:0:1:2:3:4:5", 124, NULL, 6);
|
||||
check_ip_route (s_ip6, 6, "8:9:0:1:2:3:4:6", 123, NULL, -1);
|
||||
|
||||
/* Route attributes */
|
||||
route = nm_setting_ip_config_get_route (s_ip6, 6);
|
||||
g_assert (route);
|
||||
nmtst_assert_route_attribute_string (route, NM_IP_ROUTE_ATTRIBUTE_SRC, "abce::/63");
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -402,6 +417,7 @@ test_write_wired_connection (void)
|
|||
NMSettingWired *s_wired;
|
||||
NMSettingIPConfig *s_ip4;
|
||||
NMSettingIPConfig *s_ip6;
|
||||
NMIPRoute *rt;
|
||||
const char *mac = "99:88:77:66:55:44";
|
||||
const char *dns1 = "4.2.2.1";
|
||||
const char *dns2 = "4.2.2.2";
|
||||
|
|
@ -429,6 +445,7 @@ test_write_wired_connection (void)
|
|||
const char *route6_4 = "5:6:7:8:9:0:1:2";
|
||||
const char *route6_4_nh = "::";
|
||||
guint64 timestamp = 0x12345678L;
|
||||
GError *error = NULL;
|
||||
|
||||
connection = nm_simple_connection_new ();
|
||||
|
||||
|
|
@ -473,7 +490,14 @@ test_write_wired_connection (void)
|
|||
add_one_ip_route (s_ip4, route1, route1_nh, 24, 3);
|
||||
add_one_ip_route (s_ip4, route2, route2_nh, 8, 1);
|
||||
add_one_ip_route (s_ip4, route3, route3_nh, 7, -1);
|
||||
add_one_ip_route (s_ip4, route4, route4_nh, 6, 4);
|
||||
|
||||
rt = nm_ip_route_new (AF_INET, route4, 6, route4_nh, 4, &error);
|
||||
g_assert_no_error (error);
|
||||
nm_ip_route_set_attribute (rt, NM_IP_ROUTE_ATTRIBUTE_CWND, g_variant_new_uint32 (10));
|
||||
nm_ip_route_set_attribute (rt, NM_IP_ROUTE_ATTRIBUTE_MTU, g_variant_new_uint32 (1492));
|
||||
nm_ip_route_set_attribute (rt, NM_IP_ROUTE_ATTRIBUTE_PREF_SRC, g_variant_new_string ("1.2.3.4"));
|
||||
g_assert (nm_setting_ip_config_add_route (s_ip4, rt));
|
||||
nm_ip_route_unref (rt);
|
||||
|
||||
/* DNS servers */
|
||||
nm_setting_ip_config_add_dns (s_ip4, dns1);
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ build_test_config (void)
|
|||
config = nm_ip6_config_new (1);
|
||||
|
||||
nm_ip6_config_add_address (config, nmtst_platform_ip6_address ("abcd:1234:4321::cdde", "1:2:3:4::5", 64));
|
||||
nm_ip6_config_add_route (config, nmtst_platform_ip6_route ("abcd:1234:4321::", 24, "abcd:1234:4321:cdde::2"));
|
||||
nm_ip6_config_add_route (config, nmtst_platform_ip6_route ("2001:abba::", 16, "2001:abba::2234"));
|
||||
nm_ip6_config_add_route (config, nmtst_platform_ip6_route ("abcd:1234:4321::", 24, "abcd:1234:4321:cdde::2", NULL));
|
||||
nm_ip6_config_add_route (config, nmtst_platform_ip6_route ("2001:abba::", 16, "2001:abba::2234", NULL));
|
||||
|
||||
nm_ip6_config_set_gateway (config, nmtst_inet6_from_string ("3001:abba::3234"));
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ test_subtract (void)
|
|||
/* add a couple more things to the test config */
|
||||
dst = build_test_config ();
|
||||
nm_ip6_config_add_address (dst, nmtst_platform_ip6_address (expected_addr, NULL, expected_addr_plen));
|
||||
nm_ip6_config_add_route (dst, nmtst_platform_ip6_route (expected_route_dest, expected_route_plen, expected_route_next_hop));
|
||||
nm_ip6_config_add_route (dst, nmtst_platform_ip6_route (expected_route_dest, expected_route_plen, expected_route_next_hop, NULL));
|
||||
|
||||
expected_ns1 = *nmtst_inet6_from_string ("2222:3333:4444::5555");
|
||||
nm_ip6_config_add_nameserver (dst, &expected_ns1);
|
||||
|
|
@ -139,7 +139,7 @@ test_compare_with_source (void)
|
|||
nm_ip6_config_add_address (b, &addr);
|
||||
|
||||
/* Route */
|
||||
route = *nmtst_platform_ip6_route ("abcd:1234:4321::", 24, "abcd:1234:4321:cdde::2");
|
||||
route = *nmtst_platform_ip6_route ("abcd:1234:4321::", 24, "abcd:1234:4321:cdde::2", NULL);
|
||||
route.rt_source = NM_IP_CONFIG_SOURCE_USER;
|
||||
nm_ip6_config_add_route (a, &route);
|
||||
|
||||
|
|
@ -203,7 +203,7 @@ test_add_route_with_source (void)
|
|||
a = nm_ip6_config_new (1);
|
||||
|
||||
/* Test that a higher priority source is not overwritten */
|
||||
route = *nmtst_platform_ip6_route ("abcd:1234:4321::", 24, "abcd:1234:4321:cdde::2");
|
||||
route = *nmtst_platform_ip6_route ("abcd:1234:4321::", 24, "abcd:1234:4321:cdde::2", NULL);
|
||||
route.rt_source = NM_IP_CONFIG_SOURCE_USER;
|
||||
nm_ip6_config_add_route (a, &route);
|
||||
|
||||
|
|
|
|||
|
|
@ -75,16 +75,15 @@ setup_dev1_ip4 (int ifindex)
|
|||
|
||||
/* Add some route outside of route manager. The route manager
|
||||
* should get rid of it upon sync. */
|
||||
if (!nm_platform_ip4_route_add (NM_PLATFORM_GET,
|
||||
route.ifindex,
|
||||
NM_IP_CONFIG_SOURCE_USER,
|
||||
nmtst_inet4_from_string ("9.0.0.0"),
|
||||
8,
|
||||
INADDR_ANY,
|
||||
0,
|
||||
10,
|
||||
route.mss))
|
||||
g_assert_not_reached ();
|
||||
nmtstp_ip4_route_add (NM_PLATFORM_GET,
|
||||
route.ifindex,
|
||||
NM_IP_CONFIG_SOURCE_USER,
|
||||
nmtst_inet4_from_string ("9.0.0.0"),
|
||||
8,
|
||||
INADDR_ANY,
|
||||
0,
|
||||
10,
|
||||
route.mss);
|
||||
|
||||
route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
|
||||
inet_pton (AF_INET, "6.6.6.0", &route.network);
|
||||
|
|
@ -421,15 +420,15 @@ setup_dev1_ip6 (int ifindex)
|
|||
|
||||
/* Add some route outside of route manager. The route manager
|
||||
* should get rid of it upon sync. */
|
||||
if (!nm_platform_ip6_route_add (NM_PLATFORM_GET,
|
||||
ifindex,
|
||||
NM_IP_CONFIG_SOURCE_USER,
|
||||
*nmtst_inet6_from_string ("2001:db8:8088::"),
|
||||
48,
|
||||
in6addr_any,
|
||||
10,
|
||||
0))
|
||||
g_assert_not_reached ();
|
||||
nmtstp_ip6_route_add (NM_PLATFORM_GET,
|
||||
ifindex,
|
||||
NM_IP_CONFIG_SOURCE_USER,
|
||||
*nmtst_inet6_from_string ("2001:db8:8088::"),
|
||||
48,
|
||||
in6addr_any,
|
||||
in6addr_any,
|
||||
10,
|
||||
0);
|
||||
|
||||
route = nmtst_platform_ip6_route_full ("2001:db8:8086::",
|
||||
48,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue