public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
From: Ralf Lici <ralf@mandelbit.com>
To: netdev@vger.kernel.org
Cc: "Daniel Gröber" <dxld@darkboxed.org>,
	"Ralf Lici" <ralf@mandelbit.com>,
	"Antonio Quartulli" <antonio@mandelbit.com>,
	"Andrew Lunn" <andrew+netdev@lunn.ch>,
	"David S. Miller" <davem@davemloft.net>,
	"Eric Dumazet" <edumazet@google.com>,
	"Jakub Kicinski" <kuba@kernel.org>,
	"Paolo Abeni" <pabeni@redhat.com>,
	linux-kernel@vger.kernel.org
Subject: [RFC net-next 09/15] ipxlat: emit translator-generated ICMP errors on drop
Date: Thu, 19 Mar 2026 16:12:18 +0100	[thread overview]
Message-ID: <20260319151230.655687-10-ralf@mandelbit.com> (raw)
In-Reply-To: <20260319151230.655687-1-ralf@mandelbit.com>

When validation or policy requires dropping a packet and generating an
ICMP error, route that failure through explicit ICMP emission paths so
the sender can be notified where appropriate. This commit adds
translator-originated error generation for both directions and
integrates it into dispatch action handling without changing normal
forwarding behavior.

Signed-off-by: Ralf Lici <ralf@mandelbit.com>
---
 drivers/net/ipxlat/dispatch.c | 66 ++++++++++++++++++++++++++++++++++-
 drivers/net/ipxlat/dispatch.h |  7 ++++
 drivers/net/ipxlat/packet.c   | 25 ++++++++++---
 3 files changed, 92 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ipxlat/dispatch.c b/drivers/net/ipxlat/dispatch.c
index 133d30859f49..b8b9b930b04c 100644
--- a/drivers/net/ipxlat/dispatch.c
+++ b/drivers/net/ipxlat/dispatch.c
@@ -11,7 +11,12 @@
  *		Ralf Lici <ralf@mandelbit.com>
  */
 
+#include <linux/icmp.h>
+#include <linux/icmpv6.h>
+#include <net/icmp.h>
 #include <net/ip.h>
+#include <net/route.h>
+#include <net/ipv6.h>
 
 #include "dispatch.h"
 #include "packet.h"
@@ -21,7 +26,8 @@
 static enum ipxlat_action
 ipxlat_resolve_failed_action(const struct sk_buff *skb)
 {
-	return IPXLAT_ACT_DROP;
+	return ipxlat_skb_cb(skb)->emit_icmp_err ? IPXLAT_ACT_ICMP_ERR :
+						 IPXLAT_ACT_DROP;
 }
 
 enum ipxlat_action ipxlat_translate(struct ipxlat_priv *ipxlat,
@@ -61,6 +67,59 @@ void ipxlat_mark_icmp_drop(struct sk_buff *skb, u8 type, u8 code, u32 info)
 	cb->icmp_err.info = info;
 }
 
+static void ipxlat_46_emit_icmp_err(struct ipxlat_priv *ipxlat,
+				    struct sk_buff *inner)
+{
+	struct ipxlat_cb *cb = ipxlat_skb_cb(inner);
+	const struct iphdr *iph = ip_hdr(inner);
+	struct inet_skb_parm param = {};
+
+	/* build route metadata on demand when the packet has no dst */
+	if (unlikely(!skb_dst(inner))) {
+		const int reason = ip_route_input_noref(inner, iph->daddr,
+							iph->saddr,
+							ip4h_dscp(iph),
+							inner->dev);
+
+		if (unlikely(reason)) {
+			netdev_dbg(ipxlat->dev,
+				   "icmp4 emit: route build failed reason=%d\n",
+				   reason);
+			return;
+		}
+	}
+
+	/* emit the ICMPv4 error */
+	__icmp_send(inner, cb->icmp_err.type, cb->icmp_err.code,
+		    htonl(cb->icmp_err.info), &param);
+}
+
+static void ipxlat_64_emit_icmp_err(struct sk_buff *inner)
+{
+	struct ipxlat_cb *cb = ipxlat_skb_cb(inner);
+	struct inet6_skb_parm param = {};
+
+	/* emit the ICMPv6 error */
+	icmp6_send(inner, cb->icmp_err.type, cb->icmp_err.code,
+		   cb->icmp_err.info, NULL, &param);
+}
+
+/* emit translator-generated ICMP errors for packets rejected by RFC rules */
+void ipxlat_emit_icmp_error(struct ipxlat_priv *ipxlat, struct sk_buff *inner)
+{
+	switch (ntohs(inner->protocol)) {
+	case ETH_P_IPV6:
+		ipxlat_64_emit_icmp_err(inner);
+		return;
+	case ETH_P_IP:
+		ipxlat_46_emit_icmp_err(ipxlat, inner);
+		return;
+	default:
+		DEBUG_NET_WARN_ON_ONCE(1);
+		return;
+	}
+}
+
 static void ipxlat_forward_pkt(struct ipxlat_priv *ipxlat, struct sk_buff *skb)
 {
 	const unsigned int len = skb->len;
@@ -90,6 +149,11 @@ int ipxlat_process_skb(struct ipxlat_priv *ipxlat, struct sk_buff *skb,
 		dev_dstats_tx_add(ipxlat->dev, skb->len);
 		ipxlat_forward_pkt(ipxlat, skb);
 		return 0;
+	case IPXLAT_ACT_ICMP_ERR:
+		dev_dstats_tx_dropped(ipxlat->dev);
+		ipxlat_emit_icmp_error(ipxlat, skb);
+		consume_skb(skb);
+		return 0;
 	case IPXLAT_ACT_DROP:
 		goto drop_free;
 	default:
diff --git a/drivers/net/ipxlat/dispatch.h b/drivers/net/ipxlat/dispatch.h
index fa6fafea656b..73acd831b6cf 100644
--- a/drivers/net/ipxlat/dispatch.h
+++ b/drivers/net/ipxlat/dispatch.h
@@ -44,6 +44,13 @@ enum ipxlat_action {
  */
 void ipxlat_mark_icmp_drop(struct sk_buff *skb, u8 type, u8 code, u32 info);
 
+/**
+ * ipxlat_emit_icmp_error - emit cached translator-generated ICMP error
+ * @ipxlat: translator private context
+ * @inner: offending packet used as quoted payload
+ */
+void ipxlat_emit_icmp_error(struct ipxlat_priv *ipxlat, struct sk_buff *inner);
+
 /**
  * ipxlat_translate - validate/translate one packet and return next action
  * @ipxlat: translator private context
diff --git a/drivers/net/ipxlat/packet.c b/drivers/net/ipxlat/packet.c
index b37a3e55aff8..758b72bdc6f1 100644
--- a/drivers/net/ipxlat/packet.c
+++ b/drivers/net/ipxlat/packet.c
@@ -142,6 +142,8 @@ static int ipxlat_v4_srr_check(struct sk_buff *skb, const struct iphdr *hdr)
 			if (unlikely(ptr > len - 3))
 				return -EINVAL;
 
+			ipxlat_mark_icmp_drop(skb, ICMP_DEST_UNREACH,
+					      ICMP_SR_FAILED, 0);
 			return -EINVAL;
 		}
 
@@ -272,8 +274,10 @@ static int ipxlat_v4_pull_hdrs(struct sk_buff *skb)
 	/* RFC 7915 Section 4.1 */
 	if (unlikely(ipxlat_v4_srr_check(skb, l3_hdr)))
 		return -EINVAL;
-	if (unlikely(l3_hdr->ttl <= 1))
+	if (unlikely(l3_hdr->ttl <= 1)) {
+		ipxlat_mark_icmp_drop(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
 		return -EINVAL;
+	}
 
 	/* RFC 7915 Section 1.2:
 	 * Fragmented ICMP/ICMPv6 packets will not be translated by IP/ICMP
@@ -390,8 +394,11 @@ int ipxlat_v4_validate_skb(struct ipxlat_priv *ipxlat, struct sk_buff *skb)
 	 * Fragmented checksum-less IPv4 UDP is rejected because 4->6 cannot
 	 * reliably translate it.
 	 */
-	if (unlikely(ip_is_fragment(l3_hdr)))
+	if (unlikely(ip_is_fragment(l3_hdr))) {
+		ipxlat_mark_icmp_drop(skb, ICMP_DEST_UNREACH, ICMP_PKT_FILTERED,
+				      0);
 		return -EINVAL;
+	}
 
 	/* udph->len bounds the span used to compute replacement checksum */
 	if (unlikely(ntohs(udph->len) > skb->len - cb->l4_off))
@@ -520,7 +527,7 @@ static int ipxlat_v6_walk_hdrs(struct sk_buff *skb, unsigned int l3_offset,
  */
 static int ipxlat_v6_check_rh(struct sk_buff *skb)
 {
-	unsigned int rh_off;
+	unsigned int rh_off, pointer;
 	int flags, nexthdr;
 
 	rh_off = 0;
@@ -531,6 +538,8 @@ static int ipxlat_v6_check_rh(struct sk_buff *skb)
 	if (likely(nexthdr != NEXTHDR_ROUTING))
 		return 0;
 
+	pointer = rh_off + offsetof(struct ipv6_rt_hdr, segments_left);
+	ipxlat_mark_icmp_drop(skb, ICMPV6_PARAMPROB, ICMPV6_HDR_FIELD, pointer);
 	return -EINVAL;
 }
 
@@ -550,8 +559,11 @@ static int ipxlat_v6_pull_outer_l3(struct sk_buff *skb)
 		     !ipxlat_v6_validate_saddr(&l3_hdr->saddr)))
 		return -EINVAL;
 
-	if (unlikely(l3_hdr->hop_limit <= 1))
+	if (unlikely(l3_hdr->hop_limit <= 1)) {
+		ipxlat_mark_icmp_drop(skb, ICMPV6_TIME_EXCEED,
+				      ICMPV6_EXC_HOPLIMIT, 0);
 		return -EINVAL;
+	}
 
 	return 0;
 }
@@ -617,8 +629,11 @@ static int ipxlat_v6_pull_hdrs(struct sk_buff *skb)
 	/* -EPROTONOSUPPORT means packet layout is syntactically valid but
 	 * unsupported by our RFC 7915 path
 	 */
-	if (unlikely(err == -EPROTONOSUPPORT))
+	if (unlikely(err == -EPROTONOSUPPORT)) {
+		ipxlat_mark_icmp_drop(skb, ICMPV6_DEST_UNREACH,
+				      ICMPV6_ADM_PROHIBITED, 0);
 		return -EINVAL;
+	}
 	if (unlikely(err))
 		return err;
 
-- 
2.53.0


  parent reply	other threads:[~2026-03-19 15:20 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-19 15:12 [RFC net-next 00/15] Introducing ipxlat: a stateless IPv4/IPv6 translation device Ralf Lici
2026-03-19 15:12 ` [RFC net-next 01/15] drivers/net: add ipxlat netdevice skeleton and build plumbing Ralf Lici
2026-03-19 15:12 ` [RFC net-next 02/15] ipxlat: add RFC 6052 address conversion helpers Ralf Lici
2026-03-19 15:12 ` [RFC net-next 03/15] ipxlat: add packet metadata control block helpers Ralf Lici
2026-03-19 15:12 ` [RFC net-next 04/15] ipxlat: add IPv4 packet validation path Ralf Lici
2026-03-19 15:12 ` [RFC net-next 05/15] ipxlat: add IPv6 " Ralf Lici
2026-03-19 15:12 ` [RFC net-next 06/15] ipxlat: add transport checksum and offload helpers Ralf Lici
2026-03-19 15:12 ` [RFC net-next 07/15] ipxlat: add 4to6 and 6to4 TCP/UDP translation helpers Ralf Lici
2026-03-19 15:12 ` [RFC net-next 08/15] ipxlat: add translation engine and dispatch core Ralf Lici
2026-03-19 15:12 ` Ralf Lici [this message]
2026-03-19 15:12 ` [RFC net-next 10/15] ipxlat: add 4to6 pre-fragmentation path Ralf Lici
2026-03-19 15:12 ` [RFC net-next 11/15] ipxlat: add ICMP informational translation paths Ralf Lici
2026-03-19 15:12 ` [RFC net-next 12/15] ipxlat: add ICMP error translation and quoted-inner handling Ralf Lici
2026-03-19 15:12 ` [RFC net-next 13/15] ipxlat: add netlink control plane and uapi Ralf Lici
2026-03-19 15:12 ` [RFC net-next 14/15] selftests: net: add ipxlat coverage Ralf Lici
2026-03-19 15:12 ` [RFC net-next 15/15] Documentation: networking: add ipxlat translator guide Ralf Lici
2026-03-19 22:11   ` Jonathan Corbet
2026-03-24  9:55     ` Ralf Lici

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260319151230.655687-10-ralf@mandelbit.com \
    --to=ralf@mandelbit.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=antonio@mandelbit.com \
    --cc=davem@davemloft.net \
    --cc=dxld@darkboxed.org \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox