mirror of
https://github.com/systemd/systemd.git
synced 2025-03-09 12:58:26 +03:00
networkd: support incoming/outgoing device for rule matching (#7223)
Closes #7210
This commit is contained in:
parent
172378e01b
commit
762e2659b9
@ -926,6 +926,18 @@
|
||||
integer. Higher number means lower priority, and rules get processed in order of increasing number.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>IncomingInterface=</varname></term>
|
||||
<listitem>
|
||||
<para>Specifies incoming device to match. If the interface is loopback, the rule only matches packets originating from this host.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>OutgoingInterface=</varname></term>
|
||||
<listitem>
|
||||
<para>Specifies the outgoing device to match. The outgoing interface is only available for packets originating from local sockets that are bound to a device.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -784,7 +784,7 @@ static int link_set_routing_policy_rule(Link *link) {
|
||||
|
||||
LIST_FOREACH(rules, rule, link->network->rules) {
|
||||
r = routing_policy_rule_get(link->manager, rule->family, &rule->from, rule->from_prefixlen, &rule->to,
|
||||
rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, &rrule);
|
||||
rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif, &rrule);
|
||||
if (r == 1) {
|
||||
(void) routing_policy_rule_make_local(link->manager, rrule);
|
||||
continue;
|
||||
|
@ -732,6 +732,7 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi
|
||||
union in_addr_union to, from;
|
||||
uint32_t fwmark = 0, table = 0;
|
||||
Manager *m = userdata;
|
||||
char *iif, *oif;
|
||||
uint16_t type;
|
||||
int family;
|
||||
int r;
|
||||
@ -811,13 +812,15 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi
|
||||
(void) sd_netlink_message_read_u32(message, FRA_FWMARK, &fwmark);
|
||||
(void) sd_netlink_message_read_u32(message, FRA_TABLE, &table);
|
||||
(void) sd_rtnl_message_routing_policy_rule_get_tos(message, &tos);
|
||||
(void) sd_netlink_message_read_string(message, FRA_IIFNAME, (const char **) &iif);
|
||||
(void) sd_netlink_message_read_string(message, FRA_OIFNAME, (const char **) &oif);
|
||||
|
||||
(void) routing_policy_rule_get(m, family, &from, from_prefixlen, &to, to_prefixlen, tos, fwmark, table, &rule);
|
||||
(void) routing_policy_rule_get(m, family, &from, from_prefixlen, &to, to_prefixlen, tos, fwmark, table, iif, oif, &rule);
|
||||
|
||||
switch (type) {
|
||||
case RTM_NEWRULE:
|
||||
if(!rule) {
|
||||
r = routing_policy_rule_add_foreign(m, family, &from, from_prefixlen, &to, to_prefixlen, tos, fwmark, table, &rule);
|
||||
r = routing_policy_rule_add_foreign(m, family, &from, from_prefixlen, &to, to_prefixlen, tos, fwmark, table, iif, oif, &rule);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Could not add rule: %m");
|
||||
return 0;
|
||||
|
@ -90,6 +90,8 @@ RoutingPolicyRule.Table, config_parse_routing_policy_rule_table,
|
||||
RoutingPolicyRule.FirewallMark, config_parse_routing_policy_rule_fwmark_mask, 0, 0
|
||||
RoutingPolicyRule.From, config_parse_routing_policy_rule_prefix, 0, 0
|
||||
RoutingPolicyRule.To, config_parse_routing_policy_rule_prefix, 0, 0
|
||||
RoutingPolicyRule.IncomingInterface, config_parse_routing_policy_rule_device, 0, 0
|
||||
RoutingPolicyRule.OutgoingInterface, config_parse_routing_policy_rule_device, 0, 0
|
||||
Route.Gateway, config_parse_gateway, 0, 0
|
||||
Route.Destination, config_parse_destination, 0, 0
|
||||
Route.Source, config_parse_destination, 0, 0
|
||||
|
@ -66,6 +66,8 @@ void routing_policy_rule_free(RoutingPolicyRule *rule) {
|
||||
}
|
||||
}
|
||||
|
||||
free(rule->iif);
|
||||
free(rule->oif);
|
||||
free(rule);
|
||||
}
|
||||
|
||||
@ -90,6 +92,12 @@ static void routing_policy_rule_hash_func(const void *b, struct siphash *state)
|
||||
siphash24_compress(&rule->fwmark, sizeof(rule->fwmark), state);
|
||||
siphash24_compress(&rule->table, sizeof(rule->table), state);
|
||||
|
||||
if (rule->iif)
|
||||
siphash24_compress(&rule->iif, strlen(rule->iif), state);
|
||||
|
||||
if (rule->oif)
|
||||
siphash24_compress(&rule->oif, strlen(rule->oif), state);
|
||||
|
||||
break;
|
||||
default:
|
||||
/* treat any other address family as AF_UNSPEC */
|
||||
@ -134,6 +142,14 @@ static int routing_policy_rule_compare_func(const void *_a, const void *_b) {
|
||||
if (a->table > b->table)
|
||||
return 1;
|
||||
|
||||
r = strcmp_ptr(a->iif, b->iif);
|
||||
if (!r)
|
||||
return r;
|
||||
|
||||
r = strcmp_ptr(a->oif, b->oif);
|
||||
if (!r)
|
||||
return r;
|
||||
|
||||
r = memcmp(&a->from, &b->from, FAMILY_ADDRESS_SIZE(a->family));
|
||||
if (r != 0)
|
||||
return r;
|
||||
@ -160,6 +176,8 @@ int routing_policy_rule_get(Manager *m,
|
||||
uint8_t tos,
|
||||
uint32_t fwmark,
|
||||
uint32_t table,
|
||||
char *iif,
|
||||
char *oif,
|
||||
RoutingPolicyRule **ret) {
|
||||
|
||||
RoutingPolicyRule rule, *existing;
|
||||
@ -175,6 +193,8 @@ int routing_policy_rule_get(Manager *m,
|
||||
.tos = tos,
|
||||
.fwmark = fwmark,
|
||||
.table = table,
|
||||
.iif = iif,
|
||||
.oif = oif
|
||||
};
|
||||
|
||||
if (m->rules) {
|
||||
@ -225,6 +245,8 @@ static int routing_policy_rule_add_internal(Set **rules,
|
||||
uint8_t tos,
|
||||
uint32_t fwmark,
|
||||
uint32_t table,
|
||||
char *iif,
|
||||
char *oif,
|
||||
RoutingPolicyRule **ret) {
|
||||
|
||||
_cleanup_routing_policy_rule_free_ RoutingPolicyRule *rule = NULL;
|
||||
@ -244,6 +266,8 @@ static int routing_policy_rule_add_internal(Set **rules,
|
||||
rule->tos = tos;
|
||||
rule->fwmark = fwmark;
|
||||
rule->table = table;
|
||||
rule->iif = iif;
|
||||
rule->oif = oif;
|
||||
|
||||
r = set_ensure_allocated(rules, &routing_policy_rule_hash_ops);
|
||||
if (r < 0)
|
||||
@ -270,9 +294,11 @@ int routing_policy_rule_add(Manager *m,
|
||||
uint8_t tos,
|
||||
uint32_t fwmark,
|
||||
uint32_t table,
|
||||
char *iif,
|
||||
char *oif,
|
||||
RoutingPolicyRule **ret) {
|
||||
|
||||
return routing_policy_rule_add_internal(&m->rules, family, from, from_prefixlen, to, to_prefixlen, tos, fwmark, table, ret);
|
||||
return routing_policy_rule_add_internal(&m->rules, family, from, from_prefixlen, to, to_prefixlen, tos, fwmark, table, iif, oif, ret);
|
||||
}
|
||||
|
||||
int routing_policy_rule_add_foreign(Manager *m,
|
||||
@ -284,8 +310,10 @@ int routing_policy_rule_add_foreign(Manager *m,
|
||||
uint8_t tos,
|
||||
uint32_t fwmark,
|
||||
uint32_t table,
|
||||
char *iif,
|
||||
char *oif,
|
||||
RoutingPolicyRule **ret) {
|
||||
return routing_policy_rule_add_internal(&m->rules_foreign, family, from, from_prefixlen, to, to_prefixlen, tos, fwmark, table, ret);
|
||||
return routing_policy_rule_add_internal(&m->rules_foreign, family, from, from_prefixlen, to, to_prefixlen, tos, fwmark, table, iif, oif, ret);
|
||||
}
|
||||
|
||||
static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
|
||||
@ -505,6 +533,18 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, sd_netlin
|
||||
return log_error_errno(r, "Could not append FRA_FWMASK attribute: %m");
|
||||
}
|
||||
|
||||
if (rule->iif) {
|
||||
r = sd_netlink_message_append_string(m, FRA_IFNAME, rule->iif);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not append FRA_IFNAME attribute: %m");
|
||||
}
|
||||
|
||||
if (rule->oif) {
|
||||
r = sd_netlink_message_append_string(m, FRA_OIFNAME, rule->oif);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not append FRA_OIFNAME attribute: %m");
|
||||
}
|
||||
|
||||
rule->link = link;
|
||||
|
||||
r = sd_netlink_call_async(link->manager->rtnl, m, callback, link, 0, NULL);
|
||||
@ -514,7 +554,7 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, sd_netlin
|
||||
link_ref(link);
|
||||
|
||||
r = routing_policy_rule_add(link->manager, rule->family, &rule->from, rule->from_prefixlen, &rule->to,
|
||||
rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, NULL);
|
||||
rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not add rule : %m");
|
||||
|
||||
@ -750,6 +790,52 @@ int config_parse_routing_policy_rule_prefix(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_routing_policy_rule_device(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_routing_policy_rule_free_ RoutingPolicyRule *n = NULL;
|
||||
Network *network = userdata;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(section);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = routing_policy_rule_new_static(network, filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!ifname_valid(rvalue)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse '%s' interface name, ignoring: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (streq(lvalue, "IncomingInterface")) {
|
||||
r = free_and_strdup(&n->iif, rvalue);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
} else {
|
||||
r = free_and_strdup(&n->oif, rvalue);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
n = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int routing_policy_rule_read_full_file(char *state_file, char **ret) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
size_t size;
|
||||
@ -861,6 +947,16 @@ int routing_policy_rule_load(Manager *m) {
|
||||
log_error_errno(r, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", a);
|
||||
continue;
|
||||
}
|
||||
} else if (streq(a, "IncomingInterface")) {
|
||||
|
||||
rule->iif = strdup(a);
|
||||
if (!rule->iif)
|
||||
return log_oom();
|
||||
} else if (streq(a, "OutgoingInterface")) {
|
||||
|
||||
rule->oif = strdup(a);
|
||||
if (!rule->oif)
|
||||
return log_oom();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,9 @@ struct RoutingPolicyRule {
|
||||
unsigned char to_prefixlen;
|
||||
unsigned char from_prefixlen;
|
||||
|
||||
char *iif;
|
||||
char *oif;
|
||||
|
||||
union in_addr_union to;
|
||||
union in_addr_union from;
|
||||
|
||||
@ -68,11 +71,11 @@ int link_routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message
|
||||
int link_routing_policy_rule_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
|
||||
|
||||
int routing_policy_rule_add(Manager *m, int family, const union in_addr_union *from, uint8_t from_prefixlen, const union in_addr_union *to, uint8_t to_prefixlen,
|
||||
uint8_t tos, uint32_t fwmark, uint32_t table, RoutingPolicyRule **ret);
|
||||
uint8_t tos, uint32_t fwmark, uint32_t table, char *iif, char *oif, RoutingPolicyRule **ret);
|
||||
int routing_policy_rule_add_foreign(Manager *m, int family, const union in_addr_union *from, uint8_t from_prefixlen, const union in_addr_union *to, uint8_t to_prefixlen,
|
||||
uint8_t tos, uint32_t fwmark, uint32_t table, RoutingPolicyRule **ret);
|
||||
uint8_t tos, uint32_t fwmark, uint32_t table, char *iif, char *oif, RoutingPolicyRule **ret);
|
||||
int routing_policy_rule_get(Manager *m, int family, const union in_addr_union *from, uint8_t from_prefixlen, const union in_addr_union *to, uint8_t to_prefixlen, uint8_t tos,
|
||||
uint32_t fwmark, uint32_t table, RoutingPolicyRule **ret);
|
||||
uint32_t fwmark, uint32_t table, char *iif, char *oif, RoutingPolicyRule **ret);
|
||||
int routing_policy_rule_make_local(Manager *m, RoutingPolicyRule *rule);
|
||||
int routing_policy_rule_load(Manager *m);
|
||||
void routing_policy_rule_purge(Manager *m, Link *link);
|
||||
@ -82,3 +85,4 @@ int config_parse_routing_policy_rule_table(const char *unit, const char *filenam
|
||||
int config_parse_routing_policy_rule_fwmark_mask(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_routing_policy_rule_prefix(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_routing_policy_rule_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data,void *userdata);
|
||||
int config_parse_routing_policy_rule_device(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data,void *userdata);
|
||||
|
Loading…
x
Reference in New Issue
Block a user