core: merge branch 'th/routing-rule-attr-uidrange-and-type'

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/788
This commit is contained in:
Thomas Haller 2021-03-23 14:21:16 +01:00
commit 62cd7682d9
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
12 changed files with 410 additions and 147 deletions

View file

@ -499,6 +499,8 @@ src_libnm_base_libnm_base_la_SOURCES = \
src/libnm-base/nm-ethtool-base.c \
src/libnm-base/nm-ethtool-base.h \
src/libnm-base/nm-ethtool-utils-base.h \
src/libnm-base/nm-net-aux.c \
src/libnm-base/nm-net-aux.h \
$(NULL)
src_libnm_base_libnm_base_la_LDFLAGS = \

View file

@ -14,6 +14,7 @@
#include "libnm-glib-aux/nm-c-list.h"
#include "libnm-base/nm-net-aux.h"
#include "libnm-core-aux-intern/nm-common-macros.h"
#include "nm-utils.h"
#include "nm-setting-connection.h"
@ -903,10 +904,16 @@ nm_match_spec_device_by_pllink(const NMPlatformLink *pllink,
NMPlatformRoutingRule *
nm_ip_routing_rule_to_platform(const NMIPRoutingRule *rule, NMPlatformRoutingRule *out_pl)
{
gboolean uid_range_has;
guint32 uid_range_start = 0;
guint32 uid_range_end = 0;
nm_assert(rule);
nm_assert(nm_ip_routing_rule_validate(rule, NULL));
nm_assert(out_pl);
uid_range_has = nm_ip_routing_rule_get_uid_range(rule, &uid_range_start, &uid_range_end);
*out_pl = (NMPlatformRoutingRule){
.addr_family = nm_ip_routing_rule_get_addr_family(rule),
.flags = (nm_ip_routing_rule_get_invert(rule) ? FIB_RULE_INVERT : 0),
@ -933,6 +940,12 @@ nm_ip_routing_rule_to_platform(const NMIPRoutingRule *rule, NMPlatformRoutingRul
.table = nm_ip_routing_rule_get_table(rule),
.suppress_prefixlen_inverse =
~((guint32) nm_ip_routing_rule_get_suppress_prefixlength(rule)),
.uid_range_has = uid_range_has,
.uid_range =
{
.start = uid_range_start,
.end = uid_range_end,
},
};
nm_ip_routing_rule_get_xifname_bin(rule, TRUE, out_pl->iifname);
@ -1294,9 +1307,9 @@ nm_utils_ip_route_attribute_to_platform(int addr_family,
if ((variant = nm_ip_route_get_attribute(s_route, NM_IP_ROUTE_ATTRIBUTE_TYPE))
&& g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
guint8 type;
int type;
type = nm_utils_route_type_by_name(g_variant_get_string(variant, NULL));
type = nm_net_aux_rtnl_rtntype_a2n(g_variant_get_string(variant, NULL));
nm_assert(NM_IN_SET(type, RTN_UNICAST, RTN_LOCAL));
r->type_coerced = nm_platform_route_type_coerce(type);

View file

@ -4,6 +4,7 @@ libnm_base = static_library(
'nm-base',
sources: files(
'nm-ethtool-base.c',
'nm-net-aux.c',
),
include_directories: [
src_inc,

View file

@ -0,0 +1,79 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "libnm-glib-aux/nm-default-glib-i18n-lib.h"
#include "nm-net-aux.h"
#include <linux/rtnetlink.h>
#include <linux/fib_rules.h>
/*****************************************************************************/
G_STATIC_ASSERT((int) FR_ACT_UNSPEC == RTN_UNSPEC);
G_STATIC_ASSERT((int) FR_ACT_TO_TBL == RTN_UNICAST);
G_STATIC_ASSERT((int) FR_ACT_GOTO == RTN_LOCAL);
G_STATIC_ASSERT((int) FR_ACT_NOP == RTN_BROADCAST);
G_STATIC_ASSERT((int) FR_ACT_RES3 == RTN_ANYCAST);
G_STATIC_ASSERT((int) FR_ACT_RES4 == RTN_MULTICAST);
G_STATIC_ASSERT((int) FR_ACT_BLACKHOLE == RTN_BLACKHOLE);
G_STATIC_ASSERT((int) FR_ACT_UNREACHABLE == RTN_UNREACHABLE);
G_STATIC_ASSERT((int) FR_ACT_PROHIBIT == RTN_PROHIBIT);
/* see iproute2's rtnl_rtntype_a2n() */
NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(
nm_net_aux_rtnl_rtntype_a2n,
int,
{ nm_assert(name); },
{
NM_AUTO_PROTECT_ERRNO(errsv);
return _nm_utils_ascii_str_to_int64(name, 0, 0, 255, -1);
},
{"anycast", RTN_ANYCAST},
{"blackhole", RTN_BLACKHOLE},
{"brd", RTN_BROADCAST},
{"broadcast", RTN_BROADCAST},
{"local", RTN_LOCAL},
{"multicast", RTN_MULTICAST},
{"nat", RTN_NAT},
{"prohibit", RTN_PROHIBIT},
{"throw", RTN_THROW},
{"unicast", RTN_UNICAST},
{"unreachable", RTN_UNREACHABLE},
{"xresolve", RTN_XRESOLVE}, );
const char *
nm_net_aux_rtnl_rtntype_n2a(guint8 v)
{
/* see iproute2's rtnl_rtntype_n2a(). */
switch (v) {
case RTN_UNSPEC:
return "none";
case RTN_UNICAST:
return "unicast";
case RTN_LOCAL:
return "local";
case RTN_BROADCAST:
return "broadcast";
case RTN_ANYCAST:
return "anycast";
case RTN_MULTICAST:
return "multicast";
case RTN_BLACKHOLE:
return "blackhole";
case RTN_UNREACHABLE:
return "unreachable";
case RTN_PROHIBIT:
return "prohibit";
case RTN_THROW:
return "throw";
case RTN_NAT:
return "nat";
case RTN_XRESOLVE:
return "xresolve";
}
/* unlike the iproute2 code, this returns %NULL for unknown values.
* You may represent this value as "%d" integer, but do it yourself. */
return NULL;
}

View file

@ -0,0 +1,21 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#ifndef __NM_NET_AUX_H__
#define __NM_NET_AUX_H__
const char *nm_net_aux_rtnl_rtntype_n2a(guint8 v);
int nm_net_aux_rtnl_rtntype_a2n(const char *name);
#define nm_net_aux_rtnl_rtntype_n2a_maybe_buf(v, buf) \
({ \
const guint8 _v = (v); \
\
/* Warning: this will only touch/initialize @buf if necessary.
* That means, don't assume that @buf was initialized after calling
* this macro. */ \
nm_net_aux_rtnl_rtntype_n2a(v) ?: nm_sprintf_buf((buf), "%u", _v); \
})
/*****************************************************************************/
#endif /* __NM_NET_AUX_H__ */

View file

@ -11,6 +11,7 @@
#include <arpa/inet.h>
#include <linux/fib_rules.h>
#include "libnm-base/nm-net-aux.h"
#include "libnm-glib-aux/nm-str-buf.h"
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"
@ -1385,7 +1386,7 @@ nm_ip_route_attribute_validate(const char *name,
break;
}
case 'T': /* route type. */
if (!NM_IN_SET(nm_utils_route_type_by_name(string), RTN_UNICAST, RTN_LOCAL)) {
if (!NM_IN_SET(nm_net_aux_rtnl_rtntype_a2n(string), RTN_UNICAST, RTN_LOCAL)) {
g_set_error(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
@ -1432,10 +1433,14 @@ _nm_ip_route_attribute_validate_all(const NMIPRoute *route, GError **error)
}
if ((val = g_hash_table_lookup(route->attributes, NM_IP_ROUTE_ATTRIBUTE_TYPE))) {
nm_assert(g_variant_is_of_type(val, G_VARIANT_TYPE_STRING));
u8 = nm_utils_route_type_by_name(g_variant_get_string(val, NULL));
int v_i;
if (u8 == RTN_LOCAL && route->family == AF_INET
nm_assert(g_variant_is_of_type(val, G_VARIANT_TYPE_STRING));
v_i = nm_net_aux_rtnl_rtntype_a2n(g_variant_get_string(val, NULL));
nm_assert(v_i >= 0);
if (v_i == RTN_LOCAL && route->family == AF_INET
&& (val = g_hash_table_lookup(route->attributes, NM_IP_ROUTE_ATTRIBUTE_SCOPE))) {
nm_assert(g_variant_is_of_type(val, G_VARIANT_TYPE_BYTE));
u8 = g_variant_get_byte(val);
@ -1468,6 +1473,8 @@ struct NMIPRoutingRule {
gint32 suppress_prefixlength;
guint32 fwmark;
guint32 fwmask;
guint32 uid_range_start;
guint32 uid_range_end;
guint16 sport_start;
guint16 sport_end;
guint16 dport_start;
@ -1480,6 +1487,7 @@ struct NMIPRoutingRule {
bool is_v4 : 1;
bool sealed : 1;
bool priority_has : 1;
bool uid_range_has : 1;
bool from_has : 1;
bool from_valid : 1;
bool to_has : 1;
@ -1592,6 +1600,10 @@ nm_ip_routing_rule_new_clone(const NMIPRoutingRule *rule)
.dport_start = rule->dport_start,
.dport_end = rule->dport_end,
.uid_range_start = rule->uid_range_start,
.uid_range_end = rule->uid_range_end,
.uid_range_has = rule->uid_range_has,
.ipproto = rule->ipproto,
.from_len = rule->from_len,
@ -2407,6 +2419,61 @@ nm_ip_routing_rule_set_suppress_prefixlength(NMIPRoutingRule *self, gint32 suppr
self->suppress_prefixlength = suppress_prefixlength;
}
/**
* nm_ip_routing_rule_get_uid_range:
* @self: the #NMIPRoutingRule instance
* @out_range_start: (out) (allow-none): returns the start of the range
* or 0 if the range is not set.
* @out_range_end: (out) (allow-none): returns the end of the range
* or 0 if the range is not set.
*
* Returns: %TRUE if a uid range is set.
*
* Since: 1.32
*/
gboolean
nm_ip_routing_rule_get_uid_range(const NMIPRoutingRule *self,
guint32 * out_range_start,
guint32 * out_range_end)
{
g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), -1);
nm_assert(self->uid_range_has || (self->uid_range_start == 0 && self->uid_range_end == 0));
NM_SET_OUT(out_range_start, self->uid_range_start);
NM_SET_OUT(out_range_end, self->uid_range_end);
return self->uid_range_has;
}
/**
* nm_ip_routing_rule_set_uid_range:
* @self: the #NMIPRoutingRule instance
* @uid_range_start: the uid_range start to set.
* @uid_range_end: the uid_range start to set.
*
* For a valid range, start must be less or equal to end.
* If set to an invalid range, the range gets unset.
*
* Since: 1.32
*/
void
nm_ip_routing_rule_set_uid_range(NMIPRoutingRule *self,
guint32 uid_range_start,
guint32 uid_range_end)
{
g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE));
if (uid_range_start > uid_range_end) {
self->uid_range_start = 0;
self->uid_range_end = 0;
self->uid_range_has = FALSE;
return;
}
self->uid_range_start = uid_range_start;
self->uid_range_end = uid_range_end;
self->uid_range_has = TRUE;
}
/**
* nm_ip_routing_rule_cmp:
* @rule: (allow-none): the #NMIPRoutingRule instance to compare
@ -2451,6 +2518,12 @@ nm_ip_routing_rule_cmp(const NMIPRoutingRule *rule, const NMIPRoutingRule *other
NM_CMP_FIELD(rule, other, ipproto);
NM_CMP_FIELD_UNSAFE(rule, other, uid_range_has);
if (rule->uid_range_has) {
NM_CMP_FIELD(rule, other, uid_range_end);
NM_CMP_FIELD(rule, other, uid_range_start);
}
/* We compare the plain strings, not the binary values after utf8safe unescaping.
*
* The reason is, that the rules differ already when the direct strings differ, not
@ -2571,12 +2644,14 @@ nm_ip_routing_rule_validate(const NMIPRoutingRule *self, GError **error)
_("missing table"));
return FALSE;
}
} else if (NM_IN_SET(self->action, FR_ACT_BLACKHOLE, FR_ACT_PROHIBIT, FR_ACT_UNREACHABLE)) {
/* pass */
} else {
/* whitelist the actions that we currently. */
/* we currently only support the listed actions. */
g_set_error_literal(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("invalid action"));
_("invalid action type"));
return FALSE;
}
@ -2718,11 +2793,13 @@ typedef enum {
RR_DBUS_ATTR_PRIORITY,
RR_DBUS_ATTR_SPORT_END,
RR_DBUS_ATTR_SPORT_START,
RR_DBUS_ATTR_TABLE,
RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH,
RR_DBUS_ATTR_TABLE,
RR_DBUS_ATTR_TO,
RR_DBUS_ATTR_TOS,
RR_DBUS_ATTR_TO_LEN,
RR_DBUS_ATTR_TOS,
RR_DBUS_ATTR_UID_RANGE_END,
RR_DBUS_ATTR_UID_RANGE_START,
_RR_DBUS_ATTR_NUM,
} RRDbusAttr;
@ -2760,9 +2837,42 @@ static const RRDbusData rr_dbus_data[_RR_DBUS_ATTR_NUM] = {
_D(RR_DBUS_ATTR_TO, NM_IP_ROUTING_RULE_ATTR_TO, G_VARIANT_TYPE_STRING),
_D(RR_DBUS_ATTR_TOS, NM_IP_ROUTING_RULE_ATTR_TOS, G_VARIANT_TYPE_BYTE),
_D(RR_DBUS_ATTR_TO_LEN, NM_IP_ROUTING_RULE_ATTR_TO_LEN, G_VARIANT_TYPE_BYTE),
_D(RR_DBUS_ATTR_UID_RANGE_END, NM_IP_ROUTING_RULE_ATTR_UID_RANGE_END, G_VARIANT_TYPE_UINT32),
_D(RR_DBUS_ATTR_UID_RANGE_START,
NM_IP_ROUTING_RULE_ATTR_UID_RANGE_START,
G_VARIANT_TYPE_UINT32),
#undef _D
};
static RRDbusAttr
_rr_dbus_attr_from_name(const char *name)
{
gssize idx;
nm_assert(name);
if (NM_MORE_ASSERT_ONCE(10)) {
int i;
for (i = 0; i < _RR_DBUS_ATTR_NUM; i++) {
nm_assert(rr_dbus_data[i].name);
nm_assert(g_variant_type_string_is_valid((const char *) rr_dbus_data[i].dbus_type));
if (i > 0)
nm_assert(strcmp(rr_dbus_data[i - 1].name, rr_dbus_data[i].name) < 0);
}
}
idx = nm_utils_array_find_binary_search(rr_dbus_data,
sizeof(rr_dbus_data[0]),
_RR_DBUS_ATTR_NUM,
&name,
nm_strcmp_p_with_data,
NULL);
if (idx < 0)
return _RR_DBUS_ATTR_NUM;
return idx;
}
static void
_rr_variants_free(GVariant *(*p_variants)[])
{
@ -2785,45 +2895,40 @@ nm_ip_routing_rule_from_dbus(GVariant *variant, gboolean strict, GError **error)
GVariant * iter_val;
int addr_family;
int i;
GVariant * v_start;
GVariant * v_end;
g_variant_iter_init(&iter, variant);
#if NM_MORE_ASSERTS > 10
for (attr = 0; attr < _RR_DBUS_ATTR_NUM; attr++) {
nm_assert(rr_dbus_data[attr].name);
nm_assert(g_variant_type_string_is_valid((const char *) rr_dbus_data[attr].dbus_type));
}
#endif
while (g_variant_iter_next(&iter, "{&sv}", &iter_key, &iter_val)) {
gs_unref_variant GVariant *iter_val2 = iter_val;
for (attr = 0; attr < _RR_DBUS_ATTR_NUM; attr++) {
if (nm_streq(iter_key, rr_dbus_data[attr].name)) {
if (variants[attr]) {
if (strict) {
g_set_error(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_FAILED,
_("duplicate key %s"),
iter_key);
return NULL;
}
g_variant_unref(variants[attr]);
}
variants[attr] = g_steal_pointer(&iter_val2);
break;
attr = _rr_dbus_attr_from_name(iter_key);
if (attr >= _RR_DBUS_ATTR_NUM) {
if (strict) {
g_set_error(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("invalid key \"%s\""),
iter_key);
return NULL;
}
continue;
}
if (attr >= _RR_DBUS_ATTR_NUM && strict) {
g_set_error(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("invalid key \"%s\""),
iter_key);
return NULL;
if (variants[attr]) {
if (strict) {
g_set_error(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_FAILED,
_("duplicate key %s"),
iter_key);
return NULL;
}
g_variant_unref(variants[attr]);
}
variants[attr] = g_steal_pointer(&iter_val2);
}
for (attr = 0; attr < _RR_DBUS_ATTR_NUM; attr++) {
@ -2872,22 +2977,19 @@ nm_ip_routing_rule_from_dbus(GVariant *variant, gboolean strict, GError **error)
nm_ip_routing_rule_set_ipproto(self, g_variant_get_byte(variants[RR_DBUS_ATTR_IPPROTO]));
for (i = 0; i < 2; i++) {
GVariant *v_start = variants[i ? RR_DBUS_ATTR_SPORT_START : RR_DBUS_ATTR_DPORT_START];
GVariant *v_end = variants[i ? RR_DBUS_ATTR_SPORT_END : RR_DBUS_ATTR_DPORT_END];
guint16 start, end;
guint16 start, end;
v_start = variants[i ? RR_DBUS_ATTR_SPORT_START : RR_DBUS_ATTR_DPORT_START];
v_end = variants[i ? RR_DBUS_ATTR_SPORT_END : RR_DBUS_ATTR_DPORT_END];
if (!v_start && !v_end)
continue;
/* if start or end is missing, it defaults to the other parameter, respectively. */
if (v_start)
start = g_variant_get_uint16(v_start);
else
start = g_variant_get_uint16(v_end);
if (v_end)
start = g_variant_get_uint16(v_start ?: v_end);
if (v_end && v_start)
end = g_variant_get_uint16(v_end);
else
end = g_variant_get_uint16(v_start);
end = start;
if (i)
nm_ip_routing_rule_set_source_port(self, start, end);
@ -2895,6 +2997,32 @@ nm_ip_routing_rule_from_dbus(GVariant *variant, gboolean strict, GError **error)
nm_ip_routing_rule_set_destination_port(self, start, end);
}
v_start = variants[RR_DBUS_ATTR_UID_RANGE_START];
v_end = variants[RR_DBUS_ATTR_UID_RANGE_END];
if (v_start || v_end) {
guint32 start, end;
/* if start or end is missing, it defaults to the other parameter, respectively. */
start = g_variant_get_uint32(v_start ?: v_end);
if (v_end && v_start)
end = g_variant_get_uint32(v_end);
else
end = start;
if (end < start) {
if (strict) {
g_set_error_literal(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("\"" NM_IP_ROUTING_RULE_ATTR_UID_RANGE_START
"\" is greater than \"" NM_IP_ROUTING_RULE_ATTR_UID_RANGE_END
"\""));
return FALSE;
}
} else
nm_ip_routing_rule_set_uid_range(self, start, end);
}
if (variants[RR_DBUS_ATTR_FWMARK] || variants[RR_DBUS_ATTR_FWMASK]) {
nm_ip_routing_rule_set_fwmark(
self,
@ -2929,11 +3057,17 @@ nm_ip_routing_rule_from_dbus(GVariant *variant, gboolean strict, GError **error)
nm_ip_routing_rule_set_oifname(self,
g_variant_get_string(variants[RR_DBUS_ATTR_OIFNAME], NULL));
if (variants[RR_DBUS_ATTR_ACTION])
nm_ip_routing_rule_set_action(self, g_variant_get_byte(variants[RR_DBUS_ATTR_ACTION]));
if (variants[RR_DBUS_ATTR_TABLE])
nm_ip_routing_rule_set_table(self, g_variant_get_uint32(variants[RR_DBUS_ATTR_TABLE]));
/* For the ip-rule string format, the table default depends on the action. For
* our D-Bus format it's always the same: either a table is specified or it defaults
* to zero. And either the action is specified or it defaults to FR_ACT_TO_TBL. */
nm_ip_routing_rule_set_action(self,
!variants[RR_DBUS_ATTR_ACTION]
? (guint8) FR_ACT_TO_TBL
: g_variant_get_byte(variants[RR_DBUS_ATTR_ACTION]));
nm_ip_routing_rule_set_table(self,
!variants[RR_DBUS_ATTR_TABLE]
? (guint32) 0
: g_variant_get_uint32(variants[RR_DBUS_ATTR_TABLE]));
if (variants[RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH])
nm_ip_routing_rule_set_suppress_prefixlength(
@ -3048,6 +3182,16 @@ nm_ip_routing_rule_to_dbus(const NMIPRoutingRule *self)
RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH,
g_variant_new_int32(self->suppress_prefixlength));
if (self->uid_range_has) {
_rr_to_dbus_add(&builder,
RR_DBUS_ATTR_UID_RANGE_START,
g_variant_new_uint32(self->uid_range_start));
if (self->uid_range_start != self->uid_range_end)
_rr_to_dbus_add(&builder,
RR_DBUS_ATTR_UID_RANGE_END,
g_variant_new_uint32(self->uid_range_end));
}
return g_variant_builder_end(&builder);
}
@ -3131,7 +3275,11 @@ nm_ip_routing_rule_from_string(const char * str,
gint64 i64_suppress_prefixlength = -1;
guint16 sport_end = 0;
gint64 i64_dport_start = -1;
int i_action = -1;
guint16 dport_end = 0;
guint32 uid_range_start = 0;
guint32 uid_range_end = 0;
gboolean uid_range_has = FALSE;
gboolean val_invert = FALSE;
int addr_family = AF_UNSPEC;
NMIPAddr val_from = {};
@ -3233,7 +3381,7 @@ nm_ip_routing_rule_from_string(const char * str,
continue;
if (i64_table != -1)
goto next_fail_word0_duplicate_key;
i64_table = _nm_utils_ascii_str_to_int64(word1, 0, 1, G_MAXUINT32, -1);
i64_table = _nm_utils_ascii_str_to_int64(word1, 0, 0, G_MAXUINT32, -1);
if (i64_table == -1) {
if (nm_streq(word1, "main"))
i64_table = RT_TABLE_MAIN;
@ -3329,6 +3477,44 @@ nm_ip_routing_rule_from_string(const char * str,
goto next_fail_word1_invalid_value;
goto next_words_consumed;
}
if (NM_IN_STRSET(word0, "uidrange")) {
if (!word1)
continue;
if (uid_range_has)
goto next_fail_word0_duplicate_key;
s = strchr(word1, '-');
if (s)
(s++)[0] = '\0';
uid_range_start = _nm_utils_ascii_str_to_int64(word1, 0, 0, G_MAXUINT32, 0);
if (errno)
goto next_fail_word1_invalid_value;
if (s) {
uid_range_end = _nm_utils_ascii_str_to_int64(s, 0, 0, G_MAXUINT32, 0);
if (errno)
goto next_fail_word1_invalid_value;
if (uid_range_end < uid_range_start)
goto next_fail_word1_invalid_value;
} else
uid_range_end = uid_range_start;
uid_range_has = TRUE;
goto next_words_consumed;
}
if (NM_IN_STRSET(word0, "type")) {
if (!word1)
continue;
if (i_action >= 0)
goto next_fail_word0_duplicate_key;
i_action = nm_net_aux_rtnl_rtntype_a2n(word1);
if (i_action < 0)
goto next_fail_word1_invalid_value;
goto next_words_consumed;
}
if (i_action < 0) {
i_action = nm_net_aux_rtnl_rtntype_a2n(word1);
if (i_action >= 0)
goto next_words_consumed;
}
/* also the action is still unsupported. For the moment, we only support
* FR_ACT_TO_TBL, which is the default (by not expressing it on the command
@ -3423,6 +3609,16 @@ next_words_consumed:
if (i64_priority != -1)
nm_ip_routing_rule_set_priority(self, i64_priority);
if (i_action >= 0) {
nm_ip_routing_rule_set_action(self, i_action);
if (i64_table == -1) {
if (i_action != FR_ACT_TO_TBL)
i64_table = 0;
else
i64_table = RT_TABLE_MAIN;
}
}
if (i64_tos != -1)
nm_ip_routing_rule_set_tos(self, i64_tos);
@ -3458,6 +3654,9 @@ next_words_consumed:
if (i64_table != -1)
nm_ip_routing_rule_set_table(self, i64_table);
if (uid_range_has)
nm_ip_routing_rule_set_uid_range(self, uid_range_start, uid_range_end);
if (NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE)) {
gs_free_error GError *local = NULL;
@ -3642,10 +3841,11 @@ nm_ip_routing_rule_to_string(const NMIPRoutingRule * self,
nm_utils_escaped_tokens_escape_strbuf(self->oifname, NM_ASCII_SPACES, &str);
}
if (self->table != 0) {
if (self->uid_range_has) {
nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '),
"table %u",
(guint) self->table);
"uidrange %u-%u",
self->uid_range_start,
self->uid_range_end);
}
if (self->suppress_prefixlength != -1) {
@ -3654,6 +3854,20 @@ nm_ip_routing_rule_to_string(const NMIPRoutingRule * self,
(int) self->suppress_prefixlength);
}
if (self->table != 0 || self->action == FR_ACT_TO_TBL) {
nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '),
"table %u",
(guint) self->table);
}
if (self->action != FR_ACT_TO_TBL) {
char sbuf[100];
nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '),
"type %s",
nm_net_aux_rtnl_rtntype_n2a_maybe_buf(self->action, sbuf));
}
return nm_str_buf_finalize(&str, NULL);
}

View file

@ -655,6 +655,8 @@ gboolean nm_ip_routing_rule_get_xifname_bin(const NMIPRoutingRule *self,
#define NM_IP_ROUTING_RULE_ATTR_TO "to"
#define NM_IP_ROUTING_RULE_ATTR_TOS "tos"
#define NM_IP_ROUTING_RULE_ATTR_TO_LEN "to-len"
#define NM_IP_ROUTING_RULE_ATTR_UID_RANGE_START "uid-range-start"
#define NM_IP_ROUTING_RULE_ATTR_UID_RANGE_END "uid-range-end"
NMIPRoutingRule *nm_ip_routing_rule_from_dbus(GVariant *variant, gboolean strict, GError **error);
GVariant * nm_ip_routing_rule_to_dbus(const NMIPRoutingRule *self);

View file

@ -245,6 +245,15 @@ NM_AVAILABLE_IN_1_20
void nm_ip_routing_rule_set_suppress_prefixlength(NMIPRoutingRule *self,
gint32 suppress_prefixlength);
NM_AVAILABLE_IN_1_32
gboolean nm_ip_routing_rule_get_uid_range(const NMIPRoutingRule *self,
guint32 * out_range_start,
guint32 * out_range_end);
NM_AVAILABLE_IN_1_32
void nm_ip_routing_rule_set_uid_range(NMIPRoutingRule *self,
guint32 uid_range_start,
guint32 uid_range_end);
NM_AVAILABLE_IN_1_18
int nm_ip_routing_rule_cmp(const NMIPRoutingRule *rule, const NMIPRoutingRule *other);

View file

@ -122,7 +122,7 @@ _nm_auto_free_gstring(GString **str)
#define nm_auto_free_gstring nm_auto(_nm_auto_free_gstring)
static inline void
_nm_auto_protect_errno(int *p_saved_errno)
_nm_auto_protect_errno(const int *p_saved_errno)
{
errno = *p_saved_errno;
}

View file

@ -15,7 +15,6 @@
#include <glib-unix.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <linux/rtnetlink.h>
#include "nm-errno.h"
#include "nm-str-buf.h"
@ -6114,33 +6113,3 @@ NM_ASSERT_VALID_PATH_COMPONENT(const char *name)
NM_PRINT_FMT_QUOTED(name, "\"", name, "\"", "(null)"));
g_assert_not_reached();
}
/*****************************************************************************/
NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(
nm_utils_route_type_by_name,
guint8,
{ nm_assert(name); },
{ return RTN_UNSPEC; },
{"blackhole", RTN_BLACKHOLE},
{"broadcast", RTN_BROADCAST},
{"local", RTN_LOCAL},
{"multicast", RTN_MULTICAST},
{"nat", RTN_NAT},
{"prohibit", RTN_PROHIBIT},
{"throw", RTN_THROW},
{"unicast", RTN_UNICAST},
{"unreachable", RTN_UNREACHABLE}, );
NM_UTILS_ENUM2STR_DEFINE(nm_utils_route_type2str,
guint8,
NM_UTILS_ENUM2STR(RTN_BLACKHOLE, "blackhole"),
NM_UTILS_ENUM2STR(RTN_BROADCAST, "broadcast"),
NM_UTILS_ENUM2STR(RTN_LOCAL, "local"),
NM_UTILS_ENUM2STR(RTN_MULTICAST, "multicast"),
NM_UTILS_ENUM2STR(RTN_NAT, "nat"),
NM_UTILS_ENUM2STR(RTN_PROHIBIT, "prohibit"),
NM_UTILS_ENUM2STR(RTN_THROW, "throw"),
NM_UTILS_ENUM2STR(RTN_UNICAST, "unicast"),
NM_UTILS_ENUM2STR(RTN_UNREACHABLE, "unreachable"),
NM_UTILS_ENUM2STR(RTN_UNSPEC, "unspecified"), );

View file

@ -2768,10 +2768,4 @@ gboolean nm_utils_sysctl_ip_conf_is_path(int addr_family,
const char *ifname,
const char *property);
/*****************************************************************************/
guint8 nm_utils_route_type_by_name(const char *name);
const char *nm_utils_route_type2str(guint8 val, char *buf, gsize len);
#endif /* __NM_SHARED_UTILS_H__ */

View file

@ -22,6 +22,7 @@
#include <linux/tc_act/tc_mirred.h>
#include <libudev.h>
#include "libnm-base/nm-net-aux.h"
#include "libnm-glib-aux/nm-dedup-multi.h"
#include "libnm-glib-aux/nm-secret-utils.h"
#include "libnm-glib-aux/nm-time-utils.h"
@ -6434,9 +6435,8 @@ nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsiz
"%s" /* initrwnd */
"%s" /* mtu */
"",
nm_utils_route_type2str(nm_platform_route_type_uncoerce(route->type_coerced),
str_type,
sizeof(str_type)),
nm_net_aux_rtnl_rtntype_n2a_maybe_buf(nm_platform_route_type_uncoerce(route->type_coerced),
str_type),
route->table_any
? "table ?? "
: (route->table_coerced
@ -6560,9 +6560,8 @@ nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsiz
"%s" /* mtu */
"%s" /* pref */
"",
nm_utils_route_type2str(nm_platform_route_type_uncoerce(route->type_coerced),
str_type,
sizeof(str_type)),
nm_net_aux_rtnl_rtntype_n2a_maybe_buf(nm_platform_route_type_uncoerce(route->type_coerced),
str_type),
route->table_any
? "table ?? "
: (route->table_coerced
@ -6820,53 +6819,13 @@ nm_platform_routing_rule_to_string(const NMPlatformRoutingRule *routing_rule, ch
if (NM_FLAGS_HAS(routing_rule->flags, FIB_RULE_UNRESOLVED))
nm_utils_strbuf_append_str(&buf, &len, " unresolved");
} else if (routing_rule->action != FR_ACT_TO_TBL) {
const char *ss;
char ss_buf[60];
char ss_buf[60];
#define _V(v1, v2) ((sizeof(char[(((int) (v1)) == ((int) (v2))) ? 1 : -1]) * 0) + (v1))
switch (routing_rule->action) {
case _V(FR_ACT_UNSPEC, RTN_UNSPEC):
ss = "none";
break;
case _V(FR_ACT_TO_TBL, RTN_UNICAST):
ss = "unicast";
break;
case _V(FR_ACT_GOTO, RTN_LOCAL):
ss = "local";
break;
case _V(FR_ACT_NOP, RTN_BROADCAST):
ss = "nop";
break;
case _V(FR_ACT_RES3, RTN_ANYCAST):
ss = "anycast";
break;
case _V(FR_ACT_RES4, RTN_MULTICAST):
ss = "multicast";
break;
case _V(FR_ACT_BLACKHOLE, RTN_BLACKHOLE):
ss = "blackhole";
break;
case _V(FR_ACT_UNREACHABLE, RTN_UNREACHABLE):
ss = "unreachable";
break;
case _V(FR_ACT_PROHIBIT, RTN_PROHIBIT):
ss = "prohibit";
break;
case RTN_THROW:
ss = "throw";
break;
case RTN_NAT:
ss = "nat";
break;
case RTN_XRESOLVE:
ss = "xresolve";
break;
default:
ss = nm_sprintf_buf(ss_buf, "action-%u", routing_rule->action);
break;
}
#undef _V
nm_utils_strbuf_append(&buf, &len, " %s", ss);
nm_utils_strbuf_append(&buf,
&len,
" %s",
nm_net_aux_rtnl_rtntype_n2a(routing_rule->action)
?: nm_sprintf_buf(ss_buf, "action-%u", routing_rule->action));
}
if (routing_rule->protocol != RTPROT_UNSPEC)