network: dhcp6: drop addresses and delegated prefixes on client stop

Previously, we did not drop addresses and delegated prefixes when
DHCP6 client is stopped.

Fixes #15455.
Fixes #13564.
This commit is contained in:
Yu Watanabe 2020-07-23 03:13:42 +09:00
parent 1c09d84e42
commit 1633c45731
10 changed files with 1060 additions and 693 deletions

View File

@ -129,6 +129,10 @@ void address_free(Address *address) {
address->link->dhcp_address = NULL;
if (address->link->dhcp_address_old == address)
address->link->dhcp_address_old = NULL;
set_remove(address->link->dhcp6_addresses, 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);

File diff suppressed because it is too large Load Diff

View File

@ -17,12 +17,20 @@ typedef enum DHCP6ClientStartMode {
typedef struct Link Link;
typedef struct Manager Manager;
bool dhcp6_get_prefix_delegation(Link *link);
int dhcp6_request_prefix_delegation(Link *link);
typedef struct DHCP6DelegatedPrefix {
struct in6_addr prefix; /* Prefix assigned to the link */
struct in6_addr pd_prefix; /* PD prefix provided by DHCP6 lease */
Link *link;
} DHCP6DelegatedPrefix;
DHCP6DelegatedPrefix *dhcp6_pd_free(DHCP6DelegatedPrefix *p);
DEFINE_TRIVIAL_CLEANUP_FUNC(DHCP6DelegatedPrefix*, dhcp6_pd_free);
bool link_dhcp6_pd_is_enabled(Link *link);
int dhcp6_pd_remove(Link *link);
int dhcp6_configure(Link *link);
int dhcp6_request_address(Link *link, int ir);
int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link);
int dhcp6_prefix_remove(Manager *m, struct in6_addr *addr);
int dhcp6_request_prefix_delegation(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_mud_url);

View File

@ -698,6 +698,7 @@ static void link_free_engines(Link *link) {
link->ipv4ll = sd_ipv4ll_unref(link->ipv4ll);
link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
link->dhcp6_lease = sd_dhcp6_lease_unref(link->dhcp6_lease);
link->ndisc = sd_ndisc_unref(link->ndisc);
link->radv = sd_radv_unref(link->radv);
}
@ -714,6 +715,10 @@ static Link *link_free(Link *link) {
link->routes_foreign = set_free(link->routes_foreign);
link->dhcp_routes = set_free(link->dhcp_routes);
link->dhcp_routes_old = set_free(link->dhcp_routes_old);
link->dhcp6_routes = set_free(link->dhcp6_routes);
link->dhcp6_routes_old = set_free(link->dhcp6_routes_old);
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);
@ -725,6 +730,10 @@ static Link *link_free(Link *link) {
link->addresses = set_free(link->addresses);
link->addresses_foreign = set_free(link->addresses_foreign);
link->dhcp6_addresses = set_free(link->dhcp6_addresses);
link->dhcp6_addresses_old = set_free(link->dhcp6_addresses_old);
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);
@ -839,6 +848,12 @@ int link_stop_clients(Link *link, bool may_keep_dhcp) {
r = log_link_warning_errno(link, k, "Could not stop DHCPv6 client: %m");
}
if (link_dhcp6_pd_is_enabled(link)) {
k = dhcp6_pd_remove(link);
if (k < 0)
r = log_link_warning_errno(link, k, "Could not remove DHCPv6 PD addresses and routes: %m");
}
if (link->ndisc) {
k = sd_ndisc_stop(link->ndisc);
if (k < 0)
@ -1173,7 +1188,7 @@ void link_check_ready(Link *link) {
return;
}
if (link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || dhcp6_get_prefix_delegation(link) || link_ipv6_accept_ra_enabled(link)) {
if (link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || link_dhcp6_pd_is_enabled(link) || link_ipv6_accept_ra_enabled(link)) {
if (!link->dhcp4_configured &&
!(link->dhcp6_address_configured && link->dhcp6_route_configured) &&
!(link->dhcp6_pd_address_configured && link->dhcp6_pd_route_configured) &&
@ -1619,12 +1634,14 @@ static int link_acquire_ipv6_conf(Link *link) {
r = dhcp6_request_address(link, link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST);
if (r < 0 && r != -EBUSY)
return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m");
return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m");
else
log_link_debug(link, "Acquiring DHCPv6 lease");
}
(void) dhcp6_request_prefix_delegation(link);
r = dhcp6_request_prefix_delegation(link);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to request DHCPv6 prefix delegation: %m");
return 0;
}
@ -4242,7 +4259,6 @@ int link_save(Link *link) {
if (link->network) {
char **dhcp6_domains = NULL, **dhcp_domains = NULL;
const char *dhcp_domainname = NULL, *p;
sd_dhcp6_lease *dhcp6_lease = NULL;
bool space;
fprintf(f, "REQUIRED_FOR_ONLINE=%s\n",
@ -4254,12 +4270,6 @@ int link_save(Link *link) {
st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? ":" : "",
st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? strempty(link_operstate_to_string(st.max)) : "");
if (link->dhcp6_client) {
r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease);
if (r < 0 && r != -ENOMSG)
log_link_debug_errno(link, r, "Failed to get DHCPv6 lease: %m");
}
fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
/************************************************************/
@ -4276,7 +4286,7 @@ int link_save(Link *link) {
link->dhcp_lease,
link->network->dhcp_use_dns,
SD_DHCP_LEASE_DNS,
dhcp6_lease,
link->dhcp6_lease,
link->network->dhcp6_use_dns,
sd_dhcp6_lease_get_dns,
NULL);
@ -4300,7 +4310,7 @@ int link_save(Link *link) {
link->dhcp_lease,
link->network->dhcp_use_ntp,
SD_DHCP_LEASE_NTP,
dhcp6_lease,
link->dhcp6_lease,
link->network->dhcp6_use_ntp,
sd_dhcp6_lease_get_ntp_addrs,
sd_dhcp6_lease_get_ntp_fqdn);
@ -4319,8 +4329,8 @@ int link_save(Link *link) {
(void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname);
(void) sd_dhcp_lease_get_search_domains(link->dhcp_lease, &dhcp_domains);
}
if (dhcp6_lease)
(void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains);
if (link->dhcp6_lease)
(void) sd_dhcp6_lease_get_domains(link->dhcp6_lease, &dhcp6_domains);
}
fputs("DOMAINS=", f);

View File

@ -102,23 +102,10 @@ typedef struct Link {
uint32_t original_mtu;
unsigned dhcp4_messages;
unsigned dhcp4_remove_messages;
unsigned dhcp6_address_messages;
unsigned dhcp6_route_messages;
unsigned dhcp6_pd_address_messages;
unsigned dhcp6_pd_route_messages;
bool dhcp4_route_failed:1;
bool dhcp4_route_retrying:1;
bool dhcp4_configured:1;
bool dhcp4_address_bind:1;
bool dhcp6_address_configured:1;
bool dhcp6_route_configured:1;
bool dhcp6_pd_address_configured:1;
bool dhcp6_pd_route_configured:1;
unsigned ndisc_addresses_messages;
unsigned ndisc_routes_messages;
bool ndisc_addresses_configured:1;
bool ndisc_routes_configured:1;
sd_ipv4ll *ipv4ll;
bool ipv4ll_address_configured:1;
@ -144,10 +131,28 @@ typedef struct Link {
Set *ndisc_dnssl;
Set *ndisc_addresses, *ndisc_addresses_old;
Set *ndisc_routes, *ndisc_routes_old;
unsigned ndisc_addresses_messages;
unsigned ndisc_routes_messages;
bool ndisc_addresses_configured:1;
bool ndisc_routes_configured:1;
sd_radv *radv;
sd_dhcp6_client *dhcp6_client;
sd_dhcp6_lease *dhcp6_lease;
Set *dhcp6_addresses, *dhcp6_addresses_old;
Set *dhcp6_routes, *dhcp6_routes_old;
Set *dhcp6_pd_addresses, *dhcp6_pd_addresses_old;
Set *dhcp6_pd_routes, *dhcp6_pd_routes_old;
unsigned dhcp6_address_messages;
unsigned dhcp6_route_messages;
unsigned dhcp6_pd_address_messages;
unsigned dhcp6_pd_route_messages;
bool dhcp6_address_configured:1;
bool dhcp6_route_configured:1;
bool dhcp6_pd_address_configured:1;
bool dhcp6_pd_route_configured:1;
bool dhcp6_pd_prefixes_assigned:1;
/* This is about LLDP reception */
sd_lldp *lldp;

View File

@ -1823,27 +1823,20 @@ int manager_new(Manager **ret) {
}
void manager_free(Manager *m) {
struct in6_addr *a;
AddressPool *pool;
Link *link;
Iterator i;
if (!m)
return;
free(m->state_file);
while ((a = hashmap_first_key(m->dhcp6_prefixes)))
(void) dhcp6_prefix_remove(m, a);
m->dhcp6_prefixes = hashmap_free(m->dhcp6_prefixes);
while ((link = hashmap_steal_first(m->links))) {
if (link->dhcp6_client)
(void) dhcp6_lease_pd_prefix_lost(link->dhcp6_client, link);
HASHMAP_FOREACH(link, m->links, i)
(void) link_stop_clients(link, true);
link_unref(link);
}
m->dhcp6_prefixes = hashmap_free_with_destructor(m->dhcp6_prefixes, dhcp6_pd_free);
m->dhcp6_pd_prefixes = set_free_with_destructor(m->dhcp6_pd_prefixes, dhcp6_pd_free);
m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref);
m->links_requesting_uuid = set_free_with_destructor(m->links_requesting_uuid, link_unref);

View File

@ -44,6 +44,7 @@ struct Manager {
Hashmap *netdevs;
OrderedHashmap *networks;
Hashmap *dhcp6_prefixes;
Set *dhcp6_pd_prefixes;
LIST_HEAD(AddressPool, address_pools);
usec_t network_dirs_ts_usec;

View File

@ -679,7 +679,7 @@ int radv_configure(Link *link) {
return 0;
}
int radv_add_prefix(Link *link, struct in6_addr *prefix, uint8_t prefix_len,
int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len,
uint32_t lifetime_preferred, uint32_t lifetime_valid) {
_cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL;
int r;

View File

@ -52,7 +52,7 @@ DEFINE_NETWORK_SECTION_FUNCTIONS(RoutePrefix, route_prefix_free);
int radv_emit_dns(Link *link);
int radv_configure(Link *link);
int radv_add_prefix(Link *link, struct in6_addr *prefix, uint8_t prefix_len,
int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len,
uint32_t lifetime_preferred, uint32_t lifetime_valid);
const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_;

View File

@ -146,6 +146,10 @@ void route_free(Route *route) {
set_remove(route->link->routes_foreign, route);
set_remove(route->link->dhcp_routes, route);
set_remove(route->link->dhcp_routes_old, route);
set_remove(route->link->dhcp6_routes, 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);
}