Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next] ipv4: add ip_process_options sysctl
@ 2026-11-02 15:59 Ricardo Branco
  2026-11-03 12:19 ` Ido Schimmel
  0 siblings, 1 reply; 2+ messages in thread
From: Ricardo Branco @ 2026-11-02 15:59 UTC (permalink / raw)
  To: netdev, rbranco; +Cc: davem, edumazet, horms, dsahern, idosch, linux-doc

Add net.ipv4.ip_process_options to control handling of IP options in
received packets, modelled after FreeBSD's net.inet.ip.process_options:

  0 - ignore options; the packet is handled as if it had none, and
      forwarded packets keep their options unmodified
  1 - process options (default, current behaviour)
  2 - drop packets carrying options and send an ICMP "packet filtered"
      error, as FreeBSD does

Most IP options are obsolete or rarely needed, and are commonly filtered
(RFC 7126), yet the only existing knob, accept_source_route, covers just
the source routing options; record route, timestamp and the rest are
always processed. Netfilter can match and drop such packets, but unlike
TCP options it has no way to strip or neutralise IPv4 options while
still accepting the packet. A sysctl gives a simple switch with the same
semantics as the FreeBSD one, which also eases porting existing
configurations.

The check is done first in ip_rcv_options(), so it takes precedence over
accept_source_route and skips the skb_cow() and option parsing.
Ignoring options is safe because IPCB(skb) is zeroed in ip_rcv_core().

Note that mode 2 also drops packets whose only option is Router Alert,
e.g. IGMP, which can break multicast on routers.

Tested with veth pairs in network namespaces using "ping -R", both for
local delivery and for forwarding through a router: mode 1 records the
route, mode 0 returns no list locally and forwards options without the
router recording its address, mode 2 drops the request and ping reports
"Packet filtered".

Signed-off-by: Ricardo Branco <rbranco@suse.de>
---
 Documentation/networking/ip-sysctl.rst | 15 +++++++++++++++
 include/net/netns/ipv4.h               |  1 +
 net/ipv4/af_inet.c                     |  1 +
 net/ipv4/ip_input.c                    | 14 ++++++++++++++
 net/ipv4/sysctl_net_ipv4.c             |  9 +++++++++
 5 files changed, 40 insertions(+)

diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst
index d3523c9064a2..fdbd34384453 100644
--- a/Documentation/networking/ip-sysctl.rst
+++ b/Documentation/networking/ip-sysctl.rst
@@ -172,6 +172,21 @@ ip_forward_update_priority - INTEGER
 	- 0 - Do not update priority.
 	- 1 - Update priority.
 
+ip_process_options - INTEGER
+	Control processing of IPv4 options (source routing, record route,
+	timestamp, etc.) in received packets.
+
+	Possible values:
+
+	- 0 - Ignore options. Packets are accepted or forwarded as if they
+	  carried no options; forwarded packets keep their options unchanged.
+	- 1 - Process options.
+	- 2 - Drop packets carrying options and send an ICMP "packet
+	  filtered" error. Note that this includes packets carrying only
+	  the Router Alert option (e.g. IGMP), which can break multicast.
+
+	Default: 1
+
 route/max_size - INTEGER
 	Maximum number of routes allowed in the kernel.  Increase
 	this when using large numbers of interfaces and/or routes.
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index cb7f8bf15671..3bbd15be505d 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -162,6 +162,7 @@ struct netns_ipv4 {
 
 	u8 sysctl_ip_default_ttl;
 	u8 sysctl_ip_no_pmtu_disc;
+	u8 sysctl_ip_process_options;
 	u8 sysctl_ip_fwd_update_priority;
 	u8 sysctl_ip_nonlocal_bind;
 	u8 sysctl_ip_autobind_reuse;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 7677b0343abd..2f22e69fa3cd 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1798,6 +1798,7 @@ static __net_init int inet_init_net(struct net *net)
 	 */
 	net->ipv4.sysctl_ip_default_ttl = IPDEFTTL;
 	net->ipv4.sysctl_ip_fwd_update_priority = 1;
+	net->ipv4.sysctl_ip_process_options = 1;
 	net->ipv4.sysctl_ip_dynaddr = 0;
 	net->ipv4.sysctl_ip_early_demux = 1;
 	net->ipv4.sysctl_udp_early_demux = 1;
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 9860178752b8..d1616ecddfa8 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -271,6 +271,20 @@ ip_rcv_options(struct sk_buff *skb, struct net_device *dev)
 	const struct iphdr *iph;
 	struct ip_options *opt;
 
+	switch (READ_ONCE(dev_net(dev)->ipv4.sysctl_ip_process_options)) {
+	case 0:
+		/* Ignore options: IPCB(skb)->opt was zeroed in ip_rcv_core(),
+		 * so the packet is handled as if it carried no options.
+		 */
+		return SKB_NOT_DROPPED_YET;
+	case 2:
+		__IP_INC_STATS(dev_net(dev), IPSTATS_MIB_INHDRERRORS);
+		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PKT_FILTERED, 0);
+		return SKB_DROP_REASON_IP_INHDR;
+	default:	/* 1: process options */
+		break;
+	}
+
 	/* It looks as overkill, because not all
 	   IP options require packet mangling.
 	   But it is the easiest for now, especially taking
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index bf193e7ec516..9bdf5ad23614 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -847,6 +847,15 @@ static const struct ctl_table ipv4_net_table[] = {
 		.mode		= 0644,
 		.proc_handler	= proc_dou8vec_minmax,
 	},
+	{
+		.procname	= "ip_process_options",
+		.data		= &init_net.ipv4.sysctl_ip_process_options,
+		.maxlen		= sizeof(u8),
+		.mode		= 0644,
+		.proc_handler	= proc_dou8vec_minmax,
+		.extra1		= SYSCTL_ZERO,
+		.extra2		= SYSCTL_TWO,
+	},
 	{
 		.procname	= "ip_forward_use_pmtu",
 		.data		= &init_net.ipv4.sysctl_ip_fwd_use_pmtu,
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH net-next] ipv4: add ip_process_options sysctl
  2026-11-02 15:59 [PATCH net-next] ipv4: add ip_process_options sysctl Ricardo Branco
@ 2026-11-03 12:19 ` Ido Schimmel
  0 siblings, 0 replies; 2+ messages in thread
