</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>IPv4ReversePathFilter=</varname></term>
+ <listitem>
+ <para>Configure IPv4 Reverse Path Filtering. If enabled, when an IPv4 packet is received, the machine will first check
+ whether the <emphasis>source</emphasis> of the packet would be routed through the interface it came in. If there is no
+ route to the source on that interface, the machine will drop the packet. Takes one of
+ <literal>no</literal>, <literal>strict</literal>, or <literal>loose</literal>. When <literal>no</literal>,
+ no source validation will be done. When <literal>strict</literal>, mode each incoming packet is tested against the FIB and
+ if the incoming interface is not the best reverse path, the packet check will fail. By default failed packets are discarded.
+ When <literal>loose</literal>, mode each incoming packet's source address is tested against the FIB. The packet is dropped
+ only if the source address is not reachable via any interface on that router.
+ See <ulink url="https://tools.ietf.org/html/rfc1027">RFC 3704</ulink>.
+ When unset, the kernel's default will be used.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>IPv4AcceptLocal=</varname></term>
<listitem>
Network.IPv4ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp)
Network.ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp)
Network.IPv6ProxyNDPAddress, config_parse_ipv6_proxy_ndp_address, 0, 0
+Network.IPv4ReversePathFilter, config_parse_ip_reverse_path_filter, 0, offsetof(Network, ipv4_rp_filter)
Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier)
Network.ConfigureWithoutCarrier, config_parse_bool, 0, offsetof(Network, configure_without_carrier)
Network.IgnoreCarrierLoss, config_parse_ignore_carrier_loss, 0, 0
.ipv6_hop_limit = -1,
.ipv6_proxy_ndp = -1,
.proxy_arp = -1,
+ .ipv4_rp_filter = _IP_REVERSE_PATH_FILTER_INVALID,
.ipv6_accept_ra = -1,
.ipv6_accept_ra_use_dns = true,
int proxy_arp;
uint32_t ipv6_mtu;
IPv6PrivacyExtensions ipv6_privacy_extensions;
+ IPReversePathFilter ipv4_rp_filter;
int ipv6_proxy_ndp;
Set *ipv6_proxy_ndp_addresses;
return sysctl_write_ip_property(AF_INET6, "all", "forwarding", "1");
}
+static int link_set_ipv4_rp_filter(Link *link) {
+ assert(link);
+
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
+ if (!link->network)
+ return 0;
+
+ if (link->network->ipv4_rp_filter < 0)
+ return 0;
+
+ return sysctl_write_ip_property_int(AF_INET, link->ifname, "rp_filter", link->network->ipv4_rp_filter);
+}
+
static int link_set_ipv6_privacy_extensions(Link *link) {
IPv6PrivacyExtensions val;
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv4 route_localnet flag for interface, ignoring: %m");
+ r = link_set_ipv4_rp_filter(link);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot set IPv4 reverse path filtering for interface, ignoring: %m");
+
/* If promote_secondaries is not set, DHCP will work only as long as the IP address does not
* changes between leases. The kernel will remove all secondary IP addresses of an interface
* otherwise. The way systemd-networkd works is that the new IP of a lease is added as a
IPV6_PRIVACY_EXTENSIONS_YES);
DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_privacy_extensions, ipv6_privacy_extensions, IPv6PrivacyExtensions,
"Failed to parse IPv6 privacy extensions option");
+
+static const char* const ip_reverse_path_filter_table[_IP_REVERSE_PATH_FILTER_MAX] = {
+ [IP_REVERSE_PATH_FILTER_NO] = "no",
+ [IP_REVERSE_PATH_FILTER_STRICT] = "strict",
+ [IP_REVERSE_PATH_FILTER_LOOSE] = "loose",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(ip_reverse_path_filter, IPReversePathFilter);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_ip_reverse_path_filter, ip_reverse_path_filter, IPReversePathFilter,
+ "Failed to parse IP reverse path filter option");
_IPV6_PRIVACY_EXTENSIONS_INVALID = -EINVAL,
} IPv6PrivacyExtensions;
+typedef enum IPReversePathFilter {
+ IP_REVERSE_PATH_FILTER_NO,
+ IP_REVERSE_PATH_FILTER_STRICT,
+ IP_REVERSE_PATH_FILTER_LOOSE,
+ _IP_REVERSE_PATH_FILTER_MAX,
+ _IP_REVERSE_PATH_FILTER_INVALID = -EINVAL,
+} IPReversePathFilter;
+
int link_set_sysctl(Link *link);
int link_set_ipv6_mtu(Link *link);
const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_;
IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
+const char* ip_reverse_path_filter_to_string(IPReversePathFilter i) _const_;
+IPReversePathFilter ip_reverse_path_filter_from_string(const char *s) _pure_;
+
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions);
+CONFIG_PARSER_PROTOTYPE(config_parse_ip_reverse_path_filter);