all: merge branch 'th/scope-for-ipv4-route'

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/349
This commit is contained in:
Thomas Haller
2019-11-28 00:11:34 +01:00
12 changed files with 265 additions and 115 deletions

1
NEWS
View File

@@ -25,6 +25,7 @@ USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
type instances would have been created by NMClient for a while now.
* DHCP: switch "internal" DHCPv4 plugin from code based on systemd to use nettools'
n-dhcp4 library.
* Add support for "scope" attribute for IPv4 routes.
* libnm: heavily internal rework NMClient. This slims down libnm and makes the
implementation more efficient. NMClient should work now well with a separate
GMainContext.

View File

@@ -874,4 +874,13 @@ const char *nm_utils_wifi_freq_to_band (guint32 freq);
gboolean _nm_utils_iaid_verify (const char *str, gint64 *out_value);
/*****************************************************************************/
gboolean _nmtst_variant_attribute_spec_assert_sorted (const NMVariantAttributeSpec *const*array,
gsize len);
const NMVariantAttributeSpec *_nm_variant_attribute_spec_find_binary_search (const NMVariantAttributeSpec *const*array,
gsize len,
const char *name);
#endif

View File

@@ -1197,21 +1197,22 @@ nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value)
}
static const NMVariantAttributeSpec *const ip_route_attribute_spec[] = {
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TABLE, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, .v4 = TRUE, .v6 = TRUE, .str_type = 'a', ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_FROM, G_VARIANT_TYPE_STRING, .v6 = TRUE, .str_type = 'p', ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, .v4 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_ONLINK, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_CWND, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_FROM, G_VARIANT_TYPE_STRING, .v6 = TRUE, .str_type = 'p', ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_INITCWND, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_INITRWND, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_MTU, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_MTU, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_ONLINK, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_SCOPE, G_VARIANT_TYPE_BYTE, .v4 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, .v4 = TRUE, .v6 = TRUE, .str_type = 'a', ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TABLE, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, .v4 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
NULL,
};
@@ -1250,21 +1251,16 @@ nm_ip_route_attribute_validate (const char *name,
gboolean *known,
GError **error)
{
const NMVariantAttributeSpec *const *iter;
const NMVariantAttributeSpec *spec = NULL;
const NMVariantAttributeSpec *spec;
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;
}
}
spec = _nm_variant_attribute_spec_find_binary_search (ip_route_attribute_spec,
G_N_ELEMENTS (ip_route_attribute_spec) - 1,
name);
if (!spec) {
NM_SET_OUT (known, FALSE);
g_set_error_literal (error,

View File

@@ -127,21 +127,22 @@ gboolean nm_ip_route_attribute_validate (const char *name,
gboolean *known,
GError **error);
#define NM_IP_ROUTE_ATTRIBUTE_TABLE "table"
#define NM_IP_ROUTE_ATTRIBUTE_SRC "src"
#define NM_IP_ROUTE_ATTRIBUTE_FROM "from"
#define NM_IP_ROUTE_ATTRIBUTE_TOS "tos"
#define NM_IP_ROUTE_ATTRIBUTE_ONLINK "onlink"
#define NM_IP_ROUTE_ATTRIBUTE_WINDOW "window"
#define NM_IP_ROUTE_ATTRIBUTE_CWND "cwnd"
#define NM_IP_ROUTE_ATTRIBUTE_FROM "from"
#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_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW "lock-window"
#define NM_IP_ROUTE_ATTRIBUTE_MTU "mtu"
#define NM_IP_ROUTE_ATTRIBUTE_ONLINK "onlink"
#define NM_IP_ROUTE_ATTRIBUTE_SCOPE "scope"
#define NM_IP_ROUTE_ATTRIBUTE_SRC "src"
#define NM_IP_ROUTE_ATTRIBUTE_TABLE "table"
#define NM_IP_ROUTE_ATTRIBUTE_TOS "tos"
#define NM_IP_ROUTE_ATTRIBUTE_WINDOW "window"
/*****************************************************************************/

View File

@@ -5555,6 +5555,48 @@ attribute_unescape (const char *start, const char *end)
return ret;
}
gboolean
_nmtst_variant_attribute_spec_assert_sorted (const NMVariantAttributeSpec *const*array,
gsize len)
{
gsize i;
g_assert (array);
g_assert (len > 0);
g_assert_cmpint(len, ==, NM_PTRARRAY_LEN (array));
for (i = 0; i < len; i++) {
nm_assert (array[i]->name);
nm_assert (array[i]->name[0]);
if (i > 0)
nm_assert (strcmp (array[i - 1]->name, array[i]->name) < 0);
}
nm_assert (!array[i]);
return TRUE;
}
const NMVariantAttributeSpec *
_nm_variant_attribute_spec_find_binary_search (const NMVariantAttributeSpec *const*array,
gsize len,
const char *name)
{
gssize idx;
G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMVariantAttributeSpec, name) == 0);
idx = nm_utils_ptrarray_find_binary_search ((gconstpointer *) array,
len,
&name,
nm_strcmp_p_with_data,
NULL,
NULL,
NULL);
if (idx < 0)
return NULL;
return array[idx];
}
/**
* nm_utils_parse_variant_attributes:
* @string: the input string

View File

@@ -7986,6 +7986,33 @@ test_route_attributes_format (void)
/*****************************************************************************/
static void
test_variant_attribute_spec (void)
{
const NMVariantAttributeSpec *const *const specs_list[] = {
nm_ip_route_get_variant_attribute_spec (),
};
int i_specs;
for (i_specs = 0; i_specs < G_N_ELEMENTS (specs_list); i_specs++) {
const NMVariantAttributeSpec *const *const specs = specs_list[i_specs];
gsize len;
gsize i;
g_assert (specs);
len = NM_PTRARRAY_LEN (specs);
g_assert_cmpint (len, >, 0u);
_nmtst_variant_attribute_spec_assert_sorted (specs, len);
for (i = 0; i < len; i++)
g_assert (specs[i] == _nm_variant_attribute_spec_find_binary_search (specs, len, specs[i]->name));
g_assert (!_nm_variant_attribute_spec_find_binary_search (specs, len, "bogus"));
}
}
/*****************************************************************************/
static gboolean
do_test_nm_set_out_called (int *call_count)
{
@@ -8448,6 +8475,7 @@ int main (int argc, char **argv)
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);
g_test_add_func ("/core/general/test_variant_attribute_spec", test_variant_attribute_spec);
g_test_add_func ("/core/general/get_start_time_for_pid", test_get_start_time_for_pid);
g_test_add_func ("/core/general/test_nm_va_args_macros", test_nm_va_args_macros);

