mirror of
https://github.com/systemd/systemd.git
synced 2024-11-30 13:53:39 +08:00
network: nexthop: add Blackhole= setting in [NextHop] section
As similar to unreachable type routes, blackhole nexthops do not have NHA_OID attribute, so they are managed by Manager.
This commit is contained in:
parent
5735ab0979
commit
30f1083709
@ -1349,6 +1349,14 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
|
||||
<literal>no</literal>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>Blackhole=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes a boolean. If enabled, packets to the corresponding routes are discarded
|
||||
silently, and <varname>Gateway=</varname> cannot be specified. Defaults to
|
||||
<literal>no</literal>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -894,6 +894,8 @@ Manager* manager_free(Manager *m) {
|
||||
m->routes = set_free(m->routes);
|
||||
m->routes_foreign = set_free(m->routes_foreign);
|
||||
|
||||
m->nexthops = set_free(m->nexthops);
|
||||
m->nexthops_foreign = set_free(m->nexthops_foreign);
|
||||
m->nexthops_by_id = hashmap_free(m->nexthops_by_id);
|
||||
|
||||
sd_event_source_unref(m->speed_meter_event_source);
|
||||
|
@ -64,6 +64,10 @@ struct Manager {
|
||||
/* Manage nexthops by id. */
|
||||
Hashmap *nexthops_by_id;
|
||||
|
||||
/* Manager stores nexthops without RTA_OIF attribute. */
|
||||
Set *nexthops;
|
||||
Set *nexthops_foreign;
|
||||
|
||||
/* Manager stores routes without RTA_OIF attribute. */
|
||||
Set *routes;
|
||||
Set *routes_foreign;
|
||||
|
@ -190,6 +190,7 @@ NextHop.Id, config_parse_nexthop_id,
|
||||
NextHop.Gateway, config_parse_nexthop_gateway, 0, 0
|
||||
NextHop.Family, config_parse_nexthop_family, 0, 0
|
||||
NextHop.OnLink, config_parse_nexthop_onlink, 0, 0
|
||||
NextHop.Blackhole, config_parse_nexthop_blackhole, 0, 0
|
||||
DHCPv4.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
|
||||
DHCPv4.UseDNS, config_parse_dhcp_use_dns, 0, 0
|
||||
DHCPv4.RoutesToDNS, config_parse_bool, 0, offsetof(Network, dhcp_routes_to_dns)
|
||||
|
@ -33,6 +33,14 @@ NextHop *nexthop_free(NextHop *nexthop) {
|
||||
hashmap_remove(nexthop->link->manager->nexthops_by_id, UINT32_TO_PTR(nexthop->id));
|
||||
}
|
||||
|
||||
if (nexthop->manager) {
|
||||
set_remove(nexthop->manager->nexthops, nexthop);
|
||||
set_remove(nexthop->manager->nexthops_foreign, nexthop);
|
||||
|
||||
if (nexthop->id > 0)
|
||||
hashmap_remove(nexthop->manager->nexthops_by_id, UINT32_TO_PTR(nexthop->id));
|
||||
}
|
||||
|
||||
return mfree(nexthop);
|
||||
}
|
||||
|
||||
@ -95,6 +103,7 @@ static void nexthop_hash_func(const NextHop *nexthop, struct siphash *state) {
|
||||
assert(nexthop);
|
||||
|
||||
siphash24_compress(&nexthop->id, sizeof(nexthop->id), state);
|
||||
siphash24_compress(&nexthop->blackhole, sizeof(nexthop->blackhole), state);
|
||||
siphash24_compress(&nexthop->family, sizeof(nexthop->family), state);
|
||||
|
||||
switch (nexthop->family) {
|
||||
@ -116,6 +125,10 @@ static int nexthop_compare_func(const NextHop *a, const NextHop *b) {
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = CMP(a->blackhole, b->blackhole);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = CMP(a->family, b->family);
|
||||
if (r != 0)
|
||||
return r;
|
||||
@ -133,6 +146,18 @@ DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
||||
nexthop_compare_func,
|
||||
nexthop_free);
|
||||
|
||||
static void nexthop_copy(NextHop *dest, const NextHop *src) {
|
||||
assert(dest);
|
||||
assert(src);
|
||||
|
||||
/* This only copies entries used in the above hash and compare functions. */
|
||||
|
||||
dest->id = src->id;
|
||||
dest->blackhole = src->blackhole;
|
||||
dest->family = src->family;
|
||||
dest->gw = src->gw;
|
||||
}
|
||||
|
||||
int manager_get_nexthop_by_id(Manager *manager, uint32_t id, NextHop **ret) {
|
||||
NextHop *nh;
|
||||
|
||||
@ -150,20 +175,20 @@ int manager_get_nexthop_by_id(Manager *manager, uint32_t id, NextHop **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nexthop_get(Link *link, const NextHop *in, NextHop **ret) {
|
||||
static int nexthop_get(Manager *manager, Link *link, const NextHop *in, NextHop **ret) {
|
||||
NextHop *existing;
|
||||
|
||||
assert(link);
|
||||
assert(manager || link);
|
||||
assert(in);
|
||||
|
||||
existing = set_get(link->nexthops, in);
|
||||
existing = set_get(link ? link->nexthops : manager->nexthops, in);
|
||||
if (existing) {
|
||||
if (ret)
|
||||
*ret = existing;
|
||||
return 1;
|
||||
}
|
||||
|
||||
existing = set_get(link->nexthops_foreign, in);
|
||||
existing = set_get(link ? link->nexthops_foreign : manager->nexthops_foreign, in);
|
||||
if (existing) {
|
||||
if (ret)
|
||||
*ret = existing;
|
||||
@ -173,11 +198,11 @@ static int nexthop_get(Link *link, const NextHop *in, NextHop **ret) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int nexthop_add_internal(Link *link, Set **nexthops, const NextHop *in, NextHop **ret) {
|
||||
static int nexthop_add_internal(Manager *manager, Link *link, Set **nexthops, const NextHop *in, NextHop **ret) {
|
||||
_cleanup_(nexthop_freep) NextHop *nexthop = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(manager || link);
|
||||
assert(nexthops);
|
||||
assert(in);
|
||||
|
||||
@ -185,9 +210,7 @@ static int nexthop_add_internal(Link *link, Set **nexthops, const NextHop *in, N
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
nexthop->id = in->id;
|
||||
nexthop->family = in->family;
|
||||
nexthop->gw = in->gw;
|
||||
nexthop_copy(nexthop, in);
|
||||
|
||||
r = set_ensure_put(nexthops, &nexthop_hash_ops, nexthop);
|
||||
if (r < 0)
|
||||
@ -196,6 +219,7 @@ static int nexthop_add_internal(Link *link, Set **nexthops, const NextHop *in, N
|
||||
return -EEXIST;
|
||||
|
||||
nexthop->link = link;
|
||||
nexthop->manager = manager;
|
||||
|
||||
if (ret)
|
||||
*ret = nexthop;
|
||||
@ -204,8 +228,9 @@ static int nexthop_add_internal(Link *link, Set **nexthops, const NextHop *in, N
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nexthop_add_foreign(Link *link, const NextHop *in, NextHop **ret) {
|
||||
return nexthop_add_internal(link, &link->nexthops_foreign, in, ret);
|
||||
static int nexthop_add_foreign(Manager *manager, Link *link, const NextHop *in, NextHop **ret) {
|
||||
assert(manager || link);
|
||||
return nexthop_add_internal(manager, link, link ? &link->nexthops_foreign : &manager->nexthops_foreign, in, ret);
|
||||
}
|
||||
|
||||
static int nexthop_add(Link *link, const NextHop *in, NextHop **ret) {
|
||||
@ -213,20 +238,30 @@ static int nexthop_add(Link *link, const NextHop *in, NextHop **ret) {
|
||||
NextHop *nexthop;
|
||||
int r;
|
||||
|
||||
r = nexthop_get(link, in, &nexthop);
|
||||
assert(link);
|
||||
assert(in);
|
||||
|
||||
if (in->blackhole)
|
||||
r = nexthop_get(link->manager, NULL, in, &nexthop);
|
||||
else
|
||||
r = nexthop_get(NULL, link, in, &nexthop);
|
||||
if (r == -ENOENT) {
|
||||
/* NextHop does not exist, create a new one */
|
||||
r = nexthop_add_internal(link, &link->nexthops, in, &nexthop);
|
||||
r = nexthop_add_internal(link->manager,
|
||||
in->blackhole ? NULL : link,
|
||||
in->blackhole ? &link->manager->nexthops : &link->nexthops,
|
||||
in, &nexthop);
|
||||
if (r < 0)
|
||||
return r;
|
||||
is_new = true;
|
||||
} else if (r == 0) {
|
||||
/* Take over a foreign nexthop */
|
||||
r = set_ensure_put(&link->nexthops, &nexthop_hash_ops, nexthop);
|
||||
r = set_ensure_put(in->blackhole ? &link->manager->nexthops : &link->nexthops,
|
||||
&nexthop_hash_ops, nexthop);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
set_remove(link->nexthops_foreign, nexthop);
|
||||
set_remove(in->blackhole ? link->manager->nexthops_foreign : link->nexthops_foreign, nexthop);
|
||||
} else if (r == 1) {
|
||||
/* NextHop exists, do nothing */
|
||||
;
|
||||
@ -238,11 +273,13 @@ static int nexthop_add(Link *link, const NextHop *in, NextHop **ret) {
|
||||
return is_new;
|
||||
}
|
||||
|
||||
static int nexthop_update(Link *link, NextHop *nexthop, const NextHop *in) {
|
||||
static int nexthop_update(Manager *manager, Link *link, NextHop *nexthop, const NextHop *in) {
|
||||
Set *nexthops;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
/* link may be NULL. */
|
||||
|
||||
assert(manager);
|
||||
assert(nexthop);
|
||||
assert(in);
|
||||
assert(in->id > 0);
|
||||
@ -255,19 +292,21 @@ static int nexthop_update(Link *link, NextHop *nexthop, const NextHop *in) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nexthop = set_remove(link->nexthops, nexthop);
|
||||
nexthops = link ? link->nexthops : manager->nexthops;
|
||||
|
||||
nexthop = set_remove(nexthops, nexthop);
|
||||
if (!nexthop)
|
||||
return -ENOENT;
|
||||
|
||||
nexthop->id = in->id;
|
||||
|
||||
r = set_put(link->nexthops, nexthop);
|
||||
r = set_put(nexthops, nexthop);
|
||||
if (r <= 0) {
|
||||
int k;
|
||||
|
||||
/* On failure, revert the change. */
|
||||
nexthop->id = 0;
|
||||
k = set_put(link->nexthops, nexthop);
|
||||
k = set_put(nexthops, nexthop);
|
||||
if (k <= 0) {
|
||||
nexthop_free(nexthop);
|
||||
return k < 0 ? k : -EEXIST;
|
||||
@ -277,13 +316,14 @@ static int nexthop_update(Link *link, NextHop *nexthop, const NextHop *in) {
|
||||
}
|
||||
|
||||
set_manager:
|
||||
return hashmap_ensure_put(&link->manager->nexthops_by_id, NULL, UINT32_TO_PTR(nexthop->id), nexthop);
|
||||
return hashmap_ensure_put(&manager->nexthops_by_id, NULL, UINT32_TO_PTR(nexthop->id), nexthop);
|
||||
}
|
||||
|
||||
static void log_nexthop_debug(const NextHop *nexthop, uint32_t id, const char *str, const Link *link) {
|
||||
assert(nexthop);
|
||||
assert(str);
|
||||
assert(link);
|
||||
|
||||
/* link may be NULL. */
|
||||
|
||||
if (DEBUG_LOGGING) {
|
||||
_cleanup_free_ char *gw = NULL;
|
||||
@ -291,11 +331,11 @@ static void log_nexthop_debug(const NextHop *nexthop, uint32_t id, const char *s
|
||||
(void) in_addr_to_string(nexthop->family, &nexthop->gw, &gw);
|
||||
|
||||
if (nexthop->id == id)
|
||||
log_link_debug(link, "%s nexthop: id: %"PRIu32", gw: %s",
|
||||
str, nexthop->id, strna(gw));
|
||||
log_link_debug(link, "%s nexthop: id: %"PRIu32", gw: %s, blackhole: %s",
|
||||
str, nexthop->id, strna(gw), yes_no(nexthop->blackhole));
|
||||
else
|
||||
log_link_debug(link, "%s nexthop: id: %"PRIu32"→%"PRIu32", gw: %s",
|
||||
str, nexthop->id, id, strna(gw));
|
||||
log_link_debug(link, "%s nexthop: id: %"PRIu32"→%"PRIu32", gw: %s, blackhole: %s",
|
||||
str, nexthop->id, id, strna(gw), yes_no(nexthop->blackhole));
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,19 +393,25 @@ static int nexthop_configure(const NextHop *nexthop, Link *link) {
|
||||
return log_link_error_errno(link, r, "Could not append NHA_ID attribute: %m");
|
||||
}
|
||||
|
||||
r = sd_netlink_message_append_u32(req, NHA_OIF, link->ifindex);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append NHA_OIF attribute: %m");
|
||||
|
||||
if (in_addr_is_set(nexthop->family, &nexthop->gw)) {
|
||||
r = netlink_message_append_in_addr_union(req, NHA_GATEWAY, nexthop->family, &nexthop->gw);
|
||||
if (nexthop->blackhole) {
|
||||
r = sd_netlink_message_append_flag(req, NHA_BLACKHOLE);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append NHA_GATEWAY attribute: %m");
|
||||
return log_link_error_errno(link, r, "Could not append NHA_BLACKHOLE attribute: %m");
|
||||
} else {
|
||||
r = sd_netlink_message_append_u32(req, NHA_OIF, link->ifindex);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append NHA_OIF attribute: %m");
|
||||
|
||||
if (nexthop->onlink > 0) {
|
||||
r = sd_rtnl_message_nexthop_set_flags(req, RTNH_F_ONLINK);
|
||||
if (in_addr_is_set(nexthop->family, &nexthop->gw)) {
|
||||
r = netlink_message_append_in_addr_union(req, NHA_GATEWAY, nexthop->family, &nexthop->gw);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to set RTNH_F_ONLINK flag: %m");
|
||||
return log_link_error_errno(link, r, "Could not append NHA_GATEWAY attribute: %m");
|
||||
|
||||
if (nexthop->onlink > 0) {
|
||||
r = sd_rtnl_message_nexthop_set_flags(req, RTNH_F_ONLINK);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to set RTNH_F_ONLINK flag: %m");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -431,7 +477,7 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
|
||||
NextHop *nexthop = NULL;
|
||||
uint32_t ifindex;
|
||||
uint16_t type;
|
||||
Link *link;
|
||||
Link *link = NULL;
|
||||
int r;
|
||||
|
||||
assert(rtnl);
|
||||
@ -456,22 +502,21 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_u32(message, NHA_OIF, &ifindex);
|
||||
if (r == -ENODATA) {
|
||||
log_warning_errno(r, "rtnl: received nexthop message without NHA_OIF attribute, ignoring: %m");
|
||||
return 0;
|
||||
} else if (r < 0) {
|
||||
if (r < 0 && r != -ENODATA) {
|
||||
log_warning_errno(r, "rtnl: could not get NHA_OIF attribute, ignoring: %m");
|
||||
return 0;
|
||||
} else if (ifindex <= 0) {
|
||||
log_warning("rtnl: received nexthop message with invalid ifindex %"PRIu32", ignoring.", ifindex);
|
||||
return 0;
|
||||
}
|
||||
} else if (r >= 0) {
|
||||
if (ifindex <= 0) {
|
||||
log_warning("rtnl: received nexthop message with invalid ifindex %"PRIu32", ignoring.", ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = link_get(m, ifindex, &link);
|
||||
if (r < 0 || !link) {
|
||||
if (!m->enumerating)
|
||||
log_warning("rtnl: received nexthop message for link (%"PRIu32") we do not know about, ignoring", ifindex);
|
||||
return 0;
|
||||
r = link_get(m, ifindex, &link);
|
||||
if (r < 0 || !link) {
|
||||
if (!m->enumerating)
|
||||
log_warning("rtnl: received nexthop message for link (%"PRIu32") we do not know about, ignoring", ifindex);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
r = nexthop_new(&tmp);
|
||||
@ -491,6 +536,13 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_has_flag(message, NHA_BLACKHOLE);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "rtnl: could not get NHA_BLACKHOLE attribute, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
tmp->blackhole = r;
|
||||
|
||||
r = sd_netlink_message_read_u32(message, NHA_ID, &tmp->id);
|
||||
if (r == -ENODATA) {
|
||||
log_link_warning_errno(link, r, "rtnl: received nexthop message without NHA_ID attribute, ignoring: %m");
|
||||
@ -503,7 +555,12 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = nexthop_get(link, tmp, &nexthop);
|
||||
/* All blackhole nexthops are managed by Manager. Note that the linux kernel does not set
|
||||
* NHA_OID attribute when NHA_BLACKHOLE is set. Just for safety. */
|
||||
if (tmp->blackhole)
|
||||
link = NULL;
|
||||
|
||||
r = nexthop_get(m, link, tmp, &nexthop);
|
||||
if (r < 0) {
|
||||
uint32_t id;
|
||||
|
||||
@ -512,7 +569,7 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
|
||||
id = tmp->id;
|
||||
tmp->id = 0;
|
||||
|
||||
(void) nexthop_get(link, tmp, &nexthop);
|
||||
(void) nexthop_get(m, link, tmp, &nexthop);
|
||||
|
||||
tmp->id = id;
|
||||
}
|
||||
@ -523,14 +580,14 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
|
||||
log_nexthop_debug(nexthop, tmp->id, "Received remembered", link);
|
||||
else {
|
||||
log_nexthop_debug(tmp, tmp->id, "Remembering foreign", link);
|
||||
r = nexthop_add_foreign(link, tmp, &nexthop);
|
||||
r = nexthop_add_foreign(m, link, tmp, &nexthop);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Could not remember foreign nexthop, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
r = nexthop_update(link, nexthop, tmp);
|
||||
r = nexthop_update(m, link, nexthop, tmp);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Could not update nexthop, ignoring: %m");
|
||||
return 0;
|
||||
@ -556,6 +613,12 @@ static int nexthop_section_verify(NextHop *nh) {
|
||||
/* When no Gateway= is specified, assume IPv4. */
|
||||
nh->family = AF_INET;
|
||||
|
||||
if (nh->blackhole && in_addr_is_set(nh->family, &nh->gw))
|
||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"%s: blackhole nexthop cannot have gateway address. "
|
||||
"Ignoring [NextHop] section from line %u.",
|
||||
nh->section->filename, nh->section->line);
|
||||
|
||||
if (nh->onlink < 0 && in_addr_is_set(nh->family, &nh->gw) &&
|
||||
ordered_hashmap_isempty(nh->network->addresses_by_section)) {
|
||||
/* If no address is configured, in most cases the gateway cannot be reachable.
|
||||
@ -784,3 +847,42 @@ int config_parse_nexthop_onlink(
|
||||
TAKE_PTR(n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_nexthop_blackhole(
|
||||
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_(nexthop_free_or_set_invalidp) NextHop *n = NULL;
|
||||
Network *network = userdata;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(section);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = nexthop_new_static(network, filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = parse_boolean(rvalue);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n->blackhole = r;
|
||||
|
||||
TAKE_PTR(n);
|
||||
return 0;
|
||||
}
|
||||
|
@ -20,11 +20,13 @@ typedef struct NextHop {
|
||||
Network *network;
|
||||
NetworkConfigSection *section;
|
||||
|
||||
Manager *manager;
|
||||
Link *link;
|
||||
|
||||
unsigned char protocol;
|
||||
|
||||
uint32_t id;
|
||||
bool blackhole;
|
||||
int family;
|
||||
union in_addr_union gw;
|
||||
int onlink;
|
||||
@ -43,3 +45,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_id);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_gateway);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_family);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_onlink);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_blackhole);
|
||||
|
@ -496,7 +496,10 @@ static void route_copy(Route *dest, const Route *src, const MultipathRoute *m, c
|
||||
dest->prefsrc = src->prefsrc;
|
||||
dest->scope = src->scope;
|
||||
dest->protocol = src->protocol;
|
||||
dest->type = src->type;
|
||||
if (nh && nh->blackhole)
|
||||
dest->type = RTN_BLACKHOLE;
|
||||
else
|
||||
dest->type = src->type;
|
||||
dest->tos = src->tos;
|
||||
dest->priority = src->priority;
|
||||
dest->table = src->table;
|
||||
@ -981,8 +984,8 @@ static int route_add_and_setup_timer(Link *link, const Route *route, const Multi
|
||||
|
||||
(void) manager_get_nexthop_by_id(link->manager, route->nexthop_id, &nh);
|
||||
|
||||
if (route_type_is_reject(route))
|
||||
k = route_add(link->manager, NULL, route, NULL, NULL, &nr);
|
||||
if (route_type_is_reject(route) || (nh && nh->blackhole))
|
||||
k = route_add(link->manager, NULL, route, NULL, nh, &nr);
|
||||
else if (!m || m->ifindex == 0 || m->ifindex == link->ifindex)
|
||||
k = route_add(NULL, link, route, m, nh, &nr);
|
||||
else {
|
||||
|
@ -353,6 +353,7 @@ Id=
|
||||
Gateway=
|
||||
Family=
|
||||
OnLink=
|
||||
Blackhole=
|
||||
[QDisc]
|
||||
Parent=
|
||||
Handle=
|
||||
|
Loading…
Reference in New Issue
Block a user