network: adjust sysctl setting in network_adjust_neighbor_proxy()
This also makes IPv4 proxy neighbor entries independent of proxy_arp sysctl. We can configure IPv4 proxy neighbor entries even if proxy_arp is disabled.
This commit is contained in:
@@ -15,61 +15,37 @@
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
bool network_has_neighbor_proxy_address(const Network *network, int family) {
|
||||
struct in_addr_data *a;
|
||||
|
||||
assert(network);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
|
||||
SET_FOREACH(a, network->neighbor_proxy_addresses)
|
||||
if (a->family == family)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void network_drop_neighbor_proxy_addresses(Network *network, int family) {
|
||||
struct in_addr_data *a;
|
||||
|
||||
assert(network);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
|
||||
SET_FOREACH(a, network->neighbor_proxy_addresses)
|
||||
if (a->family == family)
|
||||
free(set_remove(network->neighbor_proxy_addresses, a));
|
||||
|
||||
if (set_isempty(network->neighbor_proxy_addresses))
|
||||
network->neighbor_proxy_addresses = set_free(network->neighbor_proxy_addresses);
|
||||
}
|
||||
|
||||
void network_adjust_neighbor_proxy(Network *network) {
|
||||
assert(network);
|
||||
|
||||
if (set_isempty(network->neighbor_proxy_addresses))
|
||||
return;
|
||||
struct in_addr_data *a;
|
||||
SET_FOREACH(a, network->neighbor_proxy_addresses) {
|
||||
switch (a->family) {
|
||||
case AF_INET6:
|
||||
if (!socket_ipv6_is_supported()) {
|
||||
log_warning("%s: Specified IPv6 proxy NDP address %s, but IPv6 is not supported by the kernel, ignoring.",
|
||||
network->filename, IN_ADDR_TO_STRING(a->family, &a->address));
|
||||
free(set_remove(network->neighbor_proxy_addresses, a));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If IPv6 is not supported by the kernel, drop any IPv6 entries up front. */
|
||||
if (!socket_ipv6_is_supported() &&
|
||||
network_has_neighbor_proxy_address(network, AF_INET6)) {
|
||||
log_once(LOG_WARNING,
|
||||
"%s: IPv6 proxy NDP addresses are set, but IPv6 is not supported by kernel, "
|
||||
"ignoring IPv6 proxy NDP addresses.", network->filename);
|
||||
network_drop_neighbor_proxy_addresses(network, AF_INET6);
|
||||
}
|
||||
if (network->ipv6_proxy_ndp == 0) {
|
||||
log_warning("%s: Specified IPv6 proxy NDP address %s, but IPv6ProxyNDP= is disabled, ignoring.",
|
||||
network->filename, IN_ADDR_TO_STRING(a->family, &a->address));
|
||||
free(set_remove(network->neighbor_proxy_addresses, a));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Drop per-family entries when the corresponding proxy sysctl was explicitly disabled.
|
||||
* For IPv6 the proxy_ndp sysctl is required for manual entries to take effect; for IPv4 we
|
||||
* apply the same rule for consistency so that an explicit IPv4ProxyARP=no is respected. */
|
||||
int family;
|
||||
FOREACH_ARGUMENT(family, AF_INET, AF_INET6) {
|
||||
int tristate = family == AF_INET ? network->proxy_arp : network->ipv6_proxy_ndp;
|
||||
/* IPv6 proxy NDP entry requires that proxy_ndp sysctl is enabled. */
|
||||
network->ipv6_proxy_ndp = true;
|
||||
break;
|
||||
|
||||
if (tristate == 0 && network_has_neighbor_proxy_address(network, family)) {
|
||||
log_warning("%s: %s is disabled. Ignoring %s.",
|
||||
network->filename,
|
||||
family == AF_INET ? "IPv4ProxyARP=" : "IPv6ProxyNDP=",
|
||||
family == AF_INET ? "IPv4ProxyARPAddress=" : "IPv6ProxyNDPAddress=");
|
||||
network_drop_neighbor_proxy_addresses(network, family);
|
||||
case AF_INET:
|
||||
/* IPv4 proxy ARP entry does NOT require that proxy_arp sysctl is enabled. */
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
#include "networkd-forward.h"
|
||||
|
||||
bool network_has_neighbor_proxy_address(const Network *network, int family);
|
||||
|
||||
void network_adjust_neighbor_proxy(Network *network);
|
||||
|
||||
int link_request_static_neighbor_proxy_addresses(Link *link);
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "networkd-lldp-tx.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-ndisc.h"
|
||||
#include "networkd-neighbor-proxy.h"
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-sysctl.h"
|
||||
#include "path-util.h"
|
||||
@@ -271,25 +270,18 @@ static int link_update_ipv6_sysctl(Link *link) {
|
||||
}
|
||||
|
||||
static int link_set_proxy_arp(Link *link) {
|
||||
bool v;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
|
||||
if (!link_is_configured_for_family(link, AF_INET))
|
||||
return 0;
|
||||
|
||||
if (link->network->proxy_arp >= 0)
|
||||
v = link->network->proxy_arp;
|
||||
else if (network_has_neighbor_proxy_address(link->network, AF_INET))
|
||||
/* If IPv4ProxyARP= is not explicitly set, but per-address IPv4ProxyARPAddress=
|
||||
* entries are configured, implicitly enable the proxy_arp sysctl. This matches
|
||||
* the behavior of IPv6ProxyNDPAddress= which implies IPv6ProxyNDP=yes. */
|
||||
v = true;
|
||||
else
|
||||
if (link->network->proxy_arp < 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp", v, manager_get_sysctl_shadow(link->manager));
|
||||
return sysctl_write_ip_property_boolean(
|
||||
AF_INET, link->ifname, "proxy_arp", link->network->proxy_arp,
|
||||
manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
static int link_set_proxy_arp_pvlan(Link *link) {
|
||||
@@ -512,22 +504,18 @@ static int link_set_ipv6_retransmission_time(Link *link) {
|
||||
}
|
||||
|
||||
static int link_set_ipv6_proxy_ndp(Link *link) {
|
||||
bool v;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
|
||||
if (!link_is_configured_for_family(link, AF_INET6))
|
||||
return 0;
|
||||
|
||||
if (link->network->ipv6_proxy_ndp >= 0)
|
||||
v = link->network->ipv6_proxy_ndp;
|
||||
else if (network_has_neighbor_proxy_address(link->network, AF_INET6))
|
||||
v = true;
|
||||
else
|
||||
if (link->network->ipv6_proxy_ndp < 0)
|
||||
return 0;
|
||||
|
||||
return sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "proxy_ndp", v, manager_get_sysctl_shadow(link->manager));
|
||||
return sysctl_write_ip_property_boolean(
|
||||
AF_INET6, link->ifname, "proxy_ndp", link->network->ipv6_proxy_ndp,
|
||||
manager_get_sysctl_shadow(link->manager));
|
||||
}
|
||||
|
||||
int link_set_ipv6_mtu(Link *link, int log_level) {
|
||||
|
||||
@@ -4,7 +4,7 @@ Name=dummy98
|
||||
|
||||
[Network]
|
||||
IPv4ProxyARP=no
|
||||
ProxyNeighbor=192.0.2.1
|
||||
ProxyNeighbor=192.0.2.2
|
||||
ProxyNeighbor=192.0.3.1
|
||||
ProxyNeighbor=192.0.3.2
|
||||
IPv6AcceptRA=no
|
||||
Address=10.0.0.1/24
|
||||
|
||||
@@ -5384,13 +5384,9 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
for i in range(1, 6):
|
||||
self.assertRegex(output, f'192.0.2.{i} *proxy')
|
||||
|
||||
# When a proxy ARP address is specified, IPv4ProxyARP=yes is implied.
|
||||
self.check_ipv4_sysctl_attr('dummy98', 'proxy_arp', '1')
|
||||
# Even if a proxy ARP address is specified, IPv4ProxyARP=yes is NOT implied.
|
||||
self.check_ipv4_sysctl_attr('dummy98', 'proxy_arp', '0')
|
||||
|
||||
# Explicit IPv4ProxyARP=no must suppress all IPv4 proxy ARP address entries and
|
||||
# must not force proxy_arp=1. The module is add-only (no reconcile/remove pass),
|
||||
# so phase 2 starts from a clean interface: stop networkd, delete the dummy to
|
||||
# flush the kernel neighbor-proxy table, swap the .network file, and restart.
|
||||
stop_networkd()
|
||||
remove_link('dummy98')
|
||||
remove_network_unit('25-ipv4-proxy-arp.network')
|
||||
@@ -5398,10 +5394,14 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
start_networkd()
|
||||
self.wait_online('dummy98:routable')
|
||||
|
||||
# Even if IPv4ProxyARP= is disabled, proxy ARP addresses can be configured.
|
||||
output = check_output('ip -4 neighbor show proxy dev dummy98')
|
||||
print(output)
|
||||
for i in range(1, 6):
|
||||
self.assertNotIn(f'192.0.2.{i}', output)
|
||||
self.assertNotRegex(output, f'192.0.2.{i} *proxy')
|
||||
for i in range(1, 3):
|
||||
self.assertRegex(output, f'192.0.3.{i} *proxy')
|
||||
|
||||
self.check_ipv4_sysctl_attr('dummy98', 'proxy_arp', '0')
|
||||
|
||||
def test_ipv6_neigh_retrans_time(self):
|
||||
|
||||
Reference in New Issue
Block a user