View File

@@ -862,8 +862,13 @@ _nm_ip_config_merge_route_attributes (int addr_family,
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, table, UINT32, uint32, 0);
r->table_coerced = nm_platform_route_table_coerce (table ?: (route_table ?: RT_TABLE_MAIN));
if (addr_family == AF_INET)
if (addr_family == AF_INET) {
guint8 scope;
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TOS, r4->tos, BYTE, byte, 0);
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_SCOPE, scope, BYTE, byte, RT_SCOPE_NOWHERE);
r4->scope_inv = nm_platform_route_scope_inv (scope);
}
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_ONLINK, onlink, BOOLEAN, boolean, FALSE);

View File

@@ -496,7 +496,7 @@ struct _NMPlatformIP4Route {
/* The bitwise inverse of the route scope rtm_scope. It is inverted so that the
* default value (RT_SCOPE_NOWHERE) is zero. Use nm_platform_route_scope_inv()
* to convert back and forth between the inverese representation and the
* to convert back and forth between the inverse representation and the
* real value.
*
* rtm_scope is part of the primary key for IPv4 routes. When deleting a route,

View File

@@ -15,6 +15,7 @@
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/rtnetlink.h>
#include "nm-glib-aux/nm-secret-utils.h"
#include "nm-connection.h"
@@ -739,25 +740,36 @@ parse_route_line_is_comment (const char *line)
/*****************************************************************************/
typedef enum {
PARSE_LINE_AF_FLAG_FOR_IPV4 = 0x01,
PARSE_LINE_AF_FLAG_FOR_IPV6 = 0x02,
} ParseLineAFFlag;
typedef struct {
const char *key;
/* the element is not available in this case. */
bool disabled:1;
ParseLineAFFlag disabled:3;
bool disabled_with_options_route:1;
/* whether the element is to be ignored. Ignord is different from
* "disabled", because we still parse the option, but don't use it. */
bool ignore:1;
ParseLineAFFlag ignore:3;
bool int_base_16:1;
/* the type, one of PARSE_LINE_TYPE_* */
char type;
} ParseLineInfo;
typedef struct {
/* whether the command line option was found, and @v is
* initialized. */
bool has:1;
/* the type, one of PARSE_LINE_TYPE_* */
char type;
union {
guint8 uint8;
guint32 uint32;
@@ -772,7 +784,7 @@ typedef struct {
} addr;
} v;
} ParseLineInfo;
} ParseLineData;
enum {
/* route attributes */
@@ -780,6 +792,7 @@ enum {
PARSE_LINE_ATTR_ROUTE_SRC,
PARSE_LINE_ATTR_ROUTE_FROM,
PARSE_LINE_ATTR_ROUTE_TOS,
PARSE_LINE_ATTR_ROUTE_SCOPE,
PARSE_LINE_ATTR_ROUTE_ONLINK,
PARSE_LINE_ATTR_ROUTE_WINDOW,
PARSE_LINE_ATTR_ROUTE_CWND,
@@ -803,6 +816,7 @@ enum {
#define PARSE_LINE_TYPE_ADDR_WITH_PREFIX 'p'
#define PARSE_LINE_TYPE_IFNAME 'i'
#define PARSE_LINE_TYPE_FLAG 'f'
#define PARSE_LINE_TYPE_ROUTE_SCOPE 'S'
/**
* parse_route_line:
@@ -833,29 +847,23 @@ parse_route_line (const char *line,
NMIPRoute **out_route,
GError **error)
{
nm_auto_unref_ip_route NMIPRoute *route = NULL;
gs_free const char **words_free = NULL;
const char *const*words;
const char *s;
gsize i_words;
guint i;
char buf1[256];
char buf2[256];
ParseLineInfo infos[] = {
static const ParseLineInfo parse_infos[] = {
[PARSE_LINE_ATTR_ROUTE_TABLE] = { .key = NM_IP_ROUTE_ATTRIBUTE_TABLE,
.type = PARSE_LINE_TYPE_UINT32, },
[PARSE_LINE_ATTR_ROUTE_SRC] = { .key = NM_IP_ROUTE_ATTRIBUTE_SRC,
.type = PARSE_LINE_TYPE_ADDR, },
[PARSE_LINE_ATTR_ROUTE_FROM] = { .key = NM_IP_ROUTE_ATTRIBUTE_FROM,
.type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX,
.disabled = (addr_family != AF_INET6), },
.disabled = PARSE_LINE_AF_FLAG_FOR_IPV4, },
[PARSE_LINE_ATTR_ROUTE_TOS] = { .key = NM_IP_ROUTE_ATTRIBUTE_TOS,
.type = PARSE_LINE_TYPE_UINT8,
.int_base_16 = TRUE,
.ignore = (addr_family != AF_INET), },
.ignore = PARSE_LINE_AF_FLAG_FOR_IPV6, },
[PARSE_LINE_ATTR_ROUTE_SCOPE] = { .key = NM_IP_ROUTE_ATTRIBUTE_SCOPE,
.type = PARSE_LINE_TYPE_ROUTE_SCOPE,
.ignore = PARSE_LINE_AF_FLAG_FOR_IPV6, },
[PARSE_LINE_ATTR_ROUTE_ONLINK] = { .key = NM_IP_ROUTE_ATTRIBUTE_ONLINK,
.type = PARSE_LINE_TYPE_FLAG,
.ignore = (addr_family != AF_INET), },
.type = PARSE_LINE_TYPE_FLAG, },
[PARSE_LINE_ATTR_ROUTE_WINDOW] = { .key = NM_IP_ROUTE_ATTRIBUTE_WINDOW,
.type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, },
[PARSE_LINE_ATTR_ROUTE_CWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_CWND,
@@ -869,19 +877,31 @@ parse_route_line (const char *line,
[PARSE_LINE_ATTR_ROUTE_TO] = { .key = "to",
.type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX,
.disabled = (options_route != NULL), },
.disabled_with_options_route = TRUE, },
[PARSE_LINE_ATTR_ROUTE_VIA] = { .key = "via",
.type = PARSE_LINE_TYPE_ADDR,
.disabled = (options_route != NULL), },
.disabled_with_options_route = TRUE, },
[PARSE_LINE_ATTR_ROUTE_METRIC] = { .key = "metric",
.type = PARSE_LINE_TYPE_UINT32,
.disabled = (options_route != NULL), },
.disabled_with_options_route = TRUE, },
[PARSE_LINE_ATTR_ROUTE_DEV] = { .key = "dev",
.type = PARSE_LINE_TYPE_IFNAME,
.ignore = TRUE,
.disabled = (options_route != NULL), },
.ignore = PARSE_LINE_AF_FLAG_FOR_IPV4 | PARSE_LINE_AF_FLAG_FOR_IPV6,
.disabled_with_options_route = TRUE, },
};
nm_auto_unref_ip_route NMIPRoute *route = NULL;
gs_free const char **words_free = NULL;
const char *const*words;
const char *s;
gsize i_words;
guint i;
char buf1[256];
char buf2[256];
ParseLineData parse_datas[G_N_ELEMENTS (parse_infos)] = { };
const ParseLineAFFlag af_flag = (addr_family == AF_INET)
? PARSE_LINE_AF_FLAG_FOR_IPV4
: PARSE_LINE_AF_FLAG_FOR_IPV6;
nm_assert (line);
nm_assert_addr_family (addr_family);
@@ -909,19 +929,22 @@ parse_route_line (const char *line,
for (i_words = 0; words[i_words]; ) {
const gsize i_words0 = i_words;
const char *const w = words[i_words0];
ParseLineInfo *info;
const ParseLineInfo *p_info;
ParseLineData *p_data;
gboolean unqualified_addr = FALSE;
for (i = 0; i < G_N_ELEMENTS (infos); i++) {
info = &infos[i];
for (i = 0; i < G_N_ELEMENTS (parse_infos); i++) {
p_info = &parse_infos[i];
p_data = &parse_datas[i];
if (info->disabled)
if ( (p_info->disabled & af_flag)
|| (p_info->disabled_with_options_route && options_route))
continue;
if (!nm_streq (w, info->key))
if (!nm_streq (w, p_info->key))
continue;
if (info->has) {
if (p_data->has) {
/* iproute2 for most arguments allows specifying them multiple times.
* Let's not do that. */
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
@@ -929,8 +952,8 @@ parse_route_line (const char *line,
return -EINVAL;
}
info->has = TRUE;
switch (info->type) {
p_data->has = TRUE;
switch (p_info->type) {
case PARSE_LINE_TYPE_UINT8:
i_words++;
goto parse_line_type_uint8;
@@ -952,16 +975,22 @@ parse_route_line (const char *line,
case PARSE_LINE_TYPE_FLAG:
i_words++;
goto next;
case PARSE_LINE_TYPE_ROUTE_SCOPE:
i_words++;
goto parse_line_type_route_scope;
default:
nm_assert_not_reached ();
}
}
/* "to" is also accepted unqualified... (once) */
info = &infos[PARSE_LINE_ATTR_ROUTE_TO];
if (!info->has && !info->disabled) {
p_info = &parse_infos[PARSE_LINE_ATTR_ROUTE_TO];
p_data = &parse_datas[PARSE_LINE_ATTR_ROUTE_TO];
if ( !p_data->has
&& !(p_info->disabled & af_flag)
&& !(p_info->disabled_with_options_route && options_route)) {
unqualified_addr = TRUE;
info->has = TRUE;
p_data->has = TRUE;
goto parse_line_type_addr;
}
@@ -969,15 +998,44 @@ parse_route_line (const char *line,
"Unrecognized argument (\"to\" is duplicate or \"%s\" is garbage)", w);
return -EINVAL;
parse_line_type_route_scope:
s = words[i_words];
if (!s)
goto err_word_missing_argument;
if (nm_streq (s, "global"))
p_data->v.uint8 = RT_SCOPE_UNIVERSE;
else if (nm_streq (s, "nowhere"))
p_data->v.uint8 = RT_SCOPE_NOWHERE;
else if (nm_streq (s, "host"))
p_data->v.uint8 = RT_SCOPE_HOST;
else if (nm_streq (s, "link"))
p_data->v.uint8 = RT_SCOPE_LINK;
else if (nm_streq (s, "site"))
p_data->v.uint8 = RT_SCOPE_SITE;
else {
p_data->v.uint8 = _nm_utils_ascii_str_to_int64 (s,
0,
0,
G_MAXUINT8,
0);;
if (errno) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Argument for \"%s\" is not a valid number", w);
return -EINVAL;
}
}
i_words++;
goto next;
parse_line_type_uint8:
s = words[i_words];
if (!s)
goto err_word_missing_argument;
info->v.uint8 = _nm_utils_ascii_str_to_int64 (s,
info->int_base_16 ? 16 : 10,
0,
G_MAXUINT8,
0);;
p_data->v.uint8 = _nm_utils_ascii_str_to_int64 (s,
p_info->int_base_16 ? 16 : 10,
0,
G_MAXUINT8,
0);;
if (errno) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Argument for \"%s\" is not a valid number", w);
@@ -991,17 +1049,17 @@ parse_line_type_uint32_with_lock:
s = words[i_words];
if (!s)
goto err_word_missing_argument;
if (info->type == PARSE_LINE_TYPE_UINT32_WITH_LOCK) {
if (p_info->type == PARSE_LINE_TYPE_UINT32_WITH_LOCK) {
if (nm_streq (s, "lock")) {
s = words[++i_words];
if (!s)
goto err_word_missing_argument;
info->v.uint32_with_lock.lock = TRUE;
p_data->v.uint32_with_lock.lock = TRUE;
} else
info->v.uint32_with_lock.lock = FALSE;
info->v.uint32_with_lock.uint32 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT32, 0);;
p_data->v.uint32_with_lock.lock = FALSE;
p_data->v.uint32_with_lock.uint32 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT32, 0);;
} else {
info->v.uint32 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT32, 0);
p_data->v.uint32 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT32, 0);
}
if (errno) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
@@ -1026,16 +1084,16 @@ parse_line_type_addr_with_prefix:
{
int prefix = -1;
if (info->type == PARSE_LINE_TYPE_ADDR) {
if (p_info->type == PARSE_LINE_TYPE_ADDR) {
if (!nm_utils_parse_inaddr_bin (addr_family,
s,
NULL,
&info->v.addr.addr)) {
if ( info == &infos[PARSE_LINE_ATTR_ROUTE_VIA]
&p_data->v.addr.addr)) {
if ( p_info == &parse_infos[PARSE_LINE_ATTR_ROUTE_VIA]
&& nm_streq (s, "(null)")) {
/* Due to a bug, would older versions of NM write "via (null)"
* (rh#1452648). Workaround that, and accept it.*/
memset (&info->v.addr.addr, 0, sizeof (info->v.addr.addr));
memset (&p_data->v.addr.addr, 0, sizeof (p_data->v.addr.addr));
} else {
if (unqualified_addr) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
@@ -1050,15 +1108,15 @@ parse_line_type_addr_with_prefix:
}
}
} else {
nm_assert (info->type == PARSE_LINE_TYPE_ADDR_WITH_PREFIX);
if ( info == &infos[PARSE_LINE_ATTR_ROUTE_TO]
nm_assert (p_info->type == PARSE_LINE_TYPE_ADDR_WITH_PREFIX);
if ( p_info == &parse_infos[PARSE_LINE_ATTR_ROUTE_TO]
&& nm_streq (s, "default")) {
memset (&info->v.addr.addr, 0, sizeof (info->v.addr.addr));
memset (&p_data->v.addr.addr, 0, sizeof (p_data->v.addr.addr));
prefix = 0;
} else if (!nm_utils_parse_inaddr_prefix_bin (addr_family,
s,
NULL,
&info->v.addr.addr,
&p_data->v.addr.addr,
&prefix)) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Argument for \"%s\" is not ADDR/PREFIX format", w);
@@ -1066,10 +1124,10 @@ parse_line_type_addr_with_prefix:
}
}
if (prefix == -1)
info->v.addr.has_plen = FALSE;
p_data->v.addr.has_plen = FALSE;
else {
info->v.addr.has_plen = TRUE;
info->v.addr.plen = prefix;
p_data->v.addr.has_plen = TRUE;
p_data->v.addr.plen = prefix;
}
}
i_words++;
@@ -1087,70 +1145,76 @@ next:
route = options_route;
nm_ip_route_ref (route);
} else {
ParseLineInfo *info_to = &infos[PARSE_LINE_ATTR_ROUTE_TO];
ParseLineInfo *info_via = &infos[PARSE_LINE_ATTR_ROUTE_VIA];
ParseLineInfo *info_metric = &infos[PARSE_LINE_ATTR_ROUTE_METRIC];
ParseLineData *data_to = &parse_datas[PARSE_LINE_ATTR_ROUTE_TO];
ParseLineData *data_via = &parse_datas[PARSE_LINE_ATTR_ROUTE_VIA];
ParseLineData *data_metric = &parse_datas[PARSE_LINE_ATTR_ROUTE_METRIC];
guint prefix;
if (!info_to->has) {
if (!data_to->has) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Missing destination prefix");
return -EINVAL;
}
prefix = info_to->v.addr.has_plen
? info_to->v.addr.plen
prefix = data_to->v.addr.has_plen
? data_to->v.addr.plen
: (addr_family == AF_INET ? 32 : 128);
route = nm_ip_route_new_binary (addr_family,
&info_to->v.addr.addr,
&data_to->v.addr.addr,
prefix,
info_via->has ? &info_via->v.addr.addr : NULL,
info_metric->has ? (gint64) info_metric->v.uint32 : (gint64) -1,
data_via->has ? &data_via->v.addr.addr : NULL,
data_metric->has ? (gint64) data_metric->v.uint32 : (gint64) -1,
error);
info_to->has = FALSE;
info_via->has = FALSE;
info_metric->has = FALSE;
data_to->has = FALSE;
data_via->has = FALSE;
data_metric->has = FALSE;
if (!route)
return -EINVAL;
}
for (i = 0; i < G_N_ELEMENTS (infos); i++) {
ParseLineInfo *info = &infos[i];
for (i = 0; i < G_N_ELEMENTS (parse_infos); i++) {
const ParseLineInfo *p_info = &parse_infos[i];
ParseLineData *p_data = &parse_datas[i];
if (!info->has)
if (!p_data->has)
continue;
if (info->ignore || info->disabled)
if ( (p_info->ignore & af_flag)
|| (p_info->disabled & af_flag)
|| (p_info->disabled_with_options_route && options_route))
continue;
switch (info->type) {
switch (p_info->type) {
case PARSE_LINE_TYPE_UINT8:
case PARSE_LINE_TYPE_ROUTE_SCOPE:
nm_ip_route_set_attribute (route,
info->key,
g_variant_new_byte (info->v.uint8));
p_info->key,
g_variant_new_byte (p_data->v.uint8));
break;
case PARSE_LINE_TYPE_UINT32:
nm_ip_route_set_attribute (route,
info->key,
g_variant_new_uint32 (info->v.uint32));
p_info->key,
g_variant_new_uint32 (p_data->v.uint32));
break;
case PARSE_LINE_TYPE_UINT32_WITH_LOCK:
if (info->v.uint32_with_lock.lock) {
if (p_data->v.uint32_with_lock.lock) {
nm_ip_route_set_attribute (route,
nm_sprintf_buf (buf1, "lock-%s", info->key),
nm_sprintf_buf (buf1, "lock-%s", p_info->key),
g_variant_new_boolean (TRUE));
}
nm_ip_route_set_attribute (route,
info->key,
g_variant_new_uint32 (info->v.uint32_with_lock.uint32));
p_info->key,
g_variant_new_uint32 (p_data->v.uint32_with_lock.uint32));
break;
case PARSE_LINE_TYPE_ADDR:
case PARSE_LINE_TYPE_ADDR_WITH_PREFIX:
nm_ip_route_set_attribute (route,
info->key,
p_info->key,
g_variant_new_printf ("%s%s",
inet_ntop (addr_family, &info->v.addr.addr, buf1, sizeof (buf1)),
info->v.addr.has_plen
? nm_sprintf_buf (buf2, "/%u", (unsigned) info->v.addr.plen)
inet_ntop (addr_family, &p_data->v.addr.addr, buf1, sizeof (buf1)),
p_data->v.addr.has_plen
? nm_sprintf_buf (buf2, "/%u", (unsigned) p_data->v.addr.plen)
: ""));
break;
case PARSE_LINE_TYPE_FLAG:
@@ -1159,7 +1223,7 @@ next:
* of this attribute, hence, the file format cannot encode
* that configuration. */
nm_ip_route_set_attribute (route,
info->key,
p_info->key,
g_variant_new_boolean (TRUE));
break;
default:

View File

@@ -2084,6 +2084,8 @@ get_route_attributes_string (NMIPRoute *route, int family)
/* we also have a corresponding attribute with the numeric value. The
* lock setting is handled above. */
}
} else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_SCOPE)) {
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_TOS)) {
g_string_append_printf (str, "%s 0x%02x", names[i], (unsigned) g_variant_get_byte (attr));
} else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_TABLE)) {

View File

@@ -6,10 +6,10 @@ 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"
OPTIONS1="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 window 30000 scope 10 initcwnd lock 13 initrwnd 14"
ADDRESS2=44.55.66.78
NETMASK2=255.255.255.255
GATEWAY2=192.168.1.8
METRIC2=3
OPTIONS2="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 onlink window 30000 initcwnd lock 13 initrwnd 14"
OPTIONS2="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 onlink window 30000 initcwnd lock 13 initrwnd 14 scope link"

View File

@@ -1334,6 +1334,7 @@ test_read_wired_static_routes (void)
nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, TRUE);
nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, TRUE);
nmtst_assert_route_attribute_string (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SRC, "1.1.1.1");
nmtst_assert_route_attribute_byte (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SCOPE, 10);
ip4_route = nm_setting_ip_config_get_route (s_ip4, 2);
g_assert (ip4_route);
@@ -1351,6 +1352,7 @@ test_read_wired_static_routes (void)
nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, TRUE);
nmtst_assert_route_attribute_string (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SRC, "1.1.1.1");
nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, TRUE);
nmtst_assert_route_attribute_byte (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SCOPE, 253);
g_object_unref (connection);
}