From fbdda4bb535de2dd8e5bc930d8d533b750321fc0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 9 Nov 2021 06:26:29 +0900 Subject: [PATCH 1/3] network: ndisc: split out prefix option handling into ndsic_router_process_prefix() --- src/network/networkd-ndisc.c | 109 +++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 44 deletions(-) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 5f831b58a4..25322bb7aa 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -390,8 +390,12 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r int r; assert(link); + assert(link->network); assert(rt); + if (!link->network->ipv6_accept_ra_use_autonomous_prefix) + return 0; + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec); if (r < 0) return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); @@ -479,8 +483,12 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { int r; assert(link); + assert(link->network); assert(rt); + if (!link->network->ipv6_accept_ra_use_onlink_prefix) + return 0; + r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_sec); if (r < 0) return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m"); @@ -516,6 +524,56 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { return 0; } +static int ndisc_router_process_prefix(Link *link, sd_ndisc_router *rt) { + unsigned prefixlen; + struct in6_addr a; + uint8_t flags; + int r; + + assert(link); + assert(link->network); + assert(rt); + + r = sd_ndisc_router_prefix_get_address(rt, &a); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get prefix address: %m"); + + r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get prefix length: %m"); + + if (in6_prefix_is_filtered(&a, prefixlen, link->network->ndisc_allow_listed_prefix, link->network->ndisc_deny_listed_prefix)) { + if (DEBUG_LOGGING) { + _cleanup_free_ char *b = NULL; + + (void) in6_addr_prefix_to_string(&a, prefixlen, &b); + if (!set_isempty(link->network->ndisc_allow_listed_prefix)) + log_link_debug(link, "Prefix '%s' is not in allow list, ignoring", strna(b)); + else + log_link_debug(link, "Prefix '%s' is in deny list, ignoring", strna(b)); + } + return 0; + } + + r = sd_ndisc_router_prefix_get_flags(rt, &flags); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get RA prefix flags: %m"); + + if (FLAGS_SET(flags, ND_OPT_PI_FLAG_ONLINK)) { + r = ndisc_router_process_onlink_prefix(link, rt); + if (r < 0) + return r; + } + + if (FLAGS_SET(flags, ND_OPT_PI_FLAG_AUTO)) { + r = ndisc_router_process_autonomous_prefix(link, rt); + if (r < 0) + return r; + } + + return 0; +} + static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { _cleanup_(route_freep) Route *route = NULL; unsigned preference, prefixlen; @@ -775,11 +833,13 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { } static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) { + int r; + assert(link); assert(link->network); assert(rt); - for (int r = sd_ndisc_router_option_rewind(rt); ; r = sd_ndisc_router_option_next(rt)) { + for (r = sd_ndisc_router_option_rewind(rt); ; r = sd_ndisc_router_option_next(rt)) { uint8_t type; if (r < 0) @@ -793,51 +853,11 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) { switch (type) { - case SD_NDISC_OPTION_PREFIX_INFORMATION: { - unsigned prefixlen; - struct in6_addr a; - uint8_t flags; - - r = sd_ndisc_router_prefix_get_address(rt, &a); + case SD_NDISC_OPTION_PREFIX_INFORMATION: + r = ndisc_router_process_prefix(link, rt); if (r < 0) - return log_link_error_errno(link, r, "Failed to get prefix address: %m"); - - r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen); - if (r < 0) - return log_link_error_errno(link, r, "Failed to get prefix length: %m"); - - if (in6_prefix_is_filtered(&a, prefixlen, link->network->ndisc_allow_listed_prefix, link->network->ndisc_deny_listed_prefix)) { - if (DEBUG_LOGGING) { - _cleanup_free_ char *b = NULL; - - (void) in6_addr_prefix_to_string(&a, prefixlen, &b); - if (!set_isempty(link->network->ndisc_allow_listed_prefix)) - log_link_debug(link, "Prefix '%s' is not in allow list, ignoring", strna(b)); - else - log_link_debug(link, "Prefix '%s' is in deny list, ignoring", strna(b)); - } - break; - } - - r = sd_ndisc_router_prefix_get_flags(rt, &flags); - if (r < 0) - return log_link_error_errno(link, r, "Failed to get RA prefix flags: %m"); - - if (link->network->ipv6_accept_ra_use_onlink_prefix && - FLAGS_SET(flags, ND_OPT_PI_FLAG_ONLINK)) { - r = ndisc_router_process_onlink_prefix(link, rt); - if (r < 0) - return r; - } - - if (link->network->ipv6_accept_ra_use_autonomous_prefix && - FLAGS_SET(flags, ND_OPT_PI_FLAG_AUTO)) { - r = ndisc_router_process_autonomous_prefix(link, rt); - if (r < 0) - return r; - } + return r; break; - } case SD_NDISC_OPTION_ROUTE_INFORMATION: r = ndisc_router_process_route(link, rt); @@ -961,6 +981,7 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { r = ndisc_router_process_default(link, rt); if (r < 0) return r; + r = ndisc_router_process_options(link, rt); if (r < 0) return r; From ad0b2df6355fe9c7eae672107bb6cf9ea9263aba Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 9 Nov 2021 06:27:21 +0900 Subject: [PATCH 2/3] network: ndisc: do not read DNSSL option when UseDomains=no Previously, the following confing did not work: ``` [IPv6AcceptRA] UseDNS=no UseDomains=yes ``` --- src/network/networkd-ndisc.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 25322bb7aa..21b5d0a0c0 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -677,8 +677,12 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { int n, r; assert(link); + assert(link->network); assert(rt); + if (!link->network->ipv6_accept_ra_use_dns) + return 0; + r = sd_ndisc_router_get_address(rt, &router); if (r < 0) return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); @@ -768,8 +772,12 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { int r; assert(link); + assert(link->network); assert(rt); + if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_NO) + return 0; + r = sd_ndisc_router_get_address(rt, &router); if (r < 0) return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); @@ -866,19 +874,15 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) { break; case SD_NDISC_OPTION_RDNSS: - if (link->network->ipv6_accept_ra_use_dns) { - r = ndisc_router_process_rdnss(link, rt); - if (r < 0) - return r; - } + r = ndisc_router_process_rdnss(link, rt); + if (r < 0) + return r; break; case SD_NDISC_OPTION_DNSSL: - if (link->network->ipv6_accept_ra_use_dns) { - r = ndisc_router_process_dnssl(link, rt); - if (r < 0) - return r; - } + r = ndisc_router_process_dnssl(link, rt); + if (r < 0) + return r; break; } } From 610c0db12663bdf271e03919b49626c90aa0a2ba Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 9 Nov 2021 06:44:45 +0900 Subject: [PATCH 3/3] network: ndisc: introduce UseGateway= and UseRoutePrefix= settings Closes #21263. --- man/systemd.network.xml | 16 ++++++++ src/network/networkd-ndisc.c | 39 ++++++++++++------- src/network/networkd-network-gperf.gperf | 2 + src/network/networkd-network.c | 2 + src/network/networkd-network.h | 2 + .../fuzz-network-parser/directives.network | 2 + 6 files changed, 50 insertions(+), 13 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 49814a05eb..199fcc0a58 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2295,6 +2295,22 @@ Token=prefixstable:2002:da8:1:: + + UseGateway= + + When true (the default), the router address will be configured as the default gateway. + + + + + + UseRoutePrefix= + + When true (the default), the routes corresponding to the route prefixes received in + the Router Advertisement will be configured. + + + UseAutonomousPrefix= diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 21b5d0a0c0..470c969329 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -290,7 +290,6 @@ static int ndisc_request_address(Address *in, Link *link, sd_ndisc_router *rt) { } static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { - _cleanup_(route_freep) Route *route = NULL; usec_t lifetime_usec, timestamp_usec; struct in6_addr gateway; uint16_t lifetime_sec; @@ -299,8 +298,13 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { int r; assert(link); + assert(link->network); assert(rt); + if (!link->network->ipv6_accept_ra_use_gateway && + hashmap_isempty(link->network->routes_by_section)) + return 0; + r = sd_ndisc_router_get_lifetime(rt, &lifetime_sec); if (r < 0) return log_link_error_errno(link, r, "Failed to get gateway lifetime from RA: %m"); @@ -339,23 +343,29 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { return log_link_error_errno(link, r, "Failed to get default router MTU from RA: %m"); } - r = route_new(&route); - if (r < 0) - return log_oom(); + if (link->network->ipv6_accept_ra_use_gateway) { + _cleanup_(route_freep) Route *route = NULL; - route->family = AF_INET6; - route->pref = preference; - route->gw_family = AF_INET6; - route->gw.in6 = gateway; - route->lifetime_usec = lifetime_usec; - route->mtu = mtu; + r = route_new(&route); + if (r < 0) + return log_oom(); - r = ndisc_request_route(TAKE_PTR(route), link, rt); - if (r < 0) - return log_link_error_errno(link, r, "Could not request default route: %m"); + route->family = AF_INET6; + route->pref = preference; + route->gw_family = AF_INET6; + route->gw.in6 = gateway; + route->lifetime_usec = lifetime_usec; + route->mtu = mtu; + + r = ndisc_request_route(TAKE_PTR(route), link, rt); + if (r < 0) + return log_link_error_errno(link, r, "Could not request default route: %m"); + } Route *route_gw; HASHMAP_FOREACH(route_gw, link->network->routes_by_section) { + _cleanup_(route_freep) Route *route = NULL; + if (!route_gw->gateway_from_dhcp_or_ra) continue; @@ -584,6 +594,9 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { assert(link); + if (!link->network->ipv6_accept_ra_use_route_prefix) + return 0; + r = sd_ndisc_router_route_get_lifetime(rt, &lifetime_sec); if (r < 0) return log_link_error_errno(link, r, "Failed to get route lifetime from RA: %m"); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 1f0a625183..bf58efc932 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -255,6 +255,8 @@ DHCPv6.IAID, config_parse_iaid, DHCPv6.DUIDType, config_parse_duid_type, 0, offsetof(Network, dhcp6_duid) DHCPv6.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, dhcp6_duid) DHCPv6.RouteTable, config_parse_dhcp_or_ra_route_table, (RTPROT_DHCP<<16) | AF_INET6, 0 +IPv6AcceptRA.UseGateway, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_gateway) +IPv6AcceptRA.UseRoutePrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_route_prefix) IPv6AcceptRA.UseAutonomousPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_autonomous_prefix) IPv6AcceptRA.UseOnLinkPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_onlink_prefix) IPv6AcceptRA.UseDNS, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_dns) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 1c00b98660..93621db03b 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -464,6 +464,8 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi .ipv6_accept_ra = -1, .ipv6_accept_ra_use_dns = true, + .ipv6_accept_ra_use_gateway = true, + .ipv6_accept_ra_use_route_prefix = true, .ipv6_accept_ra_use_autonomous_prefix = true, .ipv6_accept_ra_use_onlink_prefix = true, .ipv6_accept_ra_use_mtu = true, diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index f5258c9fcd..c86a492a17 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -301,6 +301,8 @@ struct Network { /* IPv6 accept RA */ int ipv6_accept_ra; bool ipv6_accept_ra_use_dns; + bool ipv6_accept_ra_use_gateway; + bool ipv6_accept_ra_use_route_prefix; bool ipv6_accept_ra_use_autonomous_prefix; bool ipv6_accept_ra_use_onlink_prefix; bool ipv6_accept_ra_use_mtu; diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 2ff20e0f08..66038a2378 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -352,6 +352,8 @@ RouteTable= RouteMetric= UseDNS= DHCPv6Client= +UseGateway= +UseRoutePrefix= UseAutonomousPrefix= UseOnLinkPrefix= RouterAllowList=