network: address: also set IFA_FLAGS on remove

If an address is assigned with IFA_F_MANAGETEMPADDR, then the flag must
be also set on remove. Otherwise, temporary addresses will not be
removed. See also inet6_rtm_deladdr() in kernel's net/ipv6/addrconf.c.

Fixes #13218.
This commit is contained in:
Yu Watanabe
2021-02-12 23:09:21 +09:00
parent e81fd9dd23
commit a8481354f0
+37 -24
View File
@@ -517,6 +517,39 @@ static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
return 1;
}
static int address_set_netlink_message(const Address *address, sd_netlink_message *req, Link *link) {
uint32_t flags;
int r;
assert(address);
assert(req);
assert(link);
r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
if (r < 0)
return log_link_error_errno(link, r, "Could not set prefixlen: %m");
/* On remove, only IFA_F_MANAGETEMPADDR flag for IPv6 addresses are used. But anyway, set all
* flags here unconditionally. Without setting the flag, the template addresses generated by
* kernel will not be removed automatically when the main address is removed. */
flags = address->flags | IFA_F_PERMANENT;
r = sd_rtnl_message_addr_set_flags(req, flags & 0xff);
if (r < 0)
return log_link_error_errno(link, r, "Could not set flags: %m");
if (flags & ~0xff) {
r = sd_netlink_message_append_u32(req, IFA_FLAGS, flags);
if (r < 0)
return log_link_error_errno(link, r, "Could not set extended flags: %m");
}
r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
return 0;
}
int address_remove(
const Address *address,
Link *link,
@@ -539,13 +572,9 @@ int address_remove(
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_DELADDR message: %m");
r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
r = address_set_netlink_message(address, req, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not set prefixlen: %m");
r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
return r;
r = netlink_call_async(link->manager->rtnl, NULL, req,
callback ?: address_remove_handler,
@@ -809,7 +838,6 @@ int address_configure(
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
Address *acquired_address, *a;
uint32_t flags;
bool update;
int r;
@@ -846,29 +874,14 @@ int address_configure(
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_NEWADDR message: %m");
r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
r = address_set_netlink_message(address, req, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not set prefixlen: %m");
flags = address->flags | IFA_F_PERMANENT;
r = sd_rtnl_message_addr_set_flags(req, flags & 0xff);
if (r < 0)
return log_link_error_errno(link, r, "Could not set flags: %m");
if (flags & ~0xff) {
r = sd_netlink_message_append_u32(req, IFA_FLAGS, flags);
if (r < 0)
return log_link_error_errno(link, r, "Could not set extended flags: %m");
}
return r;
r = sd_rtnl_message_addr_set_scope(req, address->scope);
if (r < 0)
return log_link_error_errno(link, r, "Could not set scope: %m");
r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
if (in_addr_is_null(address->family, &address->in_addr_peer) == 0) {
r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer);
if (r < 0)