diff --git a/man/systemd.network.xml b/man/systemd.network.xml index c9ef041004..d7947836e9 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -548,6 +548,15 @@ Defaults to unset. + + ProxyARP= + A boolean. Configures proxy ARP. Proxy ARP is the technique in which one host, + usually a router, answers ARP requests intended for another machine. By "faking" its identity, + the router accepts responsibility for routing packets to the "real" destination. (see RFC 1027. + Defaults to unset. + + Bridge= @@ -844,7 +853,7 @@ global DUID that may be specified in networkd.conf 5. - The configured DHCP DUID should conform to the specification in + The configured DHCP DUID should conform to the specification in RFC 3315, RFC 6355. diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 88b3cbe90a..9059a68fe3 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -165,6 +165,21 @@ static bool link_ipv6_forward_enabled(Link *link) { return link->network->ip_forward & ADDRESS_FAMILY_IPV6; } +static bool link_proxy_arp_enabled(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if (link->network->proxy_arp < 0) + return false; + + return true; +} + static bool link_ipv6_accept_ra_enabled(Link *link) { assert(link); @@ -1039,6 +1054,22 @@ static int link_set_bridge_fdb(Link *const link) { return r; } +static int link_set_proxy_arp(Link *const link) { + const char *p = NULL; + int r; + + if (!link_proxy_arp_enabled(link)) + return 0; + + p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/proxy_arp"); + + r = write_string_file(p, one_zero(link->network->proxy_arp), WRITE_STRING_FILE_VERIFY_ON_FAILURE); + if (r < 0) + log_link_warning_errno(link, r, "Cannot configure proxy ARP for interface: %m"); + + return 0; +} + static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; @@ -2167,6 +2198,10 @@ static int link_configure(Link *link) { if (r < 0) return r; + r = link_set_proxy_arp(link); + if (r < 0) + return r; + r = link_set_ipv4_forward(link); if (r < 0) return r; diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 9793938080..1da99cd5bc 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -61,6 +61,7 @@ Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, Network.IPv6AcceptRouterAdvertisements, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra) Network.IPv6DuplicateAddressDetection, config_parse_int, 0, offsetof(Network, ipv6_dad_transmits) Network.IPv6HopLimit, config_parse_int, 0, offsetof(Network, ipv6_hop_limit) +Network.ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp) Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier) Address.Address, config_parse_address, 0, 0 Address.Peer, config_parse_address, 0, 0 diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 5946ba18dc..1c7adf5180 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -132,6 +132,7 @@ static int network_load_one(Manager *manager, const char *filename) { network->ipv6_dad_transmits = -1; network->ipv6_hop_limit = -1; network->duid_type = _DUID_TYPE_INVALID; + network->proxy_arp = -1; r = config_parse(NULL, filename, file, "Match\0" diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 5400a8bc9d..3d44113b05 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -139,6 +139,7 @@ struct Network { int ipv6_accept_ra; int ipv6_dad_transmits; int ipv6_hop_limit; + int proxy_arp; union in_addr_union ipv6_token; IPv6PrivacyExtensions ipv6_privacy_extensions;