Skip to content

Commit

Permalink
network: fix NDisc handling for the case when multiple routers exist
Browse files Browse the repository at this point in the history
69203fb does not consider the case that
multiple routers exist, and causes systemd#16719.

Fixes systemd#16719.
  • Loading branch information
yuwata committed Sep 7, 2020
1 parent 501b09d commit 5055072
Show file tree
Hide file tree
Showing 6 changed files with 339 additions and 85 deletions.
9 changes: 7 additions & 2 deletions src/network/networkd-address.c
Expand Up @@ -10,6 +10,7 @@
#include "netlink-util.h"
#include "networkd-address.h"
#include "networkd-manager.h"
#include "networkd-ndisc.h"
#include "parse-util.h"
#include "set.h"
#include "socket-util.h"
Expand Down Expand Up @@ -123,6 +124,9 @@ void address_free(Address *address) {
}

if (address->link && !address->acd) {
NDiscAddress *n;
Iterator i;

set_remove(address->link->addresses, address);
set_remove(address->link->addresses_foreign, address);
set_remove(address->link->static_addresses, address);
Expand All @@ -134,8 +138,9 @@ void address_free(Address *address) {
set_remove(address->link->dhcp6_addresses_old, address);
set_remove(address->link->dhcp6_pd_addresses, address);
set_remove(address->link->dhcp6_pd_addresses_old, address);
set_remove(address->link->ndisc_addresses, address);
set_remove(address->link->ndisc_addresses_old, address);
SET_FOREACH(n, address->link->ndisc_addresses, i)
if (n->address == address)
free(set_remove(address->link->ndisc_addresses, n));

if (in_addr_equal(AF_INET6, &address->in_addr, (const union in_addr_union *) &address->link->ipv6ll_address))
memzero(&address->link->ipv6ll_address, sizeof(struct in6_addr));
Expand Down
12 changes: 9 additions & 3 deletions src/network/networkd-link.c
Expand Up @@ -720,7 +720,6 @@ static Link *link_free(Link *link) {
link->dhcp6_pd_routes = set_free(link->dhcp6_pd_routes);
link->dhcp6_pd_routes_old = set_free(link->dhcp6_pd_routes_old);
link->ndisc_routes = set_free(link->ndisc_routes);
link->ndisc_routes_old = set_free(link->ndisc_routes_old);

link->nexthops = set_free(link->nexthops);
link->nexthops_foreign = set_free(link->nexthops_foreign);
Expand All @@ -736,7 +735,6 @@ static Link *link_free(Link *link) {
link->dhcp6_pd_addresses = set_free(link->dhcp6_pd_addresses);
link->dhcp6_pd_addresses_old = set_free(link->dhcp6_pd_addresses_old);
link->ndisc_addresses = set_free(link->ndisc_addresses);
link->ndisc_addresses_old = set_free(link->ndisc_addresses_old);

while ((address = link->pool_addresses)) {
LIST_REMOVE(addresses, link->pool_addresses, address);
Expand Down Expand Up @@ -1163,6 +1161,8 @@ void link_check_ready(Link *link) {
}

if (link_has_carrier(link) || !link->network->configure_without_carrier) {
bool has_ndisc_address = false;
NDiscAddress *n;

if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !link->ipv4ll_address_configured) {
log_link_debug(link, "%s(): IPv4LL is not configured.", __func__);
Expand All @@ -1175,8 +1175,14 @@ void link_check_ready(Link *link) {
return;
}

SET_FOREACH(n, link->ndisc_addresses, i)
if (!n->marked) {
has_ndisc_address = true;
break;
}

if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) &&
!link->dhcp_address && set_isempty(link->dhcp6_addresses) && set_isempty(link->ndisc_addresses) &&
!link->dhcp_address && set_isempty(link->dhcp6_addresses) && !has_ndisc_address &&
!(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address_configured)) {
log_link_debug(link, "%s(): DHCP4 or DHCP6 is enabled but no dynamic address is assigned yet.", __func__);
return;
Expand Down
4 changes: 2 additions & 2 deletions src/network/networkd-link.h
Expand Up @@ -132,8 +132,8 @@ typedef struct Link {
sd_ndisc *ndisc;
Set *ndisc_rdnss;
Set *ndisc_dnssl;
Set *ndisc_addresses, *ndisc_addresses_old;
Set *ndisc_routes, *ndisc_routes_old;
Set *ndisc_addresses;
Set *ndisc_routes;
unsigned ndisc_addresses_messages;
unsigned ndisc_routes_messages;
bool ndisc_addresses_configured:1;
Expand Down

0 comments on commit 5055072

Please sign in to comment.