libnm,core: support "uidrange" parameter for routing rules
This commit is contained in:
@@ -904,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),
|
||||
@@ -934,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);
|
||||
|
@@ -1473,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;
|
||||
@@ -1485,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;
|
||||
@@ -1597,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,
|
||||
@@ -2412,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
|
||||
@@ -2456,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
|
||||
@@ -2728,6 +2796,8 @@ typedef enum {
|
||||
RR_DBUS_ATTR_TO,
|
||||
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;
|
||||
@@ -2765,6 +2835,10 @@ 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
|
||||
};
|
||||
|
||||
@@ -2819,6 +2893,8 @@ 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);
|
||||
|
||||
@@ -2899,22 +2975,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);
|
||||
@@ -2922,6 +2995,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,
|
||||
@@ -3075,6 +3174,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);
|
||||
}
|
||||
|
||||
@@ -3159,6 +3268,9 @@ nm_ip_routing_rule_from_string(const char * str,
|
||||
guint16 sport_end = 0;
|
||||
gint64 i64_dport_start = -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 = {};
|
||||
@@ -3356,6 +3468,28 @@ 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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
@@ -3485,6 +3619,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;
|
||||
|
||||
@@ -3669,6 +3806,13 @@ nm_ip_routing_rule_to_string(const NMIPRoutingRule * self,
|
||||
nm_utils_escaped_tokens_escape_strbuf(self->oifname, NM_ASCII_SPACES, &str);
|
||||
}
|
||||
|
||||
if (self->uid_range_has) {
|
||||
nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '),
|
||||
"uidrange %u-%u",
|
||||
self->uid_range_start,
|
||||
self->uid_range_end);
|
||||
}
|
||||
|
||||
if (self->table != 0) {
|
||||
nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '),
|
||||
"table %u",
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user