network: fix NDisc handling for the case when multiple routers exist

69203fba70 does not consider the case that
multiple routers exist, and causes #16719.

Fixes #16719.
This commit is contained in:
Yu Watanabe
2020-08-14 17:45:44 +09:00
parent 501b09dbf2
commit 50550722e3
6 changed files with 340 additions and 86 deletions

View File

@@ -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"
@@ -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);
@@ -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));

View File

@@ -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);
@@ -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);
@@ -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__);
@@ -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;

View File

@@ -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;

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,9 @@
#pragma once
#include "conf-parser.h"
#include "networkd-address.h"
#include "networkd-link.h"
#include "networkd-route.h"
#include "time-util.h"
typedef struct IPv6Token IPv6Token;
@@ -23,9 +25,24 @@ typedef enum IPv6AcceptRAStartDHCP6Client {
_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_INVALID = -1,
} IPv6AcceptRAStartDHCP6Client;
typedef struct NDiscAddress {
/* Used when GC'ing old DNS servers when configuration changes. */
bool marked;
struct in6_addr router;
Address *address;
} NDiscAddress;
typedef struct NDiscRoute {
/* Used when GC'ing old DNS servers when configuration changes. */
bool marked;
struct in6_addr router;
Route *route;
} NDiscRoute;
typedef struct NDiscRDNSS {
/* Used when GC'ing old DNS servers when configuration changes. */
bool marked;
struct in6_addr router;
usec_t valid_until;
struct in6_addr address;
} NDiscRDNSS;
@@ -33,6 +50,7 @@ typedef struct NDiscRDNSS {
typedef struct NDiscDNSSL {
/* Used when GC'ing old domains when configuration changes. */
bool marked;
struct in6_addr router;
usec_t valid_until;
/* The domain name follows immediately. */
} NDiscDNSSL;

View File

@@ -9,6 +9,7 @@
#include "netlink-util.h"
#include "networkd-ipv4ll.h"
#include "networkd-manager.h"
#include "networkd-ndisc.h"
#include "networkd-route.h"
#include "parse-util.h"
#include "set.h"
@@ -142,6 +143,9 @@ void route_free(Route *route) {
network_config_section_free(route->section);
if (route->link) {
NDiscRoute *n;
Iterator i;
set_remove(route->link->routes, route);
set_remove(route->link->routes_foreign, route);
set_remove(route->link->dhcp_routes, route);
@@ -150,8 +154,9 @@ void route_free(Route *route) {
set_remove(route->link->dhcp6_routes_old, route);
set_remove(route->link->dhcp6_pd_routes, route);
set_remove(route->link->dhcp6_pd_routes_old, route);
set_remove(route->link->ndisc_routes, route);
set_remove(route->link->ndisc_routes_old, route);
SET_FOREACH(n, route->link->ndisc_routes, i)
if (n->route == route)
free(set_remove(route->link->ndisc_routes, n));
}
ordered_set_free_free(route->multipath_routes);