summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2021-10-14 16:16:07 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2021-10-26 08:11:19 +0900
commit928112a487e9e9716fccbebd15dd5e402387810e (patch)
tree6b876540c203d2c779cc196710d98fabe28f1327
parente817f5b0f930ab8bed97f69f2b6bd7bc39c47c07 (diff)
downloadsystemd-928112a487e9e9716fccbebd15dd5e402387810e.tar.gz
network: ndisc: fix behavior when DHCPv6Client=always
The man page says that when 'always' is set, the DHCPv6 client always starts in managed mode, and that means we need to ignore the RA flags.
-rw-r--r--src/network/networkd-ndisc.c65
1 files changed, 45 insertions, 20 deletions
diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c
index 2bcb25daad..d7b79f7416 100644
--- a/src/network/networkd-ndisc.c
+++ b/src/network/networkd-ndisc.c
@@ -883,9 +883,51 @@ static void ndisc_mark(Link *link, const struct in6_addr *router) {
dnssl->marked = true;
}
+static int ndisc_start_dhcp6_client(Link *link, sd_ndisc_router *rt) {
+ int r;
+
+ assert(link);
+ assert(link->network);
+
+ switch (link->network->ipv6_accept_ra_start_dhcp6_client) {
+ case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO:
+ return 0;
+
+ case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES: {
+ uint64_t flags;
+
+ r = sd_ndisc_router_get_flags(rt, &flags);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Failed to get RA flags: %m");
+
+ if ((flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)) == 0)
+ return 0;
+
+ /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags.
+ * Note, if both managed and other information bits are set, then ignore other
+ * information bit. See RFC 4861. */
+ r = dhcp6_request_information(link, !(flags & ND_RA_FLAG_MANAGED));
+ break;
+ }
+ case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS:
+ /* When IPv6AcceptRA.DHCPv6Client=always, start dhcp6 client in managed mode
+ * even if the router flags have neither M nor O flags. */
+ r = dhcp6_request_information(link, false);
+ break;
+
+ default:
+ assert_not_reached();
+ }
+
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m");
+
+ log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request");
+ return 0;
+}
+
static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
struct in6_addr router;
- uint64_t flags;
int r;
assert(link);
@@ -912,26 +954,9 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
ndisc_mark(link, &router);
- r = sd_ndisc_router_get_flags(rt, &flags);
+ r = ndisc_start_dhcp6_client(link, rt);
if (r < 0)
- return log_link_error_errno(link, r, "Failed to get RA flags: %m");
-
- if ((flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER) &&
- link->network->ipv6_accept_ra_start_dhcp6_client != IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO) ||
- link->network->ipv6_accept_ra_start_dhcp6_client == IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS) {
-
- if (flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))
- /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
- r = dhcp6_request_information(link, !(flags & ND_RA_FLAG_MANAGED));
- else
- /* When IPv6AcceptRA.DHCPv6Client=always, start dhcp6 client in managed mode
- * even if router does not have M or O flag. */
- r = dhcp6_request_information(link, false);
- if (r < 0 && r != -EBUSY)
- return log_link_error_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m");
- else
- log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request");
- }
+ return r;
r = ndisc_router_process_default(link, rt);
if (r < 0)