Skip to content

Commit

Permalink
networkd: Ability to selectively ignore IPv6 prefixes supplied via ro…
Browse files Browse the repository at this point in the history
…uter advertisement

Closes systemd#10647
  • Loading branch information
ssahani authored and yuwata committed May 18, 2019
1 parent cdd22d5 commit 426bf2a
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 2 deletions.
7 changes: 7 additions & 0 deletions man/systemd.network.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1606,6 +1606,13 @@
</listitem>
</varlistentry>

<varlistentry>
<term><varname>BlackList=</varname></term>
<listitem>
<para>A whitespace-separated list of IPv6 prefixes. IPv6 prefixes supplied via router advertisements in the list are ignored.</para>
</listitem>
</varlistentry>

</variablelist>
</refsect1>

Expand Down
107 changes: 105 additions & 2 deletions src/network/networkd-ndisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,34 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
return 0;
}

static int ndisc_prefix_is_black_listed(Link *link, sd_ndisc_router *rt) {
union in_addr_union a;
int r;

assert(link);
assert(link->network);
assert(rt);

r = sd_ndisc_router_prefix_get_address(rt, &a.in6);
if (r == -EMEDIUMTYPE)
return false;
if (r < 0)
return log_link_error_errno(link, r, "Failed to get prefix address: %m");

if (set_contains(link->network->ndisc_black_listed_prefix, &a.in6)) {
if (DEBUG_LOGGING) {
_cleanup_free_ char *b = NULL;

(void) in_addr_to_string(AF_INET6, &a, &b);
log_link_debug(link, "Prefix '%s' is black listed, ignoring", strna(b));
}

return true;
}

return false;
}

static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
uint64_t flags;
int r;
Expand All @@ -581,8 +609,10 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
}
}

(void) ndisc_router_process_default(link, rt);
(void) ndisc_router_process_options(link, rt);
if (ndisc_prefix_is_black_listed(link, rt) == 0) {
(void) ndisc_router_process_default(link, rt);
(void) ndisc_router_process_options(link, rt);
}

return r;
}
Expand Down Expand Up @@ -672,3 +702,76 @@ void ndisc_flush(Link *link) {
link->ndisc_rdnss = set_free_free(link->ndisc_rdnss);
link->ndisc_dnssl = set_free_free(link->ndisc_dnssl);
}

int config_parse_ndisc_black_listed_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) {

Network *network = data;
const char *p;
int r;

assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);

if (isempty(rvalue)) {
network->ndisc_black_listed_prefix = set_free_free(network->ndisc_black_listed_prefix);
return 0;
}

for (p = rvalue;;) {
_cleanup_free_ char *n = NULL;
_cleanup_free_ struct in6_addr *a = NULL;
union in_addr_union ip;

r = extract_first_word(&p, &n, NULL, 0);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse NDISC black listed prefix, ignoring assignment: %s",
rvalue);
return 0;
}
if (r == 0)
return 0;

r = in_addr_from_string(AF_INET6, n, &ip);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"NDISC black listed prefix is invalid, ignoring assignment: %s", n);
continue;
}

r = set_ensure_allocated(&network->ndisc_black_listed_prefix, &in6_addr_hash_ops);
if (r < 0)
return log_oom();

a = newdup(struct in6_addr, &ip.in6, 1);
if (!a)
return log_oom();

r = set_put(network->ndisc_black_listed_prefix, a);
if (r < 0) {
if (r == -EEXIST)
log_syntax(unit, LOG_WARNING, filename, line, r,
"NDISC black listed prefixs is duplicated, ignoring assignment: %s", n);
else
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to store NDISC black listed prefix '%s', ignoring assignment: %m", n);
continue;
}

TAKE_PTR(a);
}

return 0;
}
3 changes: 3 additions & 0 deletions src/network/networkd-ndisc.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once

#include "conf-parser.h"
#include "networkd-link.h"
#include "time-util.h"

Expand All @@ -21,3 +22,5 @@ static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) {
int ndisc_configure(Link *link);
void ndisc_vacuum(Link *link);
void ndisc_flush(Link *link);

CONFIG_PARSER_PROTOTYPE(config_parse_ndisc_black_listed_prefix);
2 changes: 2 additions & 0 deletions src/network/networkd-network-gperf.gperf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#include "conf-parser.h"
#include "network-internal.h"
#include "networkd-conf.h"
#include "networkd-ndisc.h"
#include "networkd-network.h"
#include "vlan-util.h"
%}
Expand Down Expand Up @@ -162,6 +163,7 @@ IPv6AcceptRA.UseOnLinkPrefix, config_parse_bool,
IPv6AcceptRA.UseDNS, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_dns)
IPv6AcceptRA.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, ipv6_accept_ra_use_domains)
IPv6AcceptRA.RouteTable, config_parse_section_route_table, 0, 0
IPv6AcceptRA.BlackList, config_parse_ndisc_black_listed_prefix, 0, 0
DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec)
DHCPServer.DefaultLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec)
DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_dns)
Expand Down
1 change: 1 addition & 0 deletions src/network/networkd-network.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ static Network *network_free(Network *network) {

ordered_set_free_free(network->router_search_domains);
free(network->router_dns);
set_free_free(network->ndisc_black_listed_prefix);

free(network->bridge_name);
free(network->bond_name);
Expand Down
1 change: 1 addition & 0 deletions src/network/networkd-network.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ struct Network {
DHCPUseDomains ipv6_accept_ra_use_domains;
uint32_t ipv6_accept_ra_route_table;
bool ipv6_accept_ra_route_table_set;
Set *ndisc_black_listed_prefix;

union in_addr_union ipv6_token;
IPv6PrivacyExtensions ipv6_privacy_extensions;
Expand Down
1 change: 1 addition & 0 deletions test/fuzz/fuzz-network-parser/directives.network
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ RouteTable=
UseDNS=
UseAutonomousPrefix=
UseOnLinkPrefix=
BlackList=
[DHCPServer]
EmitNTP=
PoolSize=
Expand Down

0 comments on commit 426bf2a

Please sign in to comment.