From: Ido Schimmel @ 2026-11-03 12:19 UTC (permalink / raw)
  To: Ricardo Branco; +Cc: netdev, davem, edumazet, horms, dsahern, linux-doc

On Mon, Nov 02, 2026 at 04:59:58PM +0100, Ricardo Branco wrote:
> Add net.ipv4.ip_process_options to control handling of IP options in
> received packets, modelled after FreeBSD's net.inet.ip.process_options:
> 
>   0 - ignore options; the packet is handled as if it had none, and
>       forwarded packets keep their options unmodified
>   1 - process options (default, current behaviour)
>   2 - drop packets carrying options and send an ICMP "packet filtered"
>       error, as FreeBSD does
> 
> Most IP options are obsolete or rarely needed, and are commonly filtered
> (RFC 7126), yet the only existing knob, accept_source_route, covers just
> the source routing options; record route, timestamp and the rest are
> always processed. Netfilter can match and drop such packets, but unlike
> TCP options it has no way to strip or neutralise IPv4 options while
> still accepting the packet. A sysctl gives a simple switch with the same
> semantics as the FreeBSD one, which also eases porting existing
> configurations.
> 
> The check is done first in ip_rcv_options(), so it takes precedence over
> accept_source_route and skips the skb_cow() and option parsing.
> Ignoring options is safe because IPCB(skb) is zeroed in ip_rcv_core().
> 
> Note that mode 2 also drops packets whose only option is Router Alert,
> e.g. IGMP, which can break multicast on routers.

Ease of porting from FreeBSD is not a good enough reason to add a new
sysctl that we will never be able to remove, especially when almost all
of the functionality is already covered by netfilter and in a better
way.

Netfilter already covers option 2 and it can match on specific options,
thereby avoiding the IGMP breakage.

Regarding option 0, assuming it's actually needed (beyond feature
parity), why not add "reset ip option <name>" similar to "reset tcp
option <name>" that was implemented in commit 7890cbea66e7 ("netfilter:
exthdr: add support for tcp option removal")?

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-11-03 12:19 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-02 15:59 [PATCH net-next] ipv4: add ip_process_options sysctl Ricardo Branco
2026-11-03 12:19 ` Ido Schimmel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox