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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user