network: fix NFTSet population when [DHCPPrefixDelegation] Assign=no (#40049)
When [DHCPPrefixDelegation] Assign=no, networkd creates routes instead of addresses. These routes need to populate nftables sets for firewall rules to work correctly. This commit adds dhcp_pd_route_modify_nft_set() to handle NFT set updates for DHCP-PD routes, similar to how address_modify_nft_set() handles them for addresses. Fixes: #38383
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include "hexdecoct.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "networkd-dhcp-common.h"
|
||||
#include "networkd-dhcp-prefix-delegation.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-network.h"
|
||||
@@ -106,6 +107,7 @@ void network_adjust_dhcp(Network *network) {
|
||||
}
|
||||
|
||||
network_adjust_dhcp4(network);
|
||||
network_adjust_dhcp_prefix_delegation(network);
|
||||
}
|
||||
|
||||
static bool duid_needs_product_uuid(const DUID *duid) {
|
||||
|
||||
@@ -157,6 +157,63 @@ static int dhcp_pd_get_assigned_subnet_prefix(Link *link, const struct in6_addr
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static void dhcp_pd_route_modify_nft_set(Route *route, Link *link, bool add) {
|
||||
int r;
|
||||
|
||||
assert(route);
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->network);
|
||||
|
||||
if (!link->manager->nfnl)
|
||||
return;
|
||||
|
||||
if (route->family != AF_INET6)
|
||||
return;
|
||||
|
||||
if (route->source != NETWORK_CONFIG_SOURCE_DHCP_PD)
|
||||
return;
|
||||
|
||||
/* When Assign=yes, address_modify_nft_set() manages the NFT set, not this function. */
|
||||
if (link->network->dhcp_pd_assign)
|
||||
return;
|
||||
|
||||
NFTSetContext *nft_set_context = &link->network->dhcp_pd_nft_set_context;
|
||||
|
||||
FOREACH_ARRAY(nft_set, nft_set_context->sets, nft_set_context->n_sets) {
|
||||
assert(nft_set);
|
||||
|
||||
switch (nft_set->source) {
|
||||
case NFT_SET_SOURCE_ADDRESS:
|
||||
/* Should be already warned in network_adjust_dhcp_prefix_delegation(). */
|
||||
continue;
|
||||
case NFT_SET_SOURCE_PREFIX:
|
||||
r = nft_set_element_modify_iprange(link->manager->nfnl, add, nft_set->nfproto, route->family, nft_set->table, nft_set->set,
|
||||
&route->dst, route->dst_prefixlen);
|
||||
break;
|
||||
case NFT_SET_SOURCE_IFINDEX: {
|
||||
uint32_t ifindex = link->ifindex;
|
||||
r = nft_set_element_modify_any(link->manager->nfnl, add, nft_set->nfproto, nft_set->table, nft_set->set,
|
||||
&ifindex, sizeof(ifindex));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to %s NFT set entry: family %s, table %s, set %s, IP prefix %s, ignoring: %m",
|
||||
add ? "add" : "delete",
|
||||
nfproto_to_string(nft_set->nfproto), nft_set->table, nft_set->set,
|
||||
IN_ADDR_PREFIX_TO_STRING(route->family, &route->dst, route->dst_prefixlen));
|
||||
else
|
||||
log_debug("%s NFT set entry: family %s, table %s, set %s, IP prefix %s",
|
||||
add ? "Added" : "Deleted",
|
||||
nfproto_to_string(nft_set->nfproto), nft_set->table, nft_set->set,
|
||||
IN_ADDR_PREFIX_TO_STRING(route->family, &route->dst, route->dst_prefixlen));
|
||||
}
|
||||
}
|
||||
|
||||
int dhcp_pd_remove(Link *link, bool only_marked) {
|
||||
int ret = 0;
|
||||
|
||||
@@ -185,6 +242,9 @@ int dhcp_pd_remove(Link *link, bool only_marked) {
|
||||
|
||||
link_remove_dhcp_pd_subnet_prefix(link, &route->dst.in6);
|
||||
|
||||
/* Remove NFTSet entries before removing the route */
|
||||
dhcp_pd_route_modify_nft_set(route, link, /* add= */ false);
|
||||
|
||||
RET_GATHER(ret, route_remove_and_cancel(route, link->manager));
|
||||
}
|
||||
} else {
|
||||
@@ -285,6 +345,9 @@ static int dhcp_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Reques
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
/* Update NFTSet entries when route is successfully configured */
|
||||
dhcp_pd_route_modify_nft_set(route, link, /* add= */ true);
|
||||
|
||||
r = dhcp_pd_check_ready(link);
|
||||
if (r < 0)
|
||||
link_enter_failed(link);
|
||||
@@ -1333,6 +1396,27 @@ int link_drop_dhcp_pd_config(Link *link, Network *network) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void network_adjust_dhcp_prefix_delegation(Network *network) {
|
||||
assert(network);
|
||||
|
||||
if (!network->dhcp_pd)
|
||||
return;
|
||||
|
||||
if (network->dhcp_pd_assign)
|
||||
return;
|
||||
|
||||
/* If Assign=no, then DHCPv6 PD will create routes instead of addresses.
|
||||
* NFTSet=address:... is not supported in this case. */
|
||||
|
||||
FOREACH_ARRAY(nft_set, network->dhcp_pd_nft_set_context.sets, network->dhcp_pd_nft_set_context.n_sets)
|
||||
if (nft_set->source == NFT_SET_SOURCE_ADDRESS) {
|
||||
log_warning("%s: In [DHCPPrefixDelegation] section, when Assign= is disabled, "
|
||||
"NFTSet=address:... is not supported and will be ignored.",
|
||||
network->filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int config_parse_dhcp_pd_subnet_id(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
|
||||
@@ -14,6 +14,7 @@ int dhcp6_pd_prefix_acquired(Link *uplink);
|
||||
void dhcp4_pd_prefix_lost(Link *uplink);
|
||||
void dhcp6_pd_prefix_lost(Link *uplink);
|
||||
int dhcp_pd_reconfigure_address(Address *address, Link *link);
|
||||
void network_adjust_dhcp_prefix_delegation(Network *network);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_pd_subnet_id);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_pd_prefix_route_type);
|
||||
|
||||
Reference in New Issue
Block